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 "MSXException.hh"
24#include "narrow.hh"
25#include "one_of.hh"
26#include "serialize.hh"
27#include "xrange.hh"
28#include <cassert>
29
30namespace openmsx {
31
32size_t ESE_RAM::getSramSize() const
33{
34 size_t sramSize = getDeviceConfig().getChildDataAsInt("sramsize", 256); // size in kb
35 if (sramSize != one_of(1024u, 512u, 256u, 128u)) {
36 throw MSXException(
37 "SRAM size for ", getName(),
38 " should be 128, 256, 512 or 1024kB and not ",
39 sramSize, "kB!");
40 }
41 return sramSize * 1024; // in bytes
42}
43
45 : MSXDevice(config)
46 , sram(getName() + " SRAM", getSramSize(), config)
47 , romBlockDebug(*this, mapped, 0x4000, 0x8000, 13)
48 , blockMask(narrow<byte>((sram.size() / 0x2000) - 1))
49{
50 reset(EmuTime::dummy());
51}
52
53void ESE_RAM::reset(EmuTime::param /*time*/)
54{
55 for (auto i : xrange(4)) {
56 setSRAM(i, 0);
57 }
58}
59
60byte ESE_RAM::readMem(word address, EmuTime::param /*time*/)
61{
62 if ((0x4000 <= address) && (address < 0xC000)) {
63 unsigned page = (address / 8192) - 2;
64 word addr = address & 0x1FFF;
65 return sram[8192 * mapped[page] + addr];
66 } else {
67 return 0xFF;
68 }
69}
70
71const byte* ESE_RAM::getReadCacheLine(word address) const
72{
73 if ((0x4000 <= address) && (address < 0xC000)) {
74 unsigned page = (address / 8192) - 2;
75 address &= 0x1FFF;
76 return &sram[8192 * mapped[page] + address];
77 } else {
78 return unmappedRead.data();
79 }
80}
81
82void ESE_RAM::writeMem(word address, byte value, EmuTime::param /*time*/)
83{
84 if ((0x6000 <= address) && (address < 0x8000)) {
85 byte region = ((address >> 11) & 3);
86 setSRAM(region, value);
87 } else if ((0x4000 <= address) && (address < 0xC000)) {
88 unsigned page = (address / 8192) - 2;
89 address &= 0x1FFF;
90 if (isWriteable[page]) {
91 sram.write(8192 * mapped[page] + address, value);
92 }
93 }
94}
95
97{
98 if ((0x6000 <= address) && (address < 0x8000)) {
99 return nullptr;
100 } else if ((0x4000 <= address) && (address < 0xC000)) {
101 unsigned page = (address / 8192) - 2;
102 if (isWriteable[page]) {
103 return nullptr;
104 }
105 }
106 return unmappedWrite.data();
107}
108
109void ESE_RAM::setSRAM(unsigned region, byte block)
110{
111 invalidateDeviceRWCache(region * 0x2000 + 0x4000, 0x2000);
112 assert(region < 4);
113 isWriteable[region] = (block & 0x80) != 0;
114 mapped[region] = block & blockMask;
115}
116
117template<typename Archive>
118void ESE_RAM::serialize(Archive& ar, unsigned /*version*/)
119{
120 ar.template serializeBase<MSXDevice>(*this);
121 ar.serialize("SRAM", sram,
122 "isWriteable", isWriteable,
123 "mapped", mapped);
124}
127
128} // namespace openmsx
#define REGISTER_MSXDEVICE(CLASS, NAME)
Definition MSXDevice.hh:356
void serialize(Archive &ar, unsigned version)
Definition ESE_RAM.cc:118
byte * getWriteCacheLine(word address) override
Test that the memory in the interval [start, start + CacheLine::SIZE) is cacheable for writing.
Definition ESE_RAM.cc:96
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:60
const byte * getReadCacheLine(word address) const override
Test that the memory in the interval [start, start + CacheLine::SIZE) is cacheable for reading.
Definition ESE_RAM.cc:71
void reset(EmuTime::param time) override
This method is called on reset.
Definition ESE_RAM.cc:53
ESE_RAM(const DeviceConfig &config)
Definition ESE_RAM.cc:44
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:82
An MSXDevice is an emulated hardware component connected to the bus of the emulated MSX.
Definition MSXDevice.hh:36
static std::array< byte, 0x10000 > unmappedRead
Definition MSXDevice.hh:306
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 invalidateDeviceRWCache()
Calls MSXCPUInterface::invalidateXXCache() for the specific (part of) the slot that this device is lo...
Definition MSXDevice.hh:214
const XMLElement & getDeviceConfig() const
Get the configuration section for this device.
Definition MSXDevice.hh:236
void write(size_t addr, byte value)
Definition SRAM.cc:64
int getChildDataAsInt(std::string_view childName, int defaultValue) const
Definition XMLElement.cc:83
This file implemented 3 utility functions:
Definition Autofire.cc:11
uint8_t byte
8 bit unsigned integer
Definition openmsx.hh:26
uint16_t word
16 bit unsigned integer
Definition openmsx.hh:29
constexpr To narrow(From from) noexcept
Definition narrow.hh:37
#define INSTANTIATE_SERIALIZE_METHODS(CLASS)
constexpr auto xrange(T e)
Definition xrange.hh:132