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