Merge pull request #1418 from GriffinRichards/sync-ereaderhelp

Sync e-reader helpers, document trainer hill e-reader
This commit is contained in:
GriffinR 2021-04-28 06:08:57 -04:00 committed by GitHub
commit 58cef0ae52
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 289 additions and 261 deletions

View File

@ -37,8 +37,9 @@
#define TRAINER_HILL_TEXT_PLAYER_WON 4 #define TRAINER_HILL_TEXT_PLAYER_WON 4
#define TRAINER_HILL_TEXT_AFTER 5 #define TRAINER_HILL_TEXT_AFTER 5
#define NUM_TRAINER_HILL_TRAINERS (NUM_TRAINER_HILL_FLOORS * 2) #define TRAINER_HILL_TRAINERS_PER_FLOOR 2
#define NUM_TRAINER_HILL_TRAINERS_JP (NUM_TRAINER_HILL_FLOORS_JP * 2) #define NUM_TRAINER_HILL_TRAINERS (NUM_TRAINER_HILL_FLOORS * TRAINER_HILL_TRAINERS_PER_FLOOR)
#define NUM_TRAINER_HILL_TRAINERS_JP (NUM_TRAINER_HILL_FLOORS_JP * TRAINER_HILL_TRAINERS_PER_FLOOR)
// Values returned by TrainerHillGetChallengeStatus // Values returned by TrainerHillGetChallengeStatus
#define TRAINER_HILL_PLAYER_STATUS_LOST 0 #define TRAINER_HILL_PLAYER_STATUS_LOST 0

View File

@ -5,30 +5,29 @@
struct EReaderTrainerHillTrainer struct EReaderTrainerHillTrainer
{ {
u8 unk0; u8 trainerNum;
struct TrainerHillTrainer unk4; struct TrainerHillTrainer trainer;
struct TrHillDisplay unk14C; struct TrHillDisplay display;
u32 checksum; u32 checksum;
}; // size=0x274 }; // size=0x274
struct EReaderTrainerHillSet struct EReaderTrainerHillSet
{ {
u8 count; u8 numTrainers;
u8 id; u8 id;
u16 dummy;
u32 checksum; u32 checksum;
struct EReaderTrainerHillTrainer unk_8[6]; struct EReaderTrainerHillTrainer trainers[6];
u8 unk_ec0[40]; u8 unk_ec0[40];
}; // size = 0xf00 }; // size = 0xf00
bool8 EReader_IsReceivedDataValid(struct EReaderTrainerHillSet *buffer); bool8 ValidateTrainerHillData(struct EReaderTrainerHillSet *);
bool32 TryWriteTrainerHill(struct EReaderTrainerHillSet *arg0); bool32 TryWriteTrainerHill(struct EReaderTrainerHillSet *);
bool32 ReadTrainerHillAndValidate(void); bool32 ReadTrainerHillAndValidate(void);
int EReaderHandleTransfer(u8, u32, u32*, u32*); int EReaderHandleTransfer(u8, size_t, const void *, void *);
void sub_81D3F9C(void); void EReaderHelper_Timer3Callback(void);
void sub_81D3FAC(void); void EReaderHelper_SerialCallback(void);
void EReaderHelper_SaveRegsState(void); void EReaderHelper_SaveRegsState(void);
void EReaderHelper_RestoreRegsState(void); void EReaderHelper_RestoreRegsState(void);
void sub_81D4238(void); void EReaderHelper_ClearSendRecvMgr(void);
#endif // GUARD_EREADER_HELPERS_H #endif // GUARD_EREADER_HELPERS_H

View File

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

View File

@ -14,34 +14,64 @@
#include "constants/trainers.h" #include "constants/trainers.h"
#include "constants/moves.h" #include "constants/moves.h"
#include "constants/items.h" #include "constants/items.h"
#include "constants/trainer_hill.h"
struct Unknown030012C8 enum {
{ EREADER_XFR_STATE_INIT = 0,
u8 unk0[8]; EREADER_XFR_STATE_HANDSHAKE,
u32 *unk8; EREADER_XFR_STATE_START,
int unkC; EREADER_XFR_STATE_TRANSFER,
int unk10; EREADER_XFR_STATE_TRANSFER_DONE,
int unk14; EREADER_XFR_STATE_CHECKSUM,
EREADER_XFR_STATE_DONE
}; };
static void sub_81D4170(void); #define EREADER_XFER_EXE 1
static u16 sub_81D3EE8(u8); #define EREADER_XFER_CHK 2
static void sub_81D413C(void); #define EREADER_XFER_SHIFT 0
static void sub_81D414C(void); #define EREADER_XFER_MASK 3
static void sub_81D3F1C(u32, u32*, u32*);
static void sub_81D3F68(void);
static struct Unknown030012C8 gUnknown_030012C8; #define EREADER_CANCEL_TIMEOUT 1
static u16 gUnknown_030012E0; #define EREADER_CANCEL_KEY 2
static u16 gUnknown_030012E2; #define EREADER_CANCEL_MASK 0xC
static u16 gUnknown_030012E4; #define EREADER_CANCEL_SHIFT 2
static u16 gUnknown_030012E6;
static u32 gUnknown_030012E8; #define EREADER_CHECKSUM_OK 1
static u16 gUnknown_030012EC; #define EREADER_CHECKSUM_ERR 2
static u16 gUnknown_030012EE; #define EREADER_CHECKSUM_MASK 0x30
static u16 gUnknown_030012F0; #define EREADER_CHECKSUM_SHIFT 4
static u16 gUnknown_030012F2;
static u16 gUnknown_030012F4; 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[] = { static const struct TrainerHillTrainer sTrainerHillTrainerTemplates_JP[] = {
[0] = { [0] = {
@ -390,217 +420,217 @@ static const struct TrainerHillTrainer sTrainerHillTrainerTemplates_JP[] = {
}, },
}; };
static u8 sub_81D38D4(void) static u8 GetTrainerHillUnkVal(void)
{ {
return (gSaveBlock1Ptr->trainerHill.unused + 1) % 256; return (gSaveBlock1Ptr->trainerHill.unused + 1) % 256;
} }
static bool32 Struct_EReaderTrainerHillTrainer_ValidateChecksum(struct EReaderTrainerHillTrainer *arg0) static bool32 ValidateTrainerChecksum(struct EReaderTrainerHillTrainer * hillTrainer)
{ {
int checksum = CalcByteArraySum((u8 *)arg0, 0x270); int checksum = CalcByteArraySum((u8 *)hillTrainer, offsetof(typeof(*hillTrainer), checksum));
if (checksum != arg0->checksum) if (checksum != hillTrainer->checksum)
return FALSE; return FALSE;
return TRUE; return TRUE;
} }
bool8 EReader_IsReceivedDataValid(struct EReaderTrainerHillSet *buffer) bool8 ValidateTrainerHillData(struct EReaderTrainerHillSet * hillSet)
{ {
u32 i; u32 i;
u32 checksum; u32 checksum;
int var0 = buffer->count; int numTrainers = hillSet->numTrainers;
if (var0 < 1 || var0 > 8)
// Validate number of trainers
if (numTrainers < 1 || numTrainers > NUM_TRAINER_HILL_TRAINERS)
return FALSE; return FALSE;
for (i = 0; i < var0; i++) // Validate trainers
for (i = 0; i < numTrainers; i++)
{ {
if (!Struct_EReaderTrainerHillTrainer_ValidateChecksum(&buffer->unk_8[i])) if (!ValidateTrainerChecksum(&hillSet->trainers[i]))
return FALSE; return FALSE;
} }
checksum = CalcByteArraySum((u8 *)buffer->unk_8, var0 * sizeof(struct EReaderTrainerHillTrainer)); // Validate checksum
if (checksum != buffer->checksum) checksum = CalcByteArraySum((u8 *)hillSet->trainers, numTrainers * sizeof(struct EReaderTrainerHillTrainer));
if (checksum != hillSet->checksum)
return FALSE; return FALSE;
return TRUE; return TRUE;
} }
static bool32 TrainerHill_VerifyChecksum(struct EReaderTrainerHillSet *buffer) static bool32 ValidateTrainerHillChecksum(struct EReaderTrainerHillSet *hillSet)
{ {
u32 checksum; u32 checksum;
int var0 = buffer->count; int numTrainers = hillSet->numTrainers;
if (var0 < 1 || var0 > 8) if (numTrainers < 1 || numTrainers > NUM_TRAINER_HILL_TRAINERS)
return FALSE; return FALSE;
checksum = CalcByteArraySum((u8 *)buffer->unk_8, sizeof(struct EReaderTrainerHillSet) - offsetof(struct EReaderTrainerHillSet, unk_8)); checksum = CalcByteArraySum((u8 *)hillSet->trainers, sizeof(struct EReaderTrainerHillSet) - offsetof(struct EReaderTrainerHillSet, trainers));
if (checksum != buffer->checksum) if (checksum != hillSet->checksum)
return FALSE; return FALSE;
return TRUE; return TRUE;
} }
static bool32 TryWriteTrainerHill_r(struct EReaderTrainerHillSet *ttdata, struct TrHillTag *buffer2) static bool32 TryWriteTrainerHill_Internal(struct EReaderTrainerHillSet * hillSet, struct TrHillTag * hillTag)
{ {
int i; int i;
AGB_ASSERT_EX(ttdata->dummy == 0, "cereader_tool.c", 450); AGB_ASSERT_EX(hillSet->dummy == 0, "cereader_tool.c", 450);
AGB_ASSERT_EX(ttdata->id == 0, "cereader_tool.c", 452); AGB_ASSERT_EX(hillSet->id == 0, "cereader_tool.c", 452);
memset(buffer2, 0, 0x1000); memset(hillTag, 0, SECTOR_SIZE);
buffer2->numTrainers = ttdata->count; hillTag->numTrainers = hillSet->numTrainers;
buffer2->unused1 = sub_81D38D4(); hillTag->unused1 = GetTrainerHillUnkVal();
buffer2->numFloors = (ttdata->count + 1) / 2; hillTag->numFloors = (hillSet->numTrainers + 1) / TRAINER_HILL_TRAINERS_PER_FLOOR;
for (i = 0; i < ttdata->count; i++) for (i = 0; i < hillSet->numTrainers; i++)
{ {
if (!(i & 1)) if (!(i & 1))
{ {
buffer2->floors[i / 2].trainerNum1 = ttdata->unk_8[i].unk0; hillTag->floors[i / TRAINER_HILL_TRAINERS_PER_FLOOR].trainerNum1 = hillSet->trainers[i].trainerNum;
buffer2->floors[i / 2].display = ttdata->unk_8[i].unk14C; hillTag->floors[i / TRAINER_HILL_TRAINERS_PER_FLOOR].display = hillSet->trainers[i].display;
buffer2->floors[i / 2].trainers[0] = ttdata->unk_8[i].unk4; hillTag->floors[i / TRAINER_HILL_TRAINERS_PER_FLOOR].trainers[0] = hillSet->trainers[i].trainer;
} }
else else
{ {
buffer2->floors[i / 2].trainerNum2 = ttdata->unk_8[i].unk0; hillTag->floors[i / TRAINER_HILL_TRAINERS_PER_FLOOR].trainerNum2 = hillSet->trainers[i].trainerNum;
buffer2->floors[i / 2].trainers[1] = ttdata->unk_8[i].unk4; hillTag->floors[i / TRAINER_HILL_TRAINERS_PER_FLOOR].trainers[1] = hillSet->trainers[i].trainer;
} }
} }
if (i & 1) if (i & 1)
{ {
buffer2->floors[i / 2].trainers[1] = sTrainerHillTrainerTemplates_JP[i / 2]; hillTag->floors[i / TRAINER_HILL_TRAINERS_PER_FLOOR].trainers[1] = sTrainerHillTrainerTemplates_JP[i / TRAINER_HILL_TRAINERS_PER_FLOOR];
} }
buffer2->checksum = CalcByteArraySum((u8 *)buffer2->floors, 4 * sizeof(struct TrHillFloor)); hillTag->checksum = CalcByteArraySum((u8 *)hillTag->floors, NUM_TRAINER_HILL_FLOORS * sizeof(struct TrHillFloor));
if (TryWriteSpecialSaveSection(SECTOR_ID_TRAINER_HILL, (u8 *)buffer2) != SAVE_STATUS_OK) if (TryWriteSpecialSaveSection(SECTOR_ID_TRAINER_HILL, (u8 *)hillTag) != SAVE_STATUS_OK)
return FALSE; return FALSE;
return TRUE; return TRUE;
} }
bool32 TryWriteTrainerHill(struct EReaderTrainerHillSet *arg0) bool32 TryWriteTrainerHill(struct EReaderTrainerHillSet * hillSet)
{ {
void *var0 = AllocZeroed(0x1000); void *buffer = AllocZeroed(SECTOR_SIZE);
bool32 result = TryWriteTrainerHill_r(arg0, var0); bool32 result = TryWriteTrainerHill_Internal(hillSet, buffer);
Free(var0); Free(buffer);
return result; return result;
} }
static bool32 TryReadTrainerHill_r(struct EReaderTrainerHillSet *dst, u8 *buffer) static bool32 TryReadTrainerHill_Internal(struct EReaderTrainerHillSet * dest, u8 * buffer)
{ {
if (TryReadSpecialSaveSection(SECTOR_ID_TRAINER_HILL, buffer) != SAVE_STATUS_OK) if (TryReadSpecialSaveSection(SECTOR_ID_TRAINER_HILL, buffer) != SAVE_STATUS_OK)
return FALSE; return FALSE;
memcpy(dst, buffer, sizeof(struct EReaderTrainerHillSet)); memcpy(dest, buffer, sizeof(struct EReaderTrainerHillSet));
if (!TrainerHill_VerifyChecksum(dst)) if (!ValidateTrainerHillChecksum(dest))
return FALSE; return FALSE;
return TRUE; return TRUE;
} }
static bool32 TryReadTrainerHill(struct EReaderTrainerHillSet *arg0) static bool32 TryReadTrainerHill(struct EReaderTrainerHillSet * hillSet)
{ {
u8 *var0 = AllocZeroed(0x1000); u8 *buffer = AllocZeroed(SECTOR_SIZE);
bool32 result = TryReadTrainerHill_r(arg0, var0); bool32 result = TryReadTrainerHill_Internal(hillSet, buffer);
Free(var0); Free(buffer);
return result; return result;
} }
bool32 ReadTrainerHillAndValidate(void) bool32 ReadTrainerHillAndValidate(void)
{ {
struct EReaderTrainerHillSet *var0 = AllocZeroed(0x1000); struct EReaderTrainerHillSet *hillSet = AllocZeroed(SECTOR_SIZE);
bool32 result = TryReadTrainerHill(var0); bool32 result = TryReadTrainerHill(hillSet);
Free(var0); Free(hillSet);
return result; return result;
} }
int EReader_Send(int arg0, u32 *arg1) int EReader_Send(int size, const void * src)
{ {
int result; int result;
u16 var0; int sendStatus;
int var1;
EReaderHelper_SaveRegsState(); EReaderHelper_SaveRegsState();
while (1) while (1)
{ {
sub_81D4170(); GetKeyInput();
if (gUnknown_030012E2 & 2) if (sJoyNew & B_BUTTON)
gShouldAdvanceLinkState = 2; gShouldAdvanceLinkState = 2;
var1 = EReaderHandleTransfer(1, arg0, arg1, NULL); sendStatus = EReaderHandleTransfer(1, size, src, NULL);
gUnknown_030012E4 = var1; sSendRecvStatus = sendStatus;
if ((gUnknown_030012E4 & 0x13) == 0x10) if ((sSendRecvStatus & 0x13) == 0x10)
{ {
result = 0; result = 0;
break; break;
} }
else if (sSendRecvStatus & 0x8)
if (gUnknown_030012E4 & 0x8)
{ {
result = 1; result = 1;
break; break;
} }
else if (sSendRecvStatus & 0x4)
var0 = gUnknown_030012E4 & 0x4;
if (var0)
{ {
result = 2; result = 2;
break; break;
} }
else
gShouldAdvanceLinkState = var0; {
VBlankIntrWait(); gShouldAdvanceLinkState = 0;
VBlankIntrWait();
}
} }
CpuFill32(0, &gUnknown_030012C8, sizeof(struct Unknown030012C8)); CpuFill32(0, &sSendRecvMgr, sizeof(sSendRecvMgr));
EReaderHelper_RestoreRegsState(); EReaderHelper_RestoreRegsState();
return result; return result;
} }
int EReader_Recv(u32 *arg0) int EReader_Recv(void * dest)
{ {
int result; int result;
u16 var0; int recvStatus;
int var1;
EReaderHelper_SaveRegsState(); EReaderHelper_SaveRegsState();
while (1) while (1)
{ {
sub_81D4170(); GetKeyInput();
if (gUnknown_030012E2 & 2) if (sJoyNew & B_BUTTON)
gShouldAdvanceLinkState = 2; gShouldAdvanceLinkState = 2;
var1 = EReaderHandleTransfer(0, 0, NULL, arg0); recvStatus = EReaderHandleTransfer(0, 0, NULL, dest);
gUnknown_030012E4 = var1; sSendRecvStatus = recvStatus;
if ((gUnknown_030012E4 & 0x13) == 0x10) if ((sSendRecvStatus & 0x13) == 0x10)
{ {
result = 0; result = 0;
break; break;
} }
else if (sSendRecvStatus & 0x8)
if (gUnknown_030012E4 & 0x8)
{ {
result = 1; result = 1;
break; break;
} }
else if (sSendRecvStatus & 0x4)
var0 = gUnknown_030012E4 & 0x4;
if (var0)
{ {
result = 2; result = 2;
break; break;
} }
else
gShouldAdvanceLinkState = var0; {
VBlankIntrWait(); gShouldAdvanceLinkState = 0;
VBlankIntrWait();
}
} }
CpuFill32(0, &gUnknown_030012C8, sizeof(struct Unknown030012C8)); CpuFill32(0, &sSendRecvMgr, sizeof(sSendRecvMgr));
EReaderHelper_RestoreRegsState(); EReaderHelper_RestoreRegsState();
return result; return result;
} }
static void sub_81D3C7C(void) static void CloseSerial(void)
{ {
REG_IME = 0; REG_IME = 0;
REG_IE &= ~(INTR_FLAG_TIMER3 | INTR_FLAG_SERIAL); REG_IE &= ~(INTR_FLAG_TIMER3 | INTR_FLAG_SERIAL);
@ -610,7 +640,7 @@ static void sub_81D3C7C(void)
REG_IF = INTR_FLAG_TIMER3 | INTR_FLAG_SERIAL; REG_IF = INTR_FLAG_TIMER3 | INTR_FLAG_SERIAL;
} }
static void sub_81D3CBC(void) static void OpenSerialMulti(void)
{ {
REG_IME = 0; REG_IME = 0;
REG_IE &= ~(INTR_FLAG_TIMER3 | INTR_FLAG_SERIAL); REG_IE &= ~(INTR_FLAG_TIMER3 | INTR_FLAG_SERIAL);
@ -622,273 +652,271 @@ static void sub_81D3CBC(void)
REG_IE |= INTR_FLAG_SERIAL; REG_IE |= INTR_FLAG_SERIAL;
REG_IME = 1; REG_IME = 1;
if (!gUnknown_030012C8.unk0[1]) if (sSendRecvMgr.state == 0)
CpuFill32(0, &gUnknown_030012C8, sizeof(struct Unknown030012C8)); CpuFill32(0, &sSendRecvMgr, sizeof(sSendRecvMgr));
} }
static void sub_81D3D34(void) static void OpenSerial32(void)
{ {
REG_RCNT = 0; REG_RCNT = 0;
REG_SIOCNT = SIO_32BIT_MODE | SIO_INTR_ENABLE; REG_SIOCNT = SIO_32BIT_MODE | SIO_INTR_ENABLE;
REG_SIOCNT |= SIO_MULTI_SD; REG_SIOCNT |= SIO_MULTI_SD;
gShouldAdvanceLinkState = 0; gShouldAdvanceLinkState = 0;
gUnknown_030012E6 = 0; sCounter1 = 0;
gUnknown_030012E8 = 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: case EREADER_XFR_STATE_INIT:
sub_81D3CBC(); OpenSerialMulti();
gUnknown_030012C8.unk0[2] = 1; sSendRecvMgr.xferState = EREADER_XFER_EXE;
gUnknown_030012C8.unk0[1] = 1; sSendRecvMgr.state = EREADER_XFR_STATE_HANDSHAKE;
break; break;
case 1: case EREADER_XFR_STATE_HANDSHAKE:
if (sub_81D3EE8(arg0)) if (DetermineSendRecvState(mode))
sub_81D413C(); EnableSio();
if (gShouldAdvanceLinkState == 2) if (gShouldAdvanceLinkState == 2)
{ {
gUnknown_030012C8.unk0[4] = 2; sSendRecvMgr.cancellationReason = EREADER_CANCEL_KEY;
gUnknown_030012C8.unk0[1] = 6; sSendRecvMgr.state = EREADER_XFR_STATE_DONE;
} }
break; break;
case 2: case EREADER_XFR_STATE_START:
sub_81D3D34(); OpenSerial32();
sub_81D3F1C(arg1, arg2, arg3); SetUpTransferManager(size, data, recvBuffer);
gUnknown_030012C8.unk0[1] = 3; sSendRecvMgr.state = EREADER_XFR_STATE_TRANSFER;
// fall through // fall through
case 3: case EREADER_XFR_STATE_TRANSFER:
if (gShouldAdvanceLinkState == 2) if (gShouldAdvanceLinkState == 2)
{ {
gUnknown_030012C8.unk0[4] = 2; sSendRecvMgr.cancellationReason = EREADER_CANCEL_KEY;
gUnknown_030012C8.unk0[1] = 6; sSendRecvMgr.state = EREADER_XFR_STATE_DONE;
} }
else else
{ {
gUnknown_030012E6++; sCounter1++;
gUnknown_030012E8++; sCounter2++;
if (!gUnknown_030012C8.unk0[0] && gUnknown_030012E8 > 60) if (!sSendRecvMgr.isParent && sCounter2 > 60)
{ {
gUnknown_030012C8.unk0[4] = 1; sSendRecvMgr.cancellationReason = EREADER_CANCEL_TIMEOUT;
gUnknown_030012C8.unk0[1] = 6; 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(); EnableSio();
gUnknown_030012C8.unk0[2] = 2; sSendRecvMgr.xferState = EREADER_XFER_CHK;
} }
else else
{ {
sub_81D413C(); EnableSio();
gUnknown_030012C8.unk0[2] = 2; sSendRecvMgr.xferState = EREADER_XFER_CHK;
} }
} }
} }
break; break;
case 4: case EREADER_XFR_STATE_TRANSFER_DONE:
sub_81D3CBC(); OpenSerialMulti();
gUnknown_030012C8.unk0[1] = 5; sSendRecvMgr.state = EREADER_XFR_STATE_CHECKSUM;
break; break;
case 5: case EREADER_XFR_STATE_CHECKSUM:
if (gUnknown_030012C8.unk0[0] == 1 && gUnknown_030012E6 > 2) if (sSendRecvMgr.isParent == TRUE && sCounter1 > 2)
sub_81D413C(); EnableSio();
if (++gUnknown_030012E6 > 60) if (++sCounter1 > 60)
{ {
gUnknown_030012C8.unk0[4] = 1; sSendRecvMgr.cancellationReason = EREADER_CANCEL_TIMEOUT;
gUnknown_030012C8.unk0[1] = 6; sSendRecvMgr.state = EREADER_XFR_STATE_DONE;
} }
break; break;
case 6: case EREADER_XFR_STATE_DONE:
if (gUnknown_030012C8.unk0[2]) if (sSendRecvMgr.xferState)
{ {
sub_81D3C7C(); CloseSerial();
gUnknown_030012C8.unk0[2] = 0; sSendRecvMgr.xferState = 0;
} }
break; 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); bool16 resp;
if (terminal == SIO_MULTI_SD && arg0) if ((*(vu32 *)REG_ADDR_SIOCNT & (SIO_MULTI_SI | SIO_MULTI_SD)) == SIO_MULTI_SD && mode)
{ resp = sSendRecvMgr.isParent = TRUE;
gUnknown_030012C8.unk0[0] = 1;
return 1;
}
else else
{ resp = sSendRecvMgr.isParent = FALSE;
gUnknown_030012C8.unk0[0] = 0; return resp;
return 0;
}
} }
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; REG_SIOCNT |= SIO_38400_BPS;
gUnknown_030012C8.unk8 = arg1; sSendRecvMgr.data = (void *)data;
REG_SIODATA32 = arg0; REG_SIODATA32 = size;
gUnknown_030012C8.unk10 = arg0 / 4 + 1; sSendRecvMgr.size = size / 4 + 1;
sub_81D3F68(); StartTm3();
} }
else else
{ {
REG_SIOCNT = REG_SIOCNT; 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_TM3CNT_H = TIMER_INTR_ENABLE;
REG_IME = 0; REG_IME = 0;
REG_IE |= INTR_FLAG_TIMER3; REG_IE |= INTR_FLAG_TIMER3;
REG_IME = 1; REG_IME = 1;
} }
void sub_81D3F9C(void) void EReaderHelper_Timer3Callback(void)
{ {
sub_81D414C(); DisableTm3();
sub_81D413C(); EnableSio();
} }
void sub_81D3FAC(void) void EReaderHelper_SerialCallback(void)
{ {
u16 i, playerCount, k; u16 i, cnt1, cnt2;
u32 value; u32 recv32;
u16 var0; u16 recv[4];
u16 recvBuffer[4];
switch (gUnknown_030012C8.unk0[1]) switch (sSendRecvMgr.state)
{ {
case 1: case EREADER_XFR_STATE_HANDSHAKE:
REG_SIOMLT_SEND = 0xCCD0; // Handshake id REG_SIOMLT_SEND = 0xCCD0; // Handshake id
*(u64 *)recvBuffer = REG_SIOMLT_RECV; *(u64 *)recv = REG_SIOMLT_RECV;
for (i = 0, playerCount = 0, k = 0; i < 4; i++) for (i = 0, cnt1 = 0, cnt2 = 0; i < 4; i++)
{ {
if (recvBuffer[i] == 0xCCD0) if (recv[i] == 0xCCD0)
playerCount++; cnt1++;
else if (recvBuffer[i] != 0xFFFF) else if (recv[i] != 0xFFFF)
k++; cnt2++;
} }
if (playerCount == 2 && k == 0) if (cnt1 == 2 && cnt2 == 0)
gUnknown_030012C8.unk0[1] = 2; sSendRecvMgr.state = 2;
break; break;
case 3: case EREADER_XFR_STATE_TRANSFER:
value = REG_SIODATA32; recv32 = REG_SIODATA32;
if (!gUnknown_030012C8.unkC && !gUnknown_030012C8.unk0[0]) // The first value sent by the EReader is the payload size
gUnknown_030012C8.unk10 = value / 4 + 1; 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]; REG_SIODATA32 = sSendRecvMgr.data[sSendRecvMgr.cursor];
gUnknown_030012C8.unk14 += gUnknown_030012C8.unk8[gUnknown_030012C8.unkC]; sSendRecvMgr.checksum += sSendRecvMgr.data[sSendRecvMgr.cursor];
} }
else else
{ {
REG_SIODATA32 = gUnknown_030012C8.unk14; REG_SIODATA32 = sSendRecvMgr.checksum;
} }
} }
else 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; sSendRecvMgr.data[sSendRecvMgr.cursor - 1] = recv32;
gUnknown_030012C8.unk14 += value; sSendRecvMgr.checksum += recv32;
} }
else if (gUnknown_030012C8.unkC) else if (sSendRecvMgr.cursor)
{ {
if (gUnknown_030012C8.unk14 == value) if (sSendRecvMgr.checksum == recv32)
gUnknown_030012C8.unk0[3] = 1; sSendRecvMgr.checksumResult = EREADER_CHECKSUM_OK;
else 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; REG_TM3CNT_H |= TIMER_ENABLE;
else else
sub_81D413C(); EnableSio();
} }
else else
{ {
gUnknown_030012C8.unk0[1] = 4; sSendRecvMgr.state = EREADER_XFR_STATE_TRANSFER_DONE;
gUnknown_030012E6 = 0; sCounter1 = 0;
} }
break; break;
case 5: case EREADER_XFR_STATE_CHECKSUM:
if (!gUnknown_030012C8.unk0[0]) if (!sSendRecvMgr.isParent)
REG_SIOMLT_SEND = gUnknown_030012C8.unk0[3]; REG_SIOMLT_SEND = sSendRecvMgr.checksumResult;
*(u64 *)recvBuffer = REG_SIOMLT_RECV; *(vu64 *)recv = REG_SIOMLT_RECV;
var0 = recvBuffer[1] - 1; if (recv[1] == EREADER_CHECKSUM_OK || recv[1] == EREADER_CHECKSUM_ERR)
if (var0 < 2)
{ {
if (gUnknown_030012C8.unk0[0] == 1) if (sSendRecvMgr.isParent == TRUE)
gUnknown_030012C8.unk0[3] = recvBuffer[1]; sSendRecvMgr.checksumResult = recv[1]; // EReader has (in)validated the payload
gUnknown_030012C8.unk0[1] = 6; sSendRecvMgr.state = EREADER_XFR_STATE_DONE;
} }
break; break;
} }
} }
static void sub_81D413C(void) static void EnableSio(void)
{ {
REG_SIOCNT |= SIO_ENABLE; REG_SIOCNT |= SIO_ENABLE;
} }
static void sub_81D414C(void) static void DisableTm3(void)
{ {
REG_TM3CNT_H &= ~TIMER_ENABLE; REG_TM3CNT_H &= ~TIMER_ENABLE;
REG_TM3CNT_L = 0xFDA7; REG_TM3CNT_L = 0xFDA7;
} }
static void sub_81D4170(void) static void GetKeyInput(void)
{ {
int keysMask = REG_KEYINPUT ^ KEYS_MASK; int rawKeys = REG_KEYINPUT ^ KEYS_MASK;
gUnknown_030012E2 = keysMask & ~gUnknown_030012E0; sJoyNew = rawKeys & ~sJoyNewOrRepeated;
gUnknown_030012E0 = keysMask; sJoyNewOrRepeated = rawKeys;
} }
void EReaderHelper_SaveRegsState(void) void EReaderHelper_SaveRegsState(void)
{ {
gUnknown_030012EC = REG_IME; sSavedIme = REG_IME;
gUnknown_030012EE = REG_IE; sSavedIe = REG_IE;
gUnknown_030012F0 = REG_TM3CNT_H; sSavedTm3Cnt = REG_TM3CNT_H;
gUnknown_030012F2 = REG_SIOCNT; sSavedSioCnt = REG_SIOCNT;
gUnknown_030012F4 = REG_RCNT; sSavedRCnt = REG_RCNT;
} }
void EReaderHelper_RestoreRegsState(void) void EReaderHelper_RestoreRegsState(void)
{ {
REG_IME = gUnknown_030012EC; REG_IME = sSavedIme;
REG_IE = gUnknown_030012EE; REG_IE = sSavedIe;
REG_TM3CNT_H = gUnknown_030012F0; REG_TM3CNT_H = sSavedTm3Cnt;
REG_SIOCNT = gUnknown_030012F2; REG_SIOCNT = sSavedSioCnt;
REG_RCNT = gUnknown_030012F4; 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; volatile u16 backupIME = REG_IME;
REG_IME = 0; REG_IME = 0;
gIntrTable[1] = sub_81D3FAC; gIntrTable[1] = EReaderHelper_SerialCallback;
gIntrTable[2] = sub_81D3F9C; gIntrTable[2] = EReaderHelper_Timer3Callback;
EReaderHelper_SaveRegsState(); EReaderHelper_SaveRegsState();
sub_81D4238(); EReaderHelper_ClearSendRecvMgr();
REG_IE |= INTR_FLAG_VCOUNT; REG_IE |= INTR_FLAG_VCOUNT;
REG_IME = backupIME; REG_IME = backupIME;
arg0->unk0 = 0; arg0->unk0 = 0;
@ -62,7 +62,7 @@ static void sub_81D4DB8(struct Unk03006370 *arg0)
{ {
volatile u16 backupIME = REG_IME; volatile u16 backupIME = REG_IME;
REG_IME = 0; REG_IME = 0;
sub_81D4238(); EReaderHelper_ClearSendRecvMgr();
EReaderHelper_RestoreRegsState(); EReaderHelper_RestoreRegsState();
RestoreSerialTimer3IntrHandlers(); RestoreSerialTimer3IntrHandlers();
REG_IME = backupIME; REG_IME = backupIME;
@ -401,7 +401,7 @@ static void sub_81D5084(u8 taskId)
} }
break; break;
case 15: case 15:
data->unkE = EReader_IsReceivedDataValid((struct EReaderTrainerHillSet *)gDecompressionBuffer); data->unkE = ValidateTrainerHillData((struct EReaderTrainerHillSet *)gDecompressionBuffer);
SetCloseLinkCallbackAndType(data->unkE); SetCloseLinkCallbackAndType(data->unkE);
data->unk8 = 16; data->unk8 = 16;
break; break;