openMSX
ESE_RAM.cc
Go to the documentation of this file.
1 /*
2  * MEGA-SCSI and ESE-RAM cartridge:
3  * The mapping does SRAM and MB89352A(MEGA-SCSI) to ASCII8 or
4  * an interchangeable bank controller.
5  * The rest of this documentation is only about ESE-RAM specifically.
6  *
7  * Specification:
8  * SRAM(MegaROM) controller: ASCII8 type
9  * SRAM capacity : 128, 256, 512 and 1024KB
10  *
11  * Bank changing address:
12  * bank 4(0x4000-0x5fff): 0x6000 - 0x67FF (0x6000 used)
13  * bank 6(0x6000-0x7fff): 0x6800 - 0x6FFF (0x6800 used)
14  * bank 8(0x8000-0x9fff): 0x7000 - 0x77FF (0x7000 used)
15  * bank A(0xa000-0xbfff): 0x7800 - 0x7FFF (0x7800 used)
16  *
17  * ESE-RAM Bank Map:
18  * BANK 00H-7FH (read only)
19  * BANK 80H-FFH (write and read. mirror of 00H-7FH)
20  */
21 
22 #include "ESE_RAM.hh"
23 #include "StringOp.hh"
24 #include "MSXException.hh"
25 #include "serialize.hh"
26 #include "memory.hh"
27 #include <cassert>
28 
29 namespace openmsx {
30 
31 unsigned ESE_RAM::getSramSize() const
32 {
33  unsigned sramSize = getDeviceConfig().getChildDataAsInt("sramsize", 256); // size in kb
34  if (sramSize != 1024 && sramSize != 512 && sramSize != 256 && sramSize != 128) {
35  throw MSXException(StringOp::Builder() <<
36  "SRAM size for " << getName() <<
37  " should be 128, 256, 512 or 1024kB and not " <<
38  sramSize << "kB!");
39  }
40  return sramSize * 1024; // in bytes
41 }
42 
44  : MSXDevice(config)
45  , sram(getName() + " SRAM", getSramSize(), config)
46  , romBlockDebug(*this, mapped, 0x4000, 0x8000, 13)
47  , blockMask((sram.getSize() / 8192) - 1)
48 {
50 }
51 
53 {
54  for (int i = 0; i < 4; ++i) {
55  setSRAM(i, 0);
56  }
57 }
58 
60 {
61  byte result;
62  if ((0x4000 <= address) && (address < 0xC000)) {
63  unsigned page = (address / 8192) - 2;
64  word addr = address & 0x1FFF;
65  result = sram[8192 * mapped[page] + addr];
66  } else {
67  result = 0xFF;
68  }
69  return result;
70 }
71 
72 const byte* ESE_RAM::getReadCacheLine(word address) const
73 {
74  if ((0x4000 <= address) && (address < 0xC000)) {
75  unsigned page = (address / 8192) - 2;
76  address &= 0x1FFF;
77  return &sram[8192 * mapped[page] + address];
78  } else {
79  return unmappedRead;
80  }
81 }
82 
83 void ESE_RAM::writeMem(word address, byte value, EmuTime::param /*time*/)
84 {
85  if ((0x6000 <= address) && (address < 0x8000)) {
86  byte region = ((address >> 11) & 3);
87  setSRAM(region, value);
88  } else if ((0x4000 <= address) && (address < 0xC000)) {
89  unsigned page = (address / 8192) - 2;
90  address &= 0x1FFF;
91  if (isWriteable[page]) {
92  sram.write(8192 * mapped[page] + address, value);
93  }
94  }
95 }
96 
98 {
99  if ((0x6000 <= address) && (address < 0x8000)) {
100  return nullptr;
101  } else if ((0x4000 <= address) && (address < 0xC000)) {
102  unsigned page = (address / 8192) - 2;
103  if (isWriteable[page]) {
104  return nullptr;
105  }
106  }
107  return unmappedWrite;
108 }
109 
110 void ESE_RAM::setSRAM(unsigned region, byte block)
111 {
112  invalidateMemCache(region * 0x2000 + 0x4000, 0x2000);
113  assert(region < 4);
114  isWriteable[region] = (block & 0x80) != 0;
115  mapped[region] = block & blockMask;
116 }
117 
118 template<typename Archive>
119 void ESE_RAM::serialize(Archive& ar, unsigned /*version*/)
120 {
121  ar.template serializeBase<MSXDevice>(*this);
122  ar.serialize("SRAM", sram);
123  ar.serialize("isWriteable", isWriteable);
124  ar.serialize("mapped", mapped);
125 }
127 REGISTER_MSXDEVICE(ESE_RAM, "ESE_RAM");
128 
129 } // namespace openmsx
void serialize(Archive &ar, unsigned version)
Definition: ESE_RAM.cc:119
REGISTER_MSXDEVICE(DebugDevice,"DebugDevice")
static param dummy()
Definition: EmuTime.hh:21
const byte * getReadCacheLine(word start) const override
Test that the memory in the interval [start, start + CacheLine::SIZE) is cacheable for reading...
Definition: ESE_RAM.cc:72
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: ESE_RAM.cc:83
void write(unsigned addr, byte value)
Definition: SRAM.cc:58
virtual std::string getName() const
Returns a human-readable name for this device.
Definition: MSXDevice.cc:374
Thanks to enen for testing this on a real cartridge:
Definition: Autofire.cc:5
An MSXDevice is an emulated hardware component connected to the bus of the emulated MSX...
Definition: MSXDevice.hh:32
unsigned char byte
8 bit unsigned integer
Definition: openmsx.hh:25
int getChildDataAsInt(string_ref name, int defaultValue=0) const
Definition: XMLElement.cc:211
const XMLElement & getDeviceConfig() const
Get the configuration section for this device.
Definition: MSXDevice.hh:210
byte * getWriteCacheLine(word start) const override
Test that the memory in the interval [start, start + CacheLine::SIZE) is cacheable for writing...
Definition: ESE_RAM.cc:97
static byte unmappedRead[0x10000]
Definition: MSXDevice.hh:266
ESE_RAM(const DeviceConfig &config)
Definition: ESE_RAM.cc:43
#define INSTANTIATE_SERIALIZE_METHODS(CLASS)
Definition: serialize.hh:802
static byte unmappedWrite[0x10000]
Definition: MSXDevice.hh:267
void reset(EmuTime::param time) override
This method is called on reset.
Definition: ESE_RAM.cc:52
const string getName(KeyCode keyCode)
Translate key code to key name.
Definition: Keys.cc:373
void invalidateMemCache(word start, unsigned size)
Invalidate CPU memory-mapping cache.
Definition: MSXDevice.cc:453
byte readMem(word address, EmuTime::param time) override
Read a byte from a location at a certain time from this device.
Definition: ESE_RAM.cc:59
unsigned short word
16 bit unsigned integer
Definition: openmsx.hh:28