openMSX
RomHalnote.cc
Go to the documentation of this file.
1/*
2 * HALNOTE mapper
3 *
4 * This info is extracted from the romMapperHalnote.c source in blueMSX,
5 * implemented by white_cat.
6 *
7 * This is a 1024kB mapper, it's divided in 128 pages of 8kB. The last 512kB
8 * can also be mapped as 256 pages of 2kB. There is 16kB SRAM.
9 *
10 * Main bank-switch registers:
11 * bank 0, region: [0x4000-0x5FFF], switch addr: 0x4FFF
12 * bank 1, region: [0x6000-0x7FFF], switch addr: 0x6FFF
13 * bank 2, region: [0x8000-0x9FFF], switch addr: 0x8FFF
14 * bank 3, region: [0xA000-0xBFFF], switch addr: 0xAFFF
15 * Sub-bank-switch registers:
16 * bank 0, region: [0x7000-0x77FF], switch addr: 0x77FF
17 * bank 1, region: [0x7800-0x7FFF], switch addr: 0x7FFF
18 * Note that the two sub-banks overlap with main bank 1!
19 *
20 * The upper bit (0x80) of the first two main bank-switch registers are special:
21 * bank 0, bit7 SRAM enabled in [0x0000-0x3FFF] (1=enabled)
22 * bank 1, bit7 submapper enabled in [0x7000-0x7FFF] (1=enabled)
23 * If enabled, the submapper shadows (part of) main bank 1.
24 */
25
26#include "RomHalnote.hh"
27#include "CacheLine.hh"
28#include "SRAM.hh"
29#include "MSXException.hh"
30#include "one_of.hh"
31#include "serialize.hh"
32#include "xrange.hh"
33#include <memory>
34
35namespace openmsx {
36
38 : Rom8kBBlocks(config, std::move(rom_))
39{
40 if (rom.size() != 0x100000) {
41 throw MSXException(
42 "Rom for HALNOTE mapper must be exactly 1MB in size.");
43 }
44 sram = std::make_unique<SRAM>(getName() + " SRAM", 0x4000, config);
45 reset(EmuTime::dummy());
46}
47
48void RomHalnote::reset(EmuTime::param /*time*/)
49{
50 subBanks[0] = subBanks[1] = 0;
51 sramEnabled = false;
52 subMapperEnabled = false;
53
54 setUnmapped(0);
55 setUnmapped(1);
56 for (auto i : xrange(2, 6)) {
57 setRom(i, 0);
58 }
59 setUnmapped(6);
60 setUnmapped(7);
61}
62
63const byte* RomHalnote::getReadCacheLine(word address) const
64{
65 if (subMapperEnabled && (0x7000 <= address) && (address < 0x8000)) {
66 // sub-mapper
67 int subBank = address < 0x7800 ? 0 : 1;
68 return &rom[0x80000 + subBanks[subBank] * 0x800 + (address & 0x7FF)];
69 } else {
70 // default mapper implementation
71 return Rom8kBBlocks::getReadCacheLine(address);
72 }
73}
74byte RomHalnote::readMem(word address, EmuTime::param /*time*/)
75{
76 // all reads are cacheable, reuse that implementation
77 return *RomHalnote::getReadCacheLine(address);
78}
79
80void RomHalnote::writeMem(word address, byte value, EmuTime::param /*time*/)
81{
82 if (address < 0x4000) {
83 // SRAM region
84 if (sramEnabled) {
85 sram->write(address, value);
86 }
87 } else if (address < 0xC000) {
88 if (address == one_of(0x77FF, 0x7FFF)) {
89 // sub-mapper bank switch region
90 int subBank = address < 0x7800 ? 0 : 1;
91 if (subBanks[subBank] != value) {
92 subBanks[subBank] = value;
93 if (subMapperEnabled) {
95 0x7000 + subBank * 0x800, 0x800);
96 }
97 }
98 } else if ((address & 0x1FFF) == 0x0FFF) {
99 // normal bank switch region
100 auto bank = address >> 13; // 2-5
101 setRom(bank, value);
102 if (bank == 2) {
103 // sram enable/disable
104 bool newSramEnabled = (value & 0x80) != 0;
105 if (newSramEnabled != sramEnabled) {
106 sramEnabled = newSramEnabled;
107 if (sramEnabled) {
108 setBank(0, &(*sram)[0x0000], value);
109 setBank(1, &(*sram)[0x2000], value);
110 } else {
111 setUnmapped(0);
112 setUnmapped(1);
113 }
114 // 'R' is already handled
115 invalidateDeviceWCache(0x0000, 0x4000);
116 }
117 } else if (bank == 3) {
118 // sub-mapper enable/disable
119 subMapperEnabled = (value & 0x80) != 0;
120 if (subMapperEnabled) {
121 invalidateDeviceRCache(0x7000, 0x1000);
122 }
123 }
124 }
125 }
126}
127
129{
130 if (address < 0x4000) {
131 // SRAM region
132 if (sramEnabled) {
133 return nullptr;
134 }
135 } else if (address < 0xC000) {
136 if ((address & CacheLine::HIGH) == one_of(0x77FF & CacheLine::HIGH,
137 0x7FFF & CacheLine::HIGH)) {
138 // sub-mapper bank switch region
139 return nullptr;
140 } else if ((address & 0x1FFF & CacheLine::HIGH) ==
141 (0x0FFF & CacheLine::HIGH)) {
142 // normal bank switch region
143 return nullptr;
144 }
145 }
146 return unmappedWrite.data();
147}
148
149template<typename Archive>
150void RomHalnote::serialize(Archive& ar, unsigned /*version*/)
151{
152 ar.template serializeBase<Rom8kBBlocks>(*this);
153 ar.serialize("subBanks", subBanks,
154 "sramEnabled", sramEnabled,
155 "subMapperEnabled", subMapperEnabled);
156
157}
160
161} // namespace openmsx
#define REGISTER_MSXDEVICE(CLASS, NAME)
Definition MSXDevice.hh:356
void invalidateDeviceRCache()
Definition MSXDevice.hh:215
void invalidateDeviceWCache()
Definition MSXDevice.hh:216
virtual const std::string & getName() const
Returns a human-readable name for this device.
Definition MSXDevice.cc:375
static std::array< byte, 0x10000 > unmappedWrite
Definition MSXDevice.hh:307
void setBank(unsigned region, const byte *adr, byte block)
Sets the memory visible for reading in a certain region.
Definition RomBlocks.cc:78
void setUnmapped(unsigned region)
Select 'unmapped' memory for this region.
Definition RomBlocks.cc:92
std::unique_ptr< SRAM > sram
Definition RomBlocks.hh:85
void setRom(unsigned region, unsigned block)
Selects a block of the ROM image for reading in a certain region.
Definition RomBlocks.cc:104
const byte * getReadCacheLine(word address) const override
Test that the memory in the interval [start, start + CacheLine::SIZE) is cacheable for reading.
Definition RomBlocks.cc:72
void reset(EmuTime::param time) override
This method is called on reset.
Definition RomHalnote.cc:48
byte * getWriteCacheLine(word address) override
Test that the memory in the interval [start, start + CacheLine::SIZE) is cacheable for writing.
RomHalnote(const DeviceConfig &config, Rom &&rom)
Definition RomHalnote.cc:37
const byte * getReadCacheLine(word address) const override
Test that the memory in the interval [start, start + CacheLine::SIZE) is cacheable for reading.
Definition RomHalnote.cc:63
void writeMem(word address, byte value, EmuTime::param time) override
Write a given byte to a given location at a certain time to this device.
Definition RomHalnote.cc:80
void serialize(Archive &ar, unsigned version)
byte readMem(word address, EmuTime::param time) override
Read a byte from a location at a certain time from this device.
Definition RomHalnote.cc:74
auto size() const
Definition Rom.hh:36
constexpr unsigned HIGH
Definition CacheLine.hh:10
This file implemented 3 utility functions:
Definition Autofire.cc:11
uint16_t word
16 bit unsigned integer
Definition openmsx.hh:29
STL namespace.
#define INSTANTIATE_SERIALIZE_METHODS(CLASS)
constexpr auto xrange(T e)
Definition xrange.hh:132