From 3139d09e3b65c2bd08b84a57d014da99a1416e1f Mon Sep 17 00:00:00 2001 From: Akeraiotitasoft Date: Fri, 27 Oct 2023 15:50:15 -0700 Subject: [PATCH] Add mapper 474 --- include/Cartridge.h | 7 ++-- include/Mapper.h | 6 ++++ include/Mapper474.h | 24 ++++++++++++++ include/MapperNROM.h | 1 + src/Cartridge.cpp | 25 +++++++++++++- src/MainBus.cpp | 77 ++++++++++++++++++++++++++++++++++++++------ src/Mapper.cpp | 7 ++++ src/Mapper474.cpp | 66 +++++++++++++++++++++++++++++++++++++ src/MapperNROM.cpp | 14 ++++++-- 9 files changed, 213 insertions(+), 14 deletions(-) create mode 100644 include/Mapper474.h create mode 100644 src/Mapper474.cpp diff --git a/include/Cartridge.h b/include/Cartridge.h index 4c9ef1b..5075201 100644 --- a/include/Cartridge.h +++ b/include/Cartridge.h @@ -8,6 +8,7 @@ namespace sn { using Byte = std::uint8_t; using Address = std::uint16_t; + using UShort = std::uint16_t; class Cartridge { @@ -16,14 +17,16 @@ namespace sn bool loadFromFile(std::string path); const std::vector& getROM(); const std::vector& getVROM(); - Byte getMapper(); + UShort getMapper(); + Byte getSubMapper(); Byte getNameTableMirroring(); bool hasExtendedRAM(); private: std::vector m_PRG_ROM; std::vector m_CHR_ROM; Byte m_nameTableMirroring; - Byte m_mapperNumber; + UShort m_mapperNumber; + Byte m_subMapperNumber; bool m_extendedRAM; bool m_chrRAM; }; diff --git a/include/Mapper.h b/include/Mapper.h index fe206dd..ac79395 100644 --- a/include/Mapper.h +++ b/include/Mapper.h @@ -30,6 +30,7 @@ namespace sn AxROM = 7, ColorDreams = 11, GxROM = 66, + NROM474 = 474, }; Mapper(Cartridge& cart, Type t) : m_cartridge(cart), m_type(t) {}; @@ -47,6 +48,11 @@ namespace sn return m_cartridge.hasExtendedRAM(); } + Type inline getType() + { + return m_type; + } + virtual void scanlineIRQ(){} static std::unique_ptr createMapper (Type mapper_t, Cartridge& cart, std::function interrupt_cb, std::function mirroring_cb); diff --git a/include/Mapper474.h b/include/Mapper474.h new file mode 100644 index 0000000..7cd409a --- /dev/null +++ b/include/Mapper474.h @@ -0,0 +1,24 @@ +#ifndef MAPPER474_H +#define MAPPER474_H +#include "Mapper.h" + +namespace sn +{ + class Mapper474 : public Mapper + { + public: + Mapper474(Cartridge& cart); + void writePRG (Address addr, Byte value); + Byte readPRG (Address addr); + + Byte readCHR (Address addr); + void writeCHR (Address addr, Byte value); + private: + bool m_flavor474; + bool m_usesCharacterRAM; + + std::vector m_characterRAM; + + }; +} +#endif // MAPPERNROM_H diff --git a/include/MapperNROM.h b/include/MapperNROM.h index 2867660..0b23e3b 100644 --- a/include/MapperNROM.h +++ b/include/MapperNROM.h @@ -15,6 +15,7 @@ namespace sn void writeCHR (Address addr, Byte value); private: bool m_oneBank; + bool m_flavor368; bool m_usesCharacterRAM; std::vector m_characterRAM; diff --git a/src/Cartridge.cpp b/src/Cartridge.cpp index de5c93b..6f46c5e 100644 --- a/src/Cartridge.cpp +++ b/src/Cartridge.cpp @@ -9,6 +9,7 @@ namespace sn Cartridge::Cartridge() : m_nameTableMirroring(0), m_mapperNumber(0), + m_subMapperNumber(0), m_extendedRAM(false) { @@ -23,11 +24,16 @@ namespace sn return m_CHR_ROM; } - Byte Cartridge::getMapper() + UShort Cartridge::getMapper() { return m_mapperNumber; } + Byte Cartridge::getSubMapper() + { + return m_subMapperNumber; + } + Byte Cartridge::getNameTableMirroring() { return m_nameTableMirroring; @@ -53,6 +59,7 @@ namespace sn //Header header.resize(0x10); + bool ver2_0 = false; if (!romFile.read(reinterpret_cast(&header[0]), 0x10)) { LOG(Error) << "Reading iNES header failed." << std::endl; @@ -69,6 +76,16 @@ namespace sn LOG(Info) << "Reading header, it dictates: \n"; + if (((header[7] & 0xC) >> 2) == 2) + { + ver2_0 = true; + LOG(Info) << "ines 2.0" << std::endl; + } + else + { + LOG(Info) << "ines 1.0" << std::endl; + } + Byte banks = header[4]; LOG(Info) << "16KB PRG-ROM Banks: " << +banks << std::endl; if (!banks) @@ -92,7 +109,13 @@ namespace sn } m_mapperNumber = ((header[6] >> 4) & 0xf) | (header[7] & 0xf0); + if (ver2_0) + { + m_mapperNumber += ((header[8] & 0xf) << 8); + m_subMapperNumber = (header[8] >> 4) & 0xf; + } LOG(Info) << "Mapper #: " << +m_mapperNumber << std::endl; + LOG(Info) << "Sub Mapper #: " << +m_subMapperNumber << std::endl; m_extendedRAM = header[6] & 0x2; LOG(Info) << "Extended (CPU) RAM: " << std::boolalpha << m_extendedRAM << std::endl; diff --git a/src/MainBus.cpp b/src/MainBus.cpp index bf4a6de..844ddd0 100644 --- a/src/MainBus.cpp +++ b/src/MainBus.cpp @@ -41,13 +41,34 @@ namespace sn } else if (addr < 0x6000) { - LOG(InfoVerbose) << "Expansion ROM read attempted. This is currently unsupported" << std::endl; + if (m_mapper->getType() == NROM474) + { + if (m_mapper->hasExtendedRAM()) + { + return m_extRAM[addr - 0x4000]; + } + else + { + return m_mapper->readPRG(addr); + } + } + else + { + LOG(InfoVerbose) << "Expansion ROM read attempted. This is currently unsupported" << std::endl; + } } else if (addr < 0x8000) { - if (m_mapper->hasExtendedRAM()) + if (m_mapper->getType() == NROM474) + { + return m_mapper->readPRG(addr); + } + else { - return m_extRAM[addr - 0x6000]; + if (m_mapper->hasExtendedRAM()) + { + return m_extRAM[addr - 0x6000]; + } } } else @@ -88,13 +109,34 @@ namespace sn } else if (addr < 0x6000) { - LOG(InfoVerbose) << "Expansion ROM access attempted. This is currently unsupported" << std::endl; + if (m_mapper->getType() == NROM474) + { + if (m_mapper->hasExtendedRAM()) + { + m_extRAM[addr - 0x4000] = value; + } + else + { + m_mapper->writePRG(addr, value); + } + } + else + { + LOG(InfoVerbose) << "Expansion ROM access attempted. This is currently unsupported" << std::endl; + } } else if (addr < 0x8000) { - if (m_mapper->hasExtendedRAM()) + if (m_mapper->getType() == NROM474) + { + m_mapper->writePRG(addr, value); + } + else { - m_extRAM[addr - 0x6000] = value; + if (m_mapper->hasExtendedRAM()) + { + m_extRAM[addr - 0x6000] = value; + } } } else @@ -116,13 +158,30 @@ namespace sn } else if (addr < 0x6000) { - LOG(Error) << "Expansion ROM access attempted, which is unsupported" << std::endl; + if (m_mapper->getType() == Mapper::Type::NROM474) + { + if (m_mapper->hasExtendedRAM()) + { + return &m_extRAM[addr - 0x4000]; + } + } + else + { + LOG(Error) << "Expansion ROM access attempted, which is unsupported" << std::endl; + } } else if (addr < 0x8000) { - if (m_mapper->hasExtendedRAM()) + if (m_mapper->getType() == Mapper::Type::NROM474) + { + LOG(Error) << "Unexpected DMA request: " << std::hex << "0x" << +addr << " (" << +page << ")" << std::dec << std::endl; + } + else { - return &m_extRAM[addr - 0x6000]; + if (m_mapper->hasExtendedRAM()) + { + return &m_extRAM[addr - 0x6000]; + } } } else diff --git a/src/Mapper.cpp b/src/Mapper.cpp index 017b521..bcd82b0 100644 --- a/src/Mapper.cpp +++ b/src/Mapper.cpp @@ -8,6 +8,7 @@ #include "MapperAxROM.h" #include "MapperColorDreams.h" #include "MapperGxROM.h" +#include "Mapper474.h" namespace sn { @@ -45,6 +46,12 @@ namespace sn case GxROM: ret.reset(new MapperGxROM(cart, mirroring_cb)); break; + case NROM474: + if (cart.getROM().size() == 0xC000) + { + ret.reset(new Mapper474(cart)); + } + break; default: break; } diff --git a/src/Mapper474.cpp b/src/Mapper474.cpp new file mode 100644 index 0000000..093f41f --- /dev/null +++ b/src/Mapper474.cpp @@ -0,0 +1,66 @@ +#include "Mapper474.h" +#include "Log.h" + +namespace sn +{ + Mapper474::Mapper474(Cartridge &cart) : + Mapper(cart, Mapper::NROM474) + { + if (cart.getROM().size() == 0xC000) // 3 banks + { + // this is the only correct ROM size for this mapper + m_flavor474 = true; + } + else + { + // fail + m_flavor474 = false; + LOG(Info) << "Incorrectly configured mapper" << std::endl; + } + + if (cart.getVROM().size() == 0) + { + m_usesCharacterRAM = true; + m_characterRAM.resize(0x2000); + LOG(Info) << "Uses character RAM" << std::endl; + } + else + { + m_usesCharacterRAM = false; + } + } + + Byte MapperNROM::readPRG(Address addr) + { + if (m_flavor474) + { + return m_cartridge.getROM()[addr - 0x4000]; + } + else + { + LOG(InfoVerbose) << "ROM memory read attempt while mapper is not correctly configured." << std::endl; + return 0; // fail + } + } + + void MapperNROM::writePRG(Address addr, Byte value) + { + LOG(InfoVerbose) << "ROM memory write attempt at " << +addr << " to set " << +value << std::endl; + } + + Byte MapperNROM::readCHR(Address addr) + { + if (m_usesCharacterRAM) + return m_characterRAM[addr]; + else + return m_cartridge.getVROM()[addr]; + } + + void MapperNROM::writeCHR(Address addr, Byte value) + { + if (m_usesCharacterRAM) + m_characterRAM[addr] = value; + else + LOG(Info) << "Read-only CHR memory write attempt at " << std::hex << addr << std::endl; + } +} diff --git a/src/MapperNROM.cpp b/src/MapperNROM.cpp index 663c368..d37f720 100644 --- a/src/MapperNROM.cpp +++ b/src/MapperNROM.cpp @@ -10,10 +10,18 @@ namespace sn { m_oneBank = true; } - else //2 banks + else //2 or 3 banks { m_oneBank = false; } + if (cart.getROM().size() == 0xC000) // 3 banks + { + m_flavor368 = true; + } + else + { + m_flavor368 = false; + } if (cart.getVROM().size() == 0) { @@ -27,7 +35,9 @@ namespace sn Byte MapperNROM::readPRG(Address addr) { - if (!m_oneBank) + if (m_flavor368) + return m_cartridge.getROM()[addr - 0x4000]; + else if (!m_oneBank) return m_cartridge.getROM()[addr - 0x8000]; else //mirrored return m_cartridge.getROM()[(addr - 0x8000) & 0x3fff];