diff --git a/include/mgba/gba/interface.h b/include/mgba/gba/interface.h index aedd8895d..ff484bbc8 100644 --- a/include/mgba/gba/interface.h +++ b/include/mgba/gba/interface.h @@ -98,7 +98,7 @@ struct GBASIOBattlechipGate { void GBASIOBattlechipGateCreate(struct GBASIOBattlechipGate*); -void GBAEReaderQueueCard(struct GBA* gba, const void* data, size_t size); +void GBACartEReaderQueueCard(struct GBA* gba, const void* data, size_t size); CXX_GUARD_END diff --git a/include/mgba/internal/gba/cart/ereader.h b/include/mgba/internal/gba/cart/ereader.h new file mode 100644 index 000000000..0024d9ca0 --- /dev/null +++ b/include/mgba/internal/gba/cart/ereader.h @@ -0,0 +1,90 @@ +/* Copyright (c) 2013-2015 Jeffrey Pfau + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#ifndef GBA_EREADER_H +#define GBA_EREADER_H + +#include + +CXX_GUARD_START + +struct GBACartridgeHardware; + +#define EREADER_DOTCODE_STRIDE 1420 +#define EREADER_DOTCODE_SIZE (EREADER_DOTCODE_STRIDE * 40) +#define EREADER_CARDS_MAX 16 + +DECL_BITFIELD(EReaderControl0, uint8_t); +DECL_BIT(EReaderControl0, Data, 0); +DECL_BIT(EReaderControl0, Clock, 1); +DECL_BIT(EReaderControl0, Direction, 2); +DECL_BIT(EReaderControl0, LedEnable, 3); +DECL_BIT(EReaderControl0, Scan, 4); +DECL_BIT(EReaderControl0, Phi, 5); +DECL_BIT(EReaderControl0, PowerEnable, 6); +DECL_BITFIELD(EReaderControl1, uint8_t); +DECL_BIT(EReaderControl1, Scanline, 1); +DECL_BIT(EReaderControl1, Unk1, 4); +DECL_BIT(EReaderControl1, Voltage, 5); + +enum EReaderStateMachine { + EREADER_SERIAL_INACTIVE = 0, + EREADER_SERIAL_STARTING, + EREADER_SERIAL_BIT_0, + EREADER_SERIAL_BIT_1, + EREADER_SERIAL_BIT_2, + EREADER_SERIAL_BIT_3, + EREADER_SERIAL_BIT_4, + EREADER_SERIAL_BIT_5, + EREADER_SERIAL_BIT_6, + EREADER_SERIAL_BIT_7, + EREADER_SERIAL_END_BIT, +}; + +enum EReaderCommand { + EREADER_COMMAND_IDLE = 0, // TODO: Verify on hardware + EREADER_COMMAND_WRITE_DATA = 1, + EREADER_COMMAND_SET_INDEX = 0x22, + EREADER_COMMAND_READ_DATA = 0x23, +}; + +struct EReaderCard { + void* data; + size_t size; +}; + +struct GBA; +struct GBACartEReader { + struct GBA* p; + uint16_t data[44]; + uint8_t serial[92]; + uint16_t registerUnk; + uint16_t registerReset; + EReaderControl0 registerControl0; + EReaderControl1 registerControl1; + uint16_t registerLed; + + // TODO: Serialize these + enum EReaderStateMachine state; + enum EReaderCommand command; + uint8_t activeRegister; + uint8_t byte; + int scanX; + int scanY; + uint8_t* dots; + struct EReaderCard cards[EREADER_CARDS_MAX]; +}; + +void GBACartEReaderInit(struct GBACartEReader* ereader); +void GBACartEReaderDeinit(struct GBACartEReader* ereader); +void GBACartEReaderWrite(struct GBACartEReader* ereader, uint32_t address, uint16_t value); +void GBACartEReaderWriteFlash(struct GBACartEReader* ereader, uint32_t address, uint8_t value); +uint16_t GBACartEReaderRead(struct GBACartEReader* ereader, uint32_t address); +uint8_t GBACartEReaderReadFlash(struct GBACartEReader* ereader, uint32_t address); +void GBACartEReaderScan(struct GBACartEReader* ereader, const void* data, size_t size); + +CXX_GUARD_END + +#endif diff --git a/include/mgba/internal/gba/cart/gpio.h b/include/mgba/internal/gba/cart/gpio.h index 93fd359bd..53b610fe3 100644 --- a/include/mgba/internal/gba/cart/gpio.h +++ b/include/mgba/internal/gba/cart/gpio.h @@ -13,7 +13,6 @@ CXX_GUARD_START #include #include #include -#include mLOG_DECLARE_CATEGORY(GBA_HW); @@ -102,24 +101,6 @@ struct GBACartridgeHardware { uint16_t tiltX; uint16_t tiltY; int tiltState; - - uint16_t eReaderData[44]; - uint8_t eReaderSerial[92]; - uint16_t eReaderRegisterUnk; - uint16_t eReaderRegisterReset; - EReaderControl0 eReaderRegisterControl0; - EReaderControl1 eReaderRegisterControl1; - uint16_t eReaderRegisterLed; - - // TODO: Serialize these - enum EReaderStateMachine eReaderState; - enum EReaderCommand eReaderCommand; - uint8_t eReaderActiveRegister; - uint8_t eReaderByte; - int eReaderX; - int eReaderY; - uint8_t* eReaderDots; - struct EReaderCard eReaderCards[EREADER_CARDS_MAX]; }; void GBAHardwareInit(struct GBACartridgeHardware* gpio, uint16_t* gpioBase); diff --git a/include/mgba/internal/gba/memory.h b/include/mgba/internal/gba/memory.h index fac001de4..f7d4e1eb9 100644 --- a/include/mgba/internal/gba/memory.h +++ b/include/mgba/internal/gba/memory.h @@ -15,6 +15,7 @@ CXX_GUARD_START #include #include #include +#include #include #include #include @@ -108,6 +109,7 @@ struct GBAMemory { struct GBASavedata savedata; struct GBAVFameCart vfame; struct GBAMatrix matrix; + struct GBACartEReader ereader; size_t romSize; uint32_t romMask; uint16_t romID; diff --git a/src/gba/cart/ereader.c b/src/gba/cart/ereader.c index d79bd8dbb..450bc4726 100644 --- a/src/gba/cart/ereader.c +++ b/src/gba/cart/ereader.c @@ -12,11 +12,12 @@ #define EREADER_BLOCK_SIZE 40 -static void _eReaderReset(struct GBACartridgeHardware* hw); -static void _eReaderWriteControl0(struct GBACartridgeHardware* hw, uint8_t value); -static void _eReaderWriteControl1(struct GBACartridgeHardware* hw, uint8_t value); -static void _eReaderReadData(struct GBACartridgeHardware* hw); +static void _eReaderReset(struct GBACartEReader* ereader); +static void _eReaderWriteControl0(struct GBACartEReader* ereader, uint8_t value); +static void _eReaderWriteControl1(struct GBACartEReader* ereader, uint8_t value); +static void _eReaderReadData(struct GBACartEReader* ereader); static void _eReaderReedSolomon(const uint8_t* input, uint8_t* output); +static void _eReaderScanCard(struct GBACartEReader* ereader); const int EREADER_NYBBLE_5BIT[16][5] = { { 0, 0, 0, 0, 0 }, @@ -161,30 +162,46 @@ static const uint8_t RS_GG[] = { }; -void GBAHardwareInitEReader(struct GBACartridgeHardware* hw) { - hw->devices |= HW_EREADER; - _eReaderReset(hw); +void GBACartEReaderInit(struct GBACartEReader* ereader) { + ereader->p->memory.hw.devices |= HW_EREADER; + _eReaderReset(ereader); - if (hw->p->memory.savedata.data[0xD000] == 0xFF) { - memset(&hw->p->memory.savedata.data[0xD000], 0, 0x1000); - memcpy(&hw->p->memory.savedata.data[0xD000], EREADER_CALIBRATION_TEMPLATE, sizeof(EREADER_CALIBRATION_TEMPLATE)); + if (ereader->p->memory.savedata.data[0xD000] == 0xFF) { + memset(&ereader->p->memory.savedata.data[0xD000], 0, 0x1000); + memcpy(&ereader->p->memory.savedata.data[0xD000], EREADER_CALIBRATION_TEMPLATE, sizeof(EREADER_CALIBRATION_TEMPLATE)); } - if (hw->p->memory.savedata.data[0xE000] == 0xFF) { - memset(&hw->p->memory.savedata.data[0xE000], 0, 0x1000); - memcpy(&hw->p->memory.savedata.data[0xE000], EREADER_CALIBRATION_TEMPLATE, sizeof(EREADER_CALIBRATION_TEMPLATE)); + if (ereader->p->memory.savedata.data[0xE000] == 0xFF) { + memset(&ereader->p->memory.savedata.data[0xE000], 0, 0x1000); + memcpy(&ereader->p->memory.savedata.data[0xE000], EREADER_CALIBRATION_TEMPLATE, sizeof(EREADER_CALIBRATION_TEMPLATE)); } } -void GBAHardwareEReaderWrite(struct GBACartridgeHardware* hw, uint32_t address, uint16_t value) { +void GBACartEReaderDeinit(struct GBACartEReader* ereader) { + if (ereader->dots) { + mappedMemoryFree(ereader->dots, EREADER_DOTCODE_SIZE); + ereader->dots = NULL; + } + int i; + for (i = 0; i < EREADER_CARDS_MAX; ++i) { + if (!ereader->cards[i].data) { + continue; + } + free(ereader->cards[i].data); + ereader->cards[i].data = NULL; + ereader->cards[i].size = 0; + } +} + +void GBACartEReaderWrite(struct GBACartEReader* ereader, uint32_t address, uint16_t value) { address &= 0x700FF; switch (address >> 17) { case 0: - hw->eReaderRegisterUnk = value & 0xF; + ereader->registerUnk = value & 0xF; break; case 1: - hw->eReaderRegisterReset = (value & 0x8A) | 4; + ereader->registerReset = (value & 0x8A) | 4; if (value & 2) { - _eReaderReset(hw); + _eReaderReset(ereader); } break; case 2: @@ -195,54 +212,54 @@ void GBAHardwareEReaderWrite(struct GBACartridgeHardware* hw, uint32_t address, } } -void GBAHardwareEReaderWriteFlash(struct GBACartridgeHardware* hw, uint32_t address, uint8_t value) { +void GBACartEReaderWriteFlash(struct GBACartEReader* ereader, uint32_t address, uint8_t value) { address &= 0xFFFF; switch (address) { case 0xFFB0: - _eReaderWriteControl0(hw, value); + _eReaderWriteControl0(ereader, value); break; case 0xFFB1: - _eReaderWriteControl1(hw, value); + _eReaderWriteControl1(ereader, value); break; case 0xFFB2: - hw->eReaderRegisterLed &= 0xFF00; - hw->eReaderRegisterLed |= value; + ereader->registerLed &= 0xFF00; + ereader->registerLed |= value; break; case 0xFFB3: - hw->eReaderRegisterLed &= 0x00FF; - hw->eReaderRegisterLed |= value << 8; + ereader->registerLed &= 0x00FF; + ereader->registerLed |= value << 8; break; default: mLOG(GBA_HW, STUB, "Unimplemented e-Reader write to flash: %04X:%02X", address, value); } } -uint16_t GBAHardwareEReaderRead(struct GBACartridgeHardware* hw, uint32_t address) { +uint16_t GBACartEReaderRead(struct GBACartEReader* ereader, uint32_t address) { address &= 0x700FF; uint16_t value; switch (address >> 17) { case 0: - return hw->eReaderRegisterUnk; + return ereader->registerUnk; case 1: - return hw->eReaderRegisterReset; + return ereader->registerReset; case 2: if (address > 0x40088) { return 0; } - LOAD_16(value, address & 0xFE, hw->eReaderData); + LOAD_16(value, address & 0xFE, ereader->data); return value; } mLOG(GBA_HW, STUB, "Unimplemented e-Reader read: %05X", address); return 0; } -uint8_t GBAHardwareEReaderReadFlash(struct GBACartridgeHardware* hw, uint32_t address) { +uint8_t GBACartEReaderReadFlash(struct GBACartEReader* ereader, uint32_t address) { address &= 0xFFFF; switch (address) { case 0xFFB0: - return hw->eReaderRegisterControl0; + return ereader->registerControl0; case 0xFFB1: - return hw->eReaderRegisterControl1; + return ereader->registerControl1; default: mLOG(GBA_HW, STUB, "Unimplemented e-Reader read from flash: %04X", address); return 0; @@ -329,12 +346,12 @@ static void _eReaderReedSolomon(const uint8_t* input, uint8_t* output) { } } -void GBAHardwareEReaderScan(struct GBACartridgeHardware* hw, const void* data, size_t size) { - if (!hw->eReaderDots) { - hw->eReaderDots = anonymousMemoryMap(EREADER_DOTCODE_SIZE); +void GBACartEReaderScan(struct GBACartEReader* ereader, const void* data, size_t size) { + if (!ereader->dots) { + ereader->dots = anonymousMemoryMap(EREADER_DOTCODE_SIZE); } - hw->eReaderX = -24; - memset(hw->eReaderDots, 0, EREADER_DOTCODE_SIZE); + ereader->scanX = -24; + memset(ereader->dots, 0, EREADER_DOTCODE_SIZE); uint8_t blockRS[44][0x10]; uint8_t block0[0x30]; @@ -386,7 +403,7 @@ void GBAHardwareEReaderScan(struct GBACartridgeHardware* hw, const void* data, s size_t x; for (i = 0; i < 40; ++i) { const uint8_t* line = &cdata[(i + 2) * blocks]; - uint8_t* origin = &hw->eReaderDots[EREADER_DOTCODE_STRIDE * i + 200]; + uint8_t* origin = &ereader->dots[EREADER_DOTCODE_STRIDE * i + 200]; for (x = 0; x < blocks; ++x) { uint8_t byte = line[x]; if (x == 123) { @@ -406,7 +423,7 @@ void GBAHardwareEReaderScan(struct GBACartridgeHardware* hw, const void* data, s } for (i = 0; i < blocks + 1; ++i) { - uint8_t* origin = &hw->eReaderDots[35 * i + 200]; + uint8_t* origin = &ereader->dots[35 * i + 200]; _eReaderAnchor(&origin[EREADER_DOTCODE_STRIDE * 0]); _eReaderAnchor(&origin[EREADER_DOTCODE_STRIDE * 35]); _eReaderAddress(origin, base + i); @@ -461,7 +478,7 @@ void GBAHardwareEReaderScan(struct GBACartridgeHardware* hw, const void* data, s size_t byteOffset = 0; for (i = 0; i < blocks; ++i) { uint8_t block[1040]; - uint8_t* origin = &hw->eReaderDots[35 * i + 200]; + uint8_t* origin = &ereader->dots[35 * i + 200]; _eReaderAlignment(&origin[EREADER_DOTCODE_STRIDE * 2]); _eReaderAlignment(&origin[EREADER_DOTCODE_STRIDE * 37]); @@ -532,155 +549,132 @@ void GBAHardwareEReaderScan(struct GBACartridgeHardware* hw, const void* data, s } } -void _eReaderReset(struct GBACartridgeHardware* hw) { - memset(hw->eReaderData, 0, sizeof(hw->eReaderData)); - hw->eReaderRegisterUnk = 0; - hw->eReaderRegisterReset = 4; - hw->eReaderRegisterControl0 = 0; - hw->eReaderRegisterControl1 = 0x80; - hw->eReaderRegisterLed = 0; - hw->eReaderState = 0; - hw->eReaderActiveRegister = 0; +void _eReaderReset(struct GBACartEReader* ereader) { + memset(ereader->data, 0, sizeof(ereader->data)); + ereader->registerUnk = 0; + ereader->registerReset = 4; + ereader->registerControl0 = 0; + ereader->registerControl1 = 0x80; + ereader->registerLed = 0; + ereader->state = 0; + ereader->activeRegister = 0; } -void _eReaderWriteControl0(struct GBACartridgeHardware* hw, uint8_t value) { +void _eReaderWriteControl0(struct GBACartEReader* ereader, uint8_t value) { EReaderControl0 control = value & 0x7F; - EReaderControl0 oldControl = hw->eReaderRegisterControl0; - if (hw->eReaderState == EREADER_SERIAL_INACTIVE) { + EReaderControl0 oldControl = ereader->registerControl0; + if (ereader->state == EREADER_SERIAL_INACTIVE) { if (EReaderControl0IsClock(oldControl) && EReaderControl0IsData(oldControl) && !EReaderControl0IsData(control)) { - hw->eReaderState = EREADER_SERIAL_STARTING; + ereader->state = EREADER_SERIAL_STARTING; } } else if (EReaderControl0IsClock(oldControl) && !EReaderControl0IsData(oldControl) && EReaderControl0IsData(control)) { - hw->eReaderState = EREADER_SERIAL_INACTIVE; + ereader->state = EREADER_SERIAL_INACTIVE; - } else if (hw->eReaderState == EREADER_SERIAL_STARTING) { + } else if (ereader->state == EREADER_SERIAL_STARTING) { if (EReaderControl0IsClock(oldControl) && !EReaderControl0IsData(oldControl) && !EReaderControl0IsClock(control)) { - hw->eReaderState = EREADER_SERIAL_BIT_0; - hw->eReaderCommand = EREADER_COMMAND_IDLE; + ereader->state = EREADER_SERIAL_BIT_0; + ereader->command = EREADER_COMMAND_IDLE; } } else if (EReaderControl0IsClock(oldControl) && !EReaderControl0IsClock(control)) { mLOG(GBA_HW, DEBUG, "[e-Reader] Serial falling edge: %c %i", EReaderControl0IsDirection(control) ? '>' : '<', EReaderControl0GetData(control)); // TODO: Improve direction control if (EReaderControl0IsDirection(control)) { - hw->eReaderByte |= EReaderControl0GetData(control) << (7 - (hw->eReaderState - EREADER_SERIAL_BIT_0)); - ++hw->eReaderState; - if (hw->eReaderState == EREADER_SERIAL_END_BIT) { - mLOG(GBA_HW, DEBUG, "[e-Reader] Wrote serial byte: %02x", hw->eReaderByte); - switch (hw->eReaderCommand) { + ereader->byte |= EReaderControl0GetData(control) << (7 - (ereader->state - EREADER_SERIAL_BIT_0)); + ++ereader->state; + if (ereader->state == EREADER_SERIAL_END_BIT) { + mLOG(GBA_HW, DEBUG, "[e-Reader] Wrote serial byte: %02x", ereader->byte); + switch (ereader->command) { case EREADER_COMMAND_IDLE: - hw->eReaderCommand = hw->eReaderByte; + ereader->command = ereader->byte; break; case EREADER_COMMAND_SET_INDEX: - hw->eReaderActiveRegister = hw->eReaderByte; - hw->eReaderCommand = EREADER_COMMAND_WRITE_DATA; + ereader->activeRegister = ereader->byte; + ereader->command = EREADER_COMMAND_WRITE_DATA; break; case EREADER_COMMAND_WRITE_DATA: - switch (hw->eReaderActiveRegister & 0x7F) { + switch (ereader->activeRegister & 0x7F) { case 0: case 0x57: case 0x58: case 0x59: case 0x5A: // Read-only - mLOG(GBA_HW, GAME_ERROR, "Writing to read-only e-Reader serial register: %02X", hw->eReaderActiveRegister); + mLOG(GBA_HW, GAME_ERROR, "Writing to read-only e-Reader serial register: %02X", ereader->activeRegister); break; default: - if ((hw->eReaderActiveRegister & 0x7F) > 0x5A) { - mLOG(GBA_HW, GAME_ERROR, "Writing to non-existent e-Reader serial register: %02X", hw->eReaderActiveRegister); + if ((ereader->activeRegister & 0x7F) > 0x5A) { + mLOG(GBA_HW, GAME_ERROR, "Writing to non-existent e-Reader serial register: %02X", ereader->activeRegister); break; } - hw->eReaderSerial[hw->eReaderActiveRegister & 0x7F] = hw->eReaderByte; + ereader->serial[ereader->activeRegister & 0x7F] = ereader->byte; break; } - ++hw->eReaderActiveRegister; + ++ereader->activeRegister; break; default: - mLOG(GBA_HW, ERROR, "Hit undefined state %02X in e-Reader state machine", hw->eReaderCommand); + mLOG(GBA_HW, ERROR, "Hit undefined state %02X in e-Reader state machine", ereader->command); break; } - hw->eReaderState = EREADER_SERIAL_BIT_0; - hw->eReaderByte = 0; + ereader->state = EREADER_SERIAL_BIT_0; + ereader->byte = 0; } - } else if (hw->eReaderCommand == EREADER_COMMAND_READ_DATA) { - int bit = hw->eReaderSerial[hw->eReaderActiveRegister & 0x7F] >> (7 - (hw->eReaderState - EREADER_SERIAL_BIT_0)); + } else if (ereader->command == EREADER_COMMAND_READ_DATA) { + int bit = ereader->serial[ereader->activeRegister & 0x7F] >> (7 - (ereader->state - EREADER_SERIAL_BIT_0)); control = EReaderControl0SetData(control, bit); - ++hw->eReaderState; - if (hw->eReaderState == EREADER_SERIAL_END_BIT) { - ++hw->eReaderActiveRegister; - mLOG(GBA_HW, DEBUG, "[e-Reader] Read serial byte: %02x", hw->eReaderSerial[hw->eReaderActiveRegister & 0x7F]); + ++ereader->state; + if (ereader->state == EREADER_SERIAL_END_BIT) { + ++ereader->activeRegister; + mLOG(GBA_HW, DEBUG, "[e-Reader] Read serial byte: %02x", ereader->serial[ereader->activeRegister & 0x7F]); } } } else if (!EReaderControl0IsDirection(control)) { // Clear the error bit control = EReaderControl0ClearData(control); } - hw->eReaderRegisterControl0 = control; + ereader->registerControl0 = control; if (!EReaderControl0IsScan(oldControl) && EReaderControl0IsScan(control)) { - if (hw->eReaderX > 1000) { - if (hw->eReaderDots) { - memset(hw->eReaderDots, 0, EREADER_DOTCODE_SIZE); - } - int i; - for (i = 0; i < EREADER_CARDS_MAX; ++i) { - if (!hw->eReaderCards[i].data) { - continue; - } - GBAHardwareEReaderScan(hw, hw->eReaderCards[i].data, hw->eReaderCards[i].size); - free(hw->eReaderCards[i].data); - hw->eReaderCards[i].data = NULL; - hw->eReaderCards[i].size = 0; - break; - } + if (ereader->scanX > 1000) { + _eReaderScanCard(ereader); } - hw->eReaderX = 0; - hw->eReaderY = 0; - } else if (EReaderControl0IsLedEnable(control) && EReaderControl0IsScan(control) && !EReaderControl1IsScanline(hw->eReaderRegisterControl1)) { - _eReaderReadData(hw); + ereader->scanX = 0; + ereader->scanY = 0; + } else if (EReaderControl0IsLedEnable(control) && EReaderControl0IsScan(control) && !EReaderControl1IsScanline(ereader->registerControl1)) { + _eReaderReadData(ereader); } mLOG(GBA_HW, STUB, "Unimplemented e-Reader Control0 write: %02X", value); } -void _eReaderWriteControl1(struct GBACartridgeHardware* hw, uint8_t value) { +void _eReaderWriteControl1(struct GBACartEReader* ereader, uint8_t value) { EReaderControl1 control = (value & 0x32) | 0x80; - hw->eReaderRegisterControl1 = control; - if (EReaderControl0IsScan(hw->eReaderRegisterControl0) && !EReaderControl1IsScanline(control)) { - ++hw->eReaderY; - if (hw->eReaderY == (hw->eReaderSerial[0x15] | (hw->eReaderSerial[0x14] << 8))) { - hw->eReaderY = 0; - if (hw->eReaderX < 3400) { - hw->eReaderX += 210; + ereader->registerControl1 = control; + if (EReaderControl0IsScan(ereader->registerControl0) && !EReaderControl1IsScanline(control)) { + ++ereader->scanY; + if (ereader->scanY == (ereader->serial[0x15] | (ereader->serial[0x14] << 8))) { + ereader->scanY = 0; + if (ereader->scanX < 3400) { + ereader->scanX += 210; } } - _eReaderReadData(hw); + _eReaderReadData(ereader); } mLOG(GBA_HW, STUB, "Unimplemented e-Reader Control1 write: %02X", value); } -void _eReaderReadData(struct GBACartridgeHardware* hw) { - memset(hw->eReaderData, 0, EREADER_BLOCK_SIZE); - if (!hw->eReaderDots) { - int i; - for (i = 0; i < EREADER_CARDS_MAX; ++i) { - if (!hw->eReaderCards[i].data) { - continue; - } - GBAHardwareEReaderScan(hw, hw->eReaderCards[i].data, hw->eReaderCards[i].size); - free(hw->eReaderCards[i].data); - hw->eReaderCards[i].data = NULL; - hw->eReaderCards[i].size = 0; - break; - } +void _eReaderReadData(struct GBACartEReader* ereader) { + memset(ereader->data, 0, EREADER_BLOCK_SIZE); + if (!ereader->dots) { + _eReaderScanCard(ereader); } - if (hw->eReaderDots) { - int y = hw->eReaderY - 10; + if (ereader->dots) { + int y = ereader->scanY - 10; if (y < 0 || y >= 120) { - memset(hw->eReaderData, 0, EREADER_BLOCK_SIZE); + memset(ereader->data, 0, EREADER_BLOCK_SIZE); } else { int i; - uint8_t* origin = &hw->eReaderDots[EREADER_DOTCODE_STRIDE * (y / 3) + 16]; + uint8_t* origin = &ereader->dots[EREADER_DOTCODE_STRIDE * (y / 3) + 16]; for (i = 0; i < 20; ++i) { uint16_t word = 0; - int x = hw->eReaderX + i * 16; + int x = ereader->scanX + i * 16; word |= origin[(x + 0) / 3] << 8; word |= origin[(x + 1) / 3] << 9; word |= origin[(x + 2) / 3] << 10; @@ -697,29 +691,48 @@ void _eReaderReadData(struct GBACartridgeHardware* hw) { word |= origin[(x + 13) / 3] << 5; word |= origin[(x + 14) / 3] << 6; word |= origin[(x + 15) / 3] << 7; - STORE_16(word, (19 - i) << 1, hw->eReaderData); + STORE_16(word, (19 - i) << 1, ereader->data); } } } - hw->eReaderRegisterControl1 = EReaderControl1FillScanline(hw->eReaderRegisterControl1); - if (EReaderControl0IsLedEnable(hw->eReaderRegisterControl0)) { - uint16_t led = hw->eReaderRegisterLed * 2; + ereader->registerControl1 = EReaderControl1FillScanline(ereader->registerControl1); + if (EReaderControl0IsLedEnable(ereader->registerControl0)) { + uint16_t led = ereader->registerLed * 2; if (led > 0x4000) { led = 0x4000; } - GBARaiseIRQ(hw->p, IRQ_GAMEPAK, -led); + GBARaiseIRQ(ereader->p, IRQ_GAMEPAK, -led); } } -void GBAEReaderQueueCard(struct GBA* gba, const void* data, size_t size) { + +void _eReaderScanCard(struct GBACartEReader* ereader) { + if (ereader->dots) { + memset(ereader->dots, 0, EREADER_DOTCODE_SIZE); + } int i; for (i = 0; i < EREADER_CARDS_MAX; ++i) { - if (gba->memory.hw.eReaderCards[i].data) { + if (!ereader->cards[i].data) { continue; } - gba->memory.hw.eReaderCards[i].data = malloc(size); - memcpy(gba->memory.hw.eReaderCards[i].data, data, size); - gba->memory.hw.eReaderCards[i].size = size; + GBACartEReaderScan(ereader, ereader->cards[i].data, ereader->cards[i].size); + free(ereader->cards[i].data); + ereader->cards[i].data = NULL; + ereader->cards[i].size = 0; + break; + } +} + +void GBACartEReaderQueueCard(struct GBA* gba, const void* data, size_t size) { + struct GBACartEReader* ereader = &gba->memory.ereader; + int i; + for (i = 0; i < EREADER_CARDS_MAX; ++i) { + if (ereader->cards[i].data) { + continue; + } + ereader->cards[i].data = malloc(size); + memcpy(ereader->cards[i].data, data, size); + ereader->cards[i].size = size; return; } } diff --git a/src/gba/cart/gpio.c b/src/gba/cart/gpio.c index 92196b243..c3d9536d4 100644 --- a/src/gba/cart/gpio.c +++ b/src/gba/cart/gpio.c @@ -46,8 +46,6 @@ static const int RTC_BYTES[8] = { void GBAHardwareInit(struct GBACartridgeHardware* hw, uint16_t* base) { hw->gpioBase = base; - hw->eReaderDots = NULL; - memset(hw->eReaderCards, 0, sizeof(hw->eReaderCards)); GBAHardwareClear(hw); } @@ -56,20 +54,6 @@ void GBAHardwareClear(struct GBACartridgeHardware* hw) { hw->readWrite = GPIO_WRITE_ONLY; hw->pinState = 0; hw->direction = 0; - - if (hw->eReaderDots) { - mappedMemoryFree(hw->eReaderDots, EREADER_DOTCODE_SIZE); - hw->eReaderDots = NULL; - } - int i; - for (i = 0; i < EREADER_CARDS_MAX; ++i) { - if (!hw->eReaderCards[i].data) { - continue; - } - free(hw->eReaderCards[i].data); - hw->eReaderCards[i].data = NULL; - hw->eReaderCards[i].size = 0; - } } void GBAHardwareGPIOWrite(struct GBACartridgeHardware* hw, uint32_t address, uint16_t value) { diff --git a/src/gba/memory.c b/src/gba/memory.c index 05cec7c67..f650881b1 100644 --- a/src/gba/memory.c +++ b/src/gba/memory.c @@ -94,6 +94,10 @@ void GBAMemoryInit(struct GBA* gba) { GBADMAInit(gba); GBAVFameInit(&gba->memory.vfame); + + gba->memory.ereader.p = gba; + gba->memory.ereader.dots = NULL; + memset(gba->memory.ereader.cards, 0, sizeof(gba->memory.ereader.cards)); } void GBAMemoryDeinit(struct GBA* gba) { @@ -107,6 +111,8 @@ void GBAMemoryDeinit(struct GBA* gba) { if (gba->memory.agbPrintBufferBackup) { mappedMemoryFree(gba->memory.agbPrintBufferBackup, SIZE_AGB_PRINT); } + + GBACartEReaderDeinit(&gba->memory.ereader); } void GBAMemoryReset(struct GBA* gba) { @@ -588,7 +594,7 @@ uint32_t GBALoad16(struct ARMCore* cpu, uint32_t address, int* cycleCounter) { 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); + value = GBACartEReaderRead(&memory->ereader, 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) { @@ -704,7 +710,7 @@ uint32_t GBALoad8(struct ARMCore* cpu, uint32_t address, int* cycleCounter) { break; } if (memory->hw.devices & HW_EREADER && (address & 0xE00FF80) >= 0xE00FF80) { - value = GBAHardwareEReaderReadFlash(&memory->hw, address); + value = GBACartEReaderReadFlash(&memory->ereader, 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) { @@ -965,7 +971,7 @@ void GBAStore16(struct ARMCore* cpu, uint32_t address, int16_t value, int* cycle break; case REGION_CART2_EX: if ((address & 0x0DFC0000) >= 0x0DF80000 && memory->hw.devices & HW_EREADER) { - GBAHardwareEReaderWrite(&memory->hw, address, value); + GBACartEReaderWrite(&memory->ereader, address, value); break; } else if (memory->savedata.type == SAVEDATA_AUTODETECT) { mLOG(GBA_MEM, INFO, "Detected EEPROM savegame"); @@ -1052,7 +1058,7 @@ void GBAStore8(struct ARMCore* cpu, uint32_t address, int8_t value, int* cycleCo } } if (memory->hw.devices & HW_EREADER && (address & 0xE00FF80) >= 0xE00FF80) { - GBAHardwareEReaderWriteFlash(&memory->hw, address, value); + GBACartEReaderWriteFlash(&memory->ereader, 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) { diff --git a/src/gba/overrides.c b/src/gba/overrides.c index 86446fbab..630662d31 100644 --- a/src/gba/overrides.c +++ b/src/gba/overrides.c @@ -6,6 +6,7 @@ #include #include +#include #include #include @@ -347,7 +348,7 @@ void GBAOverrideApply(struct GBA* gba, const struct GBACartridgeOverride* overri } if (override->hardware & HW_EREADER) { - GBAHardwareInitEReader(&gba->memory.hw); + GBACartEReaderInit(&gba->memory.ereader); } if (override->hardware & HW_GB_PLAYER_DETECTION) { diff --git a/src/platform/qt/CoreController.cpp b/src/platform/qt/CoreController.cpp index 81b7b3ad5..514aa84ab 100644 --- a/src/platform/qt/CoreController.cpp +++ b/src/platform/qt/CoreController.cpp @@ -812,7 +812,7 @@ void CoreController::scanCard(const QString& path) { mCoreThreadRunFunction(&m_threadContext, [](mCoreThread* thread) { CoreController* controller = static_cast(thread->userData); - GBAEReaderQueueCard(static_cast(thread->core->board), controller->m_eReaderData.constData(), controller->m_eReaderData.size()); + GBACartEReaderQueueCard(static_cast(thread->core->board), controller->m_eReaderData.constData(), controller->m_eReaderData.size()); }); #endif }