189 , scc(
"MFR SCC+ SCC-I", config, getCurrentTime(),
SCC::Mode::Compatible)
192 , flash(rom, AmdFlashChip::M29W800DB, {}, config)
194 powerUp(getCurrentTime());
195 getCPUInterface().register_IO_Out_range(0x10, 2,
this);
214 for (
auto& regs : bankRegs) {
230MegaFlashRomSCCPlus::SCCEnable MegaFlashRomSCCPlus::getSCCEnable()
const
232 if ((sccMode & 0x20) && (sccBanks[3] & 0x80)) {
234 }
else if ((!(sccMode & 0x20)) && ((sccBanks[2] & 0x3F) == 0x3F)) {
241unsigned MegaFlashRomSCCPlus::getSubslot(
unsigned addr)
const
243 return (configReg & 0x10)
244 ? (subslotReg >> (2 * (addr >> 14))) & 0x03
248unsigned MegaFlashRomSCCPlus::getFlashAddr(
unsigned addr)
const
251 addr = (addr & 0xE000) | ((addr & 0x1000) >> 12) | ((addr & 0x0FFF) << 1);
253 unsigned subslot = getSubslot(addr);
255 if ((configReg & 0xC0) == 0x40) {
256 unsigned bank = bankRegs[subslot][addr >> 14] + offsetReg;
257 return (bank * 0x4000) + (addr & 0x3FFF);
259 unsigned page = (addr >> 13) - 2;
266 unsigned bank = bankRegs[subslot][page] + offsetReg;
267 return (bank * 0x2000) + (addr & 0x1FFF);
270 return ((0x40000 * subslot) + tmp) & 0xFFFFF;
275 if ((configReg & 0x10) && (addr == 0xFFFF)) {
277 return subslotReg ^ 0xFF;
280 if ((configReg & 0xE0) == 0x00) {
281 SCCEnable enable = getSCCEnable();
282 if (((enable == EN_SCC) && (0x9800 <= addr) && (addr < 0xA000)) ||
283 ((enable == EN_SCCPLUS) && (0xB800 <= addr) && (addr < 0xC000))) {
284 return scc.
peekMem(narrow_cast<uint8_t>(addr & 0xFF), time);
288 if (((configReg & 0xC0) == 0x40) ||
289 ((0x4000 <= addr) && (addr < 0xC000))) {
291 unsigned flashAddr = getFlashAddr(addr);
292 assert(flashAddr !=
unsigned(-1));
293 return flash.
peek(flashAddr);
302 if ((configReg & 0x10) && (addr == 0xFFFF)) {
304 return subslotReg ^ 0xFF;
307 if ((configReg & 0xE0) == 0x00) {
308 SCCEnable enable = getSCCEnable();
309 if (((enable == EN_SCC) && (0x9800 <= addr) && (addr < 0xA000)) ||
310 ((enable == EN_SCCPLUS) && (0xB800 <= addr) && (addr < 0xC000))) {
311 return scc.
readMem(narrow_cast<uint8_t>(addr & 0xFF), time);
315 if (((configReg & 0xC0) == 0x40) ||
316 ((0x4000 <= addr) && (addr < 0xC000))) {
318 unsigned flashAddr = getFlashAddr(addr);
319 assert(flashAddr !=
unsigned(-1));
320 return flash.
read(flashAddr);
329 if ((configReg & 0x10) &&
335 if ((configReg & 0xE0) == 0x00) {
336 SCCEnable enable = getSCCEnable();
337 if (((enable == EN_SCC) && (0x9800 <= addr) && (addr < 0xA000)) ||
338 ((enable == EN_SCCPLUS) && (0xB800 <= addr) && (addr < 0xC000))) {
343 if (((configReg & 0xC0) == 0x40) ||
344 ((0x4000 <= addr) && (addr < 0xC000))) {
355 unsigned flashAddr = getFlashAddr(addr);
361 if ((configReg & 0x10) && (addr == 0xFFFF)) {
363 byte diff = value ^ subslotReg;
365 for (
auto i :
xrange(4)) {
366 if (diff & (3 << (2 * i))) {
372 if (((configReg & 0x04) == 0x00) && ((addr & 0xFFFE) == 0x7FFE)) {
378 if ((configReg & 0xE0) == 0x00) {
380 if ((addr & 0xFFFE) == 0xBFFE) {
387 SCCEnable enable = getSCCEnable();
388 bool isRamSegment2 = ((sccMode & 0x24) == 0x24) ||
389 ((sccMode & 0x10) == 0x10);
390 bool isRamSegment3 = ((sccMode & 0x10) == 0x10);
391 if (((enable == EN_SCC) && !isRamSegment2 &&
392 (0x9800 <= addr) && (addr < 0xA000)) ||
393 ((enable == EN_SCCPLUS) && !isRamSegment3 &&
394 (0xB800 <= addr) && (addr < 0xC000))) {
395 scc.
writeMem(narrow_cast<uint8_t>(addr & 0xFF), value, time);
400 unsigned subslot = getSubslot(addr);
401 unsigned page8kB = (addr >> 13) - 2;
402 if (((configReg & 0x02) == 0x00) && (page8kB < 4)) {
404 switch (configReg & 0xE0) {
407 if ((addr & 0x1800) == 0x1000) {
411 sccBanks[page8kB] = value;
412 if ((value & 0x80) && (page8kB == 0)) {
413 offsetReg = value & 0x7F;
418 byte mask = (configReg & 0x01) ? 0x3F : 0x7F;
419 bankRegs[subslot][page8kB] = value & mask;
426 if (((configReg & 0x08) == 0x08) && (addr < 0x6000)) {
435 if ((addr < 0x5000) || ((0x5800 <= addr) && (addr < 0x6000)))
break;
436 byte mask = (configReg & 0x01) ? 0x1F : 0x7F;
437 bankRegs[subslot][page8kB] = value & mask;
444 bankRegs[subslot][page8kB] = value;
450 if ((0x6000 <= addr) && (addr < 0x8000)) {
451 byte bank = (addr >> 11) & 0x03;
452 bankRegs[subslot][bank] = value;
465 if ((0x6000 <= addr) && (addr < 0x6800)) {
466 bankRegs[subslot][0] = narrow_cast<uint8_t>(2 * value + 0);
467 bankRegs[subslot][1] = narrow_cast<uint8_t>(2 * value + 1);
470 if ((0x7000 <= addr) && (addr < 0x7800)) {
471 bankRegs[subslot][2] = narrow_cast<uint8_t>(2 * value + 0);
472 bankRegs[subslot][3] = narrow_cast<uint8_t>(2 * value + 1);
480 if (((configReg & 0xC0) == 0x40) ||
481 ((0x4000 <= addr) && (addr < 0xC000))) {
482 assert(flashAddr !=
unsigned(-1));
483 return flash.
write(flashAddr, value);
495 if ((port & 0xFF) == 0x10) {
496 psgLatch = value & 0x0F;
498 assert((port & 0xFF) == 0x11);
504template<
typename Archive>
508 ar.template serializeBase<MSXDevice>(*
this);
510 ar.serialize(
"scc", scc,
514 "configReg", configReg,
515 "offsetReg", offsetReg,
516 "subslotReg", subslotReg,
517 "bankRegs", bankRegs,
518 "psgLatch", psgLatch,
520 "sccBanks", sccBanks);
#define REGISTER_MSXDEVICE(CLASS, NAME)
void reset(EmuTime::param time)
void writeRegister(unsigned reg, uint8_t value, EmuTime::param time)
void write(size_t address, uint8_t value)
uint8_t read(size_t address)
uint8_t peek(size_t address) const
void unregister_IO_Out_range(byte port, unsigned num, MSXDevice *device)
void invalidateDeviceRCache()
static std::array< byte, 0x10000 > unmappedRead
MSXCPUInterface & getCPUInterface() const
void reset(EmuTime::param time) override
This method is called on reset.
void powerUp(EmuTime::param time) override
This method is called when MSX is powered up.
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.
const byte * getReadCacheLine(word address) const override
Test that the memory in the interval [start, start + CacheLine::SIZE) is cacheable for reading.
byte * getWriteCacheLine(word address) 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.
MegaFlashRomSCCPlus(const DeviceConfig &config, Rom &&rom)
void serialize(Archive &ar, unsigned version)
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.
byte peekMem(word address, EmuTime::param time) const override
Read a byte from a given memory location.
~MegaFlashRomSCCPlus() override
void setMode(Mode newMode)
void powerUp(EmuTime::param time)
uint8_t readMem(uint8_t address, EmuTime::param time)
void reset(EmuTime::param time)
uint8_t peekMem(uint8_t address, EmuTime::param time) const
void writeMem(uint8_t address, uint8_t value, EmuTime::param time)
This file implemented 3 utility functions:
uint16_t word
16 bit unsigned integer
constexpr void iota(ForwardIt first, ForwardIt last, T value)
#define INSTANTIATE_SERIALIZE_METHODS(CLASS)
constexpr auto xrange(T e)