openMSX
MSXFmPac.cc
Go to the documentation of this file.
1 #include "MSXFmPac.hh"
2 #include "CacheLine.hh"
3 #include "serialize.hh"
4 
5 namespace openmsx {
6 
7 static const char* const PAC_Header = "PAC2 BACKUP DATA";
8 
10  : MSXMusicBase(config)
11  , sram(getName() + " SRAM", 0x1FFE, config, PAC_Header)
12  , romBlockDebug(*this, &bank, 0x4000, 0x4000, 14)
13 {
15 }
16 
17 void MSXFmPac::reset(EmuTime::param time)
18 {
19  MSXMusicBase::reset(time);
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 
27 void MSXFmPac::writeIO(word port, byte value, EmuTime::param time)
28 {
29  if (enable & 1) {
30  MSXMusicBase::writeIO(port, value, time);
31  }
32 }
33 
34 byte 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 
59 const 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;
72  }
73  } else {
74  return &rom[bank * 0x4000 + address];
75  }
76 }
77 
78 void 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:
97  writeRegisterPort(value, time);
98  break;
99  case 0x3FF5:
100  writeDataPort(value, time);
101  break;
102  case 0x3FF6:
103  enable = value & 0x11;
104  if (enable & 0x10) {
105  r1ffe = r1fff = 0; // actual value not important
106  checkSramEnable();
107  }
108  break;
109  case 0x3FF7: {
110  byte newBank = value & 0x03;
111  if (bank != newBank) {
112  bank = newBank;
113  invalidateMemCache(0x0000, 0x10000);
114  }
115  break;
116  }
117  default:
118  if (sramEnabled && (address < 0x1FFE)) {
119  sram.write(address, value);
120  }
121  }
122 }
123 
125 {
126  address &= 0x3FFF;
127  if (address == (0x1FFE & CacheLine::HIGH)) {
128  return nullptr;
129  }
130  if (address == (0x3FF4 & CacheLine::HIGH)) {
131  return nullptr;
132  }
133  if (sramEnabled && (address < 0x1FFE)) {
134  return nullptr;
135  } else {
136  return unmappedWrite;
137  }
138 }
139 
140 void MSXFmPac::checkSramEnable()
141 {
142  bool newEnabled = (r1ffe == 0x4D) && (r1fff == 0x69);
143  if (sramEnabled != newEnabled) {
144  sramEnabled = newEnabled;
145  invalidateMemCache(0x0000, 0x10000);
146  }
147 }
148 
149 
150 template<typename Archive>
151 void MSXFmPac::serialize(Archive& ar, unsigned version)
152 {
153  ar.template serializeInlinedBase<MSXMusicBase>(*this, version);
154  ar.serialize("sram", sram,
155  "enable", enable,
156  "bank", bank,
157  "r1ffe", r1ffe,
158  "r1fff", r1fff);
159  if (ar.isLoader()) {
160  // sramEnabled can be calculated
161  checkSramEnable();
162  }
163 }
165 REGISTER_MSXDEVICE(MSXFmPac, "FM-PAC");
166 
167 } // namespace openmsx
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:151
void writeDataPort(byte value, EmuTime::param time)
Definition: MSXMusic.cc:46
uint8_t byte
8 bit unsigned integer
Definition: openmsx.hh:26
void write(unsigned addr, byte value)
Definition: SRAM.cc:67
REGISTER_MSXDEVICE(ChakkariCopy, "ChakkariCopy")
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
EmuTime::param getCurrentTime() const
Definition: MSXDevice.cc:133
Thanks to enen for testing this on a real cartridge:
Definition: Autofire.cc:5
MSXFmPac(const DeviceConfig &config)
Definition: MSXFmPac.cc:9
void reset(EmuTime::param time) override
This method is called on reset.
Definition: MSXFmPac.cc:17
uint16_t word
16 bit unsigned integer
Definition: openmsx.hh:29
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
static byte unmappedRead[0x10000]
Definition: MSXDevice.hh:274
void reset(EmuTime::param time) override
This method is called on reset.
Definition: MSXMusic.cc:23
byte * getWriteCacheLine(word address) const override
Test that the memory in the interval [start, start + CacheLine::SIZE) is cacheable for writing...
Definition: MSXFmPac.cc:124
#define INSTANTIATE_SERIALIZE_METHODS(CLASS)
Definition: serialize.hh:1006
static byte unmappedWrite[0x10000]
Definition: MSXDevice.hh:275
string getName(KeyCode keyCode)
Translate key code to key name.
Definition: Keys.cc:589
void writeRegisterPort(byte value, EmuTime::param time)
Definition: MSXMusic.cc:41
void invalidateMemCache(word start, unsigned size)
Invalidate CPU memory-mapping cache.
Definition: MSXDevice.cc:458
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 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:29