GBA Hardware: Fix-up card scanning

This commit is contained in:
Vicki Pfau 2017-10-16 22:43:05 -07:00
parent 4b5efa2365
commit d3526be8f5
2 changed files with 30 additions and 18 deletions

View File

@ -171,12 +171,13 @@ struct GBACartridgeHardware {
enum EReaderCommand eReaderCommand; enum EReaderCommand eReaderCommand;
uint8_t eReaderActiveRegister; uint8_t eReaderActiveRegister;
uint8_t eReaderByte; uint8_t eReaderByte;
uint8_t eReaderDelay; int32_t eReaderDelay;
struct GBAEReaderDataSource* eReaderSource; struct GBAEReaderDataSource* eReaderSource;
}; };
void GBAHardwareInit(struct GBACartridgeHardware* gpio, uint16_t* gpioBase); void GBAHardwareInit(struct GBACartridgeHardware* gpio, uint16_t* gpioBase);
void GBAHardwareClear(struct GBACartridgeHardware* gpio); void GBAHardwareClear(struct GBACartridgeHardware* gpio);
int32_t GBAHardwareProcessEvents(struct GBA* gba, int32_t cycles);
void GBAHardwareInitRTC(struct GBACartridgeHardware* gpio); void GBAHardwareInitRTC(struct GBACartridgeHardware* gpio);
void GBAHardwareInitGyro(struct GBACartridgeHardware* gpio); void GBAHardwareInitGyro(struct GBACartridgeHardware* gpio);

View File

@ -40,6 +40,7 @@ static void _eReaderReset(struct GBACartridgeHardware* hw);
static void _eReaderWriteControl0(struct GBACartridgeHardware* hw, uint8_t value); static void _eReaderWriteControl0(struct GBACartridgeHardware* hw, uint8_t value);
static void _eReaderWriteControl1(struct GBACartridgeHardware* hw, uint8_t value); static void _eReaderWriteControl1(struct GBACartridgeHardware* hw, uint8_t value);
static void _eReaderReadData(struct GBACartridgeHardware* hw); static void _eReaderReadData(struct GBACartridgeHardware* hw);
static int32_t _eReaderProcessEvents(struct GBACartridgeHardware* hw, int32_t cycles);
static const int RTC_BYTES[8] = { static const int RTC_BYTES[8] = {
0, // Force reset 0, // Force reset
@ -81,6 +82,13 @@ void GBAHardwareClear(struct GBACartridgeHardware* hw) {
} }
} }
int32_t GBAHardwareProcessEvents(struct GBA* gba, int32_t cycles) {
if (gba->memory.hw.devices & HW_EREADER) {
return _eReaderProcessEvents(&gba->memory.hw, cycles);
}
return INT_MAX;
}
void GBAHardwareGPIOWrite(struct GBACartridgeHardware* hw, uint32_t address, uint16_t value) { void GBAHardwareGPIOWrite(struct GBACartridgeHardware* hw, uint32_t address, uint16_t value) {
if (!hw->gpioBase) { if (!hw->gpioBase) {
return; return;
@ -689,31 +697,22 @@ void _eReaderReset(struct GBACartridgeHardware* hw) {
void _eReaderWriteControl0(struct GBACartridgeHardware* hw, uint8_t value) { void _eReaderWriteControl0(struct GBACartridgeHardware* hw, uint8_t value) {
EReaderControl0 control = value & 0x7F; EReaderControl0 control = value & 0x7F;
EReaderControl0 oldControl = hw->eReaderRegisterControl0; EReaderControl0 oldControl = hw->eReaderRegisterControl0;
++hw->eReaderDelay;
// Huge hack to prevent having to do cycle counting for the delay
// This is the timing the e-Reader uses
if (hw->eReaderDelay > 6) {
// Timed out
hw->eReaderState = EREADER_SERIAL_INACTIVE;
}
if (hw->eReaderState == EREADER_SERIAL_INACTIVE) { if (hw->eReaderState == EREADER_SERIAL_INACTIVE) {
if (EReaderControl0IsClock(oldControl) && EReaderControl0IsData(oldControl) && !EReaderControl0IsData(control)) { if (EReaderControl0IsClock(oldControl) && EReaderControl0IsData(oldControl) && !EReaderControl0IsData(control)) {
hw->eReaderState = EREADER_SERIAL_STARTING; hw->eReaderState = EREADER_SERIAL_STARTING;
hw->eReaderDelay = 0;
} }
} else if (EReaderControl0IsClock(oldControl) && !EReaderControl0IsData(oldControl) && EReaderControl0IsData(control)) {
hw->eReaderState = EREADER_SERIAL_INACTIVE;
} else if (hw->eReaderState == EREADER_SERIAL_STARTING) { } else if (hw->eReaderState == EREADER_SERIAL_STARTING) {
if (EReaderControl0IsClock(oldControl) && !EReaderControl0IsData(oldControl) && !EReaderControl0IsClock(control)) { if (EReaderControl0IsClock(oldControl) && !EReaderControl0IsData(oldControl) && !EReaderControl0IsClock(control)) {
hw->eReaderState = EREADER_SERIAL_BIT_0; hw->eReaderState = EREADER_SERIAL_BIT_0;
hw->eReaderCommand = EREADER_COMMAND_IDLE; hw->eReaderCommand = EREADER_COMMAND_IDLE;
hw->eReaderDelay = 0;
} }
} 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 (hw->eReaderState == EREADER_SERIAL_BIT_0 && hw->eReaderDelay > 5) { if (EReaderControl0IsDirection(control)) {
// This is 4 for an actual write, and 6 an SioBegin delay
hw->eReaderCommand = EREADER_COMMAND_IDLE;
} else if (EReaderControl0IsDirection(control)) {
hw->eReaderByte |= EReaderControl0GetData(control) << (7 - (hw->eReaderState - EREADER_SERIAL_BIT_0)); hw->eReaderByte |= EReaderControl0GetData(control) << (7 - (hw->eReaderState - EREADER_SERIAL_BIT_0));
++hw->eReaderState; ++hw->eReaderState;
if (hw->eReaderState == EREADER_SERIAL_END_BIT) { if (hw->eReaderState == EREADER_SERIAL_END_BIT) {
@ -788,13 +787,25 @@ void _eReaderReadData(struct GBACartridgeHardware* hw) {
return; return;
} }
memset(hw->eReaderData, 0, EREADER_BLOCK_SIZE); memset(hw->eReaderData, 0, EREADER_BLOCK_SIZE);
hw->eReaderSource->readBlock(hw->eReaderSource, hw->eReaderData); if (hw->eReaderSource->readBlock(hw->eReaderSource, hw->eReaderData)) {
hw->eReaderRegisterControl1 = EReaderControl1FillScanline(hw->eReaderRegisterControl1); hw->eReaderRegisterControl1 = EReaderControl1FillScanline(hw->eReaderRegisterControl1);
if (EReaderControl0IsLedEnable(hw->eReaderRegisterControl0)) { if (EReaderControl0IsLedEnable(hw->eReaderRegisterControl0)) {
GBARaiseIRQ(hw->p, IRQ_GAMEPAK, 0); GBARaiseIRQ(hw->p, IRQ_GAMEPAK, 0);
}
} }
} }
static int32_t _eReaderProcessEvents(struct GBACartridgeHardware* hw, int32_t cycles) {
if (hw->eReaderState != EREADER_SERIAL_INACTIVE) {
hw->eReaderDelay += cycles;
if (hw->eReaderDelay > 1024) {
mLOG(GBA_HW, DEBUG, "[e-Reader] Command timed out");
hw->eReaderState = EREADER_SERIAL_INACTIVE;
}
}
return INT_MAX;
}
// == Serialization // == Serialization
void GBAHardwareSerialize(const struct GBACartridgeHardware* hw, struct GBASerializedState* state) { void GBAHardwareSerialize(const struct GBACartridgeHardware* hw, struct GBASerializedState* state) {