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 "serialize.hh"
28#include "xrange.hh"
29#include <bit>
30#include <memory>
31
32namespace 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(std::bit_ceil(numBlocks) - 1)
43{
44 powerUp(EmuTime::dummy());
45}
46
47MSXMegaRam::~MSXMegaRam() = default;
48
49void 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
59void 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
65byte MSXMegaRam::readMem(word address, EmuTime::param /*time*/)
66{
67 return *MSXMegaRam::getReadCacheLine(address);
68}
69
70const 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)]
82}
83
84void 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
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)])
102 } else {
103 return nullptr;
104 }
105}
106
107byte 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
123byte MSXMegaRam::peekIO(word /*port*/, EmuTime::param /*time*/) const
124{
125 return 0xFF;
126}
127
128void 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
143void 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
151template<typename Archive>
152void 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
std::string getName(KeyCode keyCode)
Translate key code to key name.
Definition: Keys.cc:727
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
STL namespace.
#define INSTANTIATE_SERIALIZE_METHODS(CLASS)
Definition: serialize.hh:1009
constexpr auto xrange(T e)
Definition: xrange.hh:133