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 constexpr unsigned MAIN_RAM_AREA_START = 0x6000;
14 constexpr unsigned MAIN_RAM_SIZE = 0x400; // 1kB
15 constexpr unsigned SGM_RAM_SIZE = 0x8000; // 32kB
16 constexpr 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  invalidateDeviceRWCache(); // 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  invalidateDeviceRWCache(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;
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
openmsx::AY8910::peekRegister
byte peekRegister(unsigned reg, EmuTime::param time) const
Definition: AY8910.cc:567
openmsx::MSXDevice
An MSXDevice is an emulated hardware component connected to the bus of the emulated MSX.
Definition: MSXDevice.hh:31
openmsx::CheckedRam::getWriteCacheLine
byte * getWriteCacheLine(unsigned addr) const
Definition: CheckedRam.cc:53
openmsx::ColecoSuperGameModule::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: ColecoSuperGameModule.cc:126
serialize.hh
openmsx::ColecoSuperGameModule::writeIO
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.
Definition: ColecoSuperGameModule.cc:75
openmsx::CheckedRam::read
byte read(unsigned addr)
Definition: CheckedRam.cc:36
openmsx::DeviceConfig
Definition: DeviceConfig.hh:19
openmsx::MSXCPUInterface::register_IO_Out
void register_IO_Out(byte port, MSXDevice *device)
Devices can register their Out ports.
Definition: MSXCPUInterface.cc:350
openmsx::MSXDevice::unmappedWrite
static byte unmappedWrite[0x10000]
Definition: MSXDevice.hh:293
openmsx::AY8910::readRegister
byte readRegister(unsigned reg, EmuTime::param time)
Definition: AY8910.cc:542
openmsx::ColecoSuperGameModule::reset
void reset(EmuTime::param time) override
This method is called on reset.
Definition: ColecoSuperGameModule.cc:50
MSXException.hh
openmsx::MSXException
Definition: MSXException.hh:9
openmsx::MSXDevice::getCPUInterface
MSXCPUInterface & getCPUInterface() const
Definition: MSXDevice.cc:138
openmsx::ColecoSuperGameModule::getReadCacheLine
const byte * getReadCacheLine(word start) const override
Test that the memory in the interval [start, start + CacheLine::SIZE) is cacheable for reading.
Definition: ColecoSuperGameModule.cc:141
openmsx::REGISTER_MSXDEVICE
REGISTER_MSXDEVICE(ChakkariCopy, "ChakkariCopy")
openmsx::AY8910::writeRegister
void writeRegister(unsigned reg, byte value, EmuTime::param time)
Definition: AY8910.cc:586
openmsx::DummyAY8910Periphery
Definition: DummyAY8910Periphery.hh:8
openmsx::SGM_RAM_SIZE
constexpr unsigned SGM_RAM_SIZE
Definition: ColecoSuperGameModule.cc:15
openmsx::CheckedRam::peek
byte peek(unsigned addr) const
Definition: CheckedRam.hh:35
openmsx::BIOS_ROM_SIZE
constexpr unsigned BIOS_ROM_SIZE
Definition: ColecoSuperGameModule.cc:16
openmsx::ColecoSuperGameModule::peekIO
byte peekIO(word port, EmuTime::param time) const override
Read a byte from a given IO port.
Definition: ColecoSuperGameModule.cc:67
openmsx::Keys::getName
string getName(KeyCode keyCode)
Translate key code to key name.
Definition: Keys.cc:589
openmsx::MAIN_RAM_AREA_START
constexpr unsigned MAIN_RAM_AREA_START
Definition: ColecoSuperGameModule.cc:13
openmsx::MSXDevice::getCurrentTime
EmuTime::param getCurrentTime() const
Definition: MSXDevice.cc:130
openmsx::CheckedRam::write
void write(unsigned addr, byte value)
Definition: CheckedRam.cc:72
openmsx::ColecoSuperGameModule::ColecoSuperGameModule
ColecoSuperGameModule(const DeviceConfig &config)
Definition: ColecoSuperGameModule.cc:18
INSTANTIATE_SERIALIZE_METHODS
#define INSTANTIATE_SERIALIZE_METHODS(CLASS)
Definition: serialize.hh:981
openmsx::MSXCPUInterface::register_IO_In
void register_IO_In(byte port, MSXDevice *device)
Devices can register their In ports.
Definition: MSXCPUInterface.cc:338
DummyAY8910Periphery.hh
openmsx::MSXDevice::invalidateDeviceRWCache
void invalidateDeviceRWCache()
Calls MSXCPUInterface::invalidateXXCache() for the specific (part of) the slot that this device is lo...
Definition: MSXDevice.hh:208
openmsx::MSXCPUInterface::unregister_IO_In
void unregister_IO_In(byte port, MSXDevice *device)
Definition: MSXCPUInterface.cc:344
openmsx::MAIN_RAM_SIZE
constexpr unsigned MAIN_RAM_SIZE
Definition: ColecoSuperGameModule.cc:14
openmsx::MSXDevice::unmappedRead
static byte unmappedRead[0x10000]
Definition: MSXDevice.hh:292
openmsx::word
uint16_t word
16 bit unsigned integer
Definition: openmsx.hh:29
MSXCPUInterface.hh
openmsx::ColecoSuperGameModule
Definition: ColecoSuperGameModule.hh:11
openmsx::ColecoSuperGameModule::peekMem
byte peekMem(word address, EmuTime::param time) const override
Read a byte from a given memory location.
Definition: ColecoSuperGameModule.cc:98
openmsx::ColecoSuperGameModule::readMem
byte readMem(word address, EmuTime::param time) override
Read a byte from a location at a certain time from this device.
Definition: ColecoSuperGameModule.cc:112
openmsx::CheckedRam::getUncheckedRam
Ram & getUncheckedRam()
Give access to the unchecked Ram.
Definition: CheckedRam.hh:51
openmsx::ColecoSuperGameModule::getWriteCacheLine
byte * getWriteCacheLine(word start) const override
Test that the memory in the interval [start, start + CacheLine::SIZE) is cacheable for writing.
Definition: ColecoSuperGameModule.cc:155
openmsx::MSXCPUInterface::unregister_IO_Out
void unregister_IO_Out(byte port, MSXDevice *device)
Definition: MSXCPUInterface.cc:356
ColecoSuperGameModule.hh
openmsx::Rom::getSize
unsigned getSize() const
Definition: Rom.hh:32
openmsx
Thanks to enen for testing this on a real cartridge:
Definition: Autofire.cc:5
openmsx::CheckedRam::getReadCacheLine
const byte * getReadCacheLine(unsigned addr) const
Definition: CheckedRam.cc:47
openmsx::AY8910::reset
void reset(EmuTime::param time)
Definition: AY8910.cc:529
openmsx::ColecoSuperGameModule::~ColecoSuperGameModule
~ColecoSuperGameModule() override
Definition: ColecoSuperGameModule.cc:36
openmsx::ColecoSuperGameModule::serialize
void serialize(Archive &ar, unsigned version)
Definition: ColecoSuperGameModule.cc:172
openmsx::ColecoSuperGameModule::readIO
byte readIO(word port, EmuTime::param time) override
Read a byte from an IO port at a certain time from this device.
Definition: ColecoSuperGameModule.cc:59