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 "one_of.hh"
19 #include "serialize.hh"
20 #include <memory>
21 
22 namespace openmsx {
23 
25  Rom&& rom_, SubType subType)
26  : Rom8kBBlocks(config, std::move(rom_))
27  , sramEnableBit((subType == WIZARDRY) ? 0x80
28  : rom.getSize() / BANK_SIZE)
29  , sramPages((subType == one_of(KOEI_8, KOEI_32)) ? 0x34 : 0x30)
30 {
31  unsigned size = (subType == one_of(KOEI_32, ASCII8_32)) ? 0x8000 // 32kB
32  : (subType == ASCII8_2) ? 0x0800 // 2kB
33  : 0x2000; // 8kB
34  sram = std::make_unique<SRAM>(getName() + " SRAM", size, config);
35  reset(EmuTime::dummy());
36 }
37 
38 void RomAscii8_8::reset(EmuTime::param /*time*/)
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 
51 byte RomAscii8_8::readMem(word address, EmuTime::param time)
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 
64 const byte* RomAscii8_8::getReadCacheLine(word address) const
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  invalidateDeviceRCache(0x2000 * region, 0x2000); // do not cache
88  } else {
89  sramEnabled &= ~(1 << region);
90  setRom(region, value);
91  }
92  // 'R' is already handled
93  invalidateDeviceWCache(0x2000 * region, 0x2000);
94  } else {
95  byte bank = address / BANK_SIZE;
96  if ((1 << bank) & sramEnabled) {
97  // write to SRAM (possibly mirror)
98  word addr = (sramBlock[bank] * BANK_SIZE)
99  + (address & (sram->getSize() - 1) & BANK_MASK);
100  sram->write(addr, value);
101  }
102  }
103 }
104 
106 {
107  if ((0x6000 <= address) && (address < 0x8000)) {
108  // bank switching
109  return nullptr;
110  } else if ((1 << (address / BANK_SIZE)) & sramEnabled) {
111  // write to SRAM
112  return nullptr;
113  } else {
114  return unmappedWrite;
115  }
116 }
117 
118 template<typename Archive>
119 void RomAscii8_8::serialize(Archive& ar, unsigned /*version*/)
120 {
121  ar.template serializeBase<Rom8kBBlocks>(*this);
122  ar.serialize("sramEnabled", sramEnabled,
123  "sramBlock", sramBlock);
124 }
127 
128 } // namespace openmsx
openmsx::RomAscii8_8::ASCII8_32
@ ASCII8_32
Definition: RomAscii8_8.hh:11
one_of.hh
openmsx::RomAscii8_8::SubType
SubType
Definition: RomAscii8_8.hh:11
openmsx::RomAscii8_8::KOEI_32
@ KOEI_32
Definition: RomAscii8_8.hh:11
serialize.hh
RomAscii8_8.hh
openmsx::DeviceConfig
Definition: DeviceConfig.hh:20
utf8::unchecked::size
size_t size(std::string_view utf8)
Definition: utf8_unchecked.hh:227
openmsx::MSXDevice::unmappedWrite
static byte unmappedWrite[0x10000]
Definition: MSXDevice.hh:301
openmsx::RomBlocks::setBank
void setBank(byte region, const byte *adr, int block)
Sets the memory visible for reading in a certain region.
Definition: RomBlocks.cc:77
openmsx::RomAscii8_8::getWriteCacheLine
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:105
openmsx::RomAscii8_8::writeMem
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
openmsx::RomAscii8_8::RomAscii8_8
RomAscii8_8(const DeviceConfig &config, Rom &&rom, SubType subType)
Definition: RomAscii8_8.cc:24
openmsx::RomBlocks::sram
std::unique_ptr< SRAM > sram
Definition: RomBlocks.hh:83
openmsx::RomAscii8_8::serialize
void serialize(Archive &ar, unsigned version)
Definition: RomAscii8_8.cc:119
openmsx::REGISTER_MSXDEVICE
REGISTER_MSXDEVICE(ChakkariCopy, "ChakkariCopy")
openmsx::RomAscii8_8::getReadCacheLine
const byte * getReadCacheLine(word address) const override
Test that the memory in the interval [start, start + CacheLine::SIZE) is cacheable for reading.
Definition: RomAscii8_8.cc:64
openmsx::RomAscii8_8
Definition: RomAscii8_8.hh:9
openmsx::RomBlocks::getReadCacheLine
const byte * getReadCacheLine(word address) const override
Test that the memory in the interval [start, start + CacheLine::SIZE) is cacheable for reading.
Definition: RomBlocks.cc:71
openmsx::RomBlocks::setRom
void setRom(byte region, unsigned block)
Selects a block of the ROM image for reading in a certain region.
Definition: RomBlocks.cc:104
openmsx::MSXDevice::invalidateDeviceWCache
void invalidateDeviceWCache()
Definition: MSXDevice.hh:210
one_of
Definition: one_of.hh:7
openmsx::RomBlocks::setUnmapped
void setUnmapped(byte region)
Select 'unmapped' memory for this region.
Definition: RomBlocks.cc:91
openmsx::RomBlocks
Definition: RomBlocks.hh:14
INSTANTIATE_SERIALIZE_METHODS
#define INSTANTIATE_SERIALIZE_METHODS(CLASS)
Definition: serialize.hh:981
openmsx::Rom
Definition: Rom.hh:21
openmsx::RomAscii8_8::readMem
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
openmsx::MSXDevice::invalidateDeviceRCache
void invalidateDeviceRCache()
Definition: MSXDevice.hh:209
SRAM.hh
openmsx::RomBlocks::readMem
byte readMem(word address, EmuTime::param time) override
Read a byte from a location at a certain time from this device.
Definition: RomBlocks.cc:65
openmsx::MSXDevice::getName
virtual std::string getName() const
Returns a human-readable name for this device.
Definition: MSXDevice.cc:381
openmsx::RomBlocks::BANK_SIZE
static constexpr unsigned BANK_SIZE
Definition: RomBlocks.hh:16
openmsx::RomBlocks::BANK_MASK
static constexpr unsigned BANK_MASK
Definition: RomBlocks.hh:18
openmsx::word
uint16_t word
16 bit unsigned integer
Definition: openmsx.hh:29
openmsx::RomAscii8_8::ASCII8_2
@ ASCII8_2
Definition: RomAscii8_8.hh:11
openmsx::RomAscii8_8::reset
void reset(EmuTime::param time) override
This method is called on reset.
Definition: RomAscii8_8.cc:38
openmsx
This file implemented 3 utility functions:
Definition: Autofire.cc:5