GBA Hardware: RTC accuracy improvements

This commit is contained in:
Vicki Pfau 2018-02-01 09:29:07 -08:00
parent ea8561347c
commit 0ce3b9a2b7
2 changed files with 19 additions and 15 deletions

View File

@ -47,6 +47,7 @@ Bugfixes:
- PSP2: Fix issues causing poor audio - PSP2: Fix issues causing poor audio
- Wii: Fix screen tear when unpausing - Wii: Fix screen tear when unpausing
- GBA: Fix some GBA ROM misdetection (fixes mgba.io/i/978) - GBA: Fix some GBA ROM misdetection (fixes mgba.io/i/978)
- GBA Hardware: RTC accuracy improvements
Misc: Misc:
- GBA Timer: Use global cycles for timers - GBA Timer: Use global cycles for timers
- GBA: Extend oddly-sized ROMs to full address space (fixes mgba.io/i/722) - GBA: Extend oddly-sized ROMs to full address space (fixes mgba.io/i/722)

View File

@ -67,7 +67,7 @@ void GBAHardwareInit(struct GBACartridgeHardware* hw, uint16_t* base) {
void GBAHardwareClear(struct GBACartridgeHardware* hw) { void GBAHardwareClear(struct GBACartridgeHardware* hw) {
hw->devices = HW_NONE | (hw->devices & HW_GB_PLAYER_DETECTION); hw->devices = HW_NONE | (hw->devices & HW_GB_PLAYER_DETECTION);
hw->direction = GPIO_WRITE_ONLY; hw->readWrite = GPIO_WRITE_ONLY;
hw->pinState = 0; hw->pinState = 0;
hw->direction = 0; hw->direction = 0;
@ -83,7 +83,7 @@ void GBAHardwareGPIOWrite(struct GBACartridgeHardware* hw, uint32_t address, uin
switch (address) { switch (address) {
case GPIO_REG_DATA: case GPIO_REG_DATA:
hw->pinState &= ~hw->direction; hw->pinState &= ~hw->direction;
hw->pinState |= value; hw->pinState |= value & hw->direction;
_readPins(hw); _readPins(hw);
break; break;
case GPIO_REG_DIRECTION: case GPIO_REG_DIRECTION:
@ -96,13 +96,13 @@ void GBAHardwareGPIOWrite(struct GBACartridgeHardware* hw, uint32_t address, uin
mLOG(GBA_HW, WARN, "Invalid GPIO address"); mLOG(GBA_HW, WARN, "Invalid GPIO address");
} }
if (hw->readWrite) { if (hw->readWrite) {
uint16_t old; STORE_16(hw->pinState, 0, hw->gpioBase);
LOAD_16(old, 0, hw->gpioBase); STORE_16(hw->direction, 2, hw->gpioBase);
old &= ~hw->direction; STORE_16(hw->readWrite, 4, hw->gpioBase);
old |= hw->pinState;
STORE_16(old, 0, hw->gpioBase);
} else { } else {
hw->gpioBase[0] = 0; hw->gpioBase[0] = 0;
hw->gpioBase[1] = 0;
hw->gpioBase[2] = 0;
} }
} }
@ -167,11 +167,13 @@ void _rtcReadPins(struct GBACartridgeHardware* hw) {
if ((hw->pinState & 5) == 1) { if ((hw->pinState & 5) == 1) {
hw->rtc.transferStep = 1; hw->rtc.transferStep = 1;
} }
_outputPins(hw, 1);
break; break;
case 1: case 1:
if ((hw->pinState & 5) == 5) { if ((hw->pinState & 5) == 5) {
hw->rtc.transferStep = 2; hw->rtc.transferStep = 2;
} }
_outputPins(hw, 5);
break; break;
case 2: case 2:
if (!(hw->pinState & 1)) { if (!(hw->pinState & 1)) {
@ -179,11 +181,7 @@ void _rtcReadPins(struct GBACartridgeHardware* hw) {
hw->rtc.bits |= ((hw->pinState & 2) >> 1) << hw->rtc.bitsRead; hw->rtc.bits |= ((hw->pinState & 2) >> 1) << hw->rtc.bitsRead;
} else { } else {
if (hw->pinState & 4) { if (hw->pinState & 4) {
// GPIO direction should always != reading if (!RTCCommandDataIsReading(hw->rtc.command)) {
if (hw->direction & 2) {
if (RTCCommandDataIsReading(hw->rtc.command)) {
mLOG(GBA_HW, GAME_ERROR, "Attempting to write to RTC while in read mode");
}
++hw->rtc.bitsRead; ++hw->rtc.bitsRead;
if (hw->rtc.bitsRead == 8) { if (hw->rtc.bitsRead == 8) {
_rtcProcessByte(hw); _rtcProcessByte(hw);
@ -195,7 +193,7 @@ void _rtcReadPins(struct GBACartridgeHardware* hw) {
--hw->rtc.bytesRemaining; --hw->rtc.bytesRemaining;
if (hw->rtc.bytesRemaining <= 0) { if (hw->rtc.bytesRemaining <= 0) {
hw->rtc.commandActive = 0; hw->rtc.commandActive = 0;
hw->rtc.command = RTCCommandDataClearReading(hw->rtc.command); hw->rtc.command = 0;
} }
hw->rtc.bitsRead = 0; hw->rtc.bitsRead = 0;
} }
@ -204,8 +202,9 @@ void _rtcReadPins(struct GBACartridgeHardware* hw) {
hw->rtc.bitsRead = 0; hw->rtc.bitsRead = 0;
hw->rtc.bytesRemaining = 0; hw->rtc.bytesRemaining = 0;
hw->rtc.commandActive = 0; hw->rtc.commandActive = 0;
hw->rtc.command = RTCCommandDataClearReading(hw->rtc.command); hw->rtc.command = 0;
hw->rtc.transferStep = 0; hw->rtc.transferStep = 0;
_outputPins(hw, 1);
} }
} }
break; break;
@ -256,12 +255,16 @@ void _rtcProcessByte(struct GBACartridgeHardware* hw) {
hw->rtc.bitsRead = 0; hw->rtc.bitsRead = 0;
if (!hw->rtc.bytesRemaining) { if (!hw->rtc.bytesRemaining) {
hw->rtc.commandActive = 0; hw->rtc.commandActive = 0;
hw->rtc.command = RTCCommandDataClearReading(hw->rtc.command); hw->rtc.command = 0;
} }
} }
unsigned _rtcOutput(struct GBACartridgeHardware* hw) { unsigned _rtcOutput(struct GBACartridgeHardware* hw) {
uint8_t outputByte = 0; 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)) { switch (RTCCommandDataGetCommand(hw->rtc.command)) {
case RTC_CONTROL: case RTC_CONTROL:
outputByte = hw->rtc.control; outputByte = hw->rtc.control;