OXYGENHUB
◆ main openmsx / src / memory / RomAscii16_2.cc
2.6 KiB · C++ · last changed chore(): initial commit 1 month ago source blame history raw
1
// ASCII 16kB based cartridges with SRAM
2
//
3
// Examples 2kB SRAM: Daisenryaku, Harry Fox MSX Special, Hydlide 2, Jyansei
4
// Examples 8kB SRAM: A-Train
5
//
6
// this type is is almost completely a ASCII16 cartridge
7
// However, it has 2 or 8kB of SRAM (and 128 kB ROM)
8
// Use value 0x10 to select the SRAM.
9
// SRAM in page 1 => read-only
10
// SRAM in page 2 => read-write
11
// The SRAM is mirrored in the 16 kB block
12
//
13
// The address to change banks (from ASCII16):
14
//  first  16kb: 0x6000 - 0x67FF (0x6000 used)
15
//  second 16kb: 0x7000 - 0x77FF (0x7000 and 0x77FF used)
16
17
#include "RomAscii16_2.hh"
18
#include "SRAM.hh"
19
#include "serialize.hh"
20
#include <memory>
21
22
namespace openmsx {
23
24
RomAscii16_2::RomAscii16_2(const DeviceConfig& config, Rom&& rom_, SubType subType)
25
	: RomAscii16kB(config, std::move(rom_))
26
{
27
	unsigned size = (subType == SubType::ASCII16_8) ? 0x2000 // 8kB
28
	                                                : 0x0800; // 2kB
29
	sram = std::make_unique<SRAM>(getName() + " SRAM", size, config);
30
	reset(EmuTime::dummy());
31
}
32
33
void RomAscii16_2::reset(EmuTime time)
34
{
35
	sramEnabled = 0;
36
	RomAscii16kB::reset(time);
37
}
38
39
byte RomAscii16_2::readMem(uint16_t address, EmuTime time)
40
{
41
	if ((1 << (address >> 14)) & sramEnabled) {
42
		return (*sram)[address & (sram->size() - 1)];
43
	} else {
44
		return RomAscii16kB::readMem(address, time);
45
	}
46
}
47
48
const byte* RomAscii16_2::getReadCacheLine(uint16_t address) const
49
{
50
	if ((1 << (address >> 14)) & sramEnabled) {
51
		return &(*sram)[address & (sram->size() - 1)];
52
	} else {
53
		return RomAscii16kB::getReadCacheLine(address);
54
	}
55
}
56
57
void RomAscii16_2::writeMem(uint16_t address, byte value, EmuTime /*time*/)
58
{
59
	if ((0x6000 <= address) && (address < 0x7800) && !(address & 0x0800)) {
60
		// bank switch
61
		byte region = ((address >> 12) & 1) + 1;
62
		if (value == 0x10) {
63
			// SRAM block
64
			sramEnabled |= (1 << region);
65
		} else {
66
			// ROM block
67
			setRom(region, value);
68
			sramEnabled &= byte(~(1 << region));
69
		}
70
		invalidateDeviceRWCache(0x4000 * region, 0x4000);
71
	} else {
72
		// write sram
73
		if ((1 << (address >> 14)) & sramEnabled & 0x04) {
74
			sram->write(address & (sram->size() - 1), value);
75
		}
76
	}
77
}
78
79
byte* RomAscii16_2::getWriteCacheLine(uint16_t address)
80
{
81
	if ((1 << (address >> 14)) & sramEnabled & 0x04) {
82
		// write sram
83
		return nullptr;
84
	} else {
85
		return RomAscii16kB::getWriteCacheLine(address);
86
	}
87
}
88
89
template<typename Archive>
90
void RomAscii16_2::serialize(Archive& ar, unsigned /*version*/)
91
{
92
	ar.template serializeBase<RomAscii16kB>(*this);
93
	ar.serialize("sramEnabled", sramEnabled);
94
}
95
INSTANTIATE_SERIALIZE_METHODS(RomAscii16_2);
96
REGISTER_MSXDEVICE(RomAscii16_2, "RomAscii16_2");
97
98
} // namespace openmsx