openMSX
MSXMegaRam.cc
Go to the documentation of this file.
1 /*
2  * Adriano Camargo Rodrigues da Cunha wrote:
3  *
4  * Any address inside a 8k page can change the page. In other
5  * words:
6  *
7  * for 4000h-5FFFh, mapping addresses are 4000h-5FFFh
8  * for 6000h-7FFFh, mapping addresses are 6000h-7FFFh
9  * for 8000h-9FFFh, mapping addresses are 8000h-9FFFh
10  * for A000h-BFFFh, mapping addresses are A000h-BFFFh
11  *
12  * If you do an IN A,(8Eh) (the value of A register is unknown and
13  * never used) you can write on MegaRAM pages, but you can't map
14  * pages. If you do an OUT (8Eh),A (the value of A register doesn't
15  * matter) you can't write to MegaRAM pages, but you can map them.
16  *
17  * Another thing: the MegaRAMs of Ademir Carchano have a mirror
18  * effect: if you map the page 0 of MegaRAM slot, you'll be
19  * acessing the same area of 8000h-BFFFh of this slot; if you map
20  * the page 3 of MegaRAM slot, you'll be acessing the same area of
21  * 4000h-7FFFh of this slot. I don't know any software that makes
22  * use of this feature, except UZIX for MSX1.
23  */
24 
25 #include "MSXMegaRam.hh"
26 #include "Rom.hh"
27 #include "Math.hh"
28 #include "serialize.hh"
29 #include "xrange.hh"
30 #include <memory>
31 
32 namespace openmsx {
33 
35  : MSXDevice(config)
36  , numBlocks(config.getChildDataAsInt("size", 0) / 8) // 8kB blocks
37  , ram(config, getName() + " RAM", "Mega-RAM", numBlocks * 0x2000)
38  , rom(config.findChild("rom")
39  ? std::make_unique<Rom>(getName() + " ROM", "Mega-RAM DiskROM", config)
40  : nullptr)
41  , romBlockDebug(*this, bank, 0x0000, 0x10000, 13, 0, 3)
42  , maskBlocks(Math::ceil2(numBlocks) - 1)
43 {
44  powerUp(EmuTime::dummy());
45 }
46 
47 MSXMegaRam::~MSXMegaRam() = default;
48 
49 void MSXMegaRam::powerUp(EmuTime::param time)
50 {
51  for (auto i : xrange(4)) {
52  setBank(i, 0);
53  }
54  writeMode = false;
55  ram.clear();
56  reset(time);
57 }
58 
59 void MSXMegaRam::reset(EmuTime::param /*time*/)
60 {
61  // selected banks nor writeMode does change after reset
62  romMode = rom != nullptr; // select rom mode if there is a rom
63 }
64 
65 byte MSXMegaRam::readMem(word address, EmuTime::param /*time*/)
66 {
67  return *MSXMegaRam::getReadCacheLine(address);
68 }
69 
70 const byte* MSXMegaRam::getReadCacheLine(word address) const
71 {
72  if (romMode) {
73  if (address >= 0x4000 && address <= 0xBFFF) {
74  return &(*rom)[address - 0x4000];
75  }
76  return unmappedRead;
77  }
78  unsigned block = bank[(address & 0x7FFF) / 0x2000];
79  return (block < numBlocks)
80  ? &ram[(block * 0x2000) + (address & 0x1FFF)]
81  : unmappedRead;
82 }
83 
84 void MSXMegaRam::writeMem(word address, byte value, EmuTime::param /*time*/)
85 {
86  if (byte* tmp = getWriteCacheLine(address)) {
87  *tmp = value;
88  } else {
89  assert(!romMode && !writeMode);
90  setBank((address & 0x7FFF) / 0x2000, value);
91  }
92 }
93 
94 byte* MSXMegaRam::getWriteCacheLine(word address) const
95 {
96  if (romMode) return unmappedWrite;
97  if (writeMode) {
98  unsigned block = bank[(address & 0x7FFF) / 0x2000];
99  return (block < numBlocks)
100  ? const_cast<byte*>(&ram[(block * 0x2000) + (address & 0x1FFF)])
101  : unmappedWrite;
102  } else {
103  return nullptr;
104  }
105 }
106 
107 byte MSXMegaRam::readIO(word port, EmuTime::param /*time*/)
108 {
109  switch (port & 1) {
110  case 0:
111  // enable writing
112  writeMode = true;
113  romMode = false;
114  break;
115  case 1:
116  if (rom) romMode = true;
117  break;
118  }
120  return 0xFF; // return value doesn't matter
121 }
122 
123 byte MSXMegaRam::peekIO(word /*port*/, EmuTime::param /*time*/) const
124 {
125  return 0xFF;
126 }
127 
128 void MSXMegaRam::writeIO(word port, byte /*value*/, EmuTime::param /*time*/)
129 {
130  switch (port & 1) {
131  case 0:
132  // enable switching
133  writeMode = false;
134  romMode = false;
135  break;
136  case 1:
137  if (rom) romMode = true;
138  break;
139  }
141 }
142 
143 void MSXMegaRam::setBank(byte page, byte block)
144 {
145  bank[page] = block & maskBlocks;
146  word adr = page * 0x2000;
147  invalidateDeviceRWCache(adr + 0x0000, 0x2000);
148  invalidateDeviceRWCache(adr + 0x8000, 0x2000);
149 }
150 
151 template<typename Archive>
152 void MSXMegaRam::serialize(Archive& ar, unsigned /*version*/)
153 {
154  ar.template serializeBase<MSXDevice>(*this);
155  ar.serialize("ram", ram,
156  "bank", bank,
157  "writeMode", writeMode,
158  "romMode", romMode);
159 }
162 
163 } // namespace openmsx
An MSXDevice is an emulated hardware component connected to the bus of the emulated MSX.
Definition: MSXDevice.hh:33
static byte unmappedRead[0x10000]
Definition: MSXDevice.hh:301
void invalidateDeviceRWCache()
Calls MSXCPUInterface::invalidateXXCache() for the specific (part of) the slot that this device is lo...
Definition: MSXDevice.hh:209
static byte unmappedWrite[0x10000]
Definition: MSXDevice.hh:302
void reset(EmuTime::param time) override
This method is called on reset.
Definition: MSXMegaRam.cc:59
void powerUp(EmuTime::param time) override
This method is called when MSX is powered up.
Definition: MSXMegaRam.cc:49
byte readMem(word address, EmuTime::param time) override
Read a byte from a location at a certain time from this device.
Definition: MSXMegaRam.cc:65
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: MSXMegaRam.cc:84
~MSXMegaRam() override
byte * getWriteCacheLine(word address) const override
Test that the memory in the interval [start, start + CacheLine::SIZE) is cacheable for writing.
Definition: MSXMegaRam.cc:94
byte readIO(word port, EmuTime::param time) override
Read a byte from an IO port at a certain time from this device.
Definition: MSXMegaRam.cc:107
void serialize(Archive &ar, unsigned version)
Definition: MSXMegaRam.cc:152
byte peekIO(word port, EmuTime::param time) const override
Read a byte from a given IO port.
Definition: MSXMegaRam.cc:123
MSXMegaRam(const DeviceConfig &config)
Definition: MSXMegaRam.cc:34
void writeIO(word port, byte value, EmuTime::param time) override
Write a byte to a given IO port at a certain time to this device.
Definition: MSXMegaRam.cc:128
const byte * getReadCacheLine(word address) const override
Test that the memory in the interval [start, start + CacheLine::SIZE) is cacheable for reading.
Definition: MSXMegaRam.cc:70
void clear(byte c=0xff)
Definition: Ram.cc:35
Definition: Math.hh:30
constexpr T ceil2(T x) noexcept
Returns the smallest number that is both >=a and a power of two.
Definition: Math.hh:85
std::string getName(KeyCode keyCode)
Translate key code to key name.
Definition: Keys.cc:741
This file implemented 3 utility functions:
Definition: Autofire.cc:9
REGISTER_MSXDEVICE(ChakkariCopy, "ChakkariCopy")
uint16_t word
16 bit unsigned integer
Definition: openmsx.hh:29
#define INSTANTIATE_SERIALIZE_METHODS(CLASS)
Definition: serialize.hh:998
constexpr auto xrange(T e)
Definition: xrange.hh:155