mirror of https://github.com/mgba-emu/mgba.git
GBA Hardware: Still-broken implementation of e-Reader serial protocol
This commit is contained in:
parent
62a198357b
commit
131cb3d938
|
@ -96,6 +96,40 @@ struct GBAGBPSIODriver {
|
|||
|
||||
DECL_BITFIELD(GPIOPin, uint16_t);
|
||||
|
||||
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 GBACartridgeHardware {
|
||||
struct GBA* p;
|
||||
uint32_t devices;
|
||||
|
@ -125,10 +159,19 @@ struct GBACartridgeHardware {
|
|||
struct GBAGBPSIODriver gbpDriver;
|
||||
|
||||
uint16_t eReaderData[44];
|
||||
uint8_t eReaderSerial[92];
|
||||
uint16_t eReaderRegisterUnk;
|
||||
uint16_t eReaderRegisterReset;
|
||||
uint16_t eReaderRegisterControl;
|
||||
EReaderControl0 eReaderRegisterControl0;
|
||||
EReaderControl1 eReaderRegisterControl1;
|
||||
uint16_t eReaderRegisterLed;
|
||||
|
||||
// TODO: Serialize these
|
||||
enum EReaderStateMachine eReaderState;
|
||||
enum EReaderCommand eReaderCommand;
|
||||
uint8_t eReaderActiveRegister;
|
||||
uint8_t eReaderByte;
|
||||
uint8_t eReaderDelay;
|
||||
};
|
||||
|
||||
void GBAHardwareInit(struct GBACartridgeHardware* gpio, uint16_t* gpioBase);
|
||||
|
|
|
@ -37,6 +37,8 @@ static uint16_t _gbpSioWriteRegister(struct GBASIODriver* driver, uint32_t addre
|
|||
static void _gbpSioProcessEvents(struct mTiming* timing, void* user, uint32_t cyclesLate);
|
||||
|
||||
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 const int RTC_BYTES[8] = {
|
||||
0, // Force reset
|
||||
|
@ -622,7 +624,16 @@ void GBAHardwareEReaderWrite(struct GBACartridgeHardware* hw, uint32_t address,
|
|||
|
||||
void GBAHardwareEReaderWriteFlash(struct GBACartridgeHardware* hw, uint32_t address, uint8_t value) {
|
||||
address &= 0xFFFF;
|
||||
mLOG(GBA_HW, STUB, "Unimplemented e-Reader write to flash: %04X:%02X", address, value);
|
||||
switch (address) {
|
||||
case 0xFFB0:
|
||||
_eReaderWriteControl0(hw, value);
|
||||
break;
|
||||
case 0xFFB1:
|
||||
_eReaderWriteControl1(hw, value);
|
||||
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) {
|
||||
|
@ -644,14 +655,102 @@ uint16_t GBAHardwareEReaderRead(struct GBACartridgeHardware* hw, uint32_t addres
|
|||
|
||||
uint8_t GBAHardwareEReaderReadFlash(struct GBACartridgeHardware* hw, uint32_t address) {
|
||||
address &= 0xFFFF;
|
||||
mLOG(GBA_HW, STUB, "Unimplemented e-Reader read from flash: %04X", address);
|
||||
return 0;
|
||||
switch (address) {
|
||||
case 0xFFB0:
|
||||
return hw->eReaderRegisterControl0;
|
||||
case 0xFFB1:
|
||||
return hw->eReaderRegisterControl1;
|
||||
default:
|
||||
mLOG(GBA_HW, STUB, "Unimplemented e-Reader read from flash: %04X", address);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void _eReaderReset(struct GBACartridgeHardware* hw) {
|
||||
memset(hw->eReaderData, 0, sizeof(hw->eReaderData));
|
||||
hw->eReaderRegisterUnk = 0;
|
||||
hw->eReaderRegisterReset = 4;
|
||||
hw->eReaderRegisterControl0 = 0;
|
||||
hw->eReaderRegisterControl1 = 0x80;
|
||||
hw->eReaderRegisterLed = 0;
|
||||
hw->eReaderState = false;
|
||||
hw->eReaderActiveRegister = 0;
|
||||
}
|
||||
|
||||
void _eReaderWriteControl0(struct GBACartridgeHardware* hw, uint8_t value) {
|
||||
EReaderControl0 control = value & 0x7F;
|
||||
EReaderControl0 oldControl = hw->eReaderRegisterControl0;
|
||||
++hw->eReaderDelay;
|
||||
if (hw->eReaderDelay > 5) {
|
||||
// Timed out
|
||||
hw->eReaderState = EREADER_SERIAL_INACTIVE;
|
||||
}
|
||||
if (hw->eReaderState == EREADER_SERIAL_INACTIVE) {
|
||||
if (EReaderControl0IsClock(oldControl) && EReaderControl0IsData(oldControl) && !EReaderControl0IsData(control)) {
|
||||
hw->eReaderState = EREADER_SERIAL_STARTING;
|
||||
hw->eReaderDelay = 0;
|
||||
}
|
||||
} else if (hw->eReaderState == EREADER_SERIAL_STARTING) {
|
||||
if (EReaderControl0IsClock(oldControl) && !EReaderControl0IsData(oldControl) && !EReaderControl0IsClock(control)) {
|
||||
hw->eReaderState = EREADER_SERIAL_BIT_0;
|
||||
hw->eReaderCommand = EREADER_COMMAND_IDLE;
|
||||
hw->eReaderDelay = 0;
|
||||
}
|
||||
} 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) {
|
||||
case EREADER_COMMAND_IDLE:
|
||||
hw->eReaderCommand = hw->eReaderByte;
|
||||
break;
|
||||
case EREADER_COMMAND_SET_INDEX:
|
||||
hw->eReaderActiveRegister = hw->eReaderByte;
|
||||
hw->eReaderCommand = EREADER_COMMAND_WRITE_DATA;
|
||||
break;
|
||||
case EREADER_COMMAND_WRITE_DATA:
|
||||
switch (hw->eReaderActiveRegister & 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);
|
||||
break;
|
||||
default:
|
||||
if ((hw->eReaderActiveRegister & 0x7F) > 0x5A) {
|
||||
mLOG(GBA_HW, GAME_ERROR, "Writing to non-existent e-Reader serial register: %02X", hw->eReaderActiveRegister);
|
||||
break;
|
||||
}
|
||||
hw->eReaderSerial[hw->eReaderActiveRegister & 0x7F] = hw->eReaderByte;
|
||||
break;
|
||||
}
|
||||
++hw->eReaderActiveRegister;
|
||||
}
|
||||
hw->eReaderState = EREADER_SERIAL_BIT_0;
|
||||
hw->eReaderByte = 0;
|
||||
}
|
||||
} else {
|
||||
if (hw->eReaderCommand != EREADER_COMMAND_READ_DATA) {
|
||||
// Clear the error bit
|
||||
control = EReaderControl0ClearData(control);
|
||||
}
|
||||
}
|
||||
hw->eReaderDelay = 0;
|
||||
}
|
||||
hw->eReaderRegisterControl0 = control;
|
||||
mLOG(GBA_HW, STUB, "Unimplemented e-Reader Control0 write: %02X", value);
|
||||
}
|
||||
|
||||
void _eReaderWriteControl1(struct GBACartridgeHardware* hw, uint8_t value) {
|
||||
EReaderControl1 control = (value & 0x32) | 0x80;
|
||||
hw->eReaderRegisterControl1 = control;
|
||||
mLOG(GBA_HW, STUB, "Unimplemented e-Reader Control1 write: %02X", value);
|
||||
}
|
||||
|
||||
// == Serialization
|
||||
|
|
Loading…
Reference in New Issue