OXYGENHUB
◆ main openmsx / src / video / ADVram.cc
2.1 KiB · C++ · last changed chore(): initial commit 1 month ago source blame history raw
e8555c89 Andy McCall 1
#include "ADVram.hh"
2
3
#include "VDP.hh"
4
#include "VDPVRAM.hh"
5
6
#include "MSXException.hh"
7
#include "serialize.hh"
8
9
#include <algorithm>
10
11
namespace openmsx {
12
13
ADVram::ADVram(const DeviceConfig& config)
14
	: MSXDevice(config)
15
	, hasEnable(config.getChildDataAsBool("hasEnable", true))
16
{
17
}
18
19
void ADVram::init()
20
{
21
	MSXDevice::init();
22
23
	const auto& refs = getReferences();
24
	if (refs.size() != 1) {
25
		throw MSXException("Invalid ADVRAM configuration: "
26
		                   "need reference to VDP device.");
27
	}
28
	vdp = dynamic_cast<VDP*>(refs[0]);
29
	if (!vdp) {
30
		throw MSXException("Invalid ADVRAM configuration: device '",
31
		                   refs[0]->getName(), "' is not a VDP device.");
32
	}
33
	vram = &vdp->getVRAM();
34
	mask = std::min(vram->getSize(), 128u * 1024) - 1;
35
	reset(EmuTime::dummy());
36
}
37
38
void ADVram::reset(EmuTime /*time*/)
39
{
40
	// TODO figure out exactly what happens during reset
41
	baseAddr = 0;
42
	planar = false;
43
	enabled = !hasEnable;
44
}
45
46
uint8_t ADVram::readIO(uint16_t port, EmuTime /*time*/)
47
{
48
	// ADVram only gets 'read's from 0x9A
49
	if (hasEnable) {
50
		enabled = ((port & 0x8000) != 0);
51
		planar  = ((port & 0x4000) != 0);
52
	} else {
53
		planar  = ((port & 0x0100) != 0);
54
	}
55
	return 0xFF;
56
}
57
58
void ADVram::writeIO(uint16_t /*port*/, uint8_t value, EmuTime /*time*/)
59
{
60
	// set mapper register
61
	baseAddr = (value & 0x07) << 14;
62
}
63
64
unsigned ADVram::calcAddress(uint16_t address) const
65
{
66
	unsigned addr = (address & 0x3FFF) | baseAddr;
67
	if (planar) {
68
		addr = ((addr & 1) << 16) | (addr >> 1);
69
	}
70
	return addr & mask;
71
}
72
73
uint8_t ADVram::readMem(uint16_t address, EmuTime time)
74
{
75
	return enabled ? vram->cpuRead(calcAddress(address), time) : 0xFF;
76
}
77
78
void ADVram::writeMem(uint16_t address, uint8_t value, EmuTime time)
79
{
80
	if (enabled) {
81
		vram->cpuWrite(calcAddress(address), value, time);
82
	}
83
}
84
85
template<typename Archive>
86
void ADVram::serialize(Archive& ar, unsigned /*version*/)
87
{
88
	ar.template serializeBase<MSXDevice>(*this);
89
	ar.serialize("baseAddr", baseAddr,
90
	             "enabled",  enabled,
91
	             "planar",   planar);
92
}
93
INSTANTIATE_SERIALIZE_METHODS(ADVram);
94
REGISTER_MSXDEVICE(ADVram, "ADVRAM");
95
96
} // namespace openmsx