From f696619b11d74c09e49485caa7d916753c6fc3f4 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Thu, 14 Oct 2021 01:59:59 -0700 Subject: [PATCH] GBA I/O: Redo internal key input, enabling edge-based key IRQs --- CHANGES | 1 + include/mgba/internal/gba/gba.h | 3 ++- src/gba/core.c | 20 ++++++++------------ src/gba/gba.c | 17 +++++++++++------ src/gba/io.c | 27 +++++++++++---------------- 5 files changed, 33 insertions(+), 35 deletions(-) diff --git a/CHANGES b/CHANGES index 2d6c8d2db..0692d5e4a 100644 --- a/CHANGES +++ b/CHANGES @@ -16,6 +16,7 @@ Emulation fixes: - GB Memory: Add cursory cartridge open bus emulation (fixes mgba.io/i/2032) - GB Video: Render SGB border when unmasking with ATTR/PAL_SET (fixes mgba.io/i/2261) - GBA: Improve timing when not booting from BIOS + - GBA I/O: Redo internal key input, enabling edge-based key IRQs - GBA Memory: Fix misaligned 32-bit I/O loads (fixes mgba.io/i/2307) - GBA SIO: Fix SI value for unattached MULTI mode - GBA Video: Fix backdrop color if DISPCNT is first set to 0 (fixes mgba.io/i/2260) diff --git a/include/mgba/internal/gba/gba.h b/include/mgba/internal/gba/gba.h index 6e8fe4990..d98cdab39 100644 --- a/include/mgba/internal/gba/gba.h +++ b/include/mgba/internal/gba/gba.h @@ -85,7 +85,8 @@ struct GBA { struct mTimingEvent irqEvent; uint32_t biosChecksum; - int* keySource; + uint16_t keysActive; + uint16_t keysLast; struct mRotationSource* rotationSource; struct GBALuminanceSource* luminanceSource; struct mRTCSource* rtcSource; diff --git a/src/gba/core.c b/src/gba/core.c index 3bd31b776..112e34618 100644 --- a/src/gba/core.c +++ b/src/gba/core.c @@ -146,7 +146,6 @@ struct GBACore { #ifndef DISABLE_THREADING struct mVideoThreadProxy threadProxy; #endif - int keys; struct mCPUComponent* components[CPU_COMPONENT_MAX]; const struct Configuration* overrides; struct mDebuggerPlatform* debuggerPlatform; @@ -205,9 +204,6 @@ static bool _GBACoreInit(struct mCore* core) { gbacore->proxyRenderer.logger = NULL; #endif - gbacore->keys = 0; - gba->keySource = &gbacore->keys; - #if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2 mDirectorySetInit(&core->dirs); #endif @@ -707,20 +703,20 @@ static bool _GBACoreSaveState(struct mCore* core, void* state) { } static void _GBACoreSetKeys(struct mCore* core, uint32_t keys) { - struct GBACore* gbacore = (struct GBACore*) core; - gbacore->keys = keys; - GBATestKeypadIRQ(core->board); + struct GBA* gba = core->board; + gba->keysActive = keys; + GBATestKeypadIRQ(gba); } static void _GBACoreAddKeys(struct mCore* core, uint32_t keys) { - struct GBACore* gbacore = (struct GBACore*) core; - gbacore->keys |= keys; - GBATestKeypadIRQ(core->board); + struct GBA* gba = core->board; + gba->keysActive |= keys; + GBATestKeypadIRQ(gba); } static void _GBACoreClearKeys(struct mCore* core, uint32_t keys) { - struct GBACore* gbacore = (struct GBACore*) core; - gbacore->keys &= ~keys; + struct GBA* gba = core->board; + gba->keysActive &= ~keys; } static int32_t _GBACoreFrameCounter(const struct mCore* core) { diff --git a/src/gba/gba.c b/src/gba/gba.c index b73fe9d86..6df5086a1 100644 --- a/src/gba/gba.c +++ b/src/gba/gba.c @@ -90,7 +90,8 @@ static void GBAInit(void* cpu, struct mCPUComponent* component) { GBAHardwareInit(&gba->memory.hw, NULL); - gba->keySource = 0; + gba->keysActive = 0; + gba->keysLast = 0; gba->rotationSource = 0; gba->luminanceSource = 0; gba->rtcSource = 0; @@ -877,18 +878,22 @@ void GBAFrameEnded(struct GBA* gba) { } void GBATestKeypadIRQ(struct GBA* gba) { + if (gba->keysActive == gba->keysLast) { + return; + } uint16_t keycnt = gba->memory.io[REG_KEYCNT >> 1]; if (!(keycnt & 0x4000)) { return; } int isAnd = keycnt & 0x8000; - if (!gba->keySource) { - // TODO? - return; - } keycnt &= 0x3FF; - uint16_t keyInput = *gba->keySource & keycnt; + uint16_t keyInput = gba->keysActive & keycnt; + uint16_t lastInput = gba->keysLast & keycnt; + gba->keysLast = gba->keysActive; + if (keyInput == lastInput) { + return; + } if (isAnd && keycnt == keyInput) { GBARaiseIRQ(gba, IRQ_KEYPAD, 0); diff --git a/src/gba/io.c b/src/gba/io.c index 7abf28047..ec16c6b93 100644 --- a/src/gba/io.c +++ b/src/gba/io.c @@ -743,24 +743,19 @@ uint16_t GBAIORead(struct GBA* gba, uint32_t address) { callbacks->keysRead(callbacks->context); } } - uint16_t input = 0; if (gba->keyCallback) { - input = gba->keyCallback->readKeys(gba->keyCallback); - if (gba->keySource) { - *gba->keySource = input; + gba->keysActive = gba->keyCallback->readKeys(gba->keyCallback); + } + uint16_t input = gba->keysActive; + if (!gba->allowOpposingDirections) { + unsigned rl = input & 0x030; + unsigned ud = input & 0x0C0; + input &= 0x30F; + if (rl != 0x030) { + input |= rl; } - } else if (gba->keySource) { - input = *gba->keySource; - if (!gba->allowOpposingDirections) { - unsigned rl = input & 0x030; - unsigned ud = input & 0x0C0; - input &= 0x30F; - if (rl != 0x030) { - input |= rl; - } - if (ud != 0x0C0) { - input |= ud; - } + if (ud != 0x0C0) { + input |= ud; } } gba->memory.io[address >> 1] = 0x3FF ^ input;