Sync ereader_helpers with pokefirered

This commit is contained in:
GriffinR 2021-04-23 17:04:44 -04:00
parent f823cd224f
commit 004c37bf02
4 changed files with 227 additions and 204 deletions

View File

@ -24,11 +24,11 @@ struct EReaderTrainerHillSet
bool8 EReader_IsReceivedDataValid(struct EReaderTrainerHillSet *buffer);
bool32 TryWriteTrainerHill(struct EReaderTrainerHillSet *arg0);
bool32 ReadTrainerHillAndValidate(void);
int EReaderHandleTransfer(u8, u32, u32*, u32*);
void sub_81D3F9C(void);
void sub_81D3FAC(void);
int EReaderHandleTransfer(u8, size_t, const void *, void *);
void EReaderHelper_Timer3Callback(void);
void EReaderHelper_SerialCallback(void);
void EReaderHelper_SaveRegsState(void);
void EReaderHelper_RestoreRegsState(void);
void sub_81D4238(void);
void EReaderHelper_ClearSendRecvMgr(void);
#endif // GUARD_EREADER_HELPERS_H

View File

@ -323,7 +323,7 @@ extern bool8 gSavedLinkPlayerCount;
extern u8 gSavedMultiplayerId;
extern struct LinkTestBGInfo gLinkTestBGInfo;
extern void (*gLinkCallback)(void);
extern bool8 gShouldAdvanceLinkState;
extern u8 gShouldAdvanceLinkState;
extern u16 gLinkTestBlockChecksums[MAX_LINK_PLAYERS];
extern u8 gBlockRequestType;
extern u8 gLastSendQueueCount;

View File

@ -15,33 +15,62 @@
#include "constants/moves.h"
#include "constants/items.h"
struct Unknown030012C8
{
u8 unk0[8];
u32 *unk8;
int unkC;
int unk10;
int unk14;
enum {
EREADER_XFR_STATE_INIT = 0,
EREADER_XFR_STATE_HANDSHAKE,
EREADER_XFR_STATE_START,
EREADER_XFR_STATE_TRANSFER,
EREADER_XFR_STATE_TRANSFER_DONE,
EREADER_XFR_STATE_CHECKSUM,
EREADER_XFR_STATE_DONE
};
static void sub_81D4170(void);
static u16 sub_81D3EE8(u8);
static void sub_81D413C(void);
static void sub_81D414C(void);
static void sub_81D3F1C(u32, u32*, u32*);
static void sub_81D3F68(void);
#define EREADER_XFER_EXE 1
#define EREADER_XFER_CHK 2
#define EREADER_XFER_SHIFT 0
#define EREADER_XFER_MASK 3
static struct Unknown030012C8 gUnknown_030012C8;
static u16 gUnknown_030012E0;
static u16 gUnknown_030012E2;
static u16 gUnknown_030012E4;
static u16 gUnknown_030012E6;
static u32 gUnknown_030012E8;
static u16 gUnknown_030012EC;
static u16 gUnknown_030012EE;
static u16 gUnknown_030012F0;
static u16 gUnknown_030012F2;
static u16 gUnknown_030012F4;
#define EREADER_CANCEL_TIMEOUT 1
#define EREADER_CANCEL_KEY 2
#define EREADER_CANCEL_MASK 0xC
#define EREADER_CANCEL_SHIFT 2
#define EREADER_CHECKSUM_OK 1
#define EREADER_CHECKSUM_ERR 2
#define EREADER_CHECKSUM_MASK 0x30
#define EREADER_CHECKSUM_SHIFT 4
struct SendRecvMgr
{
bool8 isParent;
u8 state; // EREADER_XFR_STATE_*
u8 xferState; // EREADER_XFER_*
u8 checksumResult; // EREADER_CHECKSUM_*
u8 cancellationReason; // EREADER_CANCEL_*
u32 *data; // Payload source or destination
int cursor; // Index of the next word
int size; // Last word index
int checksum;
};
static void GetKeyInput(void);
static u16 DetermineSendRecvState(u8);
static void EnableSio(void);
static void DisableTm3(void);
static void SetUpTransferManager(size_t, const void *, void *);
static void StartTm3(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 sSavedRCnt;
static const struct TrainerHillTrainer sTrainerHillTrainerTemplates_JP[] = {
[0] = {
@ -514,93 +543,89 @@ bool32 ReadTrainerHillAndValidate(void)
return result;
}
int EReader_Send(int arg0, u32 *arg1)
int EReader_Send(int size, const void * src)
{
int result;
u16 var0;
int var1;
int sendStatus;
EReaderHelper_SaveRegsState();
while (1)
{
sub_81D4170();
if (gUnknown_030012E2 & 2)
GetKeyInput();
if (sJoyNew & B_BUTTON)
gShouldAdvanceLinkState = 2;
var1 = EReaderHandleTransfer(1, arg0, arg1, NULL);
gUnknown_030012E4 = var1;
if ((gUnknown_030012E4 & 0x13) == 0x10)
sendStatus = EReaderHandleTransfer(1, size, src, NULL);
sSendRecvStatus = sendStatus;
if ((sSendRecvStatus & 0x13) == 0x10)
{
result = 0;
break;
}
if (gUnknown_030012E4 & 0x8)
else if (sSendRecvStatus & 0x8)
{
result = 1;
break;
}
var0 = gUnknown_030012E4 & 0x4;
if (var0)
else if (sSendRecvStatus & 0x4)
{
result = 2;
break;
}
gShouldAdvanceLinkState = var0;
VBlankIntrWait();
else
{
gShouldAdvanceLinkState = 0;
VBlankIntrWait();
}
}
CpuFill32(0, &gUnknown_030012C8, sizeof(struct Unknown030012C8));
CpuFill32(0, &sSendRecvMgr, sizeof(sSendRecvMgr));
EReaderHelper_RestoreRegsState();
return result;
}
int EReader_Recv(u32 *arg0)
int EReader_Recv(void * dest)
{
int result;
u16 var0;
int var1;
int recvStatus;
EReaderHelper_SaveRegsState();
while (1)
{
sub_81D4170();
if (gUnknown_030012E2 & 2)
GetKeyInput();
if (sJoyNew & B_BUTTON)
gShouldAdvanceLinkState = 2;
var1 = EReaderHandleTransfer(0, 0, NULL, arg0);
gUnknown_030012E4 = var1;
if ((gUnknown_030012E4 & 0x13) == 0x10)
recvStatus = EReaderHandleTransfer(0, 0, NULL, dest);
sSendRecvStatus = recvStatus;
if ((sSendRecvStatus & 0x13) == 0x10)
{
result = 0;
break;
}
if (gUnknown_030012E4 & 0x8)
else if (sSendRecvStatus & 0x8)
{
result = 1;
break;
}
var0 = gUnknown_030012E4 & 0x4;
if (var0)
else if (sSendRecvStatus & 0x4)
{
result = 2;
break;
}
gShouldAdvanceLinkState = var0;
VBlankIntrWait();
else
{
gShouldAdvanceLinkState = 0;
VBlankIntrWait();
}
}
CpuFill32(0, &gUnknown_030012C8, sizeof(struct Unknown030012C8));
CpuFill32(0, &sSendRecvMgr, sizeof(sSendRecvMgr));
EReaderHelper_RestoreRegsState();
return result;
}
static void sub_81D3C7C(void)
static void CloseSerial(void)
{
REG_IME = 0;
REG_IE &= ~(INTR_FLAG_TIMER3 | INTR_FLAG_SERIAL);
@ -610,7 +635,7 @@ static void sub_81D3C7C(void)
REG_IF = INTR_FLAG_TIMER3 | INTR_FLAG_SERIAL;
}
static void sub_81D3CBC(void)
static void OpenSerialMulti(void)
{
REG_IME = 0;
REG_IE &= ~(INTR_FLAG_TIMER3 | INTR_FLAG_SERIAL);
@ -622,273 +647,271 @@ static void sub_81D3CBC(void)
REG_IE |= INTR_FLAG_SERIAL;
REG_IME = 1;
if (!gUnknown_030012C8.unk0[1])
CpuFill32(0, &gUnknown_030012C8, sizeof(struct Unknown030012C8));
if (sSendRecvMgr.state == 0)
CpuFill32(0, &sSendRecvMgr, sizeof(sSendRecvMgr));
}
static void sub_81D3D34(void)
static void OpenSerial32(void)
{
REG_RCNT = 0;
REG_SIOCNT = SIO_32BIT_MODE | SIO_INTR_ENABLE;
REG_SIOCNT |= SIO_MULTI_SD;
gShouldAdvanceLinkState = 0;
gUnknown_030012E6 = 0;
gUnknown_030012E8 = 0;
sCounter1 = 0;
sCounter2 = 0;
}
int EReaderHandleTransfer(u8 arg0, u32 arg1, u32 *arg2, u32 *arg3)
int EReaderHandleTransfer(u8 mode, size_t size, const void * data, void * recvBuffer)
{
switch (gUnknown_030012C8.unk0[1])
switch (sSendRecvMgr.state)
{
case 0:
sub_81D3CBC();
gUnknown_030012C8.unk0[2] = 1;
gUnknown_030012C8.unk0[1] = 1;
case EREADER_XFR_STATE_INIT:
OpenSerialMulti();
sSendRecvMgr.xferState = EREADER_XFER_EXE;
sSendRecvMgr.state = EREADER_XFR_STATE_HANDSHAKE;
break;
case 1:
if (sub_81D3EE8(arg0))
sub_81D413C();
case EREADER_XFR_STATE_HANDSHAKE:
if (DetermineSendRecvState(mode))
EnableSio();
if (gShouldAdvanceLinkState == 2)
{
gUnknown_030012C8.unk0[4] = 2;
gUnknown_030012C8.unk0[1] = 6;
sSendRecvMgr.cancellationReason = EREADER_CANCEL_KEY;
sSendRecvMgr.state = EREADER_XFR_STATE_DONE;
}
break;
case 2:
sub_81D3D34();
sub_81D3F1C(arg1, arg2, arg3);
gUnknown_030012C8.unk0[1] = 3;
case EREADER_XFR_STATE_START:
OpenSerial32();
SetUpTransferManager(size, data, recvBuffer);
sSendRecvMgr.state = EREADER_XFR_STATE_TRANSFER;
// fall through
case 3:
case EREADER_XFR_STATE_TRANSFER:
if (gShouldAdvanceLinkState == 2)
{
gUnknown_030012C8.unk0[4] = 2;
gUnknown_030012C8.unk0[1] = 6;
sSendRecvMgr.cancellationReason = EREADER_CANCEL_KEY;
sSendRecvMgr.state = EREADER_XFR_STATE_DONE;
}
else
{
gUnknown_030012E6++;
gUnknown_030012E8++;
if (!gUnknown_030012C8.unk0[0] && gUnknown_030012E8 > 60)
sCounter1++;
sCounter2++;
if (!sSendRecvMgr.isParent && sCounter2 > 60)
{
gUnknown_030012C8.unk0[4] = 1;
gUnknown_030012C8.unk0[1] = 6;
sSendRecvMgr.cancellationReason = EREADER_CANCEL_TIMEOUT;
sSendRecvMgr.state = EREADER_XFR_STATE_DONE;
}
if (gUnknown_030012C8.unk0[2] != 2)
if (sSendRecvMgr.xferState != EREADER_XFER_CHK)
{
if (gUnknown_030012C8.unk0[0] && gUnknown_030012E6 > 2)
if (sSendRecvMgr.isParent && sCounter1 > 2)
{
sub_81D413C();
gUnknown_030012C8.unk0[2] = 2;
EnableSio();
sSendRecvMgr.xferState = EREADER_XFER_CHK;
}
else
{
sub_81D413C();
gUnknown_030012C8.unk0[2] = 2;
EnableSio();
sSendRecvMgr.xferState = EREADER_XFER_CHK;
}
}
}
break;
case 4:
sub_81D3CBC();
gUnknown_030012C8.unk0[1] = 5;
case EREADER_XFR_STATE_TRANSFER_DONE:
OpenSerialMulti();
sSendRecvMgr.state = EREADER_XFR_STATE_CHECKSUM;
break;
case 5:
if (gUnknown_030012C8.unk0[0] == 1 && gUnknown_030012E6 > 2)
sub_81D413C();
case EREADER_XFR_STATE_CHECKSUM:
if (sSendRecvMgr.isParent == TRUE && sCounter1 > 2)
EnableSio();
if (++gUnknown_030012E6 > 60)
if (++sCounter1 > 60)
{
gUnknown_030012C8.unk0[4] = 1;
gUnknown_030012C8.unk0[1] = 6;
sSendRecvMgr.cancellationReason = EREADER_CANCEL_TIMEOUT;
sSendRecvMgr.state = EREADER_XFR_STATE_DONE;
}
break;
case 6:
if (gUnknown_030012C8.unk0[2])
case EREADER_XFR_STATE_DONE:
if (sSendRecvMgr.xferState)
{
sub_81D3C7C();
gUnknown_030012C8.unk0[2] = 0;
CloseSerial();
sSendRecvMgr.xferState = 0;
}
break;
}
return gUnknown_030012C8.unk0[2] | (gUnknown_030012C8.unk0[4] << 2) | (gUnknown_030012C8.unk0[3] << 4);
return (sSendRecvMgr.xferState << EREADER_XFER_SHIFT)
| (sSendRecvMgr.cancellationReason << EREADER_CANCEL_SHIFT)
| (sSendRecvMgr.checksumResult << EREADER_CHECKSUM_SHIFT);
}
static u16 sub_81D3EE8(u8 arg0)
static u16 DetermineSendRecvState(u8 mode)
{
u16 terminal = (*(vu32 *)REG_ADDR_SIOCNT) & (SIO_MULTI_SI | SIO_MULTI_SD);
if (terminal == SIO_MULTI_SD && arg0)
{
gUnknown_030012C8.unk0[0] = 1;
return 1;
}
bool16 resp;
if ((*(vu32 *)REG_ADDR_SIOCNT & (SIO_MULTI_SI | SIO_MULTI_SD)) == SIO_MULTI_SD && mode)
resp = sSendRecvMgr.isParent = TRUE;
else
{
gUnknown_030012C8.unk0[0] = 0;
return 0;
}
resp = sSendRecvMgr.isParent = FALSE;
return resp;
}
static void sub_81D3F1C(u32 arg0, u32 *arg1, u32 *arg2)
static void SetUpTransferManager(size_t size, const void * data, void * recvBuffer)
{
if (gUnknown_030012C8.unk0[0])
if (sSendRecvMgr.isParent)
{
REG_SIOCNT |= SIO_38400_BPS;
gUnknown_030012C8.unk8 = arg1;
REG_SIODATA32 = arg0;
gUnknown_030012C8.unk10 = arg0 / 4 + 1;
sub_81D3F68();
sSendRecvMgr.data = (void *)data;
REG_SIODATA32 = size;
sSendRecvMgr.size = size / 4 + 1;
StartTm3();
}
else
{
REG_SIOCNT = REG_SIOCNT;
gUnknown_030012C8.unk8 = arg2;
sSendRecvMgr.data = recvBuffer;
}
}
static void sub_81D3F68(void)
static void StartTm3(void)
{
REG_TM3CNT_L = 0xFDA7;
REG_TM3CNT_L = -601;
REG_TM3CNT_H = TIMER_INTR_ENABLE;
REG_IME = 0;
REG_IE |= INTR_FLAG_TIMER3;
REG_IME = 1;
}
void sub_81D3F9C(void)
void EReaderHelper_Timer3Callback(void)
{
sub_81D414C();
sub_81D413C();
DisableTm3();
EnableSio();
}
void sub_81D3FAC(void)
void EReaderHelper_SerialCallback(void)
{
u16 i, playerCount, k;
u32 value;
u16 var0;
u16 recvBuffer[4];
u16 i, cnt1, cnt2;
u32 recv32;
u16 recv[4];
switch (gUnknown_030012C8.unk0[1])
switch (sSendRecvMgr.state)
{
case 1:
case EREADER_XFR_STATE_HANDSHAKE:
REG_SIOMLT_SEND = 0xCCD0; // Handshake id
*(u64 *)recvBuffer = REG_SIOMLT_RECV;
for (i = 0, playerCount = 0, k = 0; i < 4; i++)
*(u64 *)recv = REG_SIOMLT_RECV;
for (i = 0, cnt1 = 0, cnt2 = 0; i < 4; i++)
{
if (recvBuffer[i] == 0xCCD0)
playerCount++;
else if (recvBuffer[i] != 0xFFFF)
k++;
if (recv[i] == 0xCCD0)
cnt1++;
else if (recv[i] != 0xFFFF)
cnt2++;
}
if (playerCount == 2 && k == 0)
gUnknown_030012C8.unk0[1] = 2;
if (cnt1 == 2 && cnt2 == 0)
sSendRecvMgr.state = 2;
break;
case 3:
value = REG_SIODATA32;
if (!gUnknown_030012C8.unkC && !gUnknown_030012C8.unk0[0])
gUnknown_030012C8.unk10 = value / 4 + 1;
case EREADER_XFR_STATE_TRANSFER:
recv32 = REG_SIODATA32;
// The first value sent by the EReader is the payload size
if (!sSendRecvMgr.cursor && !sSendRecvMgr.isParent)
sSendRecvMgr.size = recv32 / 4 + 1;
if (gUnknown_030012C8.unk0[0] == 1)
if (sSendRecvMgr.isParent == TRUE)
{
if (gUnknown_030012C8.unkC < gUnknown_030012C8.unk10)
// Send mode
if (sSendRecvMgr.cursor < sSendRecvMgr.size)
{
REG_SIODATA32 = gUnknown_030012C8.unk8[gUnknown_030012C8.unkC];
gUnknown_030012C8.unk14 += gUnknown_030012C8.unk8[gUnknown_030012C8.unkC];
REG_SIODATA32 = sSendRecvMgr.data[sSendRecvMgr.cursor];
sSendRecvMgr.checksum += sSendRecvMgr.data[sSendRecvMgr.cursor];
}
else
{
REG_SIODATA32 = gUnknown_030012C8.unk14;
REG_SIODATA32 = sSendRecvMgr.checksum;
}
}
else
{
if (gUnknown_030012C8.unkC > 0 && gUnknown_030012C8.unkC < gUnknown_030012C8.unk10 + 1)
// Receive mode
if (sSendRecvMgr.cursor > 0 && sSendRecvMgr.cursor < sSendRecvMgr.size + 1)
{
gUnknown_030012C8.unk8[gUnknown_030012C8.unkC - 1] = value;
gUnknown_030012C8.unk14 += value;
sSendRecvMgr.data[sSendRecvMgr.cursor - 1] = recv32;
sSendRecvMgr.checksum += recv32;
}
else if (gUnknown_030012C8.unkC)
else if (sSendRecvMgr.cursor)
{
if (gUnknown_030012C8.unk14 == value)
gUnknown_030012C8.unk0[3] = 1;
if (sSendRecvMgr.checksum == recv32)
sSendRecvMgr.checksumResult = EREADER_CHECKSUM_OK;
else
gUnknown_030012C8.unk0[3] = 2;
sSendRecvMgr.checksumResult = EREADER_CHECKSUM_ERR;
}
gUnknown_030012E8 = 0;
sCounter2 = 0;
}
if (++gUnknown_030012C8.unkC < gUnknown_030012C8.unk10 + 2)
if (++sSendRecvMgr.cursor < sSendRecvMgr.size + 2)
{
if (gUnknown_030012C8.unk0[0])
if (sSendRecvMgr.isParent)
REG_TM3CNT_H |= TIMER_ENABLE;
else
sub_81D413C();
EnableSio();
}
else
{
gUnknown_030012C8.unk0[1] = 4;
gUnknown_030012E6 = 0;
sSendRecvMgr.state = EREADER_XFR_STATE_TRANSFER_DONE;
sCounter1 = 0;
}
break;
case 5:
if (!gUnknown_030012C8.unk0[0])
REG_SIOMLT_SEND = gUnknown_030012C8.unk0[3];
case EREADER_XFR_STATE_CHECKSUM:
if (!sSendRecvMgr.isParent)
REG_SIOMLT_SEND = sSendRecvMgr.checksumResult;
*(u64 *)recvBuffer = REG_SIOMLT_RECV;
var0 = recvBuffer[1] - 1;
if (var0 < 2)
*(vu64 *)recv = REG_SIOMLT_RECV;
if (recv[1] == EREADER_CHECKSUM_OK || recv[1] == EREADER_CHECKSUM_ERR)
{
if (gUnknown_030012C8.unk0[0] == 1)
gUnknown_030012C8.unk0[3] = recvBuffer[1];
if (sSendRecvMgr.isParent == TRUE)
sSendRecvMgr.checksumResult = recv[1]; // EReader has (in)validated the payload
gUnknown_030012C8.unk0[1] = 6;
sSendRecvMgr.state = EREADER_XFR_STATE_DONE;
}
break;
}
}
static void sub_81D413C(void)
static void EnableSio(void)
{
REG_SIOCNT |= SIO_ENABLE;
}
static void sub_81D414C(void)
static void DisableTm3(void)
{
REG_TM3CNT_H &= ~TIMER_ENABLE;
REG_TM3CNT_L = 0xFDA7;
}
static void sub_81D4170(void)
static void GetKeyInput(void)
{
int keysMask = REG_KEYINPUT ^ KEYS_MASK;
gUnknown_030012E2 = keysMask & ~gUnknown_030012E0;
gUnknown_030012E0 = keysMask;
int rawKeys = REG_KEYINPUT ^ KEYS_MASK;
sJoyNew = rawKeys & ~sJoyNewOrRepeated;
sJoyNewOrRepeated = rawKeys;
}
void EReaderHelper_SaveRegsState(void)
{
gUnknown_030012EC = REG_IME;
gUnknown_030012EE = REG_IE;
gUnknown_030012F0 = REG_TM3CNT_H;
gUnknown_030012F2 = REG_SIOCNT;
gUnknown_030012F4 = REG_RCNT;
sSavedIme = REG_IME;
sSavedIe = REG_IE;
sSavedTm3Cnt = REG_TM3CNT_H;
sSavedSioCnt = REG_SIOCNT;
sSavedRCnt = REG_RCNT;
}
void EReaderHelper_RestoreRegsState(void)
{
REG_IME = gUnknown_030012EC;
REG_IE = gUnknown_030012EE;
REG_TM3CNT_H = gUnknown_030012F0;
REG_SIOCNT = gUnknown_030012F2;
REG_RCNT = gUnknown_030012F4;
REG_IME = sSavedIme;
REG_IE = sSavedIe;
REG_TM3CNT_H = sSavedTm3Cnt;
REG_SIOCNT = sSavedSioCnt;
REG_RCNT = sSavedRCnt;
}
void sub_81D4238(void)
void EReaderHelper_ClearSendRecvMgr(void)
{
CpuFill32(0, &gUnknown_030012C8, sizeof(struct Unknown030012C8));
CpuFill32(0, &sSendRecvMgr, sizeof(sSendRecvMgr));
}

View File

@ -47,10 +47,10 @@ static void sub_81D4D50(struct Unk03006370 *arg0, int arg1, u32 *arg2)
{
volatile u16 backupIME = REG_IME;
REG_IME = 0;
gIntrTable[1] = sub_81D3FAC;
gIntrTable[2] = sub_81D3F9C;
gIntrTable[1] = EReaderHelper_SerialCallback;
gIntrTable[2] = EReaderHelper_Timer3Callback;
EReaderHelper_SaveRegsState();
sub_81D4238();
EReaderHelper_ClearSendRecvMgr();
REG_IE |= INTR_FLAG_VCOUNT;
REG_IME = backupIME;
arg0->unk0 = 0;
@ -62,7 +62,7 @@ static void sub_81D4DB8(struct Unk03006370 *arg0)
{
volatile u16 backupIME = REG_IME;
REG_IME = 0;
sub_81D4238();
EReaderHelper_ClearSendRecvMgr();
EReaderHelper_RestoreRegsState();
RestoreSerialTimer3IntrHandlers();
REG_IME = backupIME;