openMSX
RomAscii8_8.cc
Go to the documentation of this file.
1 // ASCII 8kB based cartridges with SRAM
2 // - ASCII8-8 / KOEI-8 / KOEI-32 / WIZARDRY / ASCII8-2
3 //
4 // The address to change banks:
5 // bank 1: 0x6000 - 0x67ff (0x6000 used)
6 // bank 2: 0x6800 - 0x6fff (0x6800 used)
7 // bank 3: 0x7000 - 0x77ff (0x7000 used)
8 // bank 4: 0x7800 - 0x7fff (0x7800 used)
9 //
10 // To select SRAM set bit 7 (for WIZARDRY) or the bit just above the
11 // rom selection bits (bit 5/6/7 depending on ROM size). For KOEI-32
12 // the lowest bits indicate which SRAM page is selected. SRAM is
13 // readable at 0x8000-0xBFFF. For the KOEI-x types SRAM is also
14 // readable at 0x4000-0x5FFF
15 
16 #include "RomAscii8_8.hh"
17 #include "Rom.hh"
18 #include "SRAM.hh"
19 #include "serialize.hh"
20 #include "memory.hh"
21 
22 namespace openmsx {
23 
25  std::unique_ptr<Rom> rom_, SubType subType)
26  : Rom8kBBlocks(config, std::move(rom_))
27  , sramEnableBit((subType == WIZARDRY) ? 0x80
28  : rom->getSize() / BANK_SIZE)
29  , sramPages(((subType == KOEI_8) || (subType == KOEI_32))
30  ? 0x34 : 0x30)
31 {
32  unsigned size = (subType == KOEI_32 ) ? 0x8000 // 32kB
33  : (subType == ASCII8_2) ? 0x0800 // 2kB
34  : 0x2000; // 8kB
35  sram = make_unique<SRAM>(getName() + " SRAM", size, config);
37 }
38 
40 {
41 }
42 
44 {
45  setUnmapped(0);
46  setUnmapped(1);
47  for (int i = 2; i < 6; i++) {
48  setRom(i, 0);
49  }
50  setUnmapped(6);
51  setUnmapped(7);
52 
53  sramEnabled = 0;
54 }
55 
57 {
58  byte bank = address / BANK_SIZE;
59  if ((1 << bank) & sramEnabled) {
60  // read from SRAM (possibly mirror)
61  word addr = (sramBlock[bank] * BANK_SIZE)
62  + (address & (sram->getSize() - 1) & BANK_MASK);
63  return (*sram)[addr];
64  } else {
65  return Rom8kBBlocks::readMem(address, time);
66  }
67 }
68 
70 {
71  byte bank = address / BANK_SIZE;
72  if ((1 << bank) & sramEnabled) {
73  // read from SRAM (possibly mirror)
74  word addr = (sramBlock[bank] * BANK_SIZE)
75  + (address & (sram->getSize() - 1) & BANK_MASK);
76  return &(*sram)[addr];
77  } else {
78  return Rom8kBBlocks::getReadCacheLine(address);
79  }
80 }
81 
82 void RomAscii8_8::writeMem(word address, byte value, EmuTime::param /*time*/)
83 {
84  if ((0x6000 <= address) && (address < 0x8000)) {
85  // bank switching
86  byte region = ((address >> 11) & 3) + 2;
87  if (value & sramEnableBit) {
88  unsigned numBlocks = (sram->getSize() + BANK_MASK) / BANK_SIZE; // round up;
89  sramEnabled |= (1 << region) & sramPages;
90  sramBlock[region] = value & (numBlocks - 1);
91  setBank(region, &(*sram)[sramBlock[region] * BANK_SIZE], value);
92  } else {
93  sramEnabled &= ~(1 << region);
94  setRom(region, value);
95  }
96  } else {
97  byte bank = address / BANK_SIZE;
98  if ((1 << bank) & sramEnabled) {
99  // write to SRAM (possibly mirror)
100  word addr = (sramBlock[bank] * BANK_SIZE)
101  + (address & (sram->getSize() - 1) & BANK_MASK);
102  sram->write(addr, value);
103  }
104  }
105 }
106 
108 {
109  if ((0x6000 <= address) && (address < 0x8000)) {
110  // bank switching
111  return nullptr;
112  } else if ((1 << (address / BANK_SIZE)) & sramEnabled) {
113  // write to SRAM
114  return nullptr;
115  } else {
116  return unmappedWrite;
117  }
118 }
119 
120 template<typename Archive>
121 void RomAscii8_8::serialize(Archive& ar, unsigned /*version*/)
122 {
123  ar.template serializeBase<Rom8kBBlocks>(*this);
124  ar.serialize("sramEnabled", sramEnabled);
125  ar.serialize("sramBlock", sramBlock);
126 }
128 REGISTER_MSXDEVICE(RomAscii8_8, "RomAscii8_8");
129 
130 } // namespace openmsx
void setRom(byte region, int block)
Selects a block of the ROM image for reading in a certain region.
Definition: RomBlocks.cc:89
REGISTER_MSXDEVICE(DebugDevice,"DebugDevice")
static param dummy()
Definition: EmuTime.hh:21
const byte * bank[NUM_BANKS]
Definition: RomBlocks.hh:80
unsigned char byte
8 bit unsigned integer
Definition: openmsx.hh:33
RomAscii8_8(const DeviceConfig &config, std::unique_ptr< Rom > rom, SubType subType)
Definition: RomAscii8_8.cc:24
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: RomAscii8_8.cc:82
STL namespace.
void reset(EmuTime::param time) override
This method is called on reset.
Definition: RomAscii8_8.cc:43
void serialize(Archive &ar, unsigned version)
Definition: RomAscii8_8.cc:121
const byte * getReadCacheLine(word start) const override
Test that the memory in the interval [start, start + CacheLine::SIZE) is cacheable for reading...
Definition: RomBlocks.cc:56
byte * getWriteCacheLine(word address) const override
Test that the memory in the interval [start, start + CacheLine::SIZE) is cacheable for writing...
Definition: RomAscii8_8.cc:107
void setBank(byte region, const byte *adr, int block)
Sets the memory visible for reading in a certain region.
Definition: RomBlocks.cc:62
byte readMem(word address, EmuTime::param time) override
Read a byte from a location at a certain time from this device.
Definition: RomAscii8_8.cc:56
const byte * getReadCacheLine(word start) const override
Test that the memory in the interval [start, start + CacheLine::SIZE) is cacheable for reading...
Definition: RomAscii8_8.cc:69
virtual std::string getName() const
Returns a human-readable name for this device.
Definition: MSXDevice.cc:374
byte readMem(word address, EmuTime::param time) override
Read a byte from a location at a certain time from this device.
Definition: RomBlocks.cc:50
Thanks to enen for testing this on a real cartridge:
Definition: Autofire.cc:7
unsigned short word
16 bit unsigned integer
Definition: openmsx.hh:38
#define INSTANTIATE_SERIALIZE_METHODS(CLASS)
Definition: serialize.hh:802
static const unsigned BANK_SIZE
Definition: RomBlocks.hh:16
static byte unmappedWrite[0x10000]
Definition: MSXDevice.hh:267
void setUnmapped(byte region)
Select 'unmapped' memory for this region.
Definition: RomBlocks.cc:76
std::unique_ptr< SRAM > sram
Definition: RomBlocks.hh:81
static const unsigned BANK_MASK
Definition: RomBlocks.hh:18
size_t size(string_ref utf8)