OXYGENHUB
◆ main openmsx / src / memory / RomAscii16X.cc
2.3 KiB · C++ · last changed chore(): initial commit 1 month ago source blame history raw
e8555c89 Andy McCall 1
// ASCII-X 16kB cartridges
2
//
3
// Banks:
4
//  first  16kB: 0x4000 - 0x7FFF and 0xC000 - 0xFFFF
5
//  second 16kB: 0x8000 - 0xBFFF and 0x0000 - 0x3FFF
6
//
7
// Address to change banks:
8
//  first  16kB: 0x6000 - 0x6FFF, 0xA000 - 0xAFFF, 0xE000 - 0xEFFF, 0x2000 - 0x2FFF
9
//  second 16kB: 0x7000 - 0x7FFF, 0xB000 - 0xBFFF, 0xF000 - 0xFFFF, 0x3000 - 0x3FFF
10
//
11
// 12-bit bank number is composed by address bits 8-11 and the data bits.
12
//
13
// Backed by FlashROM.
14
15
#include "RomAscii16X.hh"
16
#include "narrow.hh"
17
#include "outer.hh"
18
#include "serialize.hh"
19
20
namespace openmsx {
21
22
RomAscii16X::RomAscii16X(DeviceConfig& config, Rom&& rom_)
23
	: MSXRom(config, std::move(rom_))
24
	, debuggable(*this)
25
	, flash(rom, AmdFlashChip::S29GL064S70TFI040, {}, config)
26
{
27
	reset(EmuTime::dummy());
28
}
29
30
void RomAscii16X::reset(EmuTime /*time*/)
31
{
32
	ranges::iota(bankRegs, uint16_t(0));
33
34
	flash.reset();
35
36
	invalidateDeviceRCache(); // flush all to be sure
37
}
38
39
unsigned RomAscii16X::getFlashAddr(uint16_t addr) const
40
{
41
	uint16_t bank = bankRegs[((addr >> 14) & 1) ^ 1];
42
	return (bank << 14) | (addr & 0x3FFF);
43
}
44
45
byte RomAscii16X::readMem(uint16_t addr, EmuTime time)
46
{
47
	return flash.read(getFlashAddr(addr), time);
48
}
49
50
byte RomAscii16X::peekMem(uint16_t addr, EmuTime time) const
51
{
52
	return flash.peek(getFlashAddr(addr), time);
53
}
54
55
const byte* RomAscii16X::getReadCacheLine(uint16_t addr) const
56
{
57
	return flash.getReadCacheLine(getFlashAddr(addr));
58
}
59
60
void RomAscii16X::writeMem(uint16_t addr, byte value, EmuTime time)
61
{
62
	flash.write(getFlashAddr(addr), value, time);
63
64
	if ((addr & 0x3FFF) >= 0x2000) {
65
		const uint16_t index = (addr >> 12) & 1;
66
		bankRegs[index] = (addr & 0x0F00) | value;
67
		invalidateDeviceRCache(0x4000 ^ (index << 14), 0x4000);
68
		invalidateDeviceRCache(0xC000 ^ (index << 14), 0x4000);
69
	}
70
}
71
72
byte* RomAscii16X::getWriteCacheLine(uint16_t /* addr */)
73
{
74
	return nullptr; // not cacheable
75
}
76
77
unsigned RomAscii16X::Debuggable::readExt(unsigned address)
78
{
79
	auto& outer = OUTER(RomAscii16X, debuggable);
80
	return outer.bankRegs[((address >> 14) & 1) ^ 1];
81
}
82
83
template<typename Archive>
84
void RomAscii16X::serialize(Archive& ar, unsigned /*version*/)
85
{
86
	// skip MSXRom base class
87
	ar.template serializeBase<MSXDevice>(*this);
88
89
	ar.serialize("flash",       flash,
90
	             "bankRegs",    bankRegs);
91
}
92
INSTANTIATE_SERIALIZE_METHODS(RomAscii16X);
93
REGISTER_MSXDEVICE(RomAscii16X, "RomAscii16X");
94
95
} // namespace openmsx