SI: Fix GBA link by having a separate response for "error" and "no data".

This commit is contained in:
Jordan Woyak 2025-04-17 03:33:54 -05:00 committed by OatmealDome
parent e40c9b674c
commit 0109c27ad7
18 changed files with 44 additions and 37 deletions

View file

@ -560,15 +560,18 @@ void SerialInterfaceManager::UpdateDevices()
{ {
// ERRLATCH bit is maintained. // ERRLATCH bit is maintained.
u32 errlatch = m_channel[i].in_hi.ERRLATCH.Value(); u32 errlatch = m_channel[i].in_hi.ERRLATCH.Value();
if (m_channel[i].device->GetData(m_channel[i].in_hi.hex, m_channel[i].in_lo.hex)) switch (m_channel[i].device->GetData(m_channel[i].in_hi.hex, m_channel[i].in_lo.hex))
{ {
case DataResponse::Success:
m_status_reg.hex |= GetRDSTBit(i); m_status_reg.hex |= GetRDSTBit(i);
} break;
else case DataResponse::ErrorNoResponse:
{ SetNoResponse(i);
[[fallthrough]];
case DataResponse::NoData:
errlatch = 1; errlatch = 1;
m_channel[i].in_hi.ERRSTAT = 1; m_channel[i].in_hi.ERRSTAT = 1;
SetNoResponse(i); break;
} }
m_channel[i].in_hi.ERRLATCH = errlatch; m_channel[i].in_hi.ERRLATCH = errlatch;

View file

@ -106,6 +106,13 @@ enum SIDevices : int
SIDEVICE_COUNT, SIDEVICE_COUNT,
}; };
enum class DataResponse
{
NoData,
Success,
ErrorNoResponse,
};
class ISIDevice class ISIDevice
{ {
public: public:
@ -119,8 +126,7 @@ public:
virtual int RunBuffer(u8* buffer, int request_length); virtual int RunBuffer(u8* buffer, int request_length);
virtual int TransferInterval(); virtual int TransferInterval();
// Return true on new data virtual DataResponse GetData(u32& hi, u32& low) = 0;
virtual bool GetData(u32& hi, u32& low) = 0;
// Send a command directly (no detour per buffer) // Send a command directly (no detour per buffer)
virtual void SendCommand(u32 command, u8 poll) = 0; virtual void SendCommand(u32 command, u8 poll) = 0;

View file

@ -60,13 +60,13 @@ u32 CSIDevice_DanceMat::MapPadStatus(const GCPadStatus& pad_status)
return (u32)(map << 16) | 0x8080; return (u32)(map << 16) | 0x8080;
} }
bool CSIDevice_DanceMat::GetData(u32& hi, u32& low) DataResponse CSIDevice_DanceMat::GetData(u32& hi, u32& low)
{ {
CSIDevice_GCController::GetData(hi, low); CSIDevice_GCController::GetData(hi, low);
// Identifies the dance mat // Identifies the dance mat
low = 0x8080ffff; low = 0x8080ffff;
return true; return DataResponse::Success;
} }
} // namespace SerialInterface } // namespace SerialInterface

View file

@ -17,6 +17,6 @@ public:
int RunBuffer(u8* buffer, int request_length) override; int RunBuffer(u8* buffer, int request_length) override;
u32 MapPadStatus(const GCPadStatus& pad_status) override; u32 MapPadStatus(const GCPadStatus& pad_status) override;
bool GetData(u32& hi, u32& low) override; DataResponse GetData(u32& hi, u32& low) override;
}; };
} // namespace SerialInterface } // namespace SerialInterface

View file

@ -348,9 +348,9 @@ int CSIDevice_GBA::TransferInterval()
return SIDevice_GetGBATransferTime(m_system.GetSystemTimers(), m_last_cmd); return SIDevice_GetGBATransferTime(m_system.GetSystemTimers(), m_last_cmd);
} }
bool CSIDevice_GBA::GetData(u32& hi, u32& low) DataResponse CSIDevice_GBA::GetData(u32& hi, u32& low)
{ {
return false; return DataResponse::NoData;
} }
void CSIDevice_GBA::SendCommand(u32 command, u8 poll) void CSIDevice_GBA::SendCommand(u32 command, u8 poll)

View file

@ -47,7 +47,7 @@ public:
int RunBuffer(u8* buffer, int request_length) override; int RunBuffer(u8* buffer, int request_length) override;
int TransferInterval() override; int TransferInterval() override;
bool GetData(u32& hi, u32& low) override; DataResponse GetData(u32& hi, u32& low) override;
void SendCommand(u32 command, u8 poll) override; void SendCommand(u32 command, u8 poll) override;
private: private:

View file

@ -120,7 +120,7 @@ int CSIDevice_GBAEmu::TransferInterval()
return SIDevice_GetGBATransferTime(m_system.GetSystemTimers(), m_last_cmd); return SIDevice_GetGBATransferTime(m_system.GetSystemTimers(), m_last_cmd);
} }
bool CSIDevice_GBAEmu::GetData(u32& hi, u32& low) DataResponse CSIDevice_GBAEmu::GetData(u32& hi, u32& low)
{ {
GCPadStatus pad_status{}; GCPadStatus pad_status{};
if (!NetPlay::IsNetPlayRunning()) if (!NetPlay::IsNetPlayRunning())
@ -149,7 +149,7 @@ bool CSIDevice_GBAEmu::GetData(u32& hi, u32& low)
if (pad_status.button & PadButton::PAD_BUTTON_X) if (pad_status.button & PadButton::PAD_BUTTON_X)
m_core->Reset(); m_core->Reset();
return false; return DataResponse::NoData;
} }
void CSIDevice_GBAEmu::SendCommand(u32 command, u8 poll) void CSIDevice_GBAEmu::SendCommand(u32 command, u8 poll)

View file

@ -25,7 +25,7 @@ public:
int RunBuffer(u8* buffer, int request_length) override; int RunBuffer(u8* buffer, int request_length) override;
int TransferInterval() override; int TransferInterval() override;
bool GetData(u32& hi, u32& low) override; DataResponse GetData(u32& hi, u32& low) override;
void SendCommand(u32 command, u8 poll) override; void SendCommand(u32 command, u8 poll) override;
void DoState(PointerWrap& p) override; void DoState(PointerWrap& p) override;
void OnEvent(u64 userdata, s64 cycles_late) override; void OnEvent(u64 userdata, s64 cycles_late) override;

View file

@ -69,7 +69,7 @@ int CSIDevice_GCAdapter::RunBuffer(u8* buffer, int request_length)
return CSIDevice_GCController::RunBuffer(buffer, request_length); return CSIDevice_GCController::RunBuffer(buffer, request_length);
} }
bool CSIDevice_GCAdapter::GetData(u32& hi, u32& low) DataResponse CSIDevice_GCAdapter::GetData(u32& hi, u32& low)
{ {
CSIDevice_GCController::GetData(hi, low); CSIDevice_GCController::GetData(hi, low);
@ -78,7 +78,7 @@ bool CSIDevice_GCAdapter::GetData(u32& hi, u32& low)
hi &= CSIDevice_TaruKonga::HI_BUTTON_MASK; hi &= CSIDevice_TaruKonga::HI_BUTTON_MASK;
} }
return true; return DataResponse::Success;
} }
void CSIDevice_GCController::Rumble(int pad_num, ControlState strength, SIDevices device) void CSIDevice_GCController::Rumble(int pad_num, ControlState strength, SIDevices device)

View file

@ -17,7 +17,7 @@ public:
GCPadStatus GetPadStatus() override; GCPadStatus GetPadStatus() override;
int RunBuffer(u8* buffer, int request_length) override; int RunBuffer(u8* buffer, int request_length) override;
bool GetData(u32& hi, u32& low) override; DataResponse GetData(u32& hi, u32& low) override;
private: private:
bool m_simulate_konga{}; bool m_simulate_konga{};

View file

@ -170,12 +170,12 @@ GCPadStatus CSIDevice_GCController::GetPadStatus()
// [00?SYXBA] [1LRZUDRL] [x] [y] [cx] [cy] [l] [r] // [00?SYXBA] [1LRZUDRL] [x] [y] [cx] [cy] [l] [r]
// |\_ ERR_LATCH (error latched - check SISR) // |\_ ERR_LATCH (error latched - check SISR)
// |_ ERR_STATUS (error on last GetData or SendCmd?) // |_ ERR_STATUS (error on last GetData or SendCmd?)
bool CSIDevice_GCController::GetData(u32& hi, u32& low) DataResponse CSIDevice_GCController::GetData(u32& hi, u32& low)
{ {
GCPadStatus pad_status = GetPadStatus(); GCPadStatus pad_status = GetPadStatus();
if (!pad_status.isConnected) if (!pad_status.isConnected)
return false; return DataResponse::ErrorNoResponse;
if (HandleButtonCombos(pad_status) == COMBO_ORIGIN) if (HandleButtonCombos(pad_status) == COMBO_ORIGIN)
pad_status.button |= PAD_GET_ORIGIN; pad_status.button |= PAD_GET_ORIGIN;
@ -227,7 +227,7 @@ bool CSIDevice_GCController::GetData(u32& hi, u32& low)
low |= pad_status.substickX << 24; // All 8 bits low |= pad_status.substickX << 24; // All 8 bits
} }
return true; return DataResponse::Success;
} }
u32 CSIDevice_GCController::MapPadStatus(const GCPadStatus& pad_status) u32 CSIDevice_GCController::MapPadStatus(const GCPadStatus& pad_status)
@ -343,7 +343,7 @@ CSIDevice_TaruKonga::CSIDevice_TaruKonga(Core::System& system, SIDevices device,
{ {
} }
bool CSIDevice_TaruKonga::GetData(u32& hi, u32& low) DataResponse CSIDevice_TaruKonga::GetData(u32& hi, u32& low)
{ {
CSIDevice_GCController::GetData(hi, low); CSIDevice_GCController::GetData(hi, low);
@ -351,7 +351,7 @@ bool CSIDevice_TaruKonga::GetData(u32& hi, u32& low)
// and all buttons except: A, B, X, Y, Start, R // and all buttons except: A, B, X, Y, Start, R
hi &= HI_BUTTON_MASK; hi &= HI_BUTTON_MASK;
return true; return DataResponse::Success;
} }
} // namespace SerialInterface } // namespace SerialInterface

View file

@ -63,8 +63,7 @@ public:
// Run the SI Buffer // Run the SI Buffer
int RunBuffer(u8* buffer, int request_length) override; int RunBuffer(u8* buffer, int request_length) override;
// Return true on new data DataResponse GetData(u32& hi, u32& low) override;
bool GetData(u32& hi, u32& low) override;
// Send a command directly // Send a command directly
void SendCommand(u32 command, u8 poll) override; void SendCommand(u32 command, u8 poll) override;
@ -96,7 +95,7 @@ class CSIDevice_TaruKonga final : public CSIDevice_GCController
public: public:
CSIDevice_TaruKonga(Core::System& system, SIDevices device, int device_number); CSIDevice_TaruKonga(Core::System& system, SIDevices device, int device_number);
bool GetData(u32& hi, u32& low) override; DataResponse GetData(u32& hi, u32& low) override;
static const u32 HI_BUTTON_MASK = static const u32 HI_BUTTON_MASK =
(PAD_BUTTON_A | PAD_BUTTON_B | PAD_BUTTON_X | PAD_BUTTON_Y | PAD_BUTTON_START | PAD_TRIGGER_R) (PAD_BUTTON_A | PAD_BUTTON_B | PAD_BUTTON_X | PAD_BUTTON_Y | PAD_BUTTON_START | PAD_TRIGGER_R)

View file

@ -43,7 +43,7 @@ int CSIDevice_GCSteeringWheel::RunBuffer(u8* buffer, int request_length)
} }
} }
bool CSIDevice_GCSteeringWheel::GetData(u32& hi, u32& low) DataResponse CSIDevice_GCSteeringWheel::GetData(u32& hi, u32& low)
{ {
if (m_mode == 6) if (m_mode == 6)
{ {
@ -95,7 +95,7 @@ bool CSIDevice_GCSteeringWheel::GetData(u32& hi, u32& low)
return CSIDevice_GCController::GetData(hi, low); return CSIDevice_GCController::GetData(hi, low);
} }
return true; return DataResponse::Success;
} }
void CSIDevice_GCSteeringWheel::SendCommand(u32 command, u8 poll) void CSIDevice_GCSteeringWheel::SendCommand(u32 command, u8 poll)

View file

@ -13,7 +13,7 @@ public:
CSIDevice_GCSteeringWheel(Core::System& system, SIDevices device, int device_number); CSIDevice_GCSteeringWheel(Core::System& system, SIDevices device, int device_number);
int RunBuffer(u8* buffer, int request_length) override; int RunBuffer(u8* buffer, int request_length) override;
bool GetData(u32& hi, u32& low) override; DataResponse GetData(u32& hi, u32& low) override;
void SendCommand(u32 command, u8 poll) override; void SendCommand(u32 command, u8 poll) override;
private: private:

View file

@ -68,7 +68,7 @@ KeyboardStatus CSIDevice_Keyboard::GetKeyboardStatus() const
return Keyboard::GetStatus(m_device_number); return Keyboard::GetStatus(m_device_number);
} }
bool CSIDevice_Keyboard::GetData(u32& hi, u32& low) DataResponse CSIDevice_Keyboard::GetData(u32& hi, u32& low)
{ {
const KeyboardStatus key_status = GetKeyboardStatus(); const KeyboardStatus key_status = GetKeyboardStatus();
const KeyArray key = MapKeys(key_status); const KeyArray key = MapKeys(key_status);
@ -77,7 +77,7 @@ bool CSIDevice_Keyboard::GetData(u32& hi, u32& low)
hi = m_counter << 24; hi = m_counter << 24;
low = key[0] << 24 | key[1] << 16 | key[2] << 8 | checksum; low = key[0] << 24 | key[1] << 16 | key[2] << 8 | checksum;
return true; return DataResponse::Success;
} }
void CSIDevice_Keyboard::SendCommand(u32 command, u8 poll) void CSIDevice_Keyboard::SendCommand(u32 command, u8 poll)

View file

@ -21,8 +21,7 @@ public:
// Run the SI Buffer // Run the SI Buffer
int RunBuffer(u8* buffer, int request_length) override; int RunBuffer(u8* buffer, int request_length) override;
// Return true on new data DataResponse GetData(u32& hi, u32& low) override;
bool GetData(u32& hi, u32& low) override;
KeyboardStatus GetKeyboardStatus() const; KeyboardStatus GetKeyboardStatus() const;

View file

@ -15,9 +15,9 @@ int CSIDevice_Null::RunBuffer(u8* buffer, int request_length)
return -1; return -1;
} }
bool CSIDevice_Null::GetData(u32& hi, u32& low) DataResponse CSIDevice_Null::GetData(u32& hi, u32& low)
{ {
return false; return DataResponse::ErrorNoResponse;
} }
void CSIDevice_Null::SendCommand(u32 command, u8 poll) void CSIDevice_Null::SendCommand(u32 command, u8 poll)

View file

@ -15,7 +15,7 @@ public:
CSIDevice_Null(Core::System& system, SIDevices device, int device_number); CSIDevice_Null(Core::System& system, SIDevices device, int device_number);
int RunBuffer(u8* buffer, int request_length) override; int RunBuffer(u8* buffer, int request_length) override;
bool GetData(u32& hi, u32& low) override; DataResponse GetData(u32& hi, u32& low) override;
void SendCommand(u32 command, u8 poll) override; void SendCommand(u32 command, u8 poll) override;
}; };
} // namespace SerialInterface } // namespace SerialInterface