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 "narrow.hh"
19#include "one_of.hh"
20#include "serialize.hh"
21#include "xrange.hh"
22#include <memory>
23
24namespace openmsx {
25
27 Rom&& rom_, SubType subType)
28 : Rom8kBBlocks(config, std::move(rom_))
29 , sramEnableBit((subType == SubType::WIZARDRY) ? 0x80
30 : narrow_cast<byte>(rom.size() / BANK_SIZE))
31 , sramPages((subType == one_of(SubType::KOEI_8, SubType::KOEI_32)) ? 0x34 : 0x30)
32{
33 unsigned size = (subType == one_of(SubType::KOEI_32, SubType::ASCII8_32)) ? 0x8000 // 32kB
34 : (subType == SubType::ASCII8_2) ? 0x0800 // 2kB
35 : 0x2000; // 8kB
36 sram = std::make_unique<SRAM>(getName() + " SRAM", size, config);
37 reset(EmuTime::dummy());
38}
39
40void RomAscii8_8::reset(EmuTime::param /*time*/)
41{
42 setUnmapped(0);
43 setUnmapped(1);
44 for (auto i : xrange(2, 6)) {
45 setRom(i, 0);
46 }
47 setUnmapped(6);
48 setUnmapped(7);
49
50 sramEnabled = 0;
51}
52
53byte RomAscii8_8::readMem(word address, EmuTime::param time)
54{
55 auto bank = narrow<byte>(address / BANK_SIZE);
56 if ((1 << bank) & sramEnabled) {
57 // read from SRAM (possibly mirror)
58 auto addr = (sramBlock[bank] * BANK_SIZE)
59 + (address & (sram->size() - 1) & BANK_MASK);
60 return (*sram)[addr];
61 } else {
62 return Rom8kBBlocks::readMem(address, time);
63 }
64}
65
66const byte* RomAscii8_8::getReadCacheLine(word address) const
67{
68 auto bank = narrow<byte>(address / BANK_SIZE);
69 if ((1 << bank) & sramEnabled) {
70 // read from SRAM (possibly mirror)
71 auto addr = (sramBlock[bank] * BANK_SIZE)
72 + (address & (sram->size() - 1) & BANK_MASK);
73 return &(*sram)[addr];
74 } else {
75 return Rom8kBBlocks::getReadCacheLine(address);
76 }
77}
78
79void RomAscii8_8::writeMem(word address, byte value, EmuTime::param /*time*/)
80{
81 if ((0x6000 <= address) && (address < 0x8000)) {
82 // bank switching
83 byte region = ((address >> 11) & 3) + 2;
84 if (value & sramEnableBit) {
85 auto mask = narrow_cast<byte>((sram->size() + BANK_MASK) / BANK_SIZE - 1); // round up;
86 sramEnabled |= (1 << region) & sramPages;
87 sramBlock[region] = value & mask;
88 setBank(region, &(*sram)[sramBlock[region] * BANK_SIZE], value);
89 invalidateDeviceRCache(0x2000 * region, 0x2000); // do not cache
90 } else {
91 sramEnabled &= byte(~(1 << region));
92 setRom(region, value);
93 }
94 // 'R' is already handled
95 invalidateDeviceWCache(0x2000 * region, 0x2000);
96 } else {
97 auto bank = narrow<byte>(address / BANK_SIZE);
98 if ((1 << bank) & sramEnabled) {
99 // write to SRAM (possibly mirror)
100 auto addr = (sramBlock[bank] * BANK_SIZE)
101 + (address & (sram->size() - 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.data();
117 }
118}
119
120template<typename Archive>
121void RomAscii8_8::serialize(Archive& ar, unsigned /*version*/)
122{
123 ar.template serializeBase<Rom8kBBlocks>(*this);
124 ar.serialize("sramEnabled", sramEnabled,
125 "sramBlock", sramBlock);
126}
129
130} // namespace openmsx
#define REGISTER_MSXDEVICE(CLASS, NAME)
Definition MSXDevice.hh:356
void invalidateDeviceRCache()
Definition MSXDevice.hh:215
void invalidateDeviceWCache()
Definition MSXDevice.hh:216
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
byte readMem(word address, EmuTime::param time) override
Read a byte from a location at a certain time from this device.
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.
const byte * getReadCacheLine(word address) const override
Test that the memory in the interval [start, start + CacheLine::SIZE) is cacheable for reading.
void serialize(Archive &ar, unsigned version)
void reset(EmuTime::param time) override
This method is called on reset.
RomAscii8_8(const DeviceConfig &config, Rom &&rom, SubType subType)
byte * getWriteCacheLine(word address) override
Test that the memory in the interval [start, start + CacheLine::SIZE) is cacheable for writing.
void setBank(unsigned region, const byte *adr, byte block)
Sets the memory visible for reading in a certain region.
Definition RomBlocks.cc:78
void setUnmapped(unsigned region)
Select 'unmapped' memory for this region.
Definition RomBlocks.cc:92
std::unique_ptr< SRAM > sram
Definition RomBlocks.hh:85
byte readMem(word address, EmuTime::param time) override
Read a byte from a location at a certain time from this device.
Definition RomBlocks.cc:66
static constexpr unsigned BANK_MASK
Definition RomBlocks.hh:19
void setRom(unsigned region, unsigned block)
Selects a block of the ROM image for reading in a certain region.
Definition RomBlocks.cc:104
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:72
static constexpr unsigned BANK_SIZE
Definition RomBlocks.hh:17
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
STL namespace.
constexpr To narrow_cast(From &&from) noexcept
Definition narrow.hh:21
#define INSTANTIATE_SERIALIZE_METHODS(CLASS)
constexpr auto xrange(T e)
Definition xrange.hh:132