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