GBA Hardware: RTC accuracy improvements
Vicki Pfau vi@endrift.com
Thu, 01 Feb 2018 09:29:07 -0800
2 files changed,
19 insertions(+),
15 deletions(-)
M
CHANGES
→
CHANGES
@@ -47,6 +47,7 @@ - GBA Memory: Partially revert prefetch changes (fixes mgba.io/i/840)
- PSP2: Fix issues causing poor audio - Wii: Fix screen tear when unpausing - GBA: Fix some GBA ROM misdetection (fixes mgba.io/i/978) + - GBA Hardware: RTC accuracy improvements Misc: - GBA Timer: Use global cycles for timers - GBA: Extend oddly-sized ROMs to full address space (fixes mgba.io/i/722)
M
src/gba/hardware.c
→
src/gba/hardware.c
@@ -67,7 +67,7 @@ }
void GBAHardwareClear(struct GBACartridgeHardware* hw) { hw->devices = HW_NONE | (hw->devices & HW_GB_PLAYER_DETECTION); - hw->direction = GPIO_WRITE_ONLY; + hw->readWrite = GPIO_WRITE_ONLY; hw->pinState = 0; hw->direction = 0;@@ -83,7 +83,7 @@ }
switch (address) { case GPIO_REG_DATA: hw->pinState &= ~hw->direction; - hw->pinState |= value; + hw->pinState |= value & hw->direction; _readPins(hw); break; case GPIO_REG_DIRECTION:@@ -96,13 +96,13 @@ default:
mLOG(GBA_HW, WARN, "Invalid GPIO address"); } if (hw->readWrite) { - uint16_t old; - LOAD_16(old, 0, hw->gpioBase); - old &= ~hw->direction; - old |= hw->pinState; - STORE_16(old, 0, hw->gpioBase); + STORE_16(hw->pinState, 0, hw->gpioBase); + STORE_16(hw->direction, 2, hw->gpioBase); + STORE_16(hw->readWrite, 4, hw->gpioBase); } else { hw->gpioBase[0] = 0; + hw->gpioBase[1] = 0; + hw->gpioBase[2] = 0; } }@@ -167,11 +167,13 @@ case 0:
if ((hw->pinState & 5) == 1) { hw->rtc.transferStep = 1; } + _outputPins(hw, 1); break; case 1: if ((hw->pinState & 5) == 5) { hw->rtc.transferStep = 2; } + _outputPins(hw, 5); break; case 2: if (!(hw->pinState & 1)) {@@ -179,11 +181,7 @@ hw->rtc.bits &= ~(1 << hw->rtc.bitsRead);
hw->rtc.bits |= ((hw->pinState & 2) >> 1) << hw->rtc.bitsRead; } else { if (hw->pinState & 4) { - // GPIO direction should always != reading - if (hw->direction & 2) { - if (RTCCommandDataIsReading(hw->rtc.command)) { - mLOG(GBA_HW, GAME_ERROR, "Attempting to write to RTC while in read mode"); - } + if (!RTCCommandDataIsReading(hw->rtc.command)) { ++hw->rtc.bitsRead; if (hw->rtc.bitsRead == 8) { _rtcProcessByte(hw);@@ -195,7 +193,7 @@ if (hw->rtc.bitsRead == 8) {
--hw->rtc.bytesRemaining; if (hw->rtc.bytesRemaining <= 0) { hw->rtc.commandActive = 0; - hw->rtc.command = RTCCommandDataClearReading(hw->rtc.command); + hw->rtc.command = 0; } hw->rtc.bitsRead = 0; }@@ -204,8 +202,9 @@ } else {
hw->rtc.bitsRead = 0; hw->rtc.bytesRemaining = 0; hw->rtc.commandActive = 0; - hw->rtc.command = RTCCommandDataClearReading(hw->rtc.command); + hw->rtc.command = 0; hw->rtc.transferStep = 0; + _outputPins(hw, 1); } } break;@@ -256,12 +255,16 @@ hw->rtc.bits = 0;
hw->rtc.bitsRead = 0; if (!hw->rtc.bytesRemaining) { hw->rtc.commandActive = 0; - hw->rtc.command = RTCCommandDataClearReading(hw->rtc.command); + hw->rtc.command = 0; } } unsigned _rtcOutput(struct GBACartridgeHardware* hw) { uint8_t outputByte = 0; + if (!hw->rtc.commandActive) { + mLOG(GBA_HW, GAME_ERROR, "Attempting to use RTC without an active command"); + return 0; + } switch (RTCCommandDataGetCommand(hw->rtc.command)) { case RTC_CONTROL: outputByte = hw->rtc.control;