Permalink
Browse files

GBA: Add keypad IRQs (fixes #733)

  • Loading branch information...
endrift committed Jun 3, 2017
1 parent 1caa17c commit 9c23eb8428b2fd81d00c95ea1be56b508ba2b115
Showing with 44 additions and 6 deletions.
  1. +1 −0 CHANGES
  2. +2 −0 include/mgba/internal/gba/gba.h
  3. +3 −0 src/gba/core.c
  4. +28 −5 src/gba/gba.c
  5. +10 −1 src/gba/io.c
View
@@ -21,6 +21,7 @@ Features:
- 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
@@ -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);
View
@@ -398,16 +398,19 @@ 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);
}
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) {
View
@@ -409,10 +409,6 @@ void GBAApplyPatch(struct GBA* gba, struct Patch* patch) {
}
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 GBABreakpoint(struct ARMCore* cpu, int immediate) {
}
void GBAFrameStarted(struct GBA* gba) {
- UNUSED(gba);
+ GBATestKeypadIRQ(gba);
size_t c;
for (c = 0; c < mCoreCallbacksListSize(&gba->coreCallbacks); ++c) {
@@ -684,6 +680,33 @@ void GBAFrameEnded(struct GBA* gba) {
}
}
+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);
+ }
+}
+
void GBASetBreakpoint(struct GBA* gba, struct mCPUComponent* component, uint32_t address, enum ExecutionMode mode, uint32_t* opcode) {
size_t immediate;
for (immediate = 0; immediate < gba->cpu->numComponents; ++immediate) {
View
@@ -537,6 +537,11 @@ void GBAIOWrite(struct GBA* gba, uint32_t address, uint16_t 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 @@ bool GBAIOIsReadConstant(uint32_t address) {
case REG_TM2CNT_HI:
case REG_TM3CNT_HI:
case REG_KEYINPUT:
+ case REG_KEYCNT:
case REG_IE:
return true;
}
@@ -721,6 +727,9 @@ uint16_t GBAIORead(struct GBA* gba, uint32_t address) {
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 @@ uint16_t GBAIORead(struct GBA* gba, uint32_t address) {
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 @@ uint16_t GBAIORead(struct GBA* gba, uint32_t address) {
case REG_TM1CNT_HI:
case REG_TM2CNT_HI:
case REG_TM3CNT_HI:
+ case REG_KEYCNT:
case REG_SIOMULTI0:
case REG_SIOMULTI1:
case REG_SIOMULTI2:

0 comments on commit 9c23eb8

Please sign in to comment.