189 , scc(
"MFR SCC+ SCC-I", config, getCurrentTime(),
SCC::Mode::Compatible)
192 , flash(rom, AmdFlashChip::M29W800DB, {}, config)
194 powerUp(getCurrentTime());
195 for (
auto port : {0x10, 0x11}) {
196 getCPUInterface().register_IO_Out(narrow_cast<byte>(port),
this);
202 for (
auto port : {0x10, 0x11}) {
218 for (
auto& regs : bankRegs) {
234MegaFlashRomSCCPlus::SCCEnable MegaFlashRomSCCPlus::getSCCEnable()
const
236 if ((sccMode & 0x20) && (sccBanks[3] & 0x80)) {
238 }
else if ((!(sccMode & 0x20)) && ((sccBanks[2] & 0x3F) == 0x3F)) {
245unsigned MegaFlashRomSCCPlus::getSubslot(
unsigned addr)
const
247 return (configReg & 0x10)
248 ? (subslotReg >> (2 * (addr >> 14))) & 0x03
252unsigned MegaFlashRomSCCPlus::getFlashAddr(
unsigned addr)
const
255 addr = (addr & 0xE000) | ((addr & 0x1000) >> 12) | ((addr & 0x0FFF) << 1);
257 unsigned subslot = getSubslot(addr);
259 if ((configReg & 0xC0) == 0x40) {
260 unsigned bank = bankRegs[subslot][addr >> 14] + offsetReg;
261 return (bank * 0x4000) + (addr & 0x3FFF);
263 unsigned page = (addr >> 13) - 2;
270 unsigned bank = bankRegs[subslot][page] + offsetReg;
271 return (bank * 0x2000) + (addr & 0x1FFF);
274 return ((0x40000 * subslot) + tmp) & 0xFFFFF;
279 if ((configReg & 0x10) && (addr == 0xFFFF)) {
281 return subslotReg ^ 0xFF;
284 if ((configReg & 0xE0) == 0x00) {
285 SCCEnable enable = getSCCEnable();
286 if (((enable == EN_SCC) && (0x9800 <= addr) && (addr < 0xA000)) ||
287 ((enable == EN_SCCPLUS) && (0xB800 <= addr) && (addr < 0xC000))) {
288 return scc.
peekMem(narrow_cast<uint8_t>(addr & 0xFF), time);
292 if (((configReg & 0xC0) == 0x40) ||
293 ((0x4000 <= addr) && (addr < 0xC000))) {
295 unsigned flashAddr = getFlashAddr(addr);
296 assert(flashAddr !=
unsigned(-1));
297 return flash.
peek(flashAddr);
306 if ((configReg & 0x10) && (addr == 0xFFFF)) {
308 return subslotReg ^ 0xFF;
311 if ((configReg & 0xE0) == 0x00) {
312 SCCEnable enable = getSCCEnable();
313 if (((enable == EN_SCC) && (0x9800 <= addr) && (addr < 0xA000)) ||
314 ((enable == EN_SCCPLUS) && (0xB800 <= addr) && (addr < 0xC000))) {
315 return scc.
readMem(narrow_cast<uint8_t>(addr & 0xFF), time);
319 if (((configReg & 0xC0) == 0x40) ||
320 ((0x4000 <= addr) && (addr < 0xC000))) {
322 unsigned flashAddr = getFlashAddr(addr);
323 assert(flashAddr !=
unsigned(-1));
324 return flash.
read(flashAddr);
333 if ((configReg & 0x10) &&
339 if ((configReg & 0xE0) == 0x00) {
340 SCCEnable enable = getSCCEnable();
341 if (((enable == EN_SCC) && (0x9800 <= addr) && (addr < 0xA000)) ||
342 ((enable == EN_SCCPLUS) && (0xB800 <= addr) && (addr < 0xC000))) {
347 if (((configReg & 0xC0) == 0x40) ||
348 ((0x4000 <= addr) && (addr < 0xC000))) {
359 unsigned flashAddr = getFlashAddr(addr);
365 if ((configReg & 0x10) && (addr == 0xFFFF)) {
367 byte diff = value ^ subslotReg;
369 for (
auto i :
xrange(4)) {
370 if (diff & (3 << (2 * i))) {
376 if (((configReg & 0x04) == 0x00) && ((addr & 0xFFFE) == 0x7FFE)) {
382 if ((configReg & 0xE0) == 0x00) {
384 if ((addr & 0xFFFE) == 0xBFFE) {
391 SCCEnable enable = getSCCEnable();
392 bool isRamSegment2 = ((sccMode & 0x24) == 0x24) ||
393 ((sccMode & 0x10) == 0x10);
394 bool isRamSegment3 = ((sccMode & 0x10) == 0x10);
395 if (((enable == EN_SCC) && !isRamSegment2 &&
396 (0x9800 <= addr) && (addr < 0xA000)) ||
397 ((enable == EN_SCCPLUS) && !isRamSegment3 &&
398 (0xB800 <= addr) && (addr < 0xC000))) {
399 scc.
writeMem(narrow_cast<uint8_t>(addr & 0xFF), value, time);
404 unsigned subslot = getSubslot(addr);
405 unsigned page8kB = (addr >> 13) - 2;
406 if (((configReg & 0x02) == 0x00) && (page8kB < 4)) {
408 switch (configReg & 0xE0) {
411 if ((addr & 0x1800) == 0x1000) {
415 sccBanks[page8kB] = value;
416 if ((value & 0x80) && (page8kB == 0)) {
417 offsetReg = value & 0x7F;
422 byte mask = (configReg & 0x01) ? 0x3F : 0x7F;
423 bankRegs[subslot][page8kB] = value & mask;
430 if (((configReg & 0x08) == 0x08) && (addr < 0x6000)) {
439 if ((addr < 0x5000) || ((0x5800 <= addr) && (addr < 0x6000)))
break;
440 byte mask = (configReg & 0x01) ? 0x1F : 0x7F;
441 bankRegs[subslot][page8kB] = value & mask;
448 bankRegs[subslot][page8kB] = value;
454 if ((0x6000 <= addr) && (addr < 0x8000)) {
455 byte bank = (addr >> 11) & 0x03;
456 bankRegs[subslot][bank] = value;
469 if ((0x6000 <= addr) && (addr < 0x6800)) {
470 bankRegs[subslot][0] = narrow_cast<uint8_t>(2 * value + 0);
471 bankRegs[subslot][1] = narrow_cast<uint8_t>(2 * value + 1);
474 if ((0x7000 <= addr) && (addr < 0x7800)) {
475 bankRegs[subslot][2] = narrow_cast<uint8_t>(2 * value + 0);
476 bankRegs[subslot][3] = narrow_cast<uint8_t>(2 * value + 1);
484 if (((configReg & 0xC0) == 0x40) ||
485 ((0x4000 <= addr) && (addr < 0xC000))) {
486 assert(flashAddr !=
unsigned(-1));
487 return flash.
write(flashAddr, value);
499 if ((port & 0xFF) == 0x10) {
500 psgLatch = value & 0x0F;
502 assert((port & 0xFF) == 0x11);
508template<
typename Archive>
512 ar.template serializeBase<MSXDevice>(*
this);
514 ar.serialize(
"scc", scc,
518 "configReg", configReg,
519 "offsetReg", offsetReg,
520 "subslotReg", subslotReg,
521 "bankRegs", bankRegs,
522 "psgLatch", psgLatch,
524 "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(byte port, 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)