mirror of https://github.com/mgba-emu/mgba.git
GBA e-Reader: Refactor out of GPIO code
This commit is contained in:
parent
bc16a1bfe3
commit
23b5a458b8
|
@ -98,7 +98,7 @@ struct GBASIOBattlechipGate {
|
||||||
|
|
||||||
void GBASIOBattlechipGateCreate(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
|
CXX_GUARD_END
|
||||||
|
|
||||||
|
|
|
@ -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 <mgba-util/common.h>
|
||||||
|
|
||||||
|
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
|
|
@ -13,7 +13,6 @@ CXX_GUARD_START
|
||||||
#include <mgba/core/log.h>
|
#include <mgba/core/log.h>
|
||||||
#include <mgba/core/timing.h>
|
#include <mgba/core/timing.h>
|
||||||
#include <mgba/gba/interface.h>
|
#include <mgba/gba/interface.h>
|
||||||
#include <mgba/internal/gba/cart/ereader.h>
|
|
||||||
|
|
||||||
mLOG_DECLARE_CATEGORY(GBA_HW);
|
mLOG_DECLARE_CATEGORY(GBA_HW);
|
||||||
|
|
||||||
|
@ -102,24 +101,6 @@ struct GBACartridgeHardware {
|
||||||
uint16_t tiltX;
|
uint16_t tiltX;
|
||||||
uint16_t tiltY;
|
uint16_t tiltY;
|
||||||
int tiltState;
|
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);
|
void GBAHardwareInit(struct GBACartridgeHardware* gpio, uint16_t* gpioBase);
|
||||||
|
|
|
@ -15,6 +15,7 @@ CXX_GUARD_START
|
||||||
#include <mgba/internal/arm/arm.h>
|
#include <mgba/internal/arm/arm.h>
|
||||||
#include <mgba/internal/gba/dma.h>
|
#include <mgba/internal/gba/dma.h>
|
||||||
#include <mgba/internal/gba/savedata.h>
|
#include <mgba/internal/gba/savedata.h>
|
||||||
|
#include <mgba/internal/gba/cart/ereader.h>
|
||||||
#include <mgba/internal/gba/cart/gpio.h>
|
#include <mgba/internal/gba/cart/gpio.h>
|
||||||
#include <mgba/internal/gba/cart/matrix.h>
|
#include <mgba/internal/gba/cart/matrix.h>
|
||||||
#include <mgba/internal/gba/cart/vfame.h>
|
#include <mgba/internal/gba/cart/vfame.h>
|
||||||
|
@ -108,6 +109,7 @@ struct GBAMemory {
|
||||||
struct GBASavedata savedata;
|
struct GBASavedata savedata;
|
||||||
struct GBAVFameCart vfame;
|
struct GBAVFameCart vfame;
|
||||||
struct GBAMatrix matrix;
|
struct GBAMatrix matrix;
|
||||||
|
struct GBACartEReader ereader;
|
||||||
size_t romSize;
|
size_t romSize;
|
||||||
uint32_t romMask;
|
uint32_t romMask;
|
||||||
uint16_t romID;
|
uint16_t romID;
|
||||||
|
|
|
@ -12,11 +12,12 @@
|
||||||
|
|
||||||
#define EREADER_BLOCK_SIZE 40
|
#define EREADER_BLOCK_SIZE 40
|
||||||
|
|
||||||
static void _eReaderReset(struct GBACartridgeHardware* hw);
|
static void _eReaderReset(struct GBACartEReader* ereader);
|
||||||
static void _eReaderWriteControl0(struct GBACartridgeHardware* hw, uint8_t value);
|
static void _eReaderWriteControl0(struct GBACartEReader* ereader, uint8_t value);
|
||||||
static void _eReaderWriteControl1(struct GBACartridgeHardware* hw, uint8_t value);
|
static void _eReaderWriteControl1(struct GBACartEReader* ereader, uint8_t value);
|
||||||
static void _eReaderReadData(struct GBACartridgeHardware* hw);
|
static void _eReaderReadData(struct GBACartEReader* ereader);
|
||||||
static void _eReaderReedSolomon(const uint8_t* input, uint8_t* output);
|
static void _eReaderReedSolomon(const uint8_t* input, uint8_t* output);
|
||||||
|
static void _eReaderScanCard(struct GBACartEReader* ereader);
|
||||||
|
|
||||||
const int EREADER_NYBBLE_5BIT[16][5] = {
|
const int EREADER_NYBBLE_5BIT[16][5] = {
|
||||||
{ 0, 0, 0, 0, 0 },
|
{ 0, 0, 0, 0, 0 },
|
||||||
|
@ -161,30 +162,46 @@ static const uint8_t RS_GG[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
void GBAHardwareInitEReader(struct GBACartridgeHardware* hw) {
|
void GBACartEReaderInit(struct GBACartEReader* ereader) {
|
||||||
hw->devices |= HW_EREADER;
|
ereader->p->memory.hw.devices |= HW_EREADER;
|
||||||
_eReaderReset(hw);
|
_eReaderReset(ereader);
|
||||||
|
|
||||||
if (hw->p->memory.savedata.data[0xD000] == 0xFF) {
|
if (ereader->p->memory.savedata.data[0xD000] == 0xFF) {
|
||||||
memset(&hw->p->memory.savedata.data[0xD000], 0, 0x1000);
|
memset(&ereader->p->memory.savedata.data[0xD000], 0, 0x1000);
|
||||||
memcpy(&hw->p->memory.savedata.data[0xD000], EREADER_CALIBRATION_TEMPLATE, sizeof(EREADER_CALIBRATION_TEMPLATE));
|
memcpy(&ereader->p->memory.savedata.data[0xD000], EREADER_CALIBRATION_TEMPLATE, sizeof(EREADER_CALIBRATION_TEMPLATE));
|
||||||
}
|
}
|
||||||
if (hw->p->memory.savedata.data[0xE000] == 0xFF) {
|
if (ereader->p->memory.savedata.data[0xE000] == 0xFF) {
|
||||||
memset(&hw->p->memory.savedata.data[0xE000], 0, 0x1000);
|
memset(&ereader->p->memory.savedata.data[0xE000], 0, 0x1000);
|
||||||
memcpy(&hw->p->memory.savedata.data[0xE000], EREADER_CALIBRATION_TEMPLATE, sizeof(EREADER_CALIBRATION_TEMPLATE));
|
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;
|
address &= 0x700FF;
|
||||||
switch (address >> 17) {
|
switch (address >> 17) {
|
||||||
case 0:
|
case 0:
|
||||||
hw->eReaderRegisterUnk = value & 0xF;
|
ereader->registerUnk = value & 0xF;
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
hw->eReaderRegisterReset = (value & 0x8A) | 4;
|
ereader->registerReset = (value & 0x8A) | 4;
|
||||||
if (value & 2) {
|
if (value & 2) {
|
||||||
_eReaderReset(hw);
|
_eReaderReset(ereader);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 2:
|
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;
|
address &= 0xFFFF;
|
||||||
switch (address) {
|
switch (address) {
|
||||||
case 0xFFB0:
|
case 0xFFB0:
|
||||||
_eReaderWriteControl0(hw, value);
|
_eReaderWriteControl0(ereader, value);
|
||||||
break;
|
break;
|
||||||
case 0xFFB1:
|
case 0xFFB1:
|
||||||
_eReaderWriteControl1(hw, value);
|
_eReaderWriteControl1(ereader, value);
|
||||||
break;
|
break;
|
||||||
case 0xFFB2:
|
case 0xFFB2:
|
||||||
hw->eReaderRegisterLed &= 0xFF00;
|
ereader->registerLed &= 0xFF00;
|
||||||
hw->eReaderRegisterLed |= value;
|
ereader->registerLed |= value;
|
||||||
break;
|
break;
|
||||||
case 0xFFB3:
|
case 0xFFB3:
|
||||||
hw->eReaderRegisterLed &= 0x00FF;
|
ereader->registerLed &= 0x00FF;
|
||||||
hw->eReaderRegisterLed |= value << 8;
|
ereader->registerLed |= value << 8;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
mLOG(GBA_HW, STUB, "Unimplemented e-Reader write to flash: %04X:%02X", address, value);
|
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;
|
address &= 0x700FF;
|
||||||
uint16_t value;
|
uint16_t value;
|
||||||
switch (address >> 17) {
|
switch (address >> 17) {
|
||||||
case 0:
|
case 0:
|
||||||
return hw->eReaderRegisterUnk;
|
return ereader->registerUnk;
|
||||||
case 1:
|
case 1:
|
||||||
return hw->eReaderRegisterReset;
|
return ereader->registerReset;
|
||||||
case 2:
|
case 2:
|
||||||
if (address > 0x40088) {
|
if (address > 0x40088) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
LOAD_16(value, address & 0xFE, hw->eReaderData);
|
LOAD_16(value, address & 0xFE, ereader->data);
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
mLOG(GBA_HW, STUB, "Unimplemented e-Reader read: %05X", address);
|
mLOG(GBA_HW, STUB, "Unimplemented e-Reader read: %05X", address);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t GBAHardwareEReaderReadFlash(struct GBACartridgeHardware* hw, uint32_t address) {
|
uint8_t GBACartEReaderReadFlash(struct GBACartEReader* ereader, uint32_t address) {
|
||||||
address &= 0xFFFF;
|
address &= 0xFFFF;
|
||||||
switch (address) {
|
switch (address) {
|
||||||
case 0xFFB0:
|
case 0xFFB0:
|
||||||
return hw->eReaderRegisterControl0;
|
return ereader->registerControl0;
|
||||||
case 0xFFB1:
|
case 0xFFB1:
|
||||||
return hw->eReaderRegisterControl1;
|
return ereader->registerControl1;
|
||||||
default:
|
default:
|
||||||
mLOG(GBA_HW, STUB, "Unimplemented e-Reader read from flash: %04X", address);
|
mLOG(GBA_HW, STUB, "Unimplemented e-Reader read from flash: %04X", address);
|
||||||
return 0;
|
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) {
|
void GBACartEReaderScan(struct GBACartEReader* ereader, const void* data, size_t size) {
|
||||||
if (!hw->eReaderDots) {
|
if (!ereader->dots) {
|
||||||
hw->eReaderDots = anonymousMemoryMap(EREADER_DOTCODE_SIZE);
|
ereader->dots = anonymousMemoryMap(EREADER_DOTCODE_SIZE);
|
||||||
}
|
}
|
||||||
hw->eReaderX = -24;
|
ereader->scanX = -24;
|
||||||
memset(hw->eReaderDots, 0, EREADER_DOTCODE_SIZE);
|
memset(ereader->dots, 0, EREADER_DOTCODE_SIZE);
|
||||||
|
|
||||||
uint8_t blockRS[44][0x10];
|
uint8_t blockRS[44][0x10];
|
||||||
uint8_t block0[0x30];
|
uint8_t block0[0x30];
|
||||||
|
@ -386,7 +403,7 @@ void GBAHardwareEReaderScan(struct GBACartridgeHardware* hw, const void* data, s
|
||||||
size_t x;
|
size_t x;
|
||||||
for (i = 0; i < 40; ++i) {
|
for (i = 0; i < 40; ++i) {
|
||||||
const uint8_t* line = &cdata[(i + 2) * blocks];
|
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) {
|
for (x = 0; x < blocks; ++x) {
|
||||||
uint8_t byte = line[x];
|
uint8_t byte = line[x];
|
||||||
if (x == 123) {
|
if (x == 123) {
|
||||||
|
@ -406,7 +423,7 @@ void GBAHardwareEReaderScan(struct GBACartridgeHardware* hw, const void* data, s
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < blocks + 1; ++i) {
|
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 * 0]);
|
||||||
_eReaderAnchor(&origin[EREADER_DOTCODE_STRIDE * 35]);
|
_eReaderAnchor(&origin[EREADER_DOTCODE_STRIDE * 35]);
|
||||||
_eReaderAddress(origin, base + i);
|
_eReaderAddress(origin, base + i);
|
||||||
|
@ -461,7 +478,7 @@ void GBAHardwareEReaderScan(struct GBACartridgeHardware* hw, const void* data, s
|
||||||
size_t byteOffset = 0;
|
size_t byteOffset = 0;
|
||||||
for (i = 0; i < blocks; ++i) {
|
for (i = 0; i < blocks; ++i) {
|
||||||
uint8_t block[1040];
|
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 * 2]);
|
||||||
_eReaderAlignment(&origin[EREADER_DOTCODE_STRIDE * 37]);
|
_eReaderAlignment(&origin[EREADER_DOTCODE_STRIDE * 37]);
|
||||||
|
|
||||||
|
@ -532,155 +549,132 @@ void GBAHardwareEReaderScan(struct GBACartridgeHardware* hw, const void* data, s
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _eReaderReset(struct GBACartridgeHardware* hw) {
|
void _eReaderReset(struct GBACartEReader* ereader) {
|
||||||
memset(hw->eReaderData, 0, sizeof(hw->eReaderData));
|
memset(ereader->data, 0, sizeof(ereader->data));
|
||||||
hw->eReaderRegisterUnk = 0;
|
ereader->registerUnk = 0;
|
||||||
hw->eReaderRegisterReset = 4;
|
ereader->registerReset = 4;
|
||||||
hw->eReaderRegisterControl0 = 0;
|
ereader->registerControl0 = 0;
|
||||||
hw->eReaderRegisterControl1 = 0x80;
|
ereader->registerControl1 = 0x80;
|
||||||
hw->eReaderRegisterLed = 0;
|
ereader->registerLed = 0;
|
||||||
hw->eReaderState = 0;
|
ereader->state = 0;
|
||||||
hw->eReaderActiveRegister = 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 control = value & 0x7F;
|
||||||
EReaderControl0 oldControl = hw->eReaderRegisterControl0;
|
EReaderControl0 oldControl = ereader->registerControl0;
|
||||||
if (hw->eReaderState == EREADER_SERIAL_INACTIVE) {
|
if (ereader->state == EREADER_SERIAL_INACTIVE) {
|
||||||
if (EReaderControl0IsClock(oldControl) && EReaderControl0IsData(oldControl) && !EReaderControl0IsData(control)) {
|
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)) {
|
} 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)) {
|
if (EReaderControl0IsClock(oldControl) && !EReaderControl0IsData(oldControl) && !EReaderControl0IsClock(control)) {
|
||||||
hw->eReaderState = EREADER_SERIAL_BIT_0;
|
ereader->state = EREADER_SERIAL_BIT_0;
|
||||||
hw->eReaderCommand = EREADER_COMMAND_IDLE;
|
ereader->command = EREADER_COMMAND_IDLE;
|
||||||
}
|
}
|
||||||
} else if (EReaderControl0IsClock(oldControl) && !EReaderControl0IsClock(control)) {
|
} else if (EReaderControl0IsClock(oldControl) && !EReaderControl0IsClock(control)) {
|
||||||
mLOG(GBA_HW, DEBUG, "[e-Reader] Serial falling edge: %c %i", EReaderControl0IsDirection(control) ? '>' : '<', EReaderControl0GetData(control));
|
mLOG(GBA_HW, DEBUG, "[e-Reader] Serial falling edge: %c %i", EReaderControl0IsDirection(control) ? '>' : '<', EReaderControl0GetData(control));
|
||||||
// TODO: Improve direction control
|
// TODO: Improve direction control
|
||||||
if (EReaderControl0IsDirection(control)) {
|
if (EReaderControl0IsDirection(control)) {
|
||||||
hw->eReaderByte |= EReaderControl0GetData(control) << (7 - (hw->eReaderState - EREADER_SERIAL_BIT_0));
|
ereader->byte |= EReaderControl0GetData(control) << (7 - (ereader->state - EREADER_SERIAL_BIT_0));
|
||||||
++hw->eReaderState;
|
++ereader->state;
|
||||||
if (hw->eReaderState == EREADER_SERIAL_END_BIT) {
|
if (ereader->state == EREADER_SERIAL_END_BIT) {
|
||||||
mLOG(GBA_HW, DEBUG, "[e-Reader] Wrote serial byte: %02x", hw->eReaderByte);
|
mLOG(GBA_HW, DEBUG, "[e-Reader] Wrote serial byte: %02x", ereader->byte);
|
||||||
switch (hw->eReaderCommand) {
|
switch (ereader->command) {
|
||||||
case EREADER_COMMAND_IDLE:
|
case EREADER_COMMAND_IDLE:
|
||||||
hw->eReaderCommand = hw->eReaderByte;
|
ereader->command = ereader->byte;
|
||||||
break;
|
break;
|
||||||
case EREADER_COMMAND_SET_INDEX:
|
case EREADER_COMMAND_SET_INDEX:
|
||||||
hw->eReaderActiveRegister = hw->eReaderByte;
|
ereader->activeRegister = ereader->byte;
|
||||||
hw->eReaderCommand = EREADER_COMMAND_WRITE_DATA;
|
ereader->command = EREADER_COMMAND_WRITE_DATA;
|
||||||
break;
|
break;
|
||||||
case EREADER_COMMAND_WRITE_DATA:
|
case EREADER_COMMAND_WRITE_DATA:
|
||||||
switch (hw->eReaderActiveRegister & 0x7F) {
|
switch (ereader->activeRegister & 0x7F) {
|
||||||
case 0:
|
case 0:
|
||||||
case 0x57:
|
case 0x57:
|
||||||
case 0x58:
|
case 0x58:
|
||||||
case 0x59:
|
case 0x59:
|
||||||
case 0x5A:
|
case 0x5A:
|
||||||
// Read-only
|
// 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;
|
break;
|
||||||
default:
|
default:
|
||||||
if ((hw->eReaderActiveRegister & 0x7F) > 0x5A) {
|
if ((ereader->activeRegister & 0x7F) > 0x5A) {
|
||||||
mLOG(GBA_HW, GAME_ERROR, "Writing to non-existent e-Reader serial register: %02X", hw->eReaderActiveRegister);
|
mLOG(GBA_HW, GAME_ERROR, "Writing to non-existent e-Reader serial register: %02X", ereader->activeRegister);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
hw->eReaderSerial[hw->eReaderActiveRegister & 0x7F] = hw->eReaderByte;
|
ereader->serial[ereader->activeRegister & 0x7F] = ereader->byte;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
++hw->eReaderActiveRegister;
|
++ereader->activeRegister;
|
||||||
break;
|
break;
|
||||||
default:
|
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;
|
break;
|
||||||
}
|
}
|
||||||
hw->eReaderState = EREADER_SERIAL_BIT_0;
|
ereader->state = EREADER_SERIAL_BIT_0;
|
||||||
hw->eReaderByte = 0;
|
ereader->byte = 0;
|
||||||
}
|
}
|
||||||
} else if (hw->eReaderCommand == EREADER_COMMAND_READ_DATA) {
|
} else if (ereader->command == EREADER_COMMAND_READ_DATA) {
|
||||||
int bit = hw->eReaderSerial[hw->eReaderActiveRegister & 0x7F] >> (7 - (hw->eReaderState - EREADER_SERIAL_BIT_0));
|
int bit = ereader->serial[ereader->activeRegister & 0x7F] >> (7 - (ereader->state - EREADER_SERIAL_BIT_0));
|
||||||
control = EReaderControl0SetData(control, bit);
|
control = EReaderControl0SetData(control, bit);
|
||||||
++hw->eReaderState;
|
++ereader->state;
|
||||||
if (hw->eReaderState == EREADER_SERIAL_END_BIT) {
|
if (ereader->state == EREADER_SERIAL_END_BIT) {
|
||||||
++hw->eReaderActiveRegister;
|
++ereader->activeRegister;
|
||||||
mLOG(GBA_HW, DEBUG, "[e-Reader] Read serial byte: %02x", hw->eReaderSerial[hw->eReaderActiveRegister & 0x7F]);
|
mLOG(GBA_HW, DEBUG, "[e-Reader] Read serial byte: %02x", ereader->serial[ereader->activeRegister & 0x7F]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (!EReaderControl0IsDirection(control)) {
|
} else if (!EReaderControl0IsDirection(control)) {
|
||||||
// Clear the error bit
|
// Clear the error bit
|
||||||
control = EReaderControl0ClearData(control);
|
control = EReaderControl0ClearData(control);
|
||||||
}
|
}
|
||||||
hw->eReaderRegisterControl0 = control;
|
ereader->registerControl0 = control;
|
||||||
if (!EReaderControl0IsScan(oldControl) && EReaderControl0IsScan(control)) {
|
if (!EReaderControl0IsScan(oldControl) && EReaderControl0IsScan(control)) {
|
||||||
if (hw->eReaderX > 1000) {
|
if (ereader->scanX > 1000) {
|
||||||
if (hw->eReaderDots) {
|
_eReaderScanCard(ereader);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
hw->eReaderX = 0;
|
ereader->scanX = 0;
|
||||||
hw->eReaderY = 0;
|
ereader->scanY = 0;
|
||||||
} else if (EReaderControl0IsLedEnable(control) && EReaderControl0IsScan(control) && !EReaderControl1IsScanline(hw->eReaderRegisterControl1)) {
|
} else if (EReaderControl0IsLedEnable(control) && EReaderControl0IsScan(control) && !EReaderControl1IsScanline(ereader->registerControl1)) {
|
||||||
_eReaderReadData(hw);
|
_eReaderReadData(ereader);
|
||||||
}
|
}
|
||||||
mLOG(GBA_HW, STUB, "Unimplemented e-Reader Control0 write: %02X", value);
|
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;
|
EReaderControl1 control = (value & 0x32) | 0x80;
|
||||||
hw->eReaderRegisterControl1 = control;
|
ereader->registerControl1 = control;
|
||||||
if (EReaderControl0IsScan(hw->eReaderRegisterControl0) && !EReaderControl1IsScanline(control)) {
|
if (EReaderControl0IsScan(ereader->registerControl0) && !EReaderControl1IsScanline(control)) {
|
||||||
++hw->eReaderY;
|
++ereader->scanY;
|
||||||
if (hw->eReaderY == (hw->eReaderSerial[0x15] | (hw->eReaderSerial[0x14] << 8))) {
|
if (ereader->scanY == (ereader->serial[0x15] | (ereader->serial[0x14] << 8))) {
|
||||||
hw->eReaderY = 0;
|
ereader->scanY = 0;
|
||||||
if (hw->eReaderX < 3400) {
|
if (ereader->scanX < 3400) {
|
||||||
hw->eReaderX += 210;
|
ereader->scanX += 210;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_eReaderReadData(hw);
|
_eReaderReadData(ereader);
|
||||||
}
|
}
|
||||||
mLOG(GBA_HW, STUB, "Unimplemented e-Reader Control1 write: %02X", value);
|
mLOG(GBA_HW, STUB, "Unimplemented e-Reader Control1 write: %02X", value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _eReaderReadData(struct GBACartridgeHardware* hw) {
|
void _eReaderReadData(struct GBACartEReader* ereader) {
|
||||||
memset(hw->eReaderData, 0, EREADER_BLOCK_SIZE);
|
memset(ereader->data, 0, EREADER_BLOCK_SIZE);
|
||||||
if (!hw->eReaderDots) {
|
if (!ereader->dots) {
|
||||||
int i;
|
_eReaderScanCard(ereader);
|
||||||
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 (hw->eReaderDots) {
|
if (ereader->dots) {
|
||||||
int y = hw->eReaderY - 10;
|
int y = ereader->scanY - 10;
|
||||||
if (y < 0 || y >= 120) {
|
if (y < 0 || y >= 120) {
|
||||||
memset(hw->eReaderData, 0, EREADER_BLOCK_SIZE);
|
memset(ereader->data, 0, EREADER_BLOCK_SIZE);
|
||||||
} else {
|
} else {
|
||||||
int i;
|
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) {
|
for (i = 0; i < 20; ++i) {
|
||||||
uint16_t word = 0;
|
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 + 0) / 3] << 8;
|
||||||
word |= origin[(x + 1) / 3] << 9;
|
word |= origin[(x + 1) / 3] << 9;
|
||||||
word |= origin[(x + 2) / 3] << 10;
|
word |= origin[(x + 2) / 3] << 10;
|
||||||
|
@ -697,29 +691,48 @@ void _eReaderReadData(struct GBACartridgeHardware* hw) {
|
||||||
word |= origin[(x + 13) / 3] << 5;
|
word |= origin[(x + 13) / 3] << 5;
|
||||||
word |= origin[(x + 14) / 3] << 6;
|
word |= origin[(x + 14) / 3] << 6;
|
||||||
word |= origin[(x + 15) / 3] << 7;
|
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);
|
ereader->registerControl1 = EReaderControl1FillScanline(ereader->registerControl1);
|
||||||
if (EReaderControl0IsLedEnable(hw->eReaderRegisterControl0)) {
|
if (EReaderControl0IsLedEnable(ereader->registerControl0)) {
|
||||||
uint16_t led = hw->eReaderRegisterLed * 2;
|
uint16_t led = ereader->registerLed * 2;
|
||||||
if (led > 0x4000) {
|
if (led > 0x4000) {
|
||||||
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;
|
int i;
|
||||||
for (i = 0; i < EREADER_CARDS_MAX; ++i) {
|
for (i = 0; i < EREADER_CARDS_MAX; ++i) {
|
||||||
if (gba->memory.hw.eReaderCards[i].data) {
|
if (!ereader->cards[i].data) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
gba->memory.hw.eReaderCards[i].data = malloc(size);
|
GBACartEReaderScan(ereader, ereader->cards[i].data, ereader->cards[i].size);
|
||||||
memcpy(gba->memory.hw.eReaderCards[i].data, data, size);
|
free(ereader->cards[i].data);
|
||||||
gba->memory.hw.eReaderCards[i].size = size;
|
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;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,8 +46,6 @@ static const int RTC_BYTES[8] = {
|
||||||
|
|
||||||
void GBAHardwareInit(struct GBACartridgeHardware* hw, uint16_t* base) {
|
void GBAHardwareInit(struct GBACartridgeHardware* hw, uint16_t* base) {
|
||||||
hw->gpioBase = base;
|
hw->gpioBase = base;
|
||||||
hw->eReaderDots = NULL;
|
|
||||||
memset(hw->eReaderCards, 0, sizeof(hw->eReaderCards));
|
|
||||||
GBAHardwareClear(hw);
|
GBAHardwareClear(hw);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,20 +54,6 @@ void GBAHardwareClear(struct GBACartridgeHardware* hw) {
|
||||||
hw->readWrite = GPIO_WRITE_ONLY;
|
hw->readWrite = GPIO_WRITE_ONLY;
|
||||||
hw->pinState = 0;
|
hw->pinState = 0;
|
||||||
hw->direction = 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) {
|
void GBAHardwareGPIOWrite(struct GBACartridgeHardware* hw, uint32_t address, uint16_t value) {
|
||||||
|
|
|
@ -94,6 +94,10 @@ void GBAMemoryInit(struct GBA* gba) {
|
||||||
|
|
||||||
GBADMAInit(gba);
|
GBADMAInit(gba);
|
||||||
GBAVFameInit(&gba->memory.vfame);
|
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) {
|
void GBAMemoryDeinit(struct GBA* gba) {
|
||||||
|
@ -107,6 +111,8 @@ void GBAMemoryDeinit(struct GBA* gba) {
|
||||||
if (gba->memory.agbPrintBufferBackup) {
|
if (gba->memory.agbPrintBufferBackup) {
|
||||||
mappedMemoryFree(gba->memory.agbPrintBufferBackup, SIZE_AGB_PRINT);
|
mappedMemoryFree(gba->memory.agbPrintBufferBackup, SIZE_AGB_PRINT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GBACartEReaderDeinit(&gba->memory.ereader);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GBAMemoryReset(struct GBA* gba) {
|
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) {
|
if (memory->savedata.type == SAVEDATA_EEPROM || memory->savedata.type == SAVEDATA_EEPROM512) {
|
||||||
value = GBASavedataReadEEPROM(&memory->savedata);
|
value = GBASavedataReadEEPROM(&memory->savedata);
|
||||||
} else if ((address & 0x0DFC0000) >= 0x0DF80000 && memory->hw.devices & HW_EREADER) {
|
} 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) {
|
} else if ((address & (SIZE_CART0 - 1)) < memory->romSize) {
|
||||||
LOAD_16(value, address & (SIZE_CART0 - 2), memory->rom);
|
LOAD_16(value, address & (SIZE_CART0 - 2), memory->rom);
|
||||||
} else if (memory->mirroring && (address & memory->romMask) < memory->romSize) {
|
} 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;
|
break;
|
||||||
}
|
}
|
||||||
if (memory->hw.devices & HW_EREADER && (address & 0xE00FF80) >= 0xE00FF80) {
|
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) {
|
} else if (memory->savedata.type == SAVEDATA_SRAM) {
|
||||||
value = memory->savedata.data[address & (SIZE_CART_SRAM - 1)];
|
value = memory->savedata.data[address & (SIZE_CART_SRAM - 1)];
|
||||||
} else if (memory->savedata.type == SAVEDATA_FLASH512 || memory->savedata.type == SAVEDATA_FLASH1M) {
|
} 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;
|
break;
|
||||||
case REGION_CART2_EX:
|
case REGION_CART2_EX:
|
||||||
if ((address & 0x0DFC0000) >= 0x0DF80000 && memory->hw.devices & HW_EREADER) {
|
if ((address & 0x0DFC0000) >= 0x0DF80000 && memory->hw.devices & HW_EREADER) {
|
||||||
GBAHardwareEReaderWrite(&memory->hw, address, value);
|
GBACartEReaderWrite(&memory->ereader, address, value);
|
||||||
break;
|
break;
|
||||||
} else if (memory->savedata.type == SAVEDATA_AUTODETECT) {
|
} else if (memory->savedata.type == SAVEDATA_AUTODETECT) {
|
||||||
mLOG(GBA_MEM, INFO, "Detected EEPROM savegame");
|
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) {
|
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) {
|
} else if (memory->savedata.type == SAVEDATA_FLASH512 || memory->savedata.type == SAVEDATA_FLASH1M) {
|
||||||
GBASavedataWriteFlash(&memory->savedata, address, value);
|
GBASavedataWriteFlash(&memory->savedata, address, value);
|
||||||
} else if (memory->savedata.type == SAVEDATA_SRAM) {
|
} else if (memory->savedata.type == SAVEDATA_SRAM) {
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include <mgba/internal/gba/overrides.h>
|
#include <mgba/internal/gba/overrides.h>
|
||||||
|
|
||||||
#include <mgba/internal/gba/gba.h>
|
#include <mgba/internal/gba/gba.h>
|
||||||
|
#include <mgba/internal/gba/cart/ereader.h>
|
||||||
#include <mgba/internal/gba/cart/gpio.h>
|
#include <mgba/internal/gba/cart/gpio.h>
|
||||||
|
|
||||||
#include <mgba-util/configuration.h>
|
#include <mgba-util/configuration.h>
|
||||||
|
@ -347,7 +348,7 @@ void GBAOverrideApply(struct GBA* gba, const struct GBACartridgeOverride* overri
|
||||||
}
|
}
|
||||||
|
|
||||||
if (override->hardware & HW_EREADER) {
|
if (override->hardware & HW_EREADER) {
|
||||||
GBAHardwareInitEReader(&gba->memory.hw);
|
GBACartEReaderInit(&gba->memory.ereader);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (override->hardware & HW_GB_PLAYER_DETECTION) {
|
if (override->hardware & HW_GB_PLAYER_DETECTION) {
|
||||||
|
|
|
@ -812,7 +812,7 @@ void CoreController::scanCard(const QString& path) {
|
||||||
|
|
||||||
mCoreThreadRunFunction(&m_threadContext, [](mCoreThread* thread) {
|
mCoreThreadRunFunction(&m_threadContext, [](mCoreThread* thread) {
|
||||||
CoreController* controller = static_cast<CoreController*>(thread->userData);
|
CoreController* controller = static_cast<CoreController*>(thread->userData);
|
||||||
GBAEReaderQueueCard(static_cast<GBA*>(thread->core->board), controller->m_eReaderData.constData(), controller->m_eReaderData.size());
|
GBACartEReaderQueueCard(static_cast<GBA*>(thread->core->board), controller->m_eReaderData.constData(), controller->m_eReaderData.size());
|
||||||
});
|
});
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue