OXYGENHUB
◆ main openmsx / src / memory / RomNational.cc
3.5 KiB · C++ · last changed chore(): initial commit 1 month ago source blame history raw
e8555c89 Andy McCall 1
#include "RomNational.hh"
2
3
#include "SRAM.hh"
4
5
#include "CacheLine.hh"
6
#include "serialize.hh"
7
8
#include "one_of.hh"
9
#include "xrange.hh"
10
11
#include <memory>
12
13
namespace openmsx {
14
15
RomNational::RomNational(const DeviceConfig& config, Rom&& rom_)
16
	: Rom16kBBlocks(config, std::move(rom_))
17
{
18
	sram = std::make_unique<SRAM>(getName() + " SRAM", 0x1000, config);
19
	reset(EmuTime::dummy());
20
}
21
22
void RomNational::reset(EmuTime /*time*/)
23
{
24
	control = 0;
25
	for (auto region : xrange(4)) {
26
		setRom(region, 0);
27
		bankSelect[region] = 0;
28
		invalidateDeviceRCache((region * 0x4000) + (0x3FF0 & CacheLine::HIGH),
29
		                       CacheLine::SIZE);
30
	}
31
	sramAddr = 0; // TODO check this
32
}
33
34
byte RomNational::peekMem(uint16_t address, EmuTime time) const
35
{
36
	if ((control & 0x04) && ((address & 0x7FF9) == 0x7FF0)) {
37
		// TODO check mirrored
38
		// 7FF0 7FF2 7FF4 7FF6   bank select read back
39
		int bank = (address & 6) / 2;
40
		return bankSelect[bank];
41
	}
42
	if ((control & 0x02) && ((address & 0x3FFF) == 0x3FFD)) {
43
		// SRAM read
44
		return (*sram)[sramAddr & 0x0FFF];
45
	}
46
	return Rom16kBBlocks::peekMem(address, time);
47
}
48
49
byte RomNational::readMem(uint16_t address, EmuTime time)
50
{
51
	byte result = RomNational::peekMem(address, time);
52
	if ((control & 0x02) && ((address & 0x3FFF) == 0x3FFD)) {
53
		++sramAddr;
54
	}
55
	return result;
56
}
57
58
const byte* RomNational::getReadCacheLine(uint16_t address) const
59
{
60
	if ((0x3FF0 & CacheLine::HIGH) == (address & 0x3FFF)) {
61
		return nullptr;
62
	} else {
63
		return Rom16kBBlocks::getReadCacheLine(address);
64
	}
65
}
66
67
void RomNational::writeMem(uint16_t address, byte value, EmuTime /*time*/)
68
{
69
	// TODO bank switch address mirrored?
70
	if (address == 0x6000) {
71
		bankSelect[1] = value;
72
		setRom(1, value); // !!
73
		invalidateDeviceRCache(0x7FF0 & CacheLine::HIGH, CacheLine::SIZE);
74
	} else if (address == 0x6400) {
75
		bankSelect[0] = value;
76
		setRom(0, value); // !!
77
		invalidateDeviceRCache(0x3FF0 & CacheLine::HIGH, CacheLine::SIZE);
78
	} else if (address == 0x7000) {
79
		bankSelect[2] = value;
80
		setRom(2, value);
81
		invalidateDeviceRCache(0xBFF0 & CacheLine::HIGH, CacheLine::SIZE);
82
	} else if (address == 0x7400) {
83
		bankSelect[3] = value;
84
		setRom(3, value);
85
		invalidateDeviceRCache(0xFFF0 & CacheLine::HIGH, CacheLine::SIZE);
86
	} else if (address == 0x7FF9) {
87
		// write control byte
88
		control = value;
89
	} else if (control & 0x02) {
90
		address &= 0x3FFF;
91
		if (address == 0x3FFA) {
92
			// SRAM address bits 23-16
93
			sramAddr = (sramAddr & 0x00FFFF) | value << 16;
94
		} else if (address == 0x3FFB) {
95
			// SRAM address bits 15-8
96
			sramAddr = (sramAddr & 0xFF00FF) | value << 8;
97
		} else if (address == 0x3FFC) {
98
			// SRAM address bits 7-0
99
			sramAddr = (sramAddr & 0xFFFF00) | value;
100
		} else if (address == 0x3FFD) {
101
			sram->write((sramAddr++ & 0x0FFF), value);
102
		}
103
	}
104
}
105
106
byte* RomNational::getWriteCacheLine(uint16_t address)
107
{
108
	if (address == one_of(0x6000 & CacheLine::HIGH,
109
	                      0x6400 & CacheLine::HIGH,
110
	                      0x7000 & CacheLine::HIGH,
111
	                      0x7400 & CacheLine::HIGH,
112
	                      0x7FF9 & CacheLine::HIGH)) {
113
		return nullptr;
114
	} else if ((address & 0x3FFF) == (0x3FFA & CacheLine::HIGH)) {
115
		return nullptr;
116
	} else {
117
		return unmappedWrite.data();
118
	}
119
}
120
121
template<typename Archive>
122
void RomNational::serialize(Archive& ar, unsigned /*version*/)
123
{
124
	ar.template serializeBase<Rom16kBBlocks>(*this);
125
	ar.serialize("control",    control,
126
	             "sramAddr",   sramAddr,
127
	             "bankSelect", bankSelect);
128
}
129
INSTANTIATE_SERIALIZE_METHODS(RomNational);
130
REGISTER_MSXDEVICE(RomNational, "RomNational");
131
132
} // namespace openmsx