diff --git a/Core/AXROM.h b/Core/AXROM.h new file mode 100644 index 00000000..a3b9c5be --- /dev/null +++ b/Core/AXROM.h @@ -0,0 +1,24 @@ +#pragma once +#include "stdafx.h" +#include "BaseMapper.h" + +class AXROM : public BaseMapper +{ + protected: + virtual uint32_t GetPRGPageSize() { return 0x8000; } + virtual uint32_t GetCHRPageSize() { return 0x2000; } + + void InitMapper() + { + SelectPRGPage(0, 0); + SelectCHRPage(0, 0); + } + + public: + void WriteRAM(uint16_t addr, uint8_t value) + { + SelectPRGPage(0, value & 0x07); + + _mirroringType = ((value & 0x10) == 0x10) ? MirroringType::ScreenBOnly : MirroringType::ScreenAOnly; + } +}; \ No newline at end of file diff --git a/Core/Core.vcxproj b/Core/Core.vcxproj index e68e9e99..c6203628 100644 --- a/Core/Core.vcxproj +++ b/Core/Core.vcxproj @@ -88,6 +88,7 @@ + diff --git a/Core/Core.vcxproj.filters b/Core/Core.vcxproj.filters index 79b97663..a4d2e148 100644 --- a/Core/Core.vcxproj.filters +++ b/Core/Core.vcxproj.filters @@ -120,6 +120,9 @@ Header Files\Interfaces + + Header Files\Mappers + diff --git a/Core/MapperFactory.h b/Core/MapperFactory.h index 45d9ff71..20773766 100644 --- a/Core/MapperFactory.h +++ b/Core/MapperFactory.h @@ -1,5 +1,6 @@ #include "stdafx.h" #include "ROMLoader.h" +#include "AXROM.h" #include "CNROM.h" #include "MMC1.h" #include "MMC3.h" @@ -8,6 +9,22 @@ class MapperFactory { + private: + static BaseMapper* GetMapperFromID(uint8_t mapperID) + { + switch(mapperID) { + case 0: return new NROM(); + case 1: return new MMC1(); + case 2: return new UNROM(); + case 3: return new CNROM(); + case 4: return new MMC3(); + case 7: return new AXROM(); + } + + throw std::exception("Unsupported mapper"); + return nullptr; + } + public: static shared_ptr InitializeFromFile(wstring filename) { @@ -15,19 +32,7 @@ class MapperFactory uint8_t mapperID = loader.GetMapperID(); - BaseMapper* mapper = nullptr; - switch(mapperID) { - case 0: mapper = new NROM(); break; - case 1: mapper = new MMC1(); break; - case 2: mapper = new UNROM(); break; - case 3: mapper = new CNROM(); break; - case 4: mapper = new MMC3(); break; - } - - if(!mapper) { - throw std::exception("Unsupported mapper"); - } - + BaseMapper* mapper = GetMapperFromID(mapperID); mapper->Initialize(loader); return shared_ptr(mapper); } diff --git a/Core/MemoryManager.cpp b/Core/MemoryManager.cpp index e3b79f11..a0a2c6a4 100644 --- a/Core/MemoryManager.cpp +++ b/Core/MemoryManager.cpp @@ -147,7 +147,21 @@ uint8_t MemoryManager::ReadVRAM(uint16_t addr) if(addr >= 0x3000) { addr -= 0x1000; } - return _videoRAM[addr & 0x3FFF]; + + switch(_mapper->GetMirroringType()) { + case MirroringType::Vertical: + case MirroringType::Horizontal: + case MirroringType::FourScreens: + default: + return _videoRAM[addr & 0x3FFF]; + + case MirroringType::ScreenAOnly: + return _videoRAM[addr & 0x33FF]; + + case MirroringType::ScreenBOnly: + return _videoRAM[addr & 0x33FF | 0x400]; + } + } } @@ -163,52 +177,27 @@ void MemoryManager::WriteVRAM(uint16_t addr, uint8_t value) addr -= 0x1000; } - _videoRAM[addr] = value; - switch(_mapper->GetMirroringType()) { case MirroringType::Vertical: - if(addr >= 0x2000 && addr < 0x2400) { - _videoRAM[addr + 0x800] = value; - } else if(addr >= 0x2400 && addr < 0x2800) { - _videoRAM[addr + 0x800] = value; - } else if(addr >= 0x2800 && addr < 0x2C00) { - _videoRAM[addr - 0x800] = value; - } else if(addr >= 0x2C00 && addr < 0x3000) { - _videoRAM[addr - 0x800] = value; - } + _videoRAM[addr] = value; + _videoRAM[addr ^ 0x800] = value; break; case MirroringType::Horizontal: - if(addr >= 0x2000 && addr < 0x2400) { - _videoRAM[addr + 0x400] = value; - } else if(addr >= 0x2400 && addr < 0x2800) { - _videoRAM[addr - 0x400] = value; - } else if(addr >= 0x2800 && addr < 0x2C00) { - _videoRAM[addr + 0x400] = value; - } else if(addr >= 0x2C00 && addr < 0x3000) { - _videoRAM[addr - 0x400] = value; - } + _videoRAM[addr] = value; + _videoRAM[addr ^ 0x400] = value; break; - case MirroringType::ScreenAOnly: - case MirroringType::ScreenBOnly: - if(addr >= 0x2000 && addr < 0x2400) { - _videoRAM[addr + 0x400] = value; - _videoRAM[addr + 0x800] = value; - _videoRAM[addr + 0xC00] = value; - } else if(addr >= 0x2400 && addr < 0x2800) { - _videoRAM[addr - 0x400] = value; - _videoRAM[addr + 0x400] = value; - _videoRAM[addr + 0x800] = value; - } else if(addr >= 0x2800 && addr < 0x2C00) { - _videoRAM[addr + 0x400] = value; - _videoRAM[addr - 0x400] = value; - _videoRAM[addr - 0x800] = value; - } else if(addr >= 0x2C00 && addr < 0x3000) { - _videoRAM[addr - 0x400] = value; - _videoRAM[addr - 0x800] = value; - _videoRAM[addr - 0xC00] = value; - } + case MirroringType::ScreenAOnly: //Always write to 0x2000 + _videoRAM[addr & ~0xC00] = value; + break; + + case MirroringType::ScreenBOnly: //Always write to 0x2400 + _videoRAM[addr & ~0x800 | 0x400] = value; + break; + + case MirroringType::FourScreens: + _videoRAM[addr] = value; break; default: