openMSX
RomPanasonic.cc
Go to the documentation of this file.
1 #include "RomPanasonic.hh"
2 #include "PanasonicMemory.hh"
3 #include "MSXMotherBoard.hh"
4 #include "DeviceConfig.hh"
5 #include "SRAM.hh"
6 #include "CacheLine.hh"
7 #include "one_of.hh"
8 #include "ranges.hh"
9 #include "serialize.hh"
10 #include "xrange.hh"
11 #include <memory>
12 
13 namespace openmsx {
14 
15 const int SRAM_BASE = 0x80;
16 const int RAM_BASE = 0x180;
17 
19  : Rom8kBBlocks(config, std::move(rom_))
20  , panasonicMem(getMotherBoard().getPanasonicMemory())
21 {
22  unsigned sramSize = config.getChildDataAsInt("sramsize", 0);
23  if (sramSize) {
24  sram = std::make_unique<SRAM>(
25  getName() + " SRAM", sramSize * 1024, config);
26  }
27 
28  if (config.getChildDataAsBool("sram-mirrored", false)) {
29  maxSRAMBank = SRAM_BASE + 8;
30  } else {
31  maxSRAMBank = SRAM_BASE + (sramSize / 8);
32  }
33 
34  // Inform baseclass about PanasonicMemory (needed for serialization).
35  // This relies on the order of MSXDevice instantiation, the PanasonicRam
36  // device must be create before this one. (In the hardwareconfig.xml
37  // we added a device-reference from this device to the PanasonicRam
38  // device, this should protected against wrong future edits in the
39  // config file).
40  setExtraMemory(panasonicMem.getRamBlock(0), panasonicMem.getRamSize());
41 
42  reset(EmuTime::dummy());
43 }
44 
45 void RomPanasonic::reset(EmuTime::param /*time*/)
46 {
47  control = 0;
48  ranges::fill(bankSelect, 0);
49  for (auto region : xrange(8)) {
50  setRom(region, 0);
51  }
53 }
54 
55 byte RomPanasonic::peekMem(word address, EmuTime::param time) const
56 {
57  if ((control & 0x04) && (0x7FF0 <= address) && (address < 0x7FF8)) {
58  // read mapper state (lower 8 bit)
59  return bankSelect[address & 7] & 0xFF;
60  } else if ((control & 0x10) && (address == 0x7FF8)) {
61  // read mapper state (9th bit)
62  byte result = 0;
63  for (int i = 7; i >= 0; i--) {
64  result <<= 1;
65  if (bankSelect[i] & 0x100) {
66  result++;
67  }
68  }
69  return result;
70  } else if ((control & 0x08) && (address == 0x7FF9)) {
71  // read control byte
72  return control;
73  } else {
74  return Rom8kBBlocks::peekMem(address, time);
75  }
76 }
77 
78 byte RomPanasonic::readMem(word address, EmuTime::param time)
79 {
80  return RomPanasonic::peekMem(address, time);
81 }
82 
83 const byte* RomPanasonic::getReadCacheLine(word address) const
84 {
85  if ((0x7FF0 & CacheLine::HIGH) == address) {
86  // TODO check mirrored
87  return nullptr;
88  } else {
89  return Rom8kBBlocks::getReadCacheLine(address);
90  }
91 }
92 
93 void RomPanasonic::writeMem(word address, byte value, EmuTime::param /*time*/)
94 {
95  if ((0x6000 <= address) && (address < 0x7FF0)) {
96  // set mapper state (lower 8 bits)
97  int region = (address & 0x1C00) >> 10;
98  if (region == one_of(5, 6)) region ^= 3;
99  int selectedBank = bankSelect[region];
100  int newBank = (selectedBank & ~0xFF) | value;
101  changeBank(region, newBank);
102  } else if (address == 0x7FF8) {
103  // set mapper state (9th bit)
104  for (auto region : xrange(8)) {
105  if (value & 1) {
106  changeBank(region, bankSelect[region] | 0x100);
107  } else {
108  changeBank(region, bankSelect[region] & ~0x100);
109  }
110  value >>= 1;
111  }
112  } else if (address == 0x7FF9) {
113  // write control byte
114  control = value;
115  } else {
116  // Tested on real FS-A1GT:
117  // SRAM/RAM can be written to from all regions, including e.g.
118  // address 0x7ff0. (I didn't actually test 0xc000-0xffff).
119  int region = address >> 13;
120  int selectedBank = bankSelect[region];
121  if (sram && (SRAM_BASE <= selectedBank) &&
122  (selectedBank < maxSRAMBank)) {
123  // SRAM
124  int block = selectedBank - SRAM_BASE;
125  sram->write((block * 0x2000) | (address & 0x1FFF), value);
126  } else if (RAM_BASE <= selectedBank) {
127  // RAM
128  const_cast<byte*>(bankPtr[region])[address & 0x1FFF] = value;
129  }
130  }
131 }
132 
134 {
135  if ((0x6000 <= address) && (address < 0x8000)) {
136  // mapper select (low/high), control
137  return nullptr;
138  } else {
139  int region = address >> 13;
140  int selectedBank = bankSelect[region];
141  if (sram && (SRAM_BASE <= selectedBank) &&
142  (selectedBank < maxSRAMBank)) {
143  // SRAM
144  return nullptr;
145  } else if (RAM_BASE <= selectedBank) {
146  // RAM
147  return const_cast<byte*>(&bankPtr[region][address & 0x1FFF]);
148  } else {
149  return unmappedWrite;
150  }
151  }
152 }
153 
154 void RomPanasonic::changeBank(byte region, int bank)
155 {
156  if (bank == bankSelect[region]) {
157  return;
158  }
159  bankSelect[region] = bank;
160 
161  if (sram && (SRAM_BASE <= bank) && (bank < maxSRAMBank)) {
162  // SRAM
163  int offset = (bank - SRAM_BASE) * 0x2000;
164  int sramSize = sram->getSize();
165  if (offset >= sramSize) {
166  offset &= (sramSize - 1);
167  }
168  // TODO romblock debuggable is only 8 bits, here bank is 9 bits
169  setBank(region, &sram->operator[](offset), bank);
170  } else if (panasonicMem.getRamSize() && (RAM_BASE <= bank)) {
171  // RAM
172  // TODO romblock debuggable is only 8 bits, here bank is 9 bits
173  setBank(region, panasonicMem.getRamBlock(bank - RAM_BASE), bank);
174  } else {
175  // ROM
176  setRom(region, bank);
177  }
178  invalidateDeviceWCache(0x2000 * region, 0x2000); // 'R' is already handled
179  if (region == 3) {
180  // don't pre-fill [0x7ff0, 0x7fff]
182  }
183 }
184 
185 template<typename Archive>
186 void RomPanasonic::serialize(Archive& ar, unsigned /*version*/)
187 {
188  ar.template serializeBase<Rom8kBBlocks>(*this);
189  ar.serialize("bankSelect", bankSelect,
190  "control", control);
191 }
194 
195 } // namespace openmsx
Definition: one_of.hh:7
bool getChildDataAsBool(std::string_view name, bool defaultValue=false) const
Definition: DeviceConfig.cc:61
int getChildDataAsInt(std::string_view name, int defaultValue) const
Definition: DeviceConfig.cc:57
void invalidateDeviceRCache()
Definition: MSXDevice.hh:210
void invalidateDeviceWCache()
Definition: MSXDevice.hh:211
virtual const std::string & getName() const
Returns a human-readable name for this device.
Definition: MSXDevice.cc:376
static byte unmappedWrite[0x10000]
Definition: MSXDevice.hh:302
unsigned getRamSize() const
byte * getRamBlock(unsigned block)
Note that this is always unchecked RAM! There is no UMR detection when accessing Ram in DRAM mode or ...
void setExtraMemory(const byte *mem, unsigned size)
Inform this base class of extra mapable memory block.
Definition: RomBlocks.cc:98
byte peekMem(word address, EmuTime::param time) const override
Read a byte from a given memory location.
Definition: RomBlocks.cc:60
void setBank(byte region, const byte *adr, int block)
Sets the memory visible for reading in a certain region.
Definition: RomBlocks.cc:78
std::unique_ptr< SRAM > sram
Definition: RomBlocks.hh:84
void setRom(byte region, unsigned block)
Selects a block of the ROM image for reading in a certain region.
Definition: RomBlocks.cc:105
const byte * bankPtr[NUM_BANKS]
Definition: RomBlocks.hh:83
const byte * getReadCacheLine(word address) const override
Test that the memory in the interval [start, start + CacheLine::SIZE) is cacheable for reading.
Definition: RomBlocks.cc:72
void serialize(Archive &ar, unsigned version)
void reset(EmuTime::param time) override
This method is called on reset.
Definition: RomPanasonic.cc:45
byte * getWriteCacheLine(word address) const override
Test that the memory in the interval [start, start + CacheLine::SIZE) is cacheable for writing.
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: RomPanasonic.cc:93
const byte * getReadCacheLine(word address) const override
Test that the memory in the interval [start, start + CacheLine::SIZE) is cacheable for reading.
Definition: RomPanasonic.cc:83
RomPanasonic(const DeviceConfig &config, Rom &&rom)
Definition: RomPanasonic.cc:18
byte readMem(word address, EmuTime::param time) override
Read a byte from a location at a certain time from this device.
Definition: RomPanasonic.cc:78
byte peekMem(word address, EmuTime::param time) const override
Read a byte from a given memory location.
Definition: RomPanasonic.cc:55
constexpr unsigned HIGH
Definition: CacheLine.hh:10
constexpr unsigned SIZE
Definition: CacheLine.hh:7
This file implemented 3 utility functions:
Definition: Autofire.cc:9
const int RAM_BASE
Definition: RomPanasonic.cc:16
REGISTER_MSXDEVICE(ChakkariCopy, "ChakkariCopy")
const int SRAM_BASE
Definition: RomPanasonic.cc:15
uint16_t word
16 bit unsigned integer
Definition: openmsx.hh:29
void fill(ForwardRange &&range, const T &value)
Definition: ranges.hh:226
#define INSTANTIATE_SERIALIZE_METHODS(CLASS)
Definition: serialize.hh:998
constexpr auto xrange(T e)
Definition: xrange.hh:155