all repos — mgba @ 62a198357b32e519b8468950c7c00c969d701178

mGBA Game Boy Advance Emulator

GBA Hardware: Add skeleton for e-Reader support
Vicki Pfau vi@endrift.com
Mon, 16 Oct 2017 22:42:50 -0700
commit

62a198357b32e519b8468950c7c00c969d701178

parent

5e30a7bfd8d5da214a1230803a23ac549c8c13ee

4 files changed, 97 insertions(+), 4 deletions(-)

jump to
M include/mgba/internal/gba/hardware.hinclude/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.csrc/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.csrc/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.csrc/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) {