openMSX
MSXFmPac.cc
Go to the documentation of this file.
1#include "MSXFmPac.hh"
2#include "CacheLine.hh"
3#include "serialize.hh"
4
5namespace openmsx {
6
7static constexpr const char* const PAC_Header = "PAC2 BACKUP DATA";
8
10 : MSXMusicBase(config)
11 , sram(getName() + " SRAM", 0x1FFE, config, PAC_Header)
12 , romBlockDebug(*this, std::span{&bank, 1}, 0x4000, 0x4000, 14)
13{
15}
16
17void MSXFmPac::reset(EmuTime::param time)
18{
20 enable = 0;
21 sramEnabled = false;
22 bank = 0;
23 r1ffe = r1fff = 0; // actual value doesn't matter as long
24 // as it's not the magic combination
25}
26
27void MSXFmPac::writeIO(word port, byte value, EmuTime::param time)
28{
29 if (enable & 1) {
30 MSXMusicBase::writeIO(port, value, time);
31 }
32}
33
34byte MSXFmPac::readMem(word address, EmuTime::param /*time*/)
35{
36 address &= 0x3FFF;
37 switch (address) {
38 case 0x3FF6:
39 return enable;
40 case 0x3FF7:
41 return bank;
42 default:
43 if (sramEnabled) {
44 if (address < 0x1FFE) {
45 return sram[address];
46 } else if (address == 0x1FFE) {
47 return r1ffe; // always 0x4D
48 } else if (address == 0x1FFF) {
49 return r1fff; // always 0x69
50 } else {
51 return 0xFF;
52 }
53 } else {
54 return rom[bank * 0x4000 + address];
55 }
56 }
57}
58
59const byte* MSXFmPac::getReadCacheLine(word address) const
60{
61 address &= 0x3FFF;
62 if (address == (0x3FF6 & CacheLine::HIGH)) {
63 return nullptr;
64 }
65 if (sramEnabled) {
66 if (address < (0x1FFE & CacheLine::HIGH)) {
67 return &sram[address];
68 } else if (address == (0x1FFE & CacheLine::HIGH)) {
69 return nullptr;
70 } else {
71 return unmappedRead.data();
72 }
73 } else {
74 return &rom[bank * 0x4000 + address];
75 }
76}
77
78void MSXFmPac::writeMem(word address, byte value, EmuTime::param time)
79{
80 // 'enable' has no effect for memory mapped access
81 // (thanks to BiFiMSX for investigating this)
82 address &= 0x3FFF;
83 switch (address) {
84 case 0x1FFE:
85 if (!(enable & 0x10)) {
86 r1ffe = value;
87 checkSramEnable();
88 }
89 break;
90 case 0x1FFF:
91 if (!(enable & 0x10)) {
92 r1fff = value;
93 checkSramEnable();
94 }
95 break;
96 case 0x3FF4: // address
97 case 0x3FF5: // data
98 writePort(address & 1, value, time);
99 break;
100 case 0x3FF6:
101 enable = value & 0x11;
102 if (enable & 0x10) {
103 r1ffe = r1fff = 0; // actual value not important
104 checkSramEnable();
105 }
106 break;
107 case 0x3FF7: {
108 if (byte newBank = value & 0x03; bank != newBank) {
109 bank = newBank;
111 }
112 break;
113 }
114 default:
115 if (sramEnabled && (address < 0x1FFE)) {
116 sram.write(address, value);
117 }
118 }
119}
120
122{
123 address &= 0x3FFF;
124 if (address == (0x1FFE & CacheLine::HIGH)) {
125 return nullptr;
126 }
127 if (address == (0x3FF4 & CacheLine::HIGH)) {
128 return nullptr;
129 }
130 if (sramEnabled && (address < 0x1FFE)) {
131 return nullptr;
132 } else {
133 return unmappedWrite.data();
134 }
135}
136
137void MSXFmPac::checkSramEnable()
138{
139 bool newEnabled = (r1ffe == 0x4D) && (r1fff == 0x69);
140 if (sramEnabled != newEnabled) {
141 sramEnabled = newEnabled;
143 }
144}
145
146
147template<typename Archive>
148void MSXFmPac::serialize(Archive& ar, unsigned version)
149{
150 ar.template serializeInlinedBase<MSXMusicBase>(*this, version);
151 ar.serialize("sram", sram,
152 "enable", enable,
153 "bank", bank,
154 "r1ffe", r1ffe,
155 "r1fff", r1fff);
156 if constexpr (Archive::IS_LOADER) {
157 // sramEnabled can be calculated
158 checkSramEnable();
159 }
160}
163
164} // namespace openmsx
#define REGISTER_MSXDEVICE(CLASS, NAME)
Definition MSXDevice.hh:356
void invalidateDeviceRCache()
Definition MSXDevice.hh:215
static std::array< byte, 0x10000 > unmappedRead
Definition MSXDevice.hh:306
static std::array< byte, 0x10000 > unmappedWrite
Definition MSXDevice.hh:307
void invalidateDeviceRWCache()
Calls MSXCPUInterface::invalidateXXCache() for the specific (part of) the slot that this device is lo...
Definition MSXDevice.hh:214
EmuTime::param getCurrentTime() const
Definition MSXDevice.cc:125
byte * getWriteCacheLine(word address) override
Test that the memory in the interval [start, start + CacheLine::SIZE) is cacheable for writing.
Definition MSXFmPac.cc:121
MSXFmPac(const DeviceConfig &config)
Definition MSXFmPac.cc:9
byte readMem(word address, EmuTime::param time) override
Read a byte from a location at a certain time from this device.
Definition MSXFmPac.cc:34
void writeMem(word address, byte value, EmuTime::param time) override
Write a given byte to a given location at a certain time to this device.
Definition MSXFmPac.cc:78
void reset(EmuTime::param time) override
This method is called on reset.
Definition MSXFmPac.cc:17
void writeIO(word port, byte value, EmuTime::param time) override
Write a byte to a given IO port at a certain time to this device.
Definition MSXFmPac.cc:27
void serialize(Archive &ar, unsigned version)
Definition MSXFmPac.cc:148
const byte * getReadCacheLine(word address) const override
Test that the memory in the interval [start, start + CacheLine::SIZE) is cacheable for reading.
Definition MSXFmPac.cc:59
void writeIO(word port, byte value, EmuTime::param time) override
Write a byte to a given IO port at a certain time to this device.
Definition MSXMusic.cc:27
void reset(EmuTime::param time) override
This method is called on reset.
Definition MSXMusic.cc:22
void writePort(bool port, byte value, EmuTime::param time)
Definition MSXMusic.cc:32
void write(size_t addr, byte value)
Definition SRAM.cc:64
constexpr unsigned HIGH
Definition CacheLine.hh:10
This file implemented 3 utility functions:
Definition Autofire.cc:11
uint16_t word
16 bit unsigned integer
Definition openmsx.hh:29
STL namespace.
#define INSTANTIATE_SERIALIZE_METHODS(CLASS)