mirror of
https://github.com/pret/pokefirered.git
synced 2026-05-06 13:47:12 -05:00
398 lines
9.1 KiB
C
398 lines
9.1 KiB
C
#include "global.h"
|
|
#include "link.h"
|
|
#include "unk_815c27c.h"
|
|
|
|
enum {
|
|
EREADER_XFR_STATE_INIT,
|
|
EREADER_XFR_STATE_HANDSHAKE,
|
|
EREADER_XFR_STATE_START,
|
|
EREADER_XFR_STATE_TRANSFER,
|
|
};
|
|
|
|
struct SendRecvMgr
|
|
{
|
|
u8 sendOrRecv;
|
|
u8 state;
|
|
u8 field_02;
|
|
u8 field_03;
|
|
u8 field_04;
|
|
u32 * dataptr;
|
|
int cursor;
|
|
int size;
|
|
u32 checksum;
|
|
};
|
|
|
|
static bool16 DetermineSendRecvState(u8);
|
|
static void SetUpTransferManager(size_t, const void *, void *);
|
|
static void StartTm3(void);
|
|
static void EnableSio(void);
|
|
static void DisableTm3(void);
|
|
static void GetKeyInput(void);
|
|
|
|
static struct SendRecvMgr sSendRecvMgr;
|
|
static u16 sJoyNewOrRepeated;
|
|
static u16 sJoyNew;
|
|
static u16 sSendRecvStatus;
|
|
static u16 sCounter1;
|
|
static u32 sCounter2;
|
|
static u16 sSavedIme;
|
|
static u16 sSavedIe;
|
|
static u16 sSavedTm3Cnt;
|
|
static u16 sSavedSioCnt;
|
|
static u16 sSavedSioCnt;
|
|
static u16 sSavedRCnt;
|
|
|
|
int EReader_Send(size_t r6, const void * r5)
|
|
{
|
|
int result;
|
|
EReaderHelper_SaveRegsState();
|
|
|
|
while (1)
|
|
{
|
|
GetKeyInput();
|
|
if (TEST_BUTTON(sJoyNew, B_BUTTON))
|
|
gUnknown_3003F84 = 2;
|
|
|
|
sSendRecvStatus = EReaderHandleTransfer(1, r6, r5, NULL);
|
|
if ((sSendRecvStatus & 0x13) == 0x10)
|
|
{
|
|
result = 0;
|
|
break;
|
|
}
|
|
else if (sSendRecvStatus & 8)
|
|
{
|
|
result = 1;
|
|
break;
|
|
}
|
|
else if (sSendRecvStatus & 4)
|
|
{
|
|
result = 2;
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
gUnknown_3003F84 = 0;
|
|
VBlankIntrWait();
|
|
}
|
|
}
|
|
|
|
CpuFill32(0, &sSendRecvMgr, sizeof(sSendRecvMgr));
|
|
EReaderHelper_RestoreRegsState();
|
|
return result;
|
|
}
|
|
|
|
int EReader_Recv(void * r5)
|
|
{
|
|
int result;
|
|
EReaderHelper_SaveRegsState();
|
|
|
|
while (1)
|
|
{
|
|
GetKeyInput();
|
|
if (TEST_BUTTON(sJoyNew, B_BUTTON))
|
|
gUnknown_3003F84 = 2;
|
|
|
|
sSendRecvStatus = EReaderHandleTransfer(0, 0, NULL, r5);
|
|
if ((sSendRecvStatus & 0x13) == 0x10)
|
|
{
|
|
result = 0;
|
|
break;
|
|
}
|
|
else if (sSendRecvStatus & 8)
|
|
{
|
|
result = 1;
|
|
break;
|
|
}
|
|
else if (sSendRecvStatus & 4)
|
|
{
|
|
result = 2;
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
gUnknown_3003F84 = 0;
|
|
VBlankIntrWait();
|
|
}
|
|
}
|
|
|
|
CpuFill32(0, &sSendRecvMgr, sizeof(sSendRecvMgr));
|
|
EReaderHelper_RestoreRegsState();
|
|
return result;
|
|
}
|
|
|
|
static void CloseSerial(void)
|
|
{
|
|
REG_IME = 0;
|
|
REG_IE &= ~(INTR_FLAG_TIMER3 | INTR_FLAG_SERIAL);
|
|
REG_IME = 1;
|
|
REG_SIOCNT = 0;
|
|
REG_TM3CNT_H = 0;
|
|
REG_IF = INTR_FLAG_TIMER3 | INTR_FLAG_SERIAL;
|
|
}
|
|
|
|
static void OpenSerialMulti(void)
|
|
{
|
|
REG_IME = 0;
|
|
REG_IE &= ~(INTR_FLAG_TIMER3 | INTR_FLAG_SERIAL);
|
|
REG_IME = 1;
|
|
REG_RCNT = 0;
|
|
REG_SIOCNT = SIO_MULTI_MODE;
|
|
REG_SIOCNT |= SIO_INTR_ENABLE | SIO_115200_BPS;
|
|
REG_IME = 0;
|
|
REG_IE |= INTR_FLAG_SERIAL;
|
|
REG_IME = 1;
|
|
if (sSendRecvMgr.state == 0)
|
|
CpuFill32(0, &sSendRecvMgr, sizeof(sSendRecvMgr));
|
|
}
|
|
|
|
static void OpenSerial32(void)
|
|
{
|
|
REG_RCNT = 0;
|
|
REG_SIOCNT = SIO_INTR_ENABLE | SIO_32BIT_MODE;
|
|
REG_SIOCNT |= SIO_MULTI_SD;
|
|
gUnknown_3003F84 = 0;
|
|
sCounter1 = 0;
|
|
sCounter2 = 0;
|
|
}
|
|
|
|
u16 EReaderHandleTransfer(u8 mode, size_t size, const void * data, void * recvBuffer)
|
|
{
|
|
switch (sSendRecvMgr.state)
|
|
{
|
|
case 0:
|
|
OpenSerialMulti();
|
|
sSendRecvMgr.field_02 = 1;
|
|
sSendRecvMgr.state = 1;
|
|
break;
|
|
case 1:
|
|
if (DetermineSendRecvState(mode))
|
|
EnableSio();
|
|
if (gUnknown_3003F84 == 2)
|
|
{
|
|
sSendRecvMgr.field_04 = 2;
|
|
sSendRecvMgr.state = 6;
|
|
}
|
|
break;
|
|
case 2:
|
|
OpenSerial32();
|
|
SetUpTransferManager(size, data, recvBuffer);
|
|
sSendRecvMgr.state = 3;
|
|
// fallthrough
|
|
case 3:
|
|
if (gUnknown_3003F84 == 2)
|
|
{
|
|
sSendRecvMgr.field_04 = 2;
|
|
sSendRecvMgr.state = 6;
|
|
}
|
|
else
|
|
{
|
|
sCounter1++;
|
|
sCounter2++;
|
|
if (sSendRecvMgr.sendOrRecv == 0 && sCounter2 > 60)
|
|
{
|
|
sSendRecvMgr.field_04 = 1;
|
|
sSendRecvMgr.state = 6;
|
|
}
|
|
if (sSendRecvMgr.field_02 != 2)
|
|
{
|
|
if (sSendRecvMgr.sendOrRecv != 0 && sCounter1 > 2)
|
|
{
|
|
EnableSio();
|
|
sSendRecvMgr.field_02 = 2;
|
|
}
|
|
else
|
|
{
|
|
EnableSio();
|
|
sSendRecvMgr.field_02 = 2;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case 4:
|
|
OpenSerialMulti();
|
|
sSendRecvMgr.state = 5;
|
|
break;
|
|
case 5:
|
|
if (sSendRecvMgr.sendOrRecv == 1 && sCounter1 > 2)
|
|
EnableSio();
|
|
if (++sCounter1 > 60)
|
|
{
|
|
sSendRecvMgr.field_04 = 1;
|
|
sSendRecvMgr.state = 6;
|
|
}
|
|
break;
|
|
case 6:
|
|
if (sSendRecvMgr.field_02 != 0)
|
|
{
|
|
CloseSerial();
|
|
sSendRecvMgr.field_02 = 0;
|
|
}
|
|
break;
|
|
}
|
|
return sSendRecvMgr.field_02 | (sSendRecvMgr.field_04 << 2) | (sSendRecvMgr.field_03 << 4);
|
|
}
|
|
|
|
static bool16 DetermineSendRecvState(u8 mode)
|
|
{
|
|
bool16 resp;
|
|
if ((*(vu32 *)REG_ADDR_SIOCNT & (SIO_MULTI_SI | SIO_MULTI_SD)) == SIO_MULTI_SD && mode)
|
|
resp = sSendRecvMgr.sendOrRecv = TRUE;
|
|
else
|
|
resp = sSendRecvMgr.sendOrRecv = FALSE;
|
|
return resp;
|
|
}
|
|
|
|
static void SetUpTransferManager(size_t size, const void * data, void * recvBuffer)
|
|
{
|
|
if (sSendRecvMgr.sendOrRecv)
|
|
{
|
|
REG_SIOCNT |= SIO_38400_BPS;
|
|
sSendRecvMgr.dataptr = (void *)data;
|
|
REG_SIODATA32 = size;
|
|
sSendRecvMgr.size = size / 4 + 1;
|
|
StartTm3();
|
|
}
|
|
else
|
|
{
|
|
REG_SIOCNT |= SIO_9600_BPS;
|
|
sSendRecvMgr.dataptr = recvBuffer;
|
|
}
|
|
}
|
|
|
|
static void StartTm3(void)
|
|
{
|
|
REG_TM3CNT_L = -601;
|
|
REG_TM3CNT_H = TIMER_INTR_ENABLE;
|
|
REG_IME = 0;
|
|
REG_IE |= INTR_FLAG_TIMER3;
|
|
REG_IME = 1;
|
|
}
|
|
|
|
void EReaderHelper_Timer3Callback(void)
|
|
{
|
|
DisableTm3();
|
|
EnableSio();
|
|
}
|
|
|
|
void EReaderHelper_SerialCallback(void)
|
|
{
|
|
u16 recv[4];
|
|
u16 i;
|
|
u16 cnt1;
|
|
u16 cnt2;
|
|
u32 recv32;
|
|
|
|
switch (sSendRecvMgr.state)
|
|
{
|
|
case 1:
|
|
REG_SIOMLT_SEND = 0xCCD0;
|
|
*(u64 *)recv = REG_SIOMLT_RECV;
|
|
for (i = 0, cnt1 = 0, cnt2 = 0; i < 4; i++)
|
|
{
|
|
if (recv[i] == 0xCCD0)
|
|
cnt1++;
|
|
else if (recv[i] != 0xFFFF)
|
|
cnt2++;
|
|
}
|
|
if (cnt1 == 2 && cnt2 == 0)
|
|
sSendRecvMgr.state = 2;
|
|
break;
|
|
case 3:
|
|
recv32 = REG_SIODATA32;
|
|
if (sSendRecvMgr.cursor == 0 && sSendRecvMgr.sendOrRecv == 0)
|
|
sSendRecvMgr.size = recv32 / 4 + 1;
|
|
if (sSendRecvMgr.sendOrRecv == 1)
|
|
{
|
|
if (sSendRecvMgr.cursor < sSendRecvMgr.size)
|
|
{
|
|
REG_SIODATA32 = sSendRecvMgr.dataptr[sSendRecvMgr.cursor];
|
|
sSendRecvMgr.checksum += sSendRecvMgr.dataptr[sSendRecvMgr.cursor];
|
|
}
|
|
else
|
|
REG_SIODATA32 = sSendRecvMgr.checksum;
|
|
}
|
|
else
|
|
{
|
|
if (sSendRecvMgr.cursor > 0 && sSendRecvMgr.cursor < sSendRecvMgr.size + 1)
|
|
{
|
|
sSendRecvMgr.dataptr[sSendRecvMgr.cursor - 1] = recv32;
|
|
sSendRecvMgr.checksum += recv32;
|
|
}
|
|
else if (sSendRecvMgr.cursor != 0)
|
|
{
|
|
if (sSendRecvMgr.checksum == recv32)
|
|
sSendRecvMgr.field_03 = 1;
|
|
else
|
|
sSendRecvMgr.field_03 = 2;
|
|
}
|
|
sCounter2 = 0;
|
|
}
|
|
sSendRecvMgr.cursor++;
|
|
if (sSendRecvMgr.cursor < sSendRecvMgr.size + 2)
|
|
{
|
|
if (sSendRecvMgr.sendOrRecv != 0)
|
|
REG_TM3CNT_H |= TIMER_ENABLE;
|
|
else
|
|
EnableSio();
|
|
}
|
|
else
|
|
{
|
|
sSendRecvMgr.state = 4;
|
|
sCounter1 = 0;
|
|
}
|
|
break;
|
|
case 5:
|
|
if (sSendRecvMgr.sendOrRecv == 0)
|
|
REG_SIODATA8 = sSendRecvMgr.field_03;
|
|
*(vu64 *)recv = REG_SIOMLT_RECV;
|
|
if (recv[1] == 1 || recv[1] == 2)
|
|
{
|
|
if (sSendRecvMgr.sendOrRecv == 1)
|
|
sSendRecvMgr.field_03 = recv[1];
|
|
sSendRecvMgr.state = 6;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void EnableSio(void)
|
|
{
|
|
REG_SIOCNT |= SIO_ENABLE;
|
|
}
|
|
|
|
static void DisableTm3(void)
|
|
{
|
|
REG_TM3CNT_H &= ~TIMER_ENABLE;
|
|
REG_TM3CNT_L = -601;
|
|
}
|
|
|
|
static void GetKeyInput(void)
|
|
{
|
|
u16 rawKeys = REG_KEYINPUT ^ 0x3FF;
|
|
sJoyNew = rawKeys & ~sJoyNewOrRepeated;
|
|
sJoyNewOrRepeated = rawKeys;
|
|
}
|
|
|
|
void EReaderHelper_SaveRegsState(void)
|
|
{
|
|
sSavedIme = REG_IME;
|
|
sSavedIe = REG_IE;
|
|
sSavedTm3Cnt = REG_TM3CNT_H;
|
|
sSavedSioCnt = REG_SIOCNT;
|
|
sSavedRCnt = REG_RCNT;
|
|
}
|
|
|
|
void EReaderHelper_RestoreRegsState(void)
|
|
{
|
|
REG_IME = sSavedIme;
|
|
REG_IE = sSavedIe;
|
|
REG_TM3CNT_H = sSavedTm3Cnt;
|
|
REG_SIOCNT = sSavedSioCnt;
|
|
REG_RCNT = sSavedRCnt;
|
|
}
|
|
|
|
void EReaderHelper_ClearsSendRecvMgr(void)
|
|
{
|
|
CpuFill32(0, &sSendRecvMgr, sizeof(sSendRecvMgr));
|
|
}
|