all repos — mgba @ 9c23eb8428b2fd81d00c95ea1be56b508ba2b115

mGBA Game Boy Advance Emulator

GBA: Add keypad IRQs (fixes #733)
Vicki Pfau vi@endrift.com
Fri, 02 Jun 2017 18:34:24 -0700
commit

9c23eb8428b2fd81d00c95ea1be56b508ba2b115

parent

1caa17c00bf58a54956f16711a574e89536a47e4

5 files changed, 44 insertions(+), 6 deletions(-)

jump to
M CHANGESCHANGES

@@ -21,6 +21,7 @@ - Library view

- Debugger: Segment/bank support - GB: Symbol table support - GB MBC: Add MBC1 multicart support + - GBA: Implement keypad interrupts Bugfixes: - LR35902: Fix core never exiting with certain event patterns - GB Timer: Improve DIV reset behavior
M include/mgba/internal/gba/gba.hinclude/mgba/internal/gba/gba.h

@@ -175,6 +175,8 @@ bool GBAIsBIOS(struct VFile* vf);

void GBAGetGameCode(const struct GBA* gba, char* out); void GBAGetGameTitle(const struct GBA* gba, char* out); +void GBATestKeypadIRQ(struct GBA* gba); + void GBAFrameStarted(struct GBA* gba); void GBAFrameEnded(struct GBA* gba);
M src/gba/core.csrc/gba/core.c

@@ -398,16 +398,19 @@

static void _GBACoreSetKeys(struct mCore* core, uint32_t keys) { struct GBACore* gbacore = (struct GBACore*) core; gbacore->keys = keys; + GBATestKeypadIRQ(core->board); } static void _GBACoreAddKeys(struct mCore* core, uint32_t keys) { struct GBACore* gbacore = (struct GBACore*) core; gbacore->keys |= keys; + GBATestKeypadIRQ(core->board); } static void _GBACoreClearKeys(struct mCore* core, uint32_t keys) { struct GBACore* gbacore = (struct GBACore*) core; gbacore->keys &= ~keys; + GBATestKeypadIRQ(core->board); } static int32_t _GBACoreFrameCounter(const struct mCore* core) {
M src/gba/gba.csrc/gba/gba.c

@@ -409,10 +409,6 @@ gba->romCrc32 = doCrc32(gba->memory.rom, gba->memory.romSize);

} void GBAWriteIE(struct GBA* gba, uint16_t value) { - if (value & (1 << IRQ_KEYPAD)) { - mLOG(GBA, STUB, "Keypad interrupts not implemented"); - } - if (gba->memory.io[REG_IME >> 1] && value & gba->memory.io[REG_IF >> 1]) { ARMRaiseIRQ(gba->cpu); }

@@ -637,7 +633,7 @@ }

} void GBAFrameStarted(struct GBA* gba) { - UNUSED(gba); + GBATestKeypadIRQ(gba); size_t c; for (c = 0; c < mCoreCallbacksListSize(&gba->coreCallbacks); ++c) {

@@ -681,6 +677,33 @@ struct mCoreCallbacks* callbacks = mCoreCallbacksListGetPointer(&gba->coreCallbacks, c);

if (callbacks->videoFrameEnded) { callbacks->videoFrameEnded(callbacks->context); } + } +} + +void GBATestKeypadIRQ(struct GBA* gba) { + uint16_t keycnt = gba->memory.io[REG_KEYCNT >> 1]; + if (!(keycnt & 0x4000)) { + return; + } + int isAnd = keycnt & 0x8000; + uint16_t keyInput; + + if (!gba->keySource) { + // TODO? + return; + } + + keycnt &= 0x3FF; + keyInput = *gba->keySource; + + if (popcount32(keyInput) > 2) { + keycnt = keycnt; + } + + if (isAnd && keycnt == keyInput) { + GBARaiseIRQ(gba, IRQ_KEYPAD); + } else if (!isAnd && keyInput) { + GBARaiseIRQ(gba, IRQ_KEYPAD); } }
M src/gba/io.csrc/gba/io.c

@@ -537,6 +537,11 @@ value = GBASIOWriteRegister(&gba->sio, address, value);

break; // Interrupts and misc + case REG_KEYCNT: + value &= 0xC3FF; + gba->memory.io[address >> 1] = value; + GBATestKeypadIRQ(gba); + return; case REG_WAITCNT: value &= 0x5FFF; GBAAdjustWaitstates(gba, value);

@@ -689,6 +694,7 @@ case REG_TM1CNT_HI:

case REG_TM2CNT_HI: case REG_TM3CNT_HI: case REG_KEYINPUT: + case REG_KEYCNT: case REG_IE: return true; }

@@ -721,6 +727,9 @@ } else {

uint16_t input = 0x3FF; if (gba->keyCallback) { input = gba->keyCallback->readKeys(gba->keyCallback); + if (gba->keySource) { + *gba->keySource = input; + } } else if (gba->keySource) { input = *gba->keySource; }

@@ -814,7 +823,6 @@ gba->memory.io[REG_JOYSTAT >> 1] &= ~JOYSTAT_RECV_BIT;

break; case REG_SOUNDBIAS: - case REG_KEYCNT: case REG_POSTFLG: mLOG(GBA_IO, STUB, "Stub I/O register read: %03x", address); break;

@@ -863,6 +871,7 @@ case REG_TM0CNT_HI:

case REG_TM1CNT_HI: case REG_TM2CNT_HI: case REG_TM3CNT_HI: + case REG_KEYCNT: case REG_SIOMULTI0: case REG_SIOMULTI1: case REG_SIOMULTI2: