OXYGENHUB
◆ main openmsx / src / memory / PanasonicMemory.cc
2.7 KiB · C++ · last changed chore(): initial commit 1 month ago source blame history raw
1
#include "PanasonicMemory.hh"
2
3
#include "Ram.hh"
4
#include "Rom.hh"
5
6
#include "DeviceConfig.hh"
7
#include "HardwareConfig.hh"
8
#include "MSXCPU.hh"
9
#include "MSXException.hh"
10
#include "MSXMotherBoard.hh"
11
#include "XMLElement.hh"
12
13
#include "narrow.hh"
14
15
#include <memory>
16
17
namespace openmsx {
18
19
PanasonicMemory::PanasonicMemory(MSXMotherBoard& motherBoard)
20
	: msxcpu(motherBoard.getCPU())
21
	, rom([&] -> std::optional<Rom> {
22
		auto* elem = motherBoard.getMachineConfig()->
23
				getConfig().findChild("PanasonicRom");
24
		if (!elem) return std::nullopt;
25
26
		HardwareConfig* hwConf = motherBoard.getMachineConfig();
27
		assert(hwConf);
28
		DeviceConfig config(*hwConf, *elem);
29
		return std::optional<Rom>(std::in_place,
30
			"PanasonicRom", "Turbor-R main ROM", config);
31
	}())
32
{
33
}
34
35
void PanasonicMemory::registerRam(Ram& ram_)
36
{
37
	ram = ram_.data();
38
	ramSize = narrow<unsigned>(ram_.size());
39
}
40
41
std::span<const uint8_t, 0x2000> PanasonicMemory::getRomBlock(unsigned block) const
42
{
43
	if (!rom) {
44
		throw MSXException("Missing PanasonicRom.");
45
	}
46
	if (dram &&
47
	    (((0x28 <= block) && (block < 0x2C)) ||
48
	     ((0x38 <= block) && (block < 0x3C)))) {
49
		assert(ram);
50
		unsigned offset = (block & 0x03) * 0x2000;
51
		unsigned ramOffset = (block < 0x30) ? ramSize - 0x10000 :
52
		                                      ramSize - 0x08000;
53
		return std::span<const uint8_t, 0x2000>{ram + ramOffset + offset, 0x2000};
54
	} else {
55
		unsigned offset = block * 0x2000;
56
		if (offset >= rom->size()) {
57
			offset &= narrow<unsigned>(rom->size() - 1);
58
		}
59
		return subspan<0x2000>(*rom, offset);
60
	}
61
}
62
63
std::span<const uint8_t> PanasonicMemory::getRomRange(unsigned first, unsigned last) const
64
{
65
	if (!rom) {
66
		throw MSXException("Missing PanasonicRom.");
67
	}
68
	if (last < first) {
69
		throw MSXException("Error in config file: firstblock must "
70
		                   "be smaller than lastblock");
71
	}
72
	unsigned start =  first     * 0x2000;
73
	if (start >= rom->size()) {
74
		throw MSXException("Error in config file: firstblock lies "
75
		                   "outside of rom image.");
76
	}
77
	unsigned stop  = (last + 1) * 0x2000;
78
	if (stop > rom->size()) {
79
		throw MSXException("Error in config file: lastblock lies "
80
		                   "outside of rom image.");
81
	}
82
	return subspan(*rom, start, stop - start);
83
}
84
85
uint8_t* PanasonicMemory::getRamBlock(unsigned block)
86
{
87
	if (!ram) return nullptr;
88
89
	unsigned offset = block * 0x2000;
90
	if (offset >= ramSize) {
91
		offset &= ramSize - 1;
92
	}
93
	return ram + offset;
94
}
95
96
void PanasonicMemory::setDRAM(bool dram_)
97
{
98
	if (dram_ != dram) {
99
		dram = dram_;
100
		msxcpu.invalidateAllSlotsRWCache(0x0000, 0x10000);
101
	}
102
}
103
104
bool PanasonicMemory::isWritable(unsigned address) const
105
{
106
	return !dram || (address < (ramSize - 0x10000));
107
}
108
109
} // namespace openmsx