openMSX
ColecoSuperGameModule.cc
Go to the documentation of this file.
3 #include "MSXCPUInterface.hh"
4 #include "MSXException.hh"
5 #include "serialize.hh"
6 
7 namespace openmsx {
8 
9 // Disabling the SGM RAM has no effect on 0-0x1FFF, according to Oscar Toledo.
10 // So, if the BIOS is disabled to show RAM and the SGM RAM is disabled, is
11 // there is 8kB SGM RAM on 0-0x1FFF.
12 
13 static const unsigned MAIN_RAM_AREA_START = 0x6000;
14 static const unsigned MAIN_RAM_SIZE = 0x400; // 1kB
15 static const unsigned SGM_RAM_SIZE = 0x8000; // 32kB
16 static const unsigned BIOS_ROM_SIZE = 0x2000; // 8kB
17 
19  : MSXDevice(config)
20  , psg(getName() + " PSG", DummyAY8910Periphery::instance(), config, getCurrentTime())
21  , sgmRam(config, getName() + " RAM", "SGM RAM", SGM_RAM_SIZE)
22  , mainRam(config, "Main RAM", "Main RAM", MAIN_RAM_SIZE)
23  , biosRom(getName(), "BIOS ROM", config)
24 {
25  if (biosRom.getSize() != BIOS_ROM_SIZE) {
26  throw MSXException("ColecoVision BIOS ROM must be exactly 8kB in size.");
27  }
28  getCPUInterface().register_IO_Out(0x50, this);
29  getCPUInterface().register_IO_Out(0x51, this);
30  getCPUInterface().register_IO_In (0x52, this);
31  getCPUInterface().register_IO_Out(0x53, this);
32  getCPUInterface().register_IO_Out(0x7F, this);
34 }
35 
37 {
38  getCPUInterface().unregister_IO_Out(0x50, this);
39  getCPUInterface().unregister_IO_Out(0x51, this);
40  getCPUInterface().unregister_IO_In (0x52, this);
41  getCPUInterface().unregister_IO_Out(0x53, this);
42  getCPUInterface().unregister_IO_Out(0x7F, this);
43 }
44 
45 unsigned ColecoSuperGameModule::translateMainRamAddress(unsigned address) const
46 {
47  return address & (MAIN_RAM_SIZE - 1);
48 }
49 
50 void ColecoSuperGameModule::reset(EmuTime::param time)
51 {
52  ramEnabled = false;
53  ramAtBiosEnabled = false;
54  psgLatch = 0;
55  psg.reset(time);
56  invalidateMemCache(0x0000, 0x10000); // flush all to be sure
57 }
58 
59 byte ColecoSuperGameModule::readIO(word port, EmuTime::param time)
60 {
61  if ((port & 0xFF) == 0x52) {
62  return psg.readRegister(psgLatch, time);
63  }
64  return 0xFF;
65 }
66 
67 byte ColecoSuperGameModule::peekIO(word port, EmuTime::param time) const
68 {
69  if ((port & 0xFF) == 0x52) {
70  return psg.peekRegister(psgLatch, time);
71  }
72  return 0xFF;
73 }
74 
75 void ColecoSuperGameModule::writeIO(word port, byte value, EmuTime::param time)
76 {
77  switch (port & 0xFF) {
78  case 0x50: // PSG address (latch?)
79  psgLatch = value & 0x0F;
80  break;
81  case 0x51: // PSG data (register write?)
82  psg.writeRegister(psgLatch, value, time);
83  break;
84  case 0x53: // bit0=1 means enable SGM RAM in 0x2000-0x7FFF range
85  ramEnabled = (value & 1) != 0;
86  invalidateMemCache(0x0000, SGM_RAM_SIZE); // just flush the whole area
87  break;
88  case 0x7F: // bit1=0 means enable SGM RAM in BIOS area (0-0x1FFF), 1 means BIOS
89  ramAtBiosEnabled = (value & 2) == 0;
90  invalidateMemCache(0x0000, BIOS_ROM_SIZE);
91  break;
92  default:
93  // ignore
94  break;
95  }
96 }
97 
98 byte ColecoSuperGameModule::peekMem(word address, EmuTime::param /*time*/) const
99 {
100  if (address < BIOS_ROM_SIZE) {
101  return ramAtBiosEnabled ? sgmRam.peek(address) : biosRom[address];
102  } else if (address < SGM_RAM_SIZE) {
103  if (ramEnabled) {
104  return sgmRam.peek(address);
105  } else if (address >= MAIN_RAM_AREA_START) {
106  return mainRam.peek(translateMainRamAddress(address));
107  }
108  }
109  return 0xFF;
110 }
111 
112 byte ColecoSuperGameModule::readMem(word address, EmuTime::param /*time*/)
113 {
114  if (address < BIOS_ROM_SIZE) {
115  return ramAtBiosEnabled ? sgmRam.read(address) : biosRom[address];
116  } else if (address < SGM_RAM_SIZE) {
117  if (ramEnabled) {
118  return sgmRam.read(address);
119  } else if (address >= MAIN_RAM_AREA_START) {
120  return mainRam.read(translateMainRamAddress(address));
121  }
122  }
123  return 0xFF;
124 }
125 
126 void ColecoSuperGameModule::writeMem(word address, byte value, EmuTime::param /*time*/)
127 {
128  if (address < BIOS_ROM_SIZE) {
129  if (ramAtBiosEnabled) {
130  sgmRam.write(address, value);
131  }
132  } else if (address < SGM_RAM_SIZE) {
133  if (ramEnabled) {
134  sgmRam.write(address, value);
135  } else if (address >= MAIN_RAM_AREA_START) {
136  mainRam.write(translateMainRamAddress(address), value);
137  }
138  }
139 }
140 
142 {
143  if (start < BIOS_ROM_SIZE) {
144  return ramAtBiosEnabled ? sgmRam.getReadCacheLine(start) : &biosRom[start];
145  } else if (start < SGM_RAM_SIZE) {
146  if (ramEnabled) {
147  return sgmRam.getReadCacheLine(start);
148  } else if (start >= MAIN_RAM_AREA_START) {
149  return mainRam.getReadCacheLine(translateMainRamAddress(start));
150  }
151  }
152  return unmappedRead;
153 }
154 
156 {
157  if (start < BIOS_ROM_SIZE) {
158  if (ramAtBiosEnabled) {
159  return sgmRam.getWriteCacheLine(start);
160  }
161  } else if (start < SGM_RAM_SIZE) {
162  if (ramEnabled) {
163  return sgmRam.getWriteCacheLine(start);
164  } else if (start >= MAIN_RAM_AREA_START) {
165  return mainRam.getWriteCacheLine(translateMainRamAddress(start));
166  }
167  }
168  return unmappedWrite;
169 }
170 
171 template<typename Archive>
172 void ColecoSuperGameModule::serialize(Archive& ar, unsigned /*version*/)
173 {
174  ar.serialize("mainRam", mainRam.getUncheckedRam(),
175  "sgmRam", sgmRam.getUncheckedRam(),
176  "psg", psg,
177  "psgLatch", psgLatch,
178  "ramEnabled", ramEnabled,
179  "ramAtBiosEnabled", ramAtBiosEnabled);
180 }
182 REGISTER_MSXDEVICE(ColecoSuperGameModule, "ColecoSuperGameModule");
183 
184 } // namespace openmsx
void serialize(Archive &ar, unsigned version)
byte readIO(word port, EmuTime::param time) override
Read a byte from an IO port at a certain time from this device.
const byte * getReadCacheLine(unsigned addr) const
Definition: CheckedRam.cc:47
uint8_t byte
8 bit unsigned integer
Definition: openmsx.hh:26
void unregister_IO_In(byte port, MSXDevice *device)
REGISTER_MSXDEVICE(ChakkariCopy, "ChakkariCopy")
Ram & getUncheckedRam()
Give access to the unchecked Ram.
Definition: CheckedRam.hh:50
void write(unsigned addr, byte value)
Definition: CheckedRam.cc:59
byte peekIO(word port, EmuTime::param time) const override
Read a byte from a given IO port.
ColecoSuperGameModule(const DeviceConfig &config)
void register_IO_In(byte port, MSXDevice *device)
Devices can register their In ports.
void register_IO_Out(byte port, MSXDevice *device)
Devices can register their Out ports.
EmuTime::param getCurrentTime() const
Definition: MSXDevice.cc:133
byte peekRegister(unsigned reg, EmuTime::param time) const
Definition: AY8910.cc:575
Thanks to enen for testing this on a real cartridge:
Definition: Autofire.cc:5
An MSXDevice is an emulated hardware component connected to the bus of the emulated MSX...
Definition: MSXDevice.hh:31
const byte * getReadCacheLine(word start) const override
Test that the memory in the interval [start, start + CacheLine::SIZE) is cacheable for reading...
void unregister_IO_Out(byte port, MSXDevice *device)
byte peek(unsigned addr) const
Definition: CheckedRam.hh:35
byte peekMem(word address, EmuTime::param time) const override
Read a byte from a given memory location.
unsigned getSize() const
Definition: Rom.hh:32
uint16_t word
16 bit unsigned integer
Definition: openmsx.hh:29
static byte unmappedRead[0x10000]
Definition: MSXDevice.hh:274
byte read(unsigned addr)
Definition: CheckedRam.cc:36
#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 writeMem(word address, byte value, EmuTime::param time) override
Write a given byte to a given location at a certain time to this device.
MSXCPUInterface & getCPUInterface() const
Definition: MSXDevice.cc:141
byte * getWriteCacheLine(word start) const override
Test that the memory in the interval [start, start + CacheLine::SIZE) is cacheable for writing...
byte readMem(word address, EmuTime::param time) override
Read a byte from a location at a certain time from this device.
byte readRegister(unsigned reg, EmuTime::param time)
Definition: AY8910.cc:550
void reset(EmuTime::param time) override
This method is called on reset.
void reset(EmuTime::param time)
Definition: AY8910.cc:537
void invalidateMemCache(word start, unsigned size)
Invalidate CPU memory-mapping cache.
Definition: MSXDevice.cc:458
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.
void writeRegister(unsigned reg, byte value, EmuTime::param time)
Definition: AY8910.cc:594
byte * getWriteCacheLine(unsigned addr) const
Definition: CheckedRam.cc:53