mirror of https://github.com/mgba-emu/mgba.git
GBA I/O: Redo internal key input, enabling edge-based key IRQs
This commit is contained in:
parent
511a061ab0
commit
f696619b11
1
CHANGES
1
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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
27
src/gba/io.c
27
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;
|
||||
|
|
Loading…
Reference in New Issue