GBA Hardware: Add skeleton for e-Reader support
Vicki Pfau vi@endrift.com
Mon, 16 Oct 2017 22:42:50 -0700
4 files changed,
97 insertions(+),
4 deletions(-)
M
include/mgba/internal/gba/hardware.h
→
include/mgba/internal/gba/hardware.h
@@ -34,7 +34,8 @@ HW_LIGHT_SENSOR = 4,
HW_GYRO = 8, HW_TILT = 16, HW_GB_PLAYER = 32, - HW_GB_PLAYER_DETECTION = 64 + HW_GB_PLAYER_DETECTION = 64, + HW_EREADER = 128 }; enum GPIORegister {@@ -122,6 +123,12 @@ int gbpTxPosition;
struct mTimingEvent gbpNextEvent; struct GBAGBPKeyCallback gbpCallback; struct GBAGBPSIODriver gbpDriver; + + uint16_t eReaderData[44]; + uint16_t eReaderRegisterUnk; + uint16_t eReaderRegisterReset; + uint16_t eReaderRegisterControl; + uint16_t eReaderRegisterLed; }; void GBAHardwareInit(struct GBACartridgeHardware* gpio, uint16_t* gpioBase);@@ -140,6 +147,12 @@
struct GBAVideo; void GBAHardwarePlayerUpdate(struct GBA* gba); bool GBAHardwarePlayerCheckScreen(const struct GBAVideo* video); + +void GBAHardwareInitEReader(struct GBACartridgeHardware* hw); +void GBAHardwareEReaderWrite(struct GBACartridgeHardware* hw, uint32_t address, uint16_t value); +void GBAHardwareEReaderWriteFlash(struct GBACartridgeHardware* hw, uint32_t address, uint8_t value); +uint16_t GBAHardwareEReaderRead(struct GBACartridgeHardware* hw, uint32_t address); +uint8_t GBAHardwareEReaderReadFlash(struct GBACartridgeHardware* hw, uint32_t address); void GBARTCGenericSourceInit(struct GBARTCGenericSource* rtc, struct GBA* gba);
M
src/gba/hardware.c
→
src/gba/hardware.c
@@ -36,6 +36,8 @@ static uint16_t _gbpRead(struct mKeyCallback*);
static uint16_t _gbpSioWriteRegister(struct GBASIODriver* driver, uint32_t address, uint16_t value); static void _gbpSioProcessEvents(struct mTiming* timing, void* user, uint32_t cyclesLate); +static void _eReaderReset(struct GBACartridgeHardware* hw); + static const int RTC_BYTES[8] = { 0, // Force reset 0, // Empty@@ -589,6 +591,67 @@ GBARaiseIRQ(gbp->p->p, IRQ_SIO, cyclesLate);
} gbp->d.p->siocnt = GBASIONormalClearStart(gbp->d.p->siocnt); gbp->p->p->memory.io[REG_SIOCNT >> 1] = gbp->d.p->siocnt & ~0x0080; +} + +// == e-Reader + +void GBAHardwareInitEReader(struct GBACartridgeHardware* hw) { + hw->devices |= HW_EREADER; + _eReaderReset(hw); +} + +void GBAHardwareEReaderWrite(struct GBACartridgeHardware* hw, uint32_t address, uint16_t value) { + address &= 0x700FF; + switch (address >> 17) { + case 0: + hw->eReaderRegisterUnk = value & 0xF; + break; + case 1: + hw->eReaderRegisterReset = (value & 0x8A) | 4; + if (value & 2) { + _eReaderReset(hw); + } + break; + case 2: + mLOG(GBA_HW, GAME_ERROR, "e-Reader write to read-only registers: %05X:%04X", address, value); + break; + default: + mLOG(GBA_HW, STUB, "Unimplemented e-Reader write: %05X:%04X", address, value); + } +} + +void GBAHardwareEReaderWriteFlash(struct GBACartridgeHardware* hw, uint32_t address, uint8_t value) { + address &= 0xFFFF; + mLOG(GBA_HW, STUB, "Unimplemented e-Reader write to flash: %04X:%02X", address, value); +} + +uint16_t GBAHardwareEReaderRead(struct GBACartridgeHardware* hw, uint32_t address) { + address &= 0x700FF; + switch (address >> 17) { + case 0: + return hw->eReaderRegisterUnk; + case 1: + return hw->eReaderRegisterReset; + case 2: + if (address > 0x40088) { + return 0; + } + return hw->eReaderData[(address & 0xFE) >> 1]; + } + mLOG(GBA_HW, STUB, "Unimplemented e-Reader read: %05X", address); + return 0; +} + +uint8_t GBAHardwareEReaderReadFlash(struct GBACartridgeHardware* hw, uint32_t address) { + address &= 0xFFFF; + mLOG(GBA_HW, STUB, "Unimplemented e-Reader read from flash: %04X", address); + return 0; +} + +void _eReaderReset(struct GBACartridgeHardware* hw) { + memset(hw->eReaderData, 0, sizeof(hw->eReaderData)); + hw->eReaderRegisterUnk = 0; + hw->eReaderRegisterReset = 4; } // == Serialization
M
src/gba/memory.c
→
src/gba/memory.c
@@ -570,6 +570,8 @@ case REGION_CART2_EX:
wait = memory->waitstatesNonseq16[address >> BASE_OFFSET]; if (memory->savedata.type == SAVEDATA_EEPROM || memory->savedata.type == SAVEDATA_EEPROM512) { value = GBASavedataReadEEPROM(&memory->savedata); + } else if ((address & 0x0DFC0000) >= 0x0DF80000 && memory->hw.devices & HW_EREADER) { + value = GBAHardwareEReaderRead(&memory->hw, address); } else if ((address & (SIZE_CART0 - 1)) < memory->romSize) { LOAD_16(value, address & (SIZE_CART0 - 2), memory->rom); } else if (memory->mirroring && (address & memory->romMask) < memory->romSize) {@@ -683,7 +685,9 @@ }
if (gba->performingDMA == 1) { break; } - if (memory->savedata.type == SAVEDATA_SRAM) { + if (memory->hw.devices & HW_EREADER && (address & 0xE00FF80) >= 0xE00FF80) { + value = GBAHardwareEReaderReadFlash(&memory->hw, address); + } else if (memory->savedata.type == SAVEDATA_SRAM) { value = memory->savedata.data[address & (SIZE_CART_SRAM - 1)]; } else if (memory->savedata.type == SAVEDATA_FLASH512 || memory->savedata.type == SAVEDATA_FLASH1M) { value = GBASavedataReadFlash(&memory->savedata, address);@@ -911,7 +915,9 @@ }
mLOG(GBA_MEM, GAME_ERROR, "Bad cartridge Store16: 0x%08X", address); break; case REGION_CART2_EX: - if (memory->savedata.type == SAVEDATA_AUTODETECT) { + if ((address & 0x0DFC0000) >= 0x0DF80000 && memory->hw.devices & HW_EREADER) { + GBAHardwareEReaderWrite(&memory->hw, address, value); + } else if (memory->savedata.type == SAVEDATA_AUTODETECT) { mLOG(GBA_MEM, INFO, "Detected EEPROM savegame"); GBASavedataInitEEPROM(&memory->savedata); }@@ -992,7 +998,9 @@ mLOG(GBA_MEM, INFO, "Detected SRAM savegame");
GBASavedataInitSRAM(&memory->savedata); } } - if (memory->savedata.type == SAVEDATA_FLASH512 || memory->savedata.type == SAVEDATA_FLASH1M) { + if (memory->hw.devices & HW_EREADER && (address & 0xE00FF80) >= 0xE00FF80) { + GBAHardwareEReaderWriteFlash(&memory->hw, address, value); + } else if (memory->savedata.type == SAVEDATA_FLASH512 || memory->savedata.type == SAVEDATA_FLASH1M) { GBASavedataWriteFlash(&memory->savedata, address, value); } else if (memory->savedata.type == SAVEDATA_SRAM) { if (memory->vfame.cartType) {
M
src/gba/overrides.c
→
src/gba/overrides.c
@@ -50,6 +50,11 @@ // Drill Dozer
{ "V49J", SAVEDATA_SRAM, HW_RUMBLE, IDLE_LOOP_NONE, false }, { "V49E", SAVEDATA_SRAM, HW_RUMBLE, IDLE_LOOP_NONE, false }, + // e-Reader + { "PEAJ", SAVEDATA_FLASH1M, HW_EREADER, IDLE_LOOP_NONE }, + { "PSAJ", SAVEDATA_FLASH1M, HW_EREADER, IDLE_LOOP_NONE }, + { "PSAE", SAVEDATA_FLASH1M, HW_EREADER, IDLE_LOOP_NONE }, + // Final Fantasy Tactics Advance { "AFXE", SAVEDATA_FLASH512, HW_NONE, 0x8000428, false },@@ -326,6 +331,10 @@ }
if (override->hardware & HW_TILT) { GBAHardwareInitTilt(&gba->memory.hw); + } + + if (override->hardware & HW_EREADER) { + GBAHardwareInitEReader(&gba->memory.hw); } if (override->hardware & HW_GB_PLAYER_DETECTION) {