GBA: Correct key IRQ edge behavior

This commit is contained in:
Vicki Pfau 2021-12-06 03:27:35 -08:00
parent 10458aea67
commit e224b45576
3 changed files with 16 additions and 13 deletions

View File

@ -709,6 +709,7 @@ static void _GBACoreAddKeys(struct mCore* core, uint32_t keys) {
static void _GBACoreClearKeys(struct mCore* core, uint32_t keys) {
struct GBA* gba = core->board;
gba->keysActive &= ~keys;
GBATestKeypadIRQ(gba);
}
static int32_t _GBACoreFrameCounter(const struct mCore* core) {

View File

@ -91,7 +91,7 @@ static void GBAInit(void* cpu, struct mCPUComponent* component) {
GBAHardwareInit(&gba->memory.hw, NULL);
gba->keysActive = 0;
gba->keysLast = 0;
gba->keysLast = 0x400;
gba->rotationSource = 0;
gba->luminanceSource = 0;
gba->rtcSource = 0;
@ -878,27 +878,26 @@ void GBAFrameEnded(struct GBA* gba) {
}
void GBATestKeypadIRQ(struct GBA* gba) {
if (gba->keysActive == gba->keysLast) {
return;
}
uint16_t keysLast = gba->keysLast;
uint16_t keysActive = gba->keysActive;
uint16_t keycnt = gba->memory.io[REG_KEYCNT >> 1];
if (!(keycnt & 0x4000)) {
return;
}
gba->keysLast = keysActive;
int isAnd = keycnt & 0x8000;
keycnt &= 0x3FF;
uint16_t keyInput = gba->keysActive & keycnt;
uint16_t lastInput = gba->keysLast & keycnt;
gba->keysLast = gba->keysActive;
if (keyInput == lastInput) {
return;
}
if (isAnd && keycnt == keyInput) {
if (isAnd && keycnt == (keysActive & keycnt)) {
if (keysLast == keysActive) {
return;
}
GBARaiseIRQ(gba, IRQ_KEYPAD, 0);
} else if (!isAnd && keyInput) {
} else if (!isAnd && (keysActive & keycnt)) {
GBARaiseIRQ(gba, IRQ_KEYPAD, 0);
} else {
gba->keysLast = 0x400;
}
}

View File

@ -547,6 +547,9 @@ void GBAIOWrite(struct GBA* gba, uint32_t address, uint16_t value) {
// Interrupts and misc
case REG_KEYCNT:
value &= 0xC3FF;
if (gba->keysLast < 0x400) {
gba->keysLast &= gba->memory.io[address >> 1] | ~value;
}
gba->memory.io[address >> 1] = value;
GBATestKeypadIRQ(gba);
return;