OXYGENHUB
◆ main openmsx / src / sound / MSXFmPac.cc
3.4 KiB · C++ · last changed chore(): initial commit 1 month ago source blame history raw
e8555c89 Andy McCall 1
#include "MSXFmPac.hh"
2
3
#include "CacheLine.hh"
4
#include "serialize.hh"
5
6
namespace openmsx {
7
8
static constexpr const char* const PAC_Header = "PAC2 BACKUP DATA";
9
10
MSXFmPac::MSXFmPac(DeviceConfig& config)
11
	: MSXMusicBase(config)
12
	, sram(getName() + " SRAM", 0x1FFE, config, PAC_Header)
13
	, romBlockDebug(*this, std::span{&bank, 1}, 0x4000, 0x4000, 14)
14
{
15
	reset(getCurrentTime());
16
}
17
18
void MSXFmPac::reset(EmuTime time)
19
{
20
	MSXMusicBase::reset(time);
21
	enable = 0;
22
	sramEnabled = false;
23
	bank = 0;
24
	r1ffe = r1fff = 0; // actual value doesn't matter as long
25
	                   // as it's not the magic combination
26
}
27
28
void MSXFmPac::writeIO(uint16_t port, byte value, EmuTime time)
29
{
30
	if (enable & 1) {
31
		MSXMusicBase::writeIO(port, value, time);
32
	}
33
}
34
35
byte MSXFmPac::readMem(uint16_t address, EmuTime /*time*/)
36
{
37
	address &= 0x3FFF;
38
	switch (address) {
39
	case 0x3FF6:
40
		return enable;
41
	case 0x3FF7:
42
		return bank;
43
	default:
44
		if (sramEnabled) {
45
			if (address < 0x1FFE) {
46
				return sram[address];
47
			} else if (address == 0x1FFE) {
48
				return r1ffe; // always 0x4D
49
			} else if (address == 0x1FFF) {
50
				return r1fff; // always 0x69
51
			} else {
52
				return 0xFF;
53
			}
54
		} else {
55
			return rom[bank * 0x4000 + address];
56
		}
57
	}
58
}
59
60
const byte* MSXFmPac::getReadCacheLine(uint16_t address) const
61
{
62
	address &= 0x3FFF;
63
	if (address == (0x3FF6 & CacheLine::HIGH)) {
64
		return nullptr;
65
	}
66
	if (sramEnabled) {
67
		if (address < (0x1FFE & CacheLine::HIGH)) {
68
			return &sram[address];
69
		} else if (address == (0x1FFE & CacheLine::HIGH)) {
70
			return nullptr;
71
		} else {
72
			return unmappedRead.data();
73
		}
74
	} else {
75
		return &rom[bank * 0x4000 + address];
76
	}
77
}
78
79
void MSXFmPac::writeMem(uint16_t address, byte value, EmuTime time)
80
{
81
	// 'enable' has no effect for memory mapped access
82
	//   (thanks to BiFiMSX for investigating this)
83
	address &= 0x3FFF;
84
	switch (address) {
85
	case 0x1FFE:
86
		if (!(enable & 0x10)) {
87
			r1ffe = value;
88
			checkSramEnable();
89
		}
90
		break;
91
	case 0x1FFF:
92
		if (!(enable & 0x10)) {
93
			r1fff = value;
94
			checkSramEnable();
95
		}
96
		break;
97
	case 0x3FF4: // address
98
	case 0x3FF5: // data
99
		writePort(address & 1, value, time);
100
		break;
101
	case 0x3FF6:
102
		enable = value & 0x11;
103
		if (enable & 0x10) {
104
			r1ffe = r1fff = 0; // actual value not important
105
			checkSramEnable();
106
		}
107
		break;
108
	case 0x3FF7: {
109
		if (byte newBank = value & 0x03; bank != newBank) {
110
			bank = newBank;
111
			invalidateDeviceRCache();
112
		}
113
		break;
114
	}
115
	default:
116
		if (sramEnabled && (address < 0x1FFE)) {
117
			sram.write(address, value);
118
		}
119
	}
120
}
121
122
byte* MSXFmPac::getWriteCacheLine(uint16_t address)
123
{
124
	address &= 0x3FFF;
125
	if (address == (0x1FFE & CacheLine::HIGH)) {
126
		return nullptr;
127
	}
128
	if (address == (0x3FF4 & CacheLine::HIGH)) {
129
		return nullptr;
130
	}
131
	if (sramEnabled && (address < 0x1FFE)) {
132
		return nullptr;
133
	} else {
134
		return unmappedWrite.data();
135
	}
136
}
137
138
void MSXFmPac::checkSramEnable()
139
{
140
	bool newEnabled = (r1ffe == 0x4D) && (r1fff == 0x69);
141
	if (sramEnabled != newEnabled) {
142
		sramEnabled = newEnabled;
143
		invalidateDeviceRWCache();
144
	}
145
}
146
147
148
template<typename Archive>
149
void MSXFmPac::serialize(Archive& ar, unsigned version)
150
{
151
	ar.template serializeInlinedBase<MSXMusicBase>(*this, version);
152
	ar.serialize("sram",   sram,
153
	             "enable", enable,
154
	             "bank",   bank,
155
	             "r1ffe",  r1ffe,
156
	             "r1fff",  r1fff);
157
	if constexpr (Archive::IS_LOADER) {
158
		// sramEnabled can be calculated
159
		checkSramEnable();
160
	}
161
}
162
INSTANTIATE_SERIALIZE_METHODS(MSXFmPac);
163
REGISTER_MSXDEVICE(MSXFmPac, "FM-PAC");
164
165
} // namespace openmsx