openMSX
RomNational.cc
Go to the documentation of this file.
1 #include "RomNational.hh"
2 #include "CacheLine.hh"
3 #include "Rom.hh"
4 #include "SRAM.hh"
5 #include "serialize.hh"
6 #include "memory.hh"
7 
8 namespace openmsx {
9 
10 RomNational::RomNational(const DeviceConfig& config, std::unique_ptr<Rom> rom)
11  : Rom16kBBlocks(config, std::move(rom))
12 {
13  sram = make_unique<SRAM>(getName() + " SRAM", 0x1000, config);
15 }
16 
18 {
19 }
20 
22 {
23  control = 0;
24  for (int region = 0; region < 4; ++region) {
25  setRom(region, 0);
26  bankSelect[region] = 0;
27  }
28  sramAddr = 0; // TODO check this
29 }
30 
32 {
33  if ((control & 0x04) && ((address & 0x7FF9) == 0x7FF0)) {
34  // TODO check mirrored
35  // 7FF0 7FF2 7FF4 7FF6 bank select read back
36  int bank = (address & 6) / 2;
37  return bankSelect[bank];
38  }
39  if ((control & 0x02) && ((address & 0x3FFF) == 0x3FFD)) {
40  // SRAM read
41  return (*sram)[sramAddr & 0x0FFF];
42  }
43  return Rom16kBBlocks::peekMem(address, time);
44 }
45 
47 {
48  byte result = RomNational::peekMem(address, time);
49  if ((control & 0x02) && ((address & 0x3FFF) == 0x3FFD)) {
50  ++sramAddr;
51  }
52  return result;
53 }
54 
56 {
57  if ((0x3FF0 & CacheLine::HIGH) == (address & 0x3FFF)) {
58  return nullptr;
59  } else {
60  return Rom16kBBlocks::getReadCacheLine(address);
61  }
62 }
63 
64 void RomNational::writeMem(word address, byte value, EmuTime::param /*time*/)
65 {
66  // TODO bank switch address mirrored?
67  if (address == 0x6000) {
68  bankSelect[1] = value;
69  setRom(1, value); // !!
70  } else if (address == 0x6400) {
71  bankSelect[0] = value;
72  setRom(0, value); // !!
73  } else if (address == 0x7000) {
74  bankSelect[2] = value;
75  setRom(2, value);
76  } else if (address == 0x7400) {
77  bankSelect[3] = value;
78  setRom(3, value);
79  } else if (address == 0x7FF9) {
80  // write control byte
81  control = value;
82  } else if (control & 0x02) {
83  address &= 0x3FFF;
84  if (address == 0x3FFA) {
85  // SRAM address bits 23-16
86  sramAddr = (sramAddr & 0x00FFFF) | value << 16;
87  } else if (address == 0x3FFB) {
88  // SRAM address bits 15-8
89  sramAddr = (sramAddr & 0xFF00FF) | value << 8;
90  } else if (address == 0x3FFC) {
91  // SRAM address bits 7-0
92  sramAddr = (sramAddr & 0xFFFF00) | value;
93  } else if (address == 0x3FFD) {
94  sram->write((sramAddr++ & 0x0FFF), value);
95  }
96  }
97 }
98 
100 {
101  if ((address == (0x6000 & CacheLine::HIGH)) ||
102  (address == (0x6400 & CacheLine::HIGH)) ||
103  (address == (0x7000 & CacheLine::HIGH)) ||
104  (address == (0x7400 & CacheLine::HIGH)) ||
105  (address == (0x7FF9 & CacheLine::HIGH))) {
106  return nullptr;
107  } else if ((address & 0x3FFF) == (0x3FFA & CacheLine::HIGH)) {
108  return nullptr;
109  } else {
110  return unmappedWrite;
111  }
112 }
113 
114 template<typename Archive>
115 void RomNational::serialize(Archive& ar, unsigned /*version*/)
116 {
117  ar.template serializeBase<Rom16kBBlocks>(*this);
118  ar.serialize("control", control);
119  ar.serialize("sramAddr", sramAddr);
120  ar.serialize("bankSelect", bankSelect);
121 }
123 REGISTER_MSXDEVICE(RomNational, "RomNational");
124 
125 } // namespace openmsx