Document ereader screen

This commit is contained in:
GriffinR 2021-10-26 13:37:24 -04:00
parent 6dc3c9864c
commit b0c27a8521
11 changed files with 330 additions and 260 deletions

View File

@ -1 +1 @@
gUnknown_03006370 gEReaderData

6
data/ereader_link_data.s Normal file
View File

@ -0,0 +1,6 @@
.section .rodata
.align 2
gEReaderLinkData_Start::
.incbin "data/ereader_link_data.bin"
gEReaderLinkData_End::

View File

@ -1,5 +0,0 @@
.section .rodata
.align 2
gUnknown_089A3470::
.incbin "data/unknown_serial_data.bin"

View File

@ -3,6 +3,34 @@
#include "trainer_hill.h" #include "trainer_hill.h"
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
};
#define EREADER_XFER_EXE 1
#define EREADER_XFER_CHK 2
#define EREADER_XFER_SHIFT 0
#define EREADER_XFER_MASK ((EREADER_XFER_EXE | EREADER_XFER_CHK) << EREADER_XFER_SHIFT)
#define EREADER_CANCEL_TIMEOUT 1
#define EREADER_CANCEL_KEY 2
#define EREADER_CANCEL_SHIFT 2
#define EREADER_CANCEL_TIMEOUT_MASK (EREADER_CANCEL_TIMEOUT << EREADER_CANCEL_SHIFT)
#define EREADER_CANCEL_KEY_MASK (EREADER_CANCEL_KEY << EREADER_CANCEL_SHIFT)
#define EREADER_CANCEL_MASK ((EREADER_CANCEL_TIMEOUT | EREADER_CANCEL_KEY) << EREADER_CANCEL_SHIFT)
#define EREADER_CHECKSUM_OK 1
#define EREADER_CHECKSUM_ERR 2
#define EREADER_CHECKSUM_SHIFT 4
#define EREADER_CHECKSUM_OK_MASK (EREADER_CHECKSUM_OK << EREADER_CHECKSUM_SHIFT)
#define EREADER_CHECKSUM_MASK ((EREADER_CHECKSUM_OK | EREADER_CHECKSUM_ERR) << EREADER_CHECKSUM_SHIFT)
struct EReaderTrainerHillTrainer struct EReaderTrainerHillTrainer
{ {
u8 trainerNum; u8 trainerNum;

View File

@ -124,8 +124,9 @@ struct LinkStatus
u32 errors:7; u32 errors:7;
}; };
#define MASTER_HANDSHAKE 0x8FFF #define MASTER_HANDSHAKE 0x8FFF
#define SLAVE_HANDSHAKE 0xB9A0 #define SLAVE_HANDSHAKE 0xB9A0
#define EREADER_HANDSHAKE 0xCCD0
#define SIO_MULTI_CNT ((struct SioMultiCnt *)REG_ADDR_SIOCNT) #define SIO_MULTI_CNT ((struct SioMultiCnt *)REG_ADDR_SIOCNT)
@ -208,7 +209,7 @@ struct Link
/* 0x001 */ u8 state; /* 0x001 */ u8 state;
/* 0x002 */ u8 localId; // local multi-player ID /* 0x002 */ u8 localId; // local multi-player ID
/* 0x003 */ u8 playerCount; /* 0x003 */ u8 playerCount;
/* 0x004 */ u16 tempRecvBuffer[4]; /* 0x004 */ u16 handshakeBuffer[MAX_LINK_PLAYERS];
/* 0x00c */ bool8 receivedNothing; /* 0x00c */ bool8 receivedNothing;
/* 0x00d */ s8 serialIntrCounter; /* 0x00d */ s8 serialIntrCounter;
/* 0x00e */ bool8 handshakeAsMaster; /* 0x00e */ bool8 handshakeAsMaster;

View File

@ -1250,7 +1250,7 @@ SECTIONS {
other_data : other_data :
ALIGN(4) ALIGN(4)
{ {
data/unknown_serial_data.o(.rodata); data/ereader_link_data.o(.rodata);
data/multiboot_berry_glitch_fix.o(.rodata); data/multiboot_berry_glitch_fix.o(.rodata);
data/multiboot_pokemon_colosseum.o(.rodata); data/multiboot_pokemon_colosseum.o(.rodata);
} =0 } =0

View File

@ -114,7 +114,7 @@ SECTIONS {
other_data : other_data :
ALIGN(4) ALIGN(4)
{ {
data/unknown_serial_data.o(.rodata); data/ereader_link_data.o(.rodata);
data/multiboot_berry_glitch_fix.o(.rodata); data/multiboot_berry_glitch_fix.o(.rodata);
data/multiboot_pokemon_colosseum.o(.rodata); data/multiboot_pokemon_colosseum.o(.rodata);
} =0 } =0

View File

@ -16,31 +16,6 @@
#include "constants/items.h" #include "constants/items.h"
#include "constants/trainer_hill.h" #include "constants/trainer_hill.h"
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
};
#define EREADER_XFER_EXE 1
#define EREADER_XFER_CHK 2
#define EREADER_XFER_SHIFT 0
#define EREADER_XFER_MASK 3
#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 struct SendRecvMgr
{ {
bool8 isParent; bool8 isParent;
@ -562,17 +537,17 @@ int EReader_Send(int size, const void * src)
sendStatus = EReaderHandleTransfer(1, size, src, NULL); sendStatus = EReaderHandleTransfer(1, size, src, NULL);
sSendRecvStatus = sendStatus; sSendRecvStatus = sendStatus;
if ((sSendRecvStatus & 0x13) == 0x10) if ((sSendRecvStatus & EREADER_XFER_MASK) == 0 && sSendRecvStatus & EREADER_CHECKSUM_OK_MASK)
{ {
result = 0; result = 0;
break; break;
} }
else if (sSendRecvStatus & 0x8) else if (sSendRecvStatus & EREADER_CANCEL_KEY_MASK)
{ {
result = 1; result = 1;
break; break;
} }
else if (sSendRecvStatus & 0x4) else if (sSendRecvStatus & EREADER_CANCEL_TIMEOUT_MASK)
{ {
result = 2; result = 2;
break; break;
@ -603,17 +578,17 @@ int EReader_Recv(void * dest)
recvStatus = EReaderHandleTransfer(0, 0, NULL, dest); recvStatus = EReaderHandleTransfer(0, 0, NULL, dest);
sSendRecvStatus = recvStatus; sSendRecvStatus = recvStatus;
if ((sSendRecvStatus & 0x13) == 0x10) if ((sSendRecvStatus & EREADER_XFER_MASK) == 0 && sSendRecvStatus & EREADER_CHECKSUM_OK_MASK)
{ {
result = 0; result = 0;
break; break;
} }
else if (sSendRecvStatus & 0x8) else if (sSendRecvStatus & EREADER_CANCEL_KEY_MASK)
{ {
result = 1; result = 1;
break; break;
} }
else if (sSendRecvStatus & 0x4) else if (sSendRecvStatus & EREADER_CANCEL_TIMEOUT_MASK)
{ {
result = 2; result = 2;
break; break;

View File

@ -13,37 +13,38 @@
#include "util.h" #include "util.h"
#include "constants/songs.h" #include "constants/songs.h"
// Equivalent to MysteryGiftTaskData
struct EReaderTaskData struct EReaderTaskData
{ {
u16 unk0; u16 timer;
u16 unk2; u16 unused1;
u16 unk4; u16 unused2;
u16 unk6; u16 unused3;
u8 unk8; u8 state;
u8 unk9; u8 textState;
u8 unkA; u8 unused4;
u8 unkB; u8 unused5;
u8 unkC; u8 unused6;
u8 unkD; u8 unused7;
u8 unkE; u8 status;
u8 *unk10; u8 *unusedBuffer;
}; };
struct Unk03006370 struct EReaderData
{ {
u16 unk0; u16 status;
u32 unk4; u32 size;
u32 *unk8; u32 *data;
}; };
static void Task_EReader(u8); static void Task_EReader(u8);
struct Unk03006370 gUnknown_03006370; struct EReaderData gEReaderData;
extern const u8 gUnknown_089A3470[]; extern const u8 gEReaderLinkData_Start[];
extern const u8 gMultiBootProgram_BerryGlitchFix_Start[]; extern const u8 gEReaderLinkData_End[];
static void sub_81D4D50(struct Unk03006370 *arg0, int arg1, u32 *arg2) static void EReader_Load(struct EReaderData *eReader, int size, u32 *data)
{ {
volatile u16 backupIME = REG_IME; volatile u16 backupIME = REG_IME;
REG_IME = 0; REG_IME = 0;
@ -53,12 +54,12 @@ static void sub_81D4D50(struct Unk03006370 *arg0, int arg1, u32 *arg2)
EReaderHelper_ClearSendRecvMgr(); EReaderHelper_ClearSendRecvMgr();
REG_IE |= INTR_FLAG_VCOUNT; REG_IE |= INTR_FLAG_VCOUNT;
REG_IME = backupIME; REG_IME = backupIME;
arg0->unk0 = 0; eReader->status = 0;
arg0->unk4 = arg1; eReader->size = size;
arg0->unk8 = arg2; eReader->data = data;
} }
static void sub_81D4DB8(struct Unk03006370 *arg0) static void EReader_Reset(struct EReaderData *eReader)
{ {
volatile u16 backupIME = REG_IME; volatile u16 backupIME = REG_IME;
REG_IME = 0; REG_IME = 0;
@ -68,21 +69,30 @@ static void sub_81D4DB8(struct Unk03006370 *arg0)
REG_IME = backupIME; REG_IME = backupIME;
} }
static u8 sub_81D4DE8(struct Unk03006370 *arg0) // Return values for EReader_Transfer
enum {
TRANSFER_ACTIVE,
TRANSFER_SUCCESS,
TRANSFER_CANCELED,
TRANSFER_TIMEOUT,
};
static u8 EReader_Transfer(struct EReaderData *eReader)
{ {
u8 var0 = 0; u8 transferStatus = TRANSFER_ACTIVE;
arg0->unk0 = EReaderHandleTransfer(1, arg0->unk4, arg0->unk8, NULL); eReader->status = EReaderHandleTransfer(TRUE, eReader->size, eReader->data, NULL);
if ((arg0->unk0 & 0x13) == 0x10)
var0 = 1;
if (arg0->unk0 & 0x8) if ((eReader->status & EREADER_XFER_MASK) == 0 && eReader->status & EREADER_CHECKSUM_OK_MASK)
var0 = 2; transferStatus = TRANSFER_SUCCESS;
if (arg0->unk0 & 0x4) if (eReader->status & EREADER_CANCEL_KEY_MASK)
var0 = 3; transferStatus = TRANSFER_CANCELED;
if (eReader->status & EREADER_CANCEL_TIMEOUT_MASK)
transferStatus = TRANSFER_TIMEOUT;
gShouldAdvanceLinkState = 0; gShouldAdvanceLinkState = 0;
return var0; return transferStatus;
} }
static void OpenEReaderLink(void) static void OpenEReaderLink(void)
@ -93,17 +103,20 @@ static void OpenEReaderLink(void)
SetSuppressLinkErrorMessage(TRUE); SetSuppressLinkErrorMessage(TRUE);
} }
static bool32 sub_81D4E60(void) static bool32 ValidateEReaderConnection(void)
{ {
volatile u16 backupIME; volatile u16 backupIME;
u16 sp4[4]; u16 handshakes[MAX_LINK_PLAYERS];
backupIME = REG_IME; backupIME = REG_IME;
REG_IME = 0; REG_IME = 0;
*(u64 *)sp4 = *(u64 *)gLink.tempRecvBuffer; *(u64 *)handshakes = *(u64 *)gLink.handshakeBuffer;
REG_IME = backupIME; REG_IME = backupIME;
if (sp4[0] == 0xB9A0 && sp4[1] == 0xCCD0
&& sp4[2] == 0xFFFF && sp4[3] == 0xFFFF) // Validate that we are player 1, the EReader is player 2,
// and that players 3 and 4 are empty.
if (handshakes[0] == SLAVE_HANDSHAKE && handshakes[1] == EREADER_HANDSHAKE
&& handshakes[2] == 0xFFFF && handshakes[3] == 0xFFFF)
{ {
return TRUE; return TRUE;
} }
@ -111,7 +124,7 @@ static bool32 sub_81D4E60(void)
return FALSE; return FALSE;
} }
static bool32 sub_81D4EC0(void) static bool32 IsChildConnected(void)
{ {
if (IsLinkMaster() && GetLinkPlayerCount_2() == 2) if (IsLinkMaster() && GetLinkPlayerCount_2() == 2)
return TRUE; return TRUE;
@ -119,56 +132,77 @@ static bool32 sub_81D4EC0(void)
return FALSE; return FALSE;
} }
static u32 sub_81D4EE4(u8 *arg0, u16 *arg1) // States for TryReceiveCard
{ enum {
u8 var0; RECV_STATE_INIT,
RECV_STATE_WAIT_START,
RECV_STATE_START,
RECV_STATE_EXCHANGE,
RECV_STATE_START_DISCONNECT,
RECV_STATE_WAIT_DISCONNECT,
};
var0 = *arg0 - 3; // Return values for TryReceiveCard
if (var0 < 3 && HasLinkErrorOccurred()) enum {
RECV_ACTIVE,
RECV_CANCELED,
RECV_SUCCESS,
RECV_ERROR,
RECV_DISCONNECTED,
RECV_TIMEOUT,
};
static u32 TryReceiveCard(u8 *state, u16 *timer)
{
if (*state >= RECV_STATE_EXCHANGE
&& *state <= RECV_STATE_WAIT_DISCONNECT
&& HasLinkErrorOccurred())
{ {
*arg0 = 0; // Return error status if an error occurs
return 3; // during the link exchange.
*state = 0;
return RECV_ERROR;
} }
switch (*arg0) switch (*state)
{ {
case 0: case RECV_STATE_INIT:
if (IsLinkMaster() && GetLinkPlayerCount_2() > 1) if (IsLinkMaster() && GetLinkPlayerCount_2() > 1)
{ {
*arg0 = 1; *state = RECV_STATE_WAIT_START;
} }
else if (JOY_NEW(B_BUTTON)) else if (JOY_NEW(B_BUTTON))
{ {
*arg0 = 0; *state = 0;
return 1; return RECV_CANCELED;
} }
break; break;
case 1: case RECV_STATE_WAIT_START:
if (++(*arg1) > 5) if (++(*timer) > 5)
{ {
*arg1 = 0; *timer = 0;
*arg0 = 2; *state = RECV_STATE_START;
} }
break; break;
case 2: case RECV_STATE_START:
if (GetLinkPlayerCount_2() == 2) if (GetLinkPlayerCount_2() == 2)
{ {
PlaySE(SE_DING_DONG); PlaySE(SE_DING_DONG);
CheckShouldAdvanceLinkState(); CheckShouldAdvanceLinkState();
*arg1 = 0; *timer = 0;
*arg0 = 3; *state = RECV_STATE_EXCHANGE;
} }
else if (JOY_NEW(B_BUTTON)) else if (JOY_NEW(B_BUTTON))
{ {
*arg0 = 0; *state = 0;
return 1; return RECV_CANCELED;
} }
break; break;
case 3: case RECV_STATE_EXCHANGE:
if (++(*arg1) > 30) if (++(*timer) > 30)
{ {
*arg0 = 0; *state = 0;
return 5; return RECV_TIMEOUT;
} }
if (IsLinkConnectionEstablished()) if (IsLinkConnectionEstablished())
@ -177,36 +211,36 @@ static u32 sub_81D4EE4(u8 *arg0, u16 *arg1)
{ {
if (IsLinkPlayerDataExchangeComplete()) if (IsLinkPlayerDataExchangeComplete())
{ {
*arg0 = 0; *state = 0;
return 2; return RECV_SUCCESS;
} }
else else
{ {
*arg0 = 4; *state = RECV_STATE_START_DISCONNECT;
} }
} }
else else
{ {
*arg0 = 3; *state = RECV_STATE_EXCHANGE;
} }
} }
break; break;
case 4: case RECV_STATE_START_DISCONNECT:
SetCloseLinkCallbackAndType(0); SetCloseLinkCallbackAndType(0);
*arg0 = 5; *state = RECV_STATE_WAIT_DISCONNECT;
break; break;
case 5: case RECV_STATE_WAIT_DISCONNECT:
if (!gReceivedRemoteLinkPlayers) if (!gReceivedRemoteLinkPlayers)
{ {
*arg0 = 0; *state = 0;
return 4; return RECV_DISCONNECTED;
} }
break; break;
default: default:
return 0; return RECV_ACTIVE;
} }
return 0; return RECV_ACTIVE;
} }
void CreateEReaderTask(void) void CreateEReaderTask(void)
@ -214,248 +248,283 @@ void CreateEReaderTask(void)
struct EReaderTaskData *data; struct EReaderTaskData *data;
u8 taskId = CreateTask(Task_EReader, 0); u8 taskId = CreateTask(Task_EReader, 0);
data = (struct EReaderTaskData *)gTasks[taskId].data; data = (struct EReaderTaskData *)gTasks[taskId].data;
data->unk8 = 0; data->state = 0;
data->unk9 = 0; data->textState = 0;
data->unkA = 0; data->unused4 = 0;
data->unkB = 0; data->unused5 = 0;
data->unkC = 0; data->unused6 = 0;
data->unkD = 0; data->unused7 = 0;
data->unk0 = 0; data->timer = 0;
data->unk2 = 0; data->unused1 = 0;
data->unk4 = 0; data->unused2 = 0;
data->unk6 = 0; data->unused3 = 0;
data->unkE = 0; data->status = 0;
data->unk10 = AllocZeroed(0x40); data->unusedBuffer = AllocZeroed(0x40);
} }
static void sub_81D505C(u16 *arg0) static void ResetTimer(u16 *timer)
{ {
*arg0 = 0; *timer = 0;
} }
static bool32 sub_81D5064(u16 *arg0, u16 arg1) static bool32 UpdateTimer(u16 *timer, u16 time)
{ {
if (++(*arg0) > arg1) if (++(*timer) > time)
{ {
*arg0 = 0; // Timer has finished
*timer = 0;
return TRUE; return TRUE;
} }
return FALSE; return FALSE;
} }
// States for Task_EReader
enum {
ER_STATE_START,
ER_STATE_INIT_LINK,
ER_STATE_INIT_LINK_WAIT,
ER_STATE_INIT_LINK_CHECK,
ER_STATE_MSG_SELECT_CONNECT,
ER_STATE_MSG_SELECT_CONNECT_WAIT,
ER_STATE_TRY_LINK,
ER_STATE_INCORRECT_LINK,
ER_STATE_CONNECTING,
ER_STATE_TRANSFER,
ER_STATE_TRANSFER_END,
ER_STATE_TRANSFER_SUCCESS,
ER_STATE_LOAD_CARD_START,
ER_STATE_LOAD_CARD,
ER_STATE_WAIT_RECV_CARD,
ER_STATE_VALIDATE_CARD,
ER_STATE_WAIT_DISCONNECT,
ER_STATE_SAVE,
ER_STATE_SUCCESS_MSG,
ER_STATE_SUCCESS_END,
ER_STATE_LINK_ERROR,
ER_STATE_LINK_ERROR_TRY_AGAIN,
ER_STATE_SAVE_FAILED,
ER_STATE_CANCELED_CARD_READ,
ER_STATE_UNUSED_1,
ER_STATE_UNUSED_2,
ER_STATE_END,
};
static void Task_EReader(u8 taskId) static void Task_EReader(u8 taskId)
{ {
struct EReaderTaskData *data = (struct EReaderTaskData *)gTasks[taskId].data; struct EReaderTaskData *data = (struct EReaderTaskData *)gTasks[taskId].data;
switch (data->unk8) switch (data->state)
{ {
case 0: case ER_STATE_START:
if (PrintMysteryGiftMenuMessage(&data->unk9, gJPText_ReceiveMysteryGiftWithEReader)) if (PrintMysteryGiftMenuMessage(&data->textState, gJPText_ReceiveMysteryGiftWithEReader))
data->unk8 = 1; data->state = ER_STATE_INIT_LINK;
break; break;
case 1: case ER_STATE_INIT_LINK:
OpenEReaderLink(); OpenEReaderLink();
sub_81D505C(&data->unk0); ResetTimer(&data->timer);
data->unk8 = 2; data->state = ER_STATE_INIT_LINK_WAIT;
break; break;
case 2: case ER_STATE_INIT_LINK_WAIT:
if (sub_81D5064(&data->unk0, 10)) if (UpdateTimer(&data->timer, 10))
data->unk8 = 3; data->state = ER_STATE_INIT_LINK_CHECK;
break; break;
case 3: case ER_STATE_INIT_LINK_CHECK:
if (!sub_81D4EC0()) if (!IsChildConnected())
{ {
CloseLink(); CloseLink();
data->unk8 = 4; data->state = ER_STATE_MSG_SELECT_CONNECT;
} }
else else
{ {
data->unk8 = 13; data->state = ER_STATE_LOAD_CARD;
} }
break; break;
case 4: case ER_STATE_MSG_SELECT_CONNECT:
if (PrintMysteryGiftMenuMessage(&data->unk9, gJPText_SelectConnectFromEReaderMenu)) if (PrintMysteryGiftMenuMessage(&data->textState, gJPText_SelectConnectFromEReaderMenu))
{ {
AddTextPrinterToWindow1(gJPText_SelectConnectWithGBA); AddTextPrinterToWindow1(gJPText_SelectConnectWithGBA);
sub_81D505C(&data->unk0); ResetTimer(&data->timer);
data->unk8 = 5; data->state = ER_STATE_MSG_SELECT_CONNECT_WAIT;
} }
break; break;
case 5: case ER_STATE_MSG_SELECT_CONNECT_WAIT:
if (sub_81D5064(&data->unk0, 90)) if (UpdateTimer(&data->timer, 90))
{ {
OpenEReaderLink(); OpenEReaderLink();
data->unk8 = 6; data->state = ER_STATE_TRY_LINK;
} }
else if (JOY_NEW(B_BUTTON)) else if (JOY_NEW(B_BUTTON))
{ {
sub_81D505C(&data->unk0); ResetTimer(&data->timer);
PlaySE(SE_SELECT); PlaySE(SE_SELECT);
data->unk8 = 23; data->state = ER_STATE_CANCELED_CARD_READ;
} }
break; break;
case 6: case ER_STATE_TRY_LINK:
if (JOY_NEW(B_BUTTON)) if (JOY_NEW(B_BUTTON))
{ {
// Canceled
PlaySE(SE_SELECT); PlaySE(SE_SELECT);
CloseLink(); CloseLink();
sub_81D505C(&data->unk0); ResetTimer(&data->timer);
data->unk8 = 23; data->state = ER_STATE_CANCELED_CARD_READ;
} }
else if (GetLinkPlayerCount_2() > 1) else if (GetLinkPlayerCount_2() > 1)
{ {
sub_81D505C(&data->unk0); ResetTimer(&data->timer);
CloseLink(); CloseLink();
data->unk8 = 7; data->state = ER_STATE_INCORRECT_LINK;
} }
else if (sub_81D4E60()) else if (ValidateEReaderConnection())
{ {
// Successful connection
PlaySE(SE_SELECT); PlaySE(SE_SELECT);
CloseLink(); CloseLink();
sub_81D505C(&data->unk0); ResetTimer(&data->timer);
data->unk8 = 8; data->state = ER_STATE_CONNECTING;
} }
else if (sub_81D5064(&data->unk0, 10)) else if (UpdateTimer(&data->timer, 10))
{ {
// Retry connection
CloseLink(); CloseLink();
OpenEReaderLink(); OpenEReaderLink();
sub_81D505C(&data->unk0); ResetTimer(&data->timer);
} }
break; break;
case 7: case ER_STATE_INCORRECT_LINK:
if (PrintMysteryGiftMenuMessage(&data->unk9, gJPText_LinkIsIncorrect)) if (PrintMysteryGiftMenuMessage(&data->textState, gJPText_LinkIsIncorrect))
data->unk8 = 4; data->state = ER_STATE_MSG_SELECT_CONNECT;
break; break;
case 8: case ER_STATE_CONNECTING:
AddTextPrinterToWindow1(gJPText_Connecting); AddTextPrinterToWindow1(gJPText_Connecting);
// XXX: This (u32*) cast is discarding the const qualifier from gUnknown_089A3470 // XXX: This (u32*) cast is discarding the const qualifier from gEReaderLinkData_Start
sub_81D4D50(&gUnknown_03006370, gMultiBootProgram_BerryGlitchFix_Start - gUnknown_089A3470, (u32*)gUnknown_089A3470); EReader_Load(&gEReaderData, gEReaderLinkData_End - gEReaderLinkData_Start, (u32*)gEReaderLinkData_Start);
data->unk8 = 9; data->state = ER_STATE_TRANSFER;
break; break;
case 9: case ER_STATE_TRANSFER:
data->unkE = sub_81D4DE8(&gUnknown_03006370); data->status = EReader_Transfer(&gEReaderData);
if (data->unkE) if (data->status != TRANSFER_ACTIVE)
data->unk8 = 10; data->state = ER_STATE_TRANSFER_END;
break; break;
case 10: case ER_STATE_TRANSFER_END:
sub_81D4DB8(&gUnknown_03006370); EReader_Reset(&gEReaderData);
if (data->unkE == 3) if (data->status == TRANSFER_TIMEOUT)
{ {
data->unk8 = 20; data->state = ER_STATE_LINK_ERROR;
} }
else if (data->unkE == 1) else if (data->status == TRANSFER_SUCCESS)
{ {
sub_81D505C(&data->unk0); ResetTimer(&data->timer);
AddTextPrinterToWindow1(gJPText_PleaseWaitAMoment); AddTextPrinterToWindow1(gJPText_PleaseWaitAMoment);
data->unk8 = 11; data->state = ER_STATE_TRANSFER_SUCCESS;
} }
else else // TRANSFER_CANCELED
{ {
data->unk8 = 0; data->state = ER_STATE_START;
} }
break; break;
case 11: case ER_STATE_TRANSFER_SUCCESS:
if (sub_81D5064(&data->unk0, 840)) if (UpdateTimer(&data->timer, 840))
data->unk8 = 12; data->state = ER_STATE_LOAD_CARD_START;
break; break;
case 12: case ER_STATE_LOAD_CARD_START:
OpenEReaderLink(); OpenEReaderLink();
AddTextPrinterToWindow1(gJPText_AllowEReaderToLoadCard); AddTextPrinterToWindow1(gJPText_AllowEReaderToLoadCard);
data->unk8 = 13; data->state = ER_STATE_LOAD_CARD;
break; break;
case 13: case ER_STATE_LOAD_CARD:
switch (sub_81D4EE4(&data->unk9, &data->unk0)) switch (TryReceiveCard(&data->textState, &data->timer))
{ {
case 0: case RECV_ACTIVE:
break; break;
case 2: case RECV_SUCCESS:
AddTextPrinterToWindow1(gJPText_Connecting); AddTextPrinterToWindow1(gJPText_Connecting);
data->unk8 = 14; data->state = ER_STATE_WAIT_RECV_CARD;
break; break;
case 1: case RECV_CANCELED:
PlaySE(SE_SELECT); PlaySE(SE_SELECT);
CloseLink(); CloseLink();
data->unk8 = 23; data->state = ER_STATE_CANCELED_CARD_READ;
break; break;
case 5: case RECV_TIMEOUT:
CloseLink(); CloseLink();
data->unk8 = 21; data->state = ER_STATE_LINK_ERROR_TRY_AGAIN;
break; break;
case 3: case RECV_ERROR:
case 4: case RECV_DISCONNECTED:
CloseLink(); CloseLink();
data->unk8 = 20; data->state = ER_STATE_LINK_ERROR;
break; break;
} }
break; break;
case 14: case ER_STATE_WAIT_RECV_CARD:
if (HasLinkErrorOccurred()) if (HasLinkErrorOccurred())
{ {
CloseLink(); CloseLink();
data->unk8 = 20; data->state = ER_STATE_LINK_ERROR;
} }
else if (GetBlockReceivedStatus()) else if (GetBlockReceivedStatus())
{ {
ResetBlockReceivedFlags(); ResetBlockReceivedFlags();
data->unk8 = 15; data->state = ER_STATE_VALIDATE_CARD;
} }
break; break;
case 15: case ER_STATE_VALIDATE_CARD:
data->unkE = ValidateTrainerHillData((struct EReaderTrainerHillSet *)gDecompressionBuffer); data->status = ValidateTrainerHillData((struct EReaderTrainerHillSet *)gDecompressionBuffer);
SetCloseLinkCallbackAndType(data->unkE); SetCloseLinkCallbackAndType(data->status);
data->unk8 = 16; data->state = ER_STATE_WAIT_DISCONNECT;
break; break;
case 16: case ER_STATE_WAIT_DISCONNECT:
if (!gReceivedRemoteLinkPlayers) if (!gReceivedRemoteLinkPlayers)
{ {
if (data->unkE == 1) if (data->status == TRUE) // Was data valid?
data->unk8 = 17; data->state = ER_STATE_SAVE;
else else
data->unk8 = 20; data->state = ER_STATE_LINK_ERROR;
} }
break; break;
case 17: case ER_STATE_SAVE:
if (TryWriteTrainerHill((struct EReaderTrainerHillSet *)&gDecompressionBuffer)) if (TryWriteTrainerHill((struct EReaderTrainerHillSet *)&gDecompressionBuffer))
{ {
AddTextPrinterToWindow1(gJPText_ConnectionComplete); AddTextPrinterToWindow1(gJPText_ConnectionComplete);
sub_81D505C(&data->unk0); ResetTimer(&data->timer);
data->unk8 = 18; data->state = ER_STATE_SUCCESS_MSG;
} }
else else
{ {
data->unk8 = 22; data->state = ER_STATE_SAVE_FAILED;
} }
break; break;
case 18: case ER_STATE_SUCCESS_MSG:
if (sub_81D5064(&data->unk0, 120)) if (UpdateTimer(&data->timer, 120))
{ {
AddTextPrinterToWindow1(gJPText_NewTrainerHasComeToHoenn); AddTextPrinterToWindow1(gJPText_NewTrainerHasComeToHoenn);
PlayFanfare(MUS_OBTAIN_ITEM); PlayFanfare(MUS_OBTAIN_ITEM);
data->unk8 = 19; data->state = ER_STATE_SUCCESS_END;
} }
break; break;
case 19: case ER_STATE_SUCCESS_END:
if (IsFanfareTaskInactive() && (JOY_NEW(A_BUTTON | B_BUTTON))) if (IsFanfareTaskInactive() && (JOY_NEW(A_BUTTON | B_BUTTON)))
data->unk8 = 26; data->state = ER_STATE_END;
break; break;
case 23: case ER_STATE_CANCELED_CARD_READ:
if (PrintMysteryGiftMenuMessage(&data->unk9, gJPText_CardReadingHasBeenHalted)) if (PrintMysteryGiftMenuMessage(&data->textState, gJPText_CardReadingHasBeenHalted))
data->unk8 = 26; data->state = ER_STATE_END;
break; break;
case 20: case ER_STATE_LINK_ERROR:
if (PrintMysteryGiftMenuMessage(&data->unk9, gJPText_ConnectionErrorCheckLink)) if (PrintMysteryGiftMenuMessage(&data->textState, gJPText_ConnectionErrorCheckLink))
data->unk8 = 0; data->state = ER_STATE_START;
break; break;
case 21: case ER_STATE_LINK_ERROR_TRY_AGAIN:
if (PrintMysteryGiftMenuMessage(&data->unk9, gJPText_ConnectionErrorTryAgain)) if (PrintMysteryGiftMenuMessage(&data->textState, gJPText_ConnectionErrorTryAgain))
data->unk8 = 0; data->state = ER_STATE_START;
break; break;
case 22: case ER_STATE_SAVE_FAILED:
if (PrintMysteryGiftMenuMessage(&data->unk9, gJPText_WriteErrorUnableToSaveData)) if (PrintMysteryGiftMenuMessage(&data->textState, gJPText_WriteErrorUnableToSaveData))
data->unk8 = 0; data->state = ER_STATE_START;
break; break;
case 26: case ER_STATE_END:
Free(data->unk10); Free(data->unusedBuffer);
DestroyTask(taskId); DestroyTask(taskId);
SetMainCallback2(MainCB_FreeAllBuffersAndReturnToInitTitleScreen); SetMainCallback2(MainCB_FreeAllBuffersAndReturnToInitTitleScreen);
break; break;

View File

@ -2192,30 +2192,26 @@ static bool8 DoHandshake(void)
{ {
REG_SIOMLT_SEND = SLAVE_HANDSHAKE; REG_SIOMLT_SEND = SLAVE_HANDSHAKE;
} }
*(u64 *)gLink.tempRecvBuffer = REG_SIOMLT_RECV; *(u64 *)gLink.handshakeBuffer = REG_SIOMLT_RECV;
REG_SIOMLT_RECV = 0; REG_SIOMLT_RECV = 0;
gLink.handshakeAsMaster = FALSE; gLink.handshakeAsMaster = FALSE;
for (i = 0; i < 4; i++) for (i = 0; i < MAX_LINK_PLAYERS; i++)
{ {
if ((gLink.tempRecvBuffer[i] & ~0x3) == SLAVE_HANDSHAKE || gLink.tempRecvBuffer[i] == MASTER_HANDSHAKE) if ((gLink.handshakeBuffer[i] & ~0x3) == SLAVE_HANDSHAKE || gLink.handshakeBuffer[i] == MASTER_HANDSHAKE)
{ {
playerCount++; playerCount++;
if (minRecv > gLink.tempRecvBuffer[i] && gLink.tempRecvBuffer[i] != 0) if (minRecv > gLink.handshakeBuffer[i] && gLink.handshakeBuffer[i] != 0)
{ minRecv = gLink.handshakeBuffer[i];
minRecv = gLink.tempRecvBuffer[i];
}
} }
else else
{ {
if (gLink.tempRecvBuffer[i] != 0xFFFF) if (gLink.handshakeBuffer[i] != 0xFFFF)
{
playerCount = 0; playerCount = 0;
}
break; break;
} }
} }
gLink.playerCount = playerCount; gLink.playerCount = playerCount;
if (gLink.playerCount > 1 && gLink.playerCount == sHandshakePlayerCount && gLink.tempRecvBuffer[0] == MASTER_HANDSHAKE) if (gLink.playerCount > 1 && gLink.playerCount == sHandshakePlayerCount && gLink.handshakeBuffer[0] == MASTER_HANDSHAKE)
{ {
return TRUE; return TRUE;
} }