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 GBAEReaderQueueCard(struct GBA* gba, const void* data, size_t size);
|
||||
void GBACartEReaderQueueCard(struct GBA* gba, const void* data, size_t size);
|
||||
|
||||
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/timing.h>
|
||||
#include <mgba/gba/interface.h>
|
||||
#include <mgba/internal/gba/cart/ereader.h>
|
||||
|
||||
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);
|
||||
|
|
|
@ -15,6 +15,7 @@ CXX_GUARD_START
|
|||
#include <mgba/internal/arm/arm.h>
|
||||
#include <mgba/internal/gba/dma.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/matrix.h>
|
||||
#include <mgba/internal/gba/cart/vfame.h>
|
||||
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include <mgba/internal/gba/overrides.h>
|
||||
|
||||
#include <mgba/internal/gba/gba.h>
|
||||
#include <mgba/internal/gba/cart/ereader.h>
|
||||
#include <mgba/internal/gba/cart/gpio.h>
|
||||
|
||||
#include <mgba-util/configuration.h>
|
||||
|
@ -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) {
|
||||
|
|
|
@ -812,7 +812,7 @@ void CoreController::scanCard(const QString& path) {
|
|||
|
||||
mCoreThreadRunFunction(&m_threadContext, [](mCoreThread* thread) {
|
||||
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
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue