enums and RTC work

This commit is contained in:
2026-03-18 01:09:03 -07:00
parent 80e23312de
commit c242fb7574
5 changed files with 62 additions and 16 deletions

View File

@@ -43,7 +43,6 @@ public:
Byte TAC = 0xF8; Byte TAC = 0xF8;
// interrupt flag and enable // interrupt flag and enable
Byte IF = 0xE1; Byte IF = 0xE1;
;
// Sound registers // Sound registers
Byte NR10; Byte NR10;
Byte NR11; Byte NR11;
@@ -103,7 +102,7 @@ public:
void loadRomBank(); void loadRomBank();
void createRamBank(); void createRamBank();
void loadRamBank(); void loadRamBank();
MBCType MBC = {}; MBCType_enum MBC = {};
uint32_t romSize = 0; uint32_t romSize = 0;
uint32_t romBanks = 0; uint32_t romBanks = 0;
uint32_t externalRamSize = 0; uint32_t externalRamSize = 0;
@@ -116,7 +115,8 @@ public:
// Selected ROM Bank in MBC1 = (Secondary Bank << 5) + ROM Bank // Selected ROM Bank in MBC1 = (Secondary Bank << 5) + ROM Bank
Byte selectedRomBank = 0; Byte selectedRomBank = 0;
Byte romBankRegister = 0x00; 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 twoBitBankRegister = 0x0;
Byte selectedExternalRamBank = 0; Byte selectedExternalRamBank = 0;
Byte romRamSelect = 0x00; Byte romRamSelect = 0x00;
@@ -128,6 +128,13 @@ public:
// MBC3 // MBC3
Byte latchClockData = 0x00; Byte latchClockData = 0x00;
Byte ramBankRTCRegister = 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); void setTesting(bool state);
@@ -144,6 +151,20 @@ public:
else if (address < 0xA000) else if (address < 0xA000)
return memoryLayout.vram[address - 0x8000]; return memoryLayout.vram[address - 0x8000];
else if (address < 0xC000) { 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) if (externalRamSize == 0)
return 0xFF; return 0xFF;
// MBC2 echos 15 times and only stores lower 4 bits // MBC2 echos 15 times and only stores lower 4 bits

View File

@@ -79,7 +79,7 @@ struct Input {
bool SELECT = false; bool SELECT = false;
}; };
enum MBCType { enum MBCType_enum {
romOnly = 0x00, romOnly = 0x00,
MBC1 = 0x01, MBC1 = 0x01,
MBC1Ram = 0x02, MBC1Ram = 0x02,
@@ -111,7 +111,7 @@ enum MBCType {
HuC1RamBattery = 0xFF HuC1RamBattery = 0xFF
}; };
enum PPUMode { enum PPUMode_enum {
mode0, // Horizontal Blank (Mode 0): No access to video RAM, occurs during mode0, // Horizontal Blank (Mode 0): No access to video RAM, occurs during
// horizontal blanking period. // horizontal blanking period.
mode1, // Vertical Blank (Mode 1): No access to video RAM, occurs during mode1, // Vertical Blank (Mode 1): No access to video RAM, occurs during
@@ -122,4 +122,12 @@ enum PPUMode {
// pixel transfer to the screen. // pixel transfer to the screen.
}; };
enum enabledRTCRegister_enum {
NONE = 0x00,
RTCS = 0x08,
RTCM = 0x09,
RTCH = 0x0A,
RTCDL = 0x0B,
RTCDH = 0x0C
};
#endif #endif

View File

@@ -50,7 +50,7 @@ class GameBoy {
AddressSpace addressSpace; AddressSpace addressSpace;
const AddressSpace &readOnlyAddressSpace = addressSpace; const AddressSpace &readOnlyAddressSpace = addressSpace;
PPUMode currentMode = PPUMode::mode0; PPUMode_enum currentMode = PPUMode_enum::mode0;
Byte windowLineCounter = 0; Byte windowLineCounter = 0;
int16_t cyclesUntilDMATransfer = 160; int16_t cyclesUntilDMATransfer = 160;
@@ -86,7 +86,7 @@ class GameBoy {
void SDL2present(); void SDL2present();
void checkPPUMode(); void checkPPUMode();
void setPPUMode(PPUMode mode); void setPPUMode(PPUMode_enum mode);
uint64_t cyclesSinceLastScanline() const; uint64_t cyclesSinceLastScanline() const;
uint64_t cyclesSinceLastRefresh() const; uint64_t cyclesSinceLastRefresh() const;

View File

@@ -1,7 +1,8 @@
#include "addressSpace.hpp" #include "addressSpace.hpp"
#include "defines.hpp"
void AddressSpace::determineMBCInfo() { void AddressSpace::determineMBCInfo() {
MBC = static_cast<MBCType>(memoryLayout.romBank0[0x147]); MBC = static_cast<MBCType_enum>(memoryLayout.romBank0[0x147]);
romSize = 32768 * (1 << memoryLayout.romBank0[0x147]); romSize = 32768 * (1 << memoryLayout.romBank0[0x147]);
romBanks = 1 << (memoryLayout.romBank0[0x147] + 1); romBanks = 1 << (memoryLayout.romBank0[0x147] + 1);
@@ -130,17 +131,33 @@ void AddressSpace::MBCUpdate() {
loadRamBank(); loadRamBank();
} else if (MBC == MBC2 || MBC == MBC2Battery) { } else if (MBC == MBC2 || MBC == MBC2Battery) {
selectedRomBank = romBankRegister & 0x0F; selectedRomBank = romBankRegister & 0x0F;
selectedExternalRamBank = 0;
loadRomBank(); loadRomBank();
loadRamBank(); loadRamBank();
} else if (MBC == MBC3 || MBC == MBC3TimerBattery) { } else if (MBC == MBC3 || MBC == MBC3TimerBattery) {
selectedRomBank = romBankRegister & 0x7F; selectedRomBank = romBankRegister & 0x7F;
selectedExternalRamBank = 0;
if (MBC == MBC3TimerBattery) {
if(ramBankRTCRegister >= 0x8 && ramBankRTCRegister <= 0xC)
enabledRTCRegister = static_cast<enabledRTCRegister_enum>(ramBankRTCRegister);
else
enabledRTCRegister = NONE;
}
loadRomBank(); loadRomBank();
loadRamBank(); loadRamBank();
} else if (MBC == MBC3Ram || MBC == MBC3RamBattery || } else if (MBC == MBC3Ram || MBC == MBC3RamBattery ||
MBC == MBC3TimerRamBattery) { MBC == MBC3TimerRamBattery) {
selectedRomBank = romBankRegister & 0x7F; selectedRomBank = romBankRegister & 0x7F;
selectedExternalRamBank = ramBankRTCRegister & 0b11;
if (MBC == MBC3TimerRamBattery) {
if(ramBankRTCRegister >= 0x8 && ramBankRTCRegister <= 0xC)
enabledRTCRegister = static_cast<enabledRTCRegister_enum>(ramBankRTCRegister);
else
enabledRTCRegister = NONE;
}
loadRomBank(); loadRomBank();
loadRamBank(); loadRamBank();
} }

View File

@@ -46,9 +46,9 @@ void GameBoy::ppuUpdate() {
readOnlyAddressSpace.memoryLayout.STAT & (1 << 5); readOnlyAddressSpace.memoryLayout.STAT & (1 << 5);
const bool previousInterruptLine = statInteruptLine; const bool previousInterruptLine = statInteruptLine;
if (currentMode == PPUMode::mode0 && hBlankInterruptEnabled || if (currentMode == PPUMode_enum::mode0 && hBlankInterruptEnabled ||
currentMode == PPUMode::mode3 && drawingInterruptEnabled || currentMode == PPUMode_enum::mode3 && drawingInterruptEnabled ||
currentMode == PPUMode::mode2 && oamInterruptEnabled) { currentMode == PPUMode_enum::mode2 && oamInterruptEnabled) {
statInteruptLine = true; statInteruptLine = true;
} else { } else {
statInteruptLine = false; statInteruptLine = false;
@@ -84,13 +84,13 @@ void GameBoy::checkPPUMode() {
break; break;
case 2: case 2:
if (cyclesSinceScanline > MODE2_DURATION) { if (cyclesSinceScanline > MODE2_DURATION) {
setPPUMode(PPUMode::mode3); setPPUMode(PPUMode_enum::mode3);
} }
break; break;
case 3: case 3:
if (cyclesSinceScanline > MODE2_DURATION + MODE3_MIN_DURATION) { if (cyclesSinceScanline > MODE2_DURATION + MODE3_MIN_DURATION) {
drawLine(); drawLine();
setPPUMode(PPUMode::mode0); setPPUMode(PPUMode_enum::mode0);
} }
break; break;
} }
@@ -98,14 +98,14 @@ void GameBoy::checkPPUMode() {
void GameBoy::incLY() { void GameBoy::incLY() {
addressSpace.memoryLayout.LY += 1; addressSpace.memoryLayout.LY += 1;
setPPUMode(PPUMode::mode2); setPPUMode(PPUMode_enum::mode2);
if (addressSpace.memoryLayout.LY > SCANLINES_PER_FRAME - 1) { if (addressSpace.memoryLayout.LY > SCANLINES_PER_FRAME - 1) {
addressSpace.memoryLayout.LY = 0; addressSpace.memoryLayout.LY = 0;
windowLineCounter = 0; windowLineCounter = 0;
} else if (addressSpace.memoryLayout.LY == 144) { } else if (addressSpace.memoryLayout.LY == 144) {
// VBlank Period // VBlank Period
SDL2present(); SDL2present();
setPPUMode(PPUMode::mode1); setPPUMode(PPUMode_enum::mode1);
addressSpace.memoryLayout.IF |= 0x1; addressSpace.memoryLayout.IF |= 0x1;
} }
} }
@@ -120,7 +120,7 @@ uint64_t GameBoy::cyclesSinceLastRefresh() const {
return difference; return difference;
} }
void GameBoy::setPPUMode(const PPUMode mode) { void GameBoy::setPPUMode(const PPUMode_enum mode) {
switch (mode) { switch (mode) {
case mode0: case mode0:
addressSpace.memoryLayout.STAT &= ~0x03; addressSpace.memoryLayout.STAT &= ~0x03;