mirror of
https://github.com/cemu-project/Cemu.git
synced 2025-07-06 06:51:18 +12:00
* script changes - no arguments * script changes with 2 arguments * script changes with > 2 arguments * script conversions with 1 argument - pt. 1 * script conversions with 1 argument - pt. 2 * script conversions with 1 argument - pt. 3 * script conversions with 1 argument - pt. 4 * script conversions with 1 argument - pt. 5 Pointer format hunting * Fixed pointer format * script conversions with 1 argument - final * fixed conversion in non utf-8 file * fixed conversion with capital letter * actually fixed conversion with capital letter * fixed another capital lettering issue * Added conversions with LR removed * removed LR from logs * Converted logs that previously contained LR * converted log that originally specified string length * fixed log with commas in main text * fixed multi-line log * Fixed more logs with commas in main text * Fixed unformatted pointer * added conversion with float value * converted lines with double parameters * converted missed line * corrected argument formatting Co-authored-by: Crementif <26669564+Crementif@users.noreply.github.com> * Fixed misspellings of "unhandled" unhandeled -> unhandled Co-authored-by: Crementif <26669564+Crementif@users.noreply.github.com> --------- Co-authored-by: Crementif <26669564+Crementif@users.noreply.github.com>
162 lines
4.1 KiB
C++
162 lines
4.1 KiB
C++
#include "Cafe/HW/MMU/MMU.h"
|
|
#include "Cafe/HW/Common/HwReg.h"
|
|
#include "si.h"
|
|
|
|
namespace HW_SI
|
|
{
|
|
|
|
struct
|
|
{
|
|
struct
|
|
{
|
|
HWREG::SICOMCSR sicomcsr{};
|
|
HWREG::SIPOLL sipoll{};
|
|
HWREG::SICOUTBUF outBuf[4]{};
|
|
}registerState;
|
|
struct
|
|
{
|
|
uint8 cmd{};
|
|
uint8 buf[2]{};
|
|
}outputBufferState[4];
|
|
struct
|
|
{
|
|
bool hasErrorNoResponse{};
|
|
}channelStatus[4];
|
|
}g_si;
|
|
|
|
// normally we should call this periodically according to the parameters set in SIPOLL
|
|
// but for now we just call it whenever status registers are read
|
|
void handlePollUpdate()
|
|
{
|
|
for (uint32 i = 0; i < 4; i++)
|
|
{
|
|
// note: Order of EN and VBCPY is from MSB to LSB
|
|
bool isEnabled = ((g_si.registerState.sipoll.get_EN() >> (3 - i))&1) != 0;
|
|
if (isEnabled)
|
|
{
|
|
g_si.channelStatus[i].hasErrorNoResponse = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
void handleQueuedTransfers()
|
|
{
|
|
|
|
}
|
|
|
|
void flushAllOutputBuffers()
|
|
{
|
|
for (uint32 i = 0; i < 4; i++)
|
|
{
|
|
g_si.outputBufferState[i].cmd = g_si.registerState.outBuf[i].get_CMD();
|
|
g_si.outputBufferState[i].buf[0] = g_si.registerState.outBuf[i].get_OUTPUT0();
|
|
g_si.outputBufferState[i].buf[1] = g_si.registerState.outBuf[i].get_OUTPUT1();
|
|
}
|
|
}
|
|
|
|
/* +0x6400/0x640C/0x6418/0x6424 | SI0COUTBUF - SI3COUTBUF */
|
|
|
|
HWREG::SICOUTBUF SI_COUTBUF_R32(PAddr addr)
|
|
{
|
|
uint32 joyChannelIndex = (addr & 0xFF) / 0xC;
|
|
|
|
cemu_assert_debug(false);
|
|
return HWREG::SICOUTBUF();
|
|
}
|
|
|
|
void SI_COUTBUF_W32(PAddr addr, HWREG::SICOUTBUF newValue)
|
|
{
|
|
uint32 joyChannelIndex = (addr & 0xFF) / 0xC;
|
|
g_si.registerState.outBuf[joyChannelIndex] = newValue;
|
|
}
|
|
|
|
/* +0x6430 | SIPOLL */
|
|
|
|
HWREG::SIPOLL SI_POLL_R32(PAddr addr)
|
|
{
|
|
cemu_assert_debug(false);
|
|
return g_si.registerState.sipoll;
|
|
}
|
|
|
|
void SI_POLL_W32(PAddr addr, HWREG::SIPOLL newValue)
|
|
{
|
|
g_si.registerState.sipoll = newValue;
|
|
}
|
|
|
|
/* +0x6434 | SICOMCSR */
|
|
|
|
HWREG::SICOMCSR SI_COMCSR_R32(PAddr addr)
|
|
{
|
|
//cemuLog_logDebug(LogType::Force, "Read SICOMCSR");
|
|
return g_si.registerState.sicomcsr;
|
|
}
|
|
|
|
void SI_COMCSR_W32(PAddr addr, HWREG::SICOMCSR newValue)
|
|
{
|
|
uint32 unhandledBits = g_si.registerState.sicomcsr.getRawValue() & ~(0x80000000);
|
|
cemu_assert_debug(unhandledBits == 0);
|
|
// clear transfer complete interrupt
|
|
if (newValue.get_TCINT())
|
|
{
|
|
g_si.registerState.sicomcsr.set_TCINT(0);
|
|
}
|
|
|
|
if (newValue.get_TRANSFER_START())
|
|
{
|
|
cemu_assert_debug(false);
|
|
handleQueuedTransfers();
|
|
}
|
|
}
|
|
|
|
/* +0x6438 | SISR */
|
|
|
|
HWREG::SISR SI_SR_R32(PAddr addr)
|
|
{
|
|
handlePollUpdate();
|
|
HWREG::SISR reg;
|
|
// no response error
|
|
if (g_si.channelStatus[0].hasErrorNoResponse)
|
|
reg.set_NOREP0(1);
|
|
if (g_si.channelStatus[1].hasErrorNoResponse)
|
|
reg.set_NOREP1(1);
|
|
if (g_si.channelStatus[2].hasErrorNoResponse)
|
|
reg.set_NOREP2(1);
|
|
if (g_si.channelStatus[3].hasErrorNoResponse)
|
|
reg.set_NOREP3(1);
|
|
|
|
// todo - other status fields
|
|
|
|
return reg;
|
|
}
|
|
|
|
void SI_SR_W32(PAddr addr, HWREG::SISR newValue)
|
|
{
|
|
if (newValue.get_NOREP0())
|
|
g_si.channelStatus[0].hasErrorNoResponse = false;
|
|
if (newValue.get_NOREP1())
|
|
g_si.channelStatus[1].hasErrorNoResponse = false;
|
|
if (newValue.get_NOREP2())
|
|
g_si.channelStatus[2].hasErrorNoResponse = false;
|
|
if (newValue.get_NOREP3())
|
|
g_si.channelStatus[3].hasErrorNoResponse = false;
|
|
|
|
|
|
if (newValue.get_WR())
|
|
{
|
|
// copies contents of SICOUTBUF to the internal shadow buffers
|
|
flushAllOutputBuffers();
|
|
}
|
|
}
|
|
|
|
void Initialize()
|
|
{
|
|
MMU::RegisterMMIO_32<HWREG::SICOUTBUF, SI_COUTBUF_R32, SI_COUTBUF_W32>(MMU::MMIOInterface::INTERFACE_0D000000, 0x6400);
|
|
MMU::RegisterMMIO_32<HWREG::SICOUTBUF, SI_COUTBUF_R32, SI_COUTBUF_W32>(MMU::MMIOInterface::INTERFACE_0D000000, 0x640C);
|
|
MMU::RegisterMMIO_32<HWREG::SICOUTBUF, SI_COUTBUF_R32, SI_COUTBUF_W32>(MMU::MMIOInterface::INTERFACE_0D000000, 0x6418);
|
|
MMU::RegisterMMIO_32<HWREG::SICOUTBUF, SI_COUTBUF_R32, SI_COUTBUF_W32>(MMU::MMIOInterface::INTERFACE_0D000000, 0x6424);
|
|
|
|
MMU::RegisterMMIO_32<HWREG::SIPOLL, SI_POLL_R32, SI_POLL_W32>(MMU::MMIOInterface::INTERFACE_0D000000, 0x6430);
|
|
MMU::RegisterMMIO_32<HWREG::SICOMCSR, SI_COMCSR_R32, SI_COMCSR_W32>(MMU::MMIOInterface::INTERFACE_0D000000, 0x6434);
|
|
MMU::RegisterMMIO_32<HWREG::SISR, SI_SR_R32, SI_SR_W32>(MMU::MMIOInterface::INTERFACE_0D000000, 0x6438);
|
|
}
|
|
}
|