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 "SRAM.hh"
18 #include "serialize.hh"
19 #include "memory.hh"
20 
21 namespace openmsx {
22 
24  Rom&& rom_, SubType subType)
25  : Rom8kBBlocks(config, std::move(rom_))
26  , sramEnableBit((subType == WIZARDRY) ? 0x80
27  : rom.getSize() / BANK_SIZE)
28  , sramPages(((subType == KOEI_8) || (subType == KOEI_32))
29  ? 0x34 : 0x30)
30 {
31  unsigned size = (subType == KOEI_32 ) ? 0x8000 // 32kB
32  : (subType == ASCII8_2) ? 0x0800 // 2kB
33  : 0x2000; // 8kB
34  sram = make_unique<SRAM>(getName() + " SRAM", size, config);
36 }
37 
39 {
40  setUnmapped(0);
41  setUnmapped(1);
42  for (int i = 2; i < 6; i++) {
43  setRom(i, 0);
44  }
45  setUnmapped(6);
46  setUnmapped(7);
47 
48  sramEnabled = 0;
49 }
50 
52 {
53  byte bank = address / BANK_SIZE;
54  if ((1 << bank) & sramEnabled) {
55  // read from SRAM (possibly mirror)
56  word addr = (sramBlock[bank] * BANK_SIZE)
57  + (address & (sram->getSize() - 1) & BANK_MASK);
58  return (*sram)[addr];
59  } else {
60  return Rom8kBBlocks::readMem(address, time);
61  }
62 }
63 
65 {
66  byte bank = address / BANK_SIZE;
67  if ((1 << bank) & sramEnabled) {
68  // read from SRAM (possibly mirror)
69  word addr = (sramBlock[bank] * BANK_SIZE)
70  + (address & (sram->getSize() - 1) & BANK_MASK);
71  return &(*sram)[addr];
72  } else {
73  return Rom8kBBlocks::getReadCacheLine(address);
74  }
75 }
76 
77 void RomAscii8_8::writeMem(word address, byte value, EmuTime::param /*time*/)
78 {
79  if ((0x6000 <= address) && (address < 0x8000)) {
80  // bank switching
81  byte region = ((address >> 11) & 3) + 2;
82  if (value & sramEnableBit) {
83  unsigned numBlocks = (sram->getSize() + BANK_MASK) / BANK_SIZE; // round up;
84  sramEnabled |= (1 << region) & sramPages;
85  sramBlock[region] = value & (numBlocks - 1);
86  setBank(region, &(*sram)[sramBlock[region] * BANK_SIZE], value);
87  } else {
88  sramEnabled &= ~(1 << region);
89  setRom(region, value);
90  }
91  } else {
92  byte bank = address / BANK_SIZE;
93  if ((1 << bank) & sramEnabled) {
94  // write to SRAM (possibly mirror)
95  word addr = (sramBlock[bank] * BANK_SIZE)
96  + (address & (sram->getSize() - 1) & BANK_MASK);
97  sram->write(addr, value);
98  }
99  }
100 }
101 
103 {
104  if ((0x6000 <= address) && (address < 0x8000)) {
105  // bank switching
106  return nullptr;
107  } else if ((1 << (address / BANK_SIZE)) & sramEnabled) {
108  // write to SRAM
109  return nullptr;
110  } else {
111  return unmappedWrite;
112  }
113 }
114 
115 template<typename Archive>
116 void RomAscii8_8::serialize(Archive& ar, unsigned /*version*/)
117 {
118  ar.template serializeBase<Rom8kBBlocks>(*this);
119  ar.serialize("sramEnabled", sramEnabled);
120  ar.serialize("sramBlock", sramBlock);
121 }
123 REGISTER_MSXDEVICE(RomAscii8_8, "RomAscii8_8");
124 
125 } // namespace openmsx
void setRom(byte region, int block)
Selects a block of the ROM image for reading in a certain region.
Definition: RomBlocks.cc:86
REGISTER_MSXDEVICE(DebugDevice,"DebugDevice")
static param dummy()
Definition: EmuTime.hh:21
const byte * bank[NUM_BANKS]
Definition: RomBlocks.hh:80
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:77
STL namespace.
void reset(EmuTime::param time) override
This method is called on reset.
Definition: RomAscii8_8.cc:38
void serialize(Archive &ar, unsigned version)
Definition: RomAscii8_8.cc:116
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:53
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:102
void setBank(byte region, const byte *adr, int block)
Sets the memory visible for reading in a certain region.
Definition: RomBlocks.cc:59
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:51
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:64
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:47
Thanks to enen for testing this on a real cartridge:
Definition: Autofire.cc:5
unsigned char byte
8 bit unsigned integer
Definition: openmsx.hh:25
RomAscii8_8(const DeviceConfig &config, Rom &&rom, SubType subType)
Definition: RomAscii8_8.cc:23
#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:73
std::unique_ptr< SRAM > sram
Definition: RomBlocks.hh:81
size_t size() const
static const unsigned BANK_MASK
Definition: RomBlocks.hh:18
unsigned short word
16 bit unsigned integer
Definition: openmsx.hh:28