pokeemerald/src/librfu_sio32id.c

170 lines
4.4 KiB
C
Raw Normal View History

2020-01-16 00:21:54 +01:00
#include "librfu.h"
static void Sio32IDIntr(void);
static void Sio32IDInit(void);
static s32 Sio32IDMain(void);
2020-02-16 19:49:36 +01:00
struct RfuSIO32Id
{
u8 MS_mode;
u8 state;
u16 count;
u16 send_id;
u16 recv_id;
u16 unk8; // unused
u16 lastId;
};
2020-01-16 00:28:23 +01:00
struct RfuSIO32Id gRfuSIO32Id;
2020-01-16 00:21:54 +01:00
2020-01-16 00:28:23 +01:00
static const u16 Sio32ConnectionData[] = { 0x494e, 0x544e, 0x4e45, 0x4f44 }; // NINTENDO
static const char Sio32IDLib_Var[] = "Sio32ID_030820";
2020-01-16 00:21:54 +01:00
2020-02-16 19:49:36 +01:00
s32 AgbRFU_checkID(u8 maxTries)
2020-01-16 00:21:54 +01:00
{
2020-02-16 19:49:36 +01:00
u16 ieBak;
vu16 *regTMCNTL;
s32 id;
2020-01-16 00:21:54 +01:00
2020-02-16 19:49:36 +01:00
// Interrupts must be enabled
2020-01-16 00:21:54 +01:00
if (REG_IME == 0)
return -1;
2020-02-16 19:49:36 +01:00
ieBak = REG_IE;
2020-01-16 00:21:54 +01:00
gSTWIStatus->state = 10;
STWI_set_Callback_ID(Sio32IDIntr);
Sio32IDInit();
2020-02-16 19:49:36 +01:00
regTMCNTL = &REG_TMCNT_L(gSTWIStatus->timerSelect);
maxTries *= 8;
while (--maxTries != 0xFF)
2020-01-16 00:21:54 +01:00
{
2020-02-16 19:49:36 +01:00
id = Sio32IDMain();
if (id != 0)
2020-01-16 00:21:54 +01:00
break;
2020-02-16 19:49:36 +01:00
regTMCNTL[1] = 0;
regTMCNTL[0] = 0;
regTMCNTL[1] = TIMER_1024CLK | TIMER_ENABLE;
while (regTMCNTL[0] < 32)
2020-01-16 00:21:54 +01:00
;
2020-02-16 19:49:36 +01:00
regTMCNTL[1] = 0;
regTMCNTL[0] = 0;
2020-01-16 00:21:54 +01:00
}
REG_IME = 0;
2020-02-16 19:49:36 +01:00
REG_IE = ieBak;
2020-01-16 00:21:54 +01:00
REG_IME = 1;
gSTWIStatus->state = 0;
STWI_set_Callback_ID(NULL);
2020-02-16 19:49:36 +01:00
return id;
2020-01-16 00:21:54 +01:00
}
static void Sio32IDInit(void)
{
REG_IME = 0;
REG_IE &= ~((8 << gSTWIStatus->timerSelect) | INTR_FLAG_SERIAL);
REG_IME = 1;
REG_RCNT = 0;
REG_SIOCNT = SIO_32BIT_MODE;
REG_SIOCNT |= SIO_INTR_ENABLE | SIO_ENABLE;
CpuFill32(0, &gRfuSIO32Id, sizeof(struct RfuSIO32Id));
REG_IF = INTR_FLAG_SERIAL;
}
static s32 Sio32IDMain(void)
{
2020-02-16 19:49:36 +01:00
switch (gRfuSIO32Id.state)
2020-01-16 00:21:54 +01:00
{
case 0:
2020-02-16 19:49:36 +01:00
gRfuSIO32Id.MS_mode = AGB_CLK_MASTER;
2020-01-16 00:21:54 +01:00
REG_SIOCNT |= SIO_38400_BPS;
2020-02-16 19:49:36 +01:00
REG_IME = 0;
2020-01-16 00:21:54 +01:00
REG_IE |= INTR_FLAG_SERIAL;
REG_IME = 1;
2020-02-16 19:49:36 +01:00
gRfuSIO32Id.state = 1;
2020-01-16 00:21:54 +01:00
*(vu8 *)&REG_SIOCNT |= SIO_ENABLE;
break;
case 1:
2020-02-16 19:49:36 +01:00
if (gRfuSIO32Id.lastId == 0)
2020-01-16 00:21:54 +01:00
{
2020-02-16 19:49:36 +01:00
if (gRfuSIO32Id.MS_mode == AGB_CLK_MASTER)
2020-01-16 00:21:54 +01:00
{
2020-02-16 19:49:36 +01:00
if (gRfuSIO32Id.count == 0)
2020-01-16 00:21:54 +01:00
{
2020-02-16 19:49:36 +01:00
REG_IME = 0;
2020-01-16 00:21:54 +01:00
REG_SIOCNT |= SIO_ENABLE;
2020-02-16 19:49:36 +01:00
REG_IME = 1;
2020-01-16 00:21:54 +01:00
}
}
2020-02-16 19:49:36 +01:00
else if (gRfuSIO32Id.send_id != RFU_ID && !gRfuSIO32Id.count)
2020-01-16 00:21:54 +01:00
{
2020-02-16 19:49:36 +01:00
REG_IME = 0;
2020-01-16 00:21:54 +01:00
REG_IE &= ~INTR_FLAG_SERIAL;
2020-02-16 19:49:36 +01:00
REG_IME = 1;
REG_SIOCNT = 0;
2020-01-16 00:21:54 +01:00
REG_SIOCNT = SIO_32BIT_MODE;
REG_IF = INTR_FLAG_SERIAL;
REG_SIOCNT |= SIO_INTR_ENABLE | SIO_ENABLE;
2020-02-16 19:49:36 +01:00
REG_IME = 0;
2020-01-16 00:21:54 +01:00
REG_IE |= INTR_FLAG_SERIAL;
2020-02-16 19:49:36 +01:00
REG_IME = 1;
2020-01-16 00:21:54 +01:00
}
break;
}
else
{
2020-02-16 19:49:36 +01:00
gRfuSIO32Id.state = 2;
2020-01-16 00:21:54 +01:00
// fallthrough
}
default:
2020-02-16 19:49:36 +01:00
return gRfuSIO32Id.lastId;
2020-01-16 00:21:54 +01:00
}
return 0;
}
static void Sio32IDIntr(void)
{
2020-02-16 19:49:36 +01:00
u32 regSIODATA32;
u16 delay;
u32 rfuSIO32IdUnk0_times_16;
2020-01-16 00:21:54 +01:00
2020-02-16 19:49:36 +01:00
regSIODATA32 = REG_SIODATA32;
if (gRfuSIO32Id.MS_mode != AGB_CLK_MASTER)
2020-01-16 00:21:54 +01:00
REG_SIOCNT |= SIO_ENABLE;
rfuSIO32IdUnk0_times_16 = (regSIODATA32 << (16 * gRfuSIO32Id.MS_mode)) >> 16;
2020-02-16 19:49:36 +01:00
regSIODATA32 = (regSIODATA32 << 16 * (1 - gRfuSIO32Id.MS_mode)) >> 16;
if (gRfuSIO32Id.lastId == 0)
2020-01-16 00:21:54 +01:00
{
u16 backup = rfuSIO32IdUnk0_times_16;
if (backup == gRfuSIO32Id.recv_id)
2020-01-16 00:21:54 +01:00
{
if (gRfuSIO32Id.count < 4)
2020-01-16 00:21:54 +01:00
{
backup = (u16)~gRfuSIO32Id.send_id;
if (gRfuSIO32Id.recv_id == backup)
{
if (regSIODATA32 == (u16)~gRfuSIO32Id.recv_id)
++gRfuSIO32Id.count;
}
2020-01-16 00:21:54 +01:00
}
else
gRfuSIO32Id.lastId = regSIODATA32;
2020-01-16 00:21:54 +01:00
}
else
{
2020-02-16 19:49:36 +01:00
gRfuSIO32Id.count = 0;
2020-01-16 00:21:54 +01:00
}
}
2020-02-16 19:49:36 +01:00
if (gRfuSIO32Id.count < 4)
gRfuSIO32Id.send_id = *(gRfuSIO32Id.count + Sio32ConnectionData);
2020-01-16 00:21:54 +01:00
else
2020-02-16 19:49:36 +01:00
gRfuSIO32Id.send_id = RFU_ID;
gRfuSIO32Id.recv_id = ~regSIODATA32;
REG_SIODATA32 = (gRfuSIO32Id.send_id << 16 * (1 - gRfuSIO32Id.MS_mode))
+ (gRfuSIO32Id.recv_id << 16 * gRfuSIO32Id.MS_mode);
if (gRfuSIO32Id.MS_mode == AGB_CLK_MASTER && (gRfuSIO32Id.count != 0 || regSIODATA32 == 0x494e))
2020-01-16 00:21:54 +01:00
{
2020-02-16 19:49:36 +01:00
for (delay = 0; delay < 600; ++delay)
2020-01-16 00:21:54 +01:00
;
2020-02-16 19:49:36 +01:00
if (gRfuSIO32Id.lastId == 0)
2020-01-16 00:21:54 +01:00
REG_SIOCNT |= SIO_ENABLE;
}
}