diff --git a/src/addressSpace.hpp b/src/addressSpace.hpp index f4f9ba0..d7e2c8f 100644 --- a/src/addressSpace.hpp +++ b/src/addressSpace.hpp @@ -43,7 +43,6 @@ public: Byte TAC = 0xF8; // interrupt flag and enable Byte IF = 0xE1; - ; // Sound registers Byte NR10; Byte NR11; @@ -103,7 +102,7 @@ public: void loadRomBank(); void createRamBank(); void loadRamBank(); - MBCType MBC = {}; + MBCType_enum MBC = {}; uint32_t romSize = 0; uint32_t romBanks = 0; uint32_t externalRamSize = 0; @@ -116,7 +115,8 @@ public: // Selected ROM Bank in MBC1 = (Secondary Bank << 5) + ROM Bank Byte selectedRomBank = 0; Byte romBankRegister = 0x00; - // 2 bit register acts as secondary rom bank register or ram bank number in MBC1 + // 2 bit register acts as secondary rom bank register or ram bank number in + // MBC1 Byte twoBitBankRegister = 0x0; Byte selectedExternalRamBank = 0; Byte romRamSelect = 0x00; @@ -128,6 +128,13 @@ public: // MBC3 Byte latchClockData = 0x00; Byte ramBankRTCRegister = 0x00; + // RTC registers + enabledRTCRegister_enum enabledRTCRegister = NONE; + Byte RTCSeconds = 0x0; + Byte RTCMinutes = 0x0; + Byte RTCHours = 0x0; + Byte RTCDayLower = 0x0; + Byte RTCDayHigher = 0x0; void setTesting(bool state); @@ -144,6 +151,20 @@ public: else if (address < 0xA000) return memoryLayout.vram[address - 0x8000]; else if (address < 0xC000) { + if (enabledRTCRegister != NONE) { + switch (enabledRTCRegister) { + case RTCS: + return RTCSeconds; + case RTCM: + return RTCMinutes; + case RTCH: + return RTCHours; + case RTCDL: + return RTCDayLower; + case RTCDH: + return RTCDayHigher; + } + } if (externalRamSize == 0) return 0xFF; // MBC2 echos 15 times and only stores lower 4 bits diff --git a/src/defines.hpp b/src/defines.hpp index f6eaca5..0a00d6a 100644 --- a/src/defines.hpp +++ b/src/defines.hpp @@ -79,7 +79,7 @@ struct Input { bool SELECT = false; }; -enum MBCType { +enum MBCType_enum { romOnly = 0x00, MBC1 = 0x01, MBC1Ram = 0x02, @@ -111,7 +111,7 @@ enum MBCType { HuC1RamBattery = 0xFF }; -enum PPUMode { +enum PPUMode_enum { mode0, // Horizontal Blank (Mode 0): No access to video RAM, occurs during // horizontal blanking period. mode1, // Vertical Blank (Mode 1): No access to video RAM, occurs during @@ -122,4 +122,12 @@ enum PPUMode { // pixel transfer to the screen. }; +enum enabledRTCRegister_enum { + NONE = 0x00, + RTCS = 0x08, + RTCM = 0x09, + RTCH = 0x0A, + RTCDL = 0x0B, + RTCDH = 0x0C +}; #endif diff --git a/src/gameboy.hpp b/src/gameboy.hpp index 2c81ab5..8b4003e 100644 --- a/src/gameboy.hpp +++ b/src/gameboy.hpp @@ -50,7 +50,7 @@ class GameBoy { AddressSpace addressSpace; const AddressSpace &readOnlyAddressSpace = addressSpace; - PPUMode currentMode = PPUMode::mode0; + PPUMode_enum currentMode = PPUMode_enum::mode0; Byte windowLineCounter = 0; int16_t cyclesUntilDMATransfer = 160; @@ -86,7 +86,7 @@ class GameBoy { void SDL2present(); void checkPPUMode(); - void setPPUMode(PPUMode mode); + void setPPUMode(PPUMode_enum mode); uint64_t cyclesSinceLastScanline() const; uint64_t cyclesSinceLastRefresh() const; diff --git a/src/mbc.cpp b/src/mbc.cpp index 248466f..4b59c46 100644 --- a/src/mbc.cpp +++ b/src/mbc.cpp @@ -1,7 +1,8 @@ #include "addressSpace.hpp" +#include "defines.hpp" void AddressSpace::determineMBCInfo() { - MBC = static_cast(memoryLayout.romBank0[0x147]); + MBC = static_cast(memoryLayout.romBank0[0x147]); romSize = 32768 * (1 << memoryLayout.romBank0[0x147]); romBanks = 1 << (memoryLayout.romBank0[0x147] + 1); @@ -130,17 +131,33 @@ void AddressSpace::MBCUpdate() { loadRamBank(); } else if (MBC == MBC2 || MBC == MBC2Battery) { selectedRomBank = romBankRegister & 0x0F; + selectedExternalRamBank = 0; + loadRomBank(); loadRamBank(); } else if (MBC == MBC3 || MBC == MBC3TimerBattery) { selectedRomBank = romBankRegister & 0x7F; + selectedExternalRamBank = 0; + if (MBC == MBC3TimerBattery) { + if(ramBankRTCRegister >= 0x8 && ramBankRTCRegister <= 0xC) + enabledRTCRegister = static_cast(ramBankRTCRegister); + else + enabledRTCRegister = NONE; + } loadRomBank(); loadRamBank(); } else if (MBC == MBC3Ram || MBC == MBC3RamBattery || MBC == MBC3TimerRamBattery) { selectedRomBank = romBankRegister & 0x7F; + selectedExternalRamBank = ramBankRTCRegister & 0b11; + if (MBC == MBC3TimerRamBattery) { + if(ramBankRTCRegister >= 0x8 && ramBankRTCRegister <= 0xC) + enabledRTCRegister = static_cast(ramBankRTCRegister); + else + enabledRTCRegister = NONE; + } loadRomBank(); loadRamBank(); } diff --git a/src/ppu.cpp b/src/ppu.cpp index db74d63..f84ae2e 100644 --- a/src/ppu.cpp +++ b/src/ppu.cpp @@ -46,9 +46,9 @@ void GameBoy::ppuUpdate() { readOnlyAddressSpace.memoryLayout.STAT & (1 << 5); const bool previousInterruptLine = statInteruptLine; - if (currentMode == PPUMode::mode0 && hBlankInterruptEnabled || - currentMode == PPUMode::mode3 && drawingInterruptEnabled || - currentMode == PPUMode::mode2 && oamInterruptEnabled) { + if (currentMode == PPUMode_enum::mode0 && hBlankInterruptEnabled || + currentMode == PPUMode_enum::mode3 && drawingInterruptEnabled || + currentMode == PPUMode_enum::mode2 && oamInterruptEnabled) { statInteruptLine = true; } else { statInteruptLine = false; @@ -84,13 +84,13 @@ void GameBoy::checkPPUMode() { break; case 2: if (cyclesSinceScanline > MODE2_DURATION) { - setPPUMode(PPUMode::mode3); + setPPUMode(PPUMode_enum::mode3); } break; case 3: if (cyclesSinceScanline > MODE2_DURATION + MODE3_MIN_DURATION) { drawLine(); - setPPUMode(PPUMode::mode0); + setPPUMode(PPUMode_enum::mode0); } break; } @@ -98,14 +98,14 @@ void GameBoy::checkPPUMode() { void GameBoy::incLY() { addressSpace.memoryLayout.LY += 1; - setPPUMode(PPUMode::mode2); + setPPUMode(PPUMode_enum::mode2); if (addressSpace.memoryLayout.LY > SCANLINES_PER_FRAME - 1) { addressSpace.memoryLayout.LY = 0; windowLineCounter = 0; } else if (addressSpace.memoryLayout.LY == 144) { // VBlank Period SDL2present(); - setPPUMode(PPUMode::mode1); + setPPUMode(PPUMode_enum::mode1); addressSpace.memoryLayout.IF |= 0x1; } } @@ -120,7 +120,7 @@ uint64_t GameBoy::cyclesSinceLastRefresh() const { return difference; } -void GameBoy::setPPUMode(const PPUMode mode) { +void GameBoy::setPPUMode(const PPUMode_enum mode) { switch (mode) { case mode0: addressSpace.memoryLayout.STAT &= ~0x03;