Sync mystery gift menu, ereader screen

This commit is contained in:
GriffinR
2022-11-21 22:10:41 -05:00
parent af6837c093
commit 76c3b014d8
13 changed files with 1068 additions and 999 deletions
+1
View File
@@ -0,0 +1 @@
gEReaderData
-1
View File
@@ -1 +0,0 @@
sMEventSendToEReaderManager
+6 -3
View File
@@ -14,17 +14,20 @@ enum {
#define EREADER_XFER_EXE 1
#define EREADER_XFER_CHK 2
#define EREADER_XFER_SHIFT 0
#define EREADER_XFER_MASK 3
#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_MASK 0xC
#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_MASK 0x30
#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)
void EReaderHelper_SerialCallback(void);
void EReaderHelper_Timer3Callback(void);
+12 -6
View File
@@ -85,12 +85,12 @@
#define LINKCMD_PARTNER_CANCEL_TRADE 0xEECC
#define LINKCMD_NONE 0xEFFF
#define LINKTYPE_TRADE 0x1111 // trade
#define LINKTYPE_0x1122 0x1122 // trade
#define LINKTYPE_TRADE 0x1111
#define LINKTYPE_TRADE_CONNECTING 0x1122
#define LINKTYPE_TRADE_SETUP 0x1133
#define LINKTYPE_0x1144 0x1144 // trade
#define LINKTYPE_TRADE_DISCONNECTED 0x1144
#define LINKTYPE_BATTLE 0x2211
#define LINKTYPE_0x2222 0x2222 // unused battle?
#define LINKTYPE_UNUSED_BATTLE 0x2222 // Unused, inferred from gap
#define LINKTYPE_SINGLE_BATTLE 0x2233
#define LINKTYPE_DOUBLE_BATTLE 0x2244
#define LINKTYPE_MULTI_BATTLE 0x2255
@@ -100,7 +100,12 @@
#define LINKTYPE_RECORD_MIX_BEFORE 0x3311
#define LINKTYPE_RECORD_MIX_AFTER 0x3322
#define LINKTYPE_BERRY_BLENDER_SETUP 0x4411
#define LINKTYPE_BERRY_BLENDER 0x4422
#define LINKTYPE_MYSTERY_EVENT 0x5501
#define LINKTYPE_EREADER_FRLG 0x5502
#define LINKTYPE_EREADER_EM 0x5503
#define LINKTYPE_CONTEST_GMODE 0x6601
#define LINKTYPE_CONTEST_EMODE 0x6602
enum {
BLOCK_REQ_SIZE_NONE, // Identical to 200
@@ -110,8 +115,9 @@ enum {
BLOCK_REQ_SIZE_40,
};
#define MASTER_HANDSHAKE 0x8FFF
#define SLAVE_HANDSHAKE 0xB9A0
#define MASTER_HANDSHAKE 0x8FFF
#define SLAVE_HANDSHAKE 0xB9A0
#define EREADER_HANDSHAKE 0xCCD0
#define IsSendCmdComplete() (gSendCmd[0] == 0)
-2
View File
@@ -233,8 +233,6 @@ extern struct RfuGameData gHostRfuGameData;
extern u8 gHostRfuUsername[];
extern struct RfuManager gRfu;
void AddTextPrinterToWindow1(const u8 *str);
bool32 PrintMysteryGiftMenuMessage(u8 * cmdPtr, const u8 * src);
void LinkRfu_FatalError(void);
void MG_DrawCheckerboardPattern(void);
void Rfu_SetCloseLinkCallback(void);
-12
View File
@@ -37,18 +37,6 @@ struct MysteryGiftLinkGameData
u8 version;
};
struct MEvent_Str_1
{
u16 status;
size_t size;
const void *data;
};
struct MEvent_Str_2
{
u8 fill_00[0x40];
};
struct WonderGraphics
{
u8 titleTextPal:4;
+3 -1
View File
@@ -3,9 +3,11 @@
extern bool8 gGiftIsFromEReader;
bool32 PrintMysteryGiftMenuMessage(u8 * cmdPtr, const u8 * src);
void AddTextPrinterToWindow1(const u8 *str);
void MainCB_FreeAllBuffersAndReturnToInitTitleScreen(void);
void PrintMysteryGiftOrEReaderTopMenu(bool8, bool32);
void c2_mystery_gift(void);
void CB2_InitMysteryGift(void);
void CB2_MysteryGiftEReader(void);
s8 DoMysteryGiftYesNo(u8 * textState, u16 * windowId, bool8 yesNoBoxPlacement, const u8 * str);
void MG_DrawTextBorder(u8 windowId);
+2
View File
@@ -275,6 +275,7 @@ SECTIONS {
src/slot_machine.o(.text);
src/roamer.o(.text);
src/mystery_gift_menu.o(.text);
src/ereader_screen.o(.text);
src/mystery_gift.o(.text);
src/mystery_gift_link.o(.text);
src/mystery_gift_client.o(.text);
@@ -568,6 +569,7 @@ SECTIONS {
src/slot_machine.o(.rodata);
src/roamer.o(.rodata);
src/mystery_gift_menu.o(.rodata);
src/ereader_screen.o(.rodata);
src/mystery_gift.o(.rodata);
src/mystery_gift_link.o(.rodata);
src/mystery_gift_client.o(.rodata);
+520
View File
@@ -0,0 +1,520 @@
#include "global.h"
#include "malloc.h"
#include "decompress.h"
#include "ereader_helpers.h"
#include "link.h"
#include "main.h"
#include "mystery_gift_menu.h"
#include "mystery_gift_client.h"
#include "save.h"
#include "sound.h"
#include "sprite.h"
#include "task.h"
#include "strings.h"
#include "util.h"
#include "cereader_tool.h"
#include "help_system.h"
#include "constants/songs.h"
struct EReaderTaskData
{
u16 timer;
u16 unused1;
u16 unused2;
u16 unused3;
u8 state;
u8 textState;
u8 unused4;
u8 unused5;
u8 unused6;
u8 unused7;
u8 status;
u8 *unusedBuffer;
};
struct EReaderData
{
u16 status;
size_t size;
const void *data;
};
static void Task_EReader(u8);
struct EReaderData gEReaderData;
extern const u8 gMultiBootProgram_EReader_Start[];
extern const u8 gMultiBootProgram_EReader_End[];
static void EReader_Load(struct EReaderData *eReader, size_t size, const void *data)
{
vu16 imeBak = REG_IME;
REG_IME = 0;
gIntrTable[1] = EReaderHelper_SerialCallback;
gIntrTable[2] = EReaderHelper_Timer3Callback;
EReaderHelper_SaveRegsState();
EReaderHelper_ClearsSendRecvMgr();
REG_IE |= INTR_FLAG_VCOUNT;
REG_IME = imeBak;
eReader->status = 0;
eReader->size = size;
eReader->data = data;
}
static void EReader_Reset(struct EReaderData *eReader)
{
vu16 imeBak = REG_IME;
REG_IME = 0;
EReaderHelper_ClearsSendRecvMgr();
EReaderHelper_RestoreRegsState();
RestoreSerialTimer3IntrHandlers();
REG_IME = imeBak;
}
// Return values for EReader_Transfer
enum {
TRANSFER_ACTIVE,
TRANSFER_SUCCESS,
TRANSFER_CANCELED,
TRANSFER_TIMEOUT,
};
static u8 EReader_Transfer(struct EReaderData *eReader)
{
u8 transferStatus = TRANSFER_ACTIVE;
eReader->status = EReaderHandleTransfer(TRUE, eReader->size, eReader->data, NULL);
if ((eReader->status & EREADER_XFER_MASK) == 0 && eReader->status & EREADER_CHECKSUM_OK_MASK)
transferStatus = TRANSFER_SUCCESS;
if (eReader->status & EREADER_CANCEL_KEY_MASK)
transferStatus = TRANSFER_CANCELED;
if (eReader->status & EREADER_CANCEL_TIMEOUT_MASK)
transferStatus = TRANSFER_TIMEOUT;
gShouldAdvanceLinkState = 0;
return transferStatus;
}
static void OpenEReaderLink(void)
{
memset(gDecompressionBuffer, 0, 0x2000);
gLinkType = LINKTYPE_EREADER_FRLG;
OpenLink();
SetSuppressLinkErrorMessage(TRUE);
}
static bool32 ValidateEReaderConnection(void)
{
vu16 imeBak = REG_IME;
u16 handshakes[MAX_LINK_PLAYERS];
REG_IME = 0;
*(u64 *)handshakes = *(u64 *)gLink.tempRecvBuffer;
REG_IME = imeBak;
// 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 FALSE;
}
static bool32 IsEReaderConnectionSane(void)
{
if (IsLinkMaster() && GetLinkPlayerCount_2() == 2)
return TRUE;
return FALSE;
}
// States for TryReceiveCard
enum {
RECV_STATE_INIT,
RECV_STATE_WAIT_START,
RECV_STATE_START,
RECV_STATE_EXCHANGE,
RECV_STATE_START_DISCONNECT,
RECV_STATE_WAIT_DISCONNECT,
};
// Return values for TryReceiveCard
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_START_DISCONNECT
|| *state == RECV_STATE_WAIT_DISCONNECT)
&& HasLinkErrorOccurred())
{
// Return error status if an error occurs
// during the link exchange.
*state = 0;
return RECV_ERROR;
}
switch (*state)
{
case RECV_STATE_INIT:
if (IsLinkMaster() && GetLinkPlayerCount_2() > 1)
{
*state = RECV_STATE_WAIT_START;
}
else if (JOY_NEW(B_BUTTON))
{
*state = 0;
return RECV_CANCELED;
}
break;
case RECV_STATE_WAIT_START:
if (++(*timer) > 5)
{
*timer = 0;
*state = RECV_STATE_START;
}
break;
case RECV_STATE_START:
if (GetLinkPlayerCount_2() == 2)
{
PlaySE(SE_DING_DONG);
CheckShouldAdvanceLinkState();
*timer = 0;
*state = RECV_STATE_EXCHANGE;
}
else if (JOY_NEW(B_BUTTON))
{
*state = 0;
return RECV_CANCELED;
}
break;
case RECV_STATE_EXCHANGE:
if (++(*timer) > 30)
{
*state = 0;
return RECV_TIMEOUT;
}
if (IsLinkConnectionEstablished())
{
if (gReceivedRemoteLinkPlayers)
{
if (IsLinkPlayerDataExchangeComplete())
{
*state = 0;
return RECV_SUCCESS;
}
else
*state = RECV_STATE_START_DISCONNECT;
}
else
*state = RECV_STATE_EXCHANGE;
}
break;
case RECV_STATE_START_DISCONNECT:
SetCloseLinkCallbackAndType(0);
*state = RECV_STATE_WAIT_DISCONNECT;
break;
case RECV_STATE_WAIT_DISCONNECT:
if (!gReceivedRemoteLinkPlayers)
{
*state = 0;
return RECV_DISCONNECTED;
}
break;
}
return RECV_ACTIVE;
}
void CreateEReaderTask(void)
{
u8 taskId = CreateTask(Task_EReader, 0);
struct EReaderTaskData *data = (struct EReaderTaskData *)gTasks[taskId].data;
data->state = 0;
data->textState = 0;
data->unused4 = 0;
data->unused5 = 0;
data->unused6 = 0;
data->unused7 = 0;
data->timer = 0;
data->unused1 = 0;
data->unused2 = 0;
data->unused3 = 0;
data->status = 0;
data->unusedBuffer = AllocZeroed(CLIENT_MAX_MSG_SIZE);
}
static void ResetTimer(u16 *timer)
{
*timer = 0;
}
static bool32 UpdateTimer(u16 * timer, u16 time)
{
if (++(*timer) > time)
{
// Timer has finished
*timer = 0;
return TRUE;
}
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)
{
struct EReaderTaskData *data = (struct EReaderTaskData *)gTasks[taskId].data;
switch (data->state)
{
case ER_STATE_START:
if (PrintMysteryGiftMenuMessage(&data->textState, gJPText_ReceiveMysteryGiftWithEReader))
data->state = ER_STATE_INIT_LINK;
break;
case ER_STATE_INIT_LINK:
OpenEReaderLink();
ResetTimer(&data->timer);
data->state = ER_STATE_INIT_LINK_WAIT;
break;
case ER_STATE_INIT_LINK_WAIT:
if (UpdateTimer(&data->timer, 10))
data->state = ER_STATE_INIT_LINK_CHECK;
break;
case ER_STATE_INIT_LINK_CHECK:
if (!IsEReaderConnectionSane())
{
CloseLink();
data->state = ER_STATE_MSG_SELECT_CONNECT;
}
else
data->state = ER_STATE_LOAD_CARD;
break;
case ER_STATE_MSG_SELECT_CONNECT:
if (PrintMysteryGiftMenuMessage(&data->textState, gJPText_SelectConnectFromEReaderMenu))
{
AddTextPrinterToWindow1(gJPText_SelectConnectWithGBA);
ResetTimer(&data->timer);
data->state = ER_STATE_MSG_SELECT_CONNECT_WAIT;
}
break;
case ER_STATE_MSG_SELECT_CONNECT_WAIT:
if (UpdateTimer(&data->timer, 90))
{
OpenEReaderLink();
data->state = ER_STATE_TRY_LINK;
}
else if (JOY_NEW(B_BUTTON))
{
ResetTimer(&data->timer);
PlaySE(SE_SELECT);
data->state = ER_STATE_CANCELED_CARD_READ;
}
break;
case ER_STATE_TRY_LINK:
if (JOY_NEW(B_BUTTON))
{
// Canceled
PlaySE(SE_SELECT);
CloseLink();
ResetTimer(&data->timer);
data->state = ER_STATE_CANCELED_CARD_READ;
}
else if (GetLinkPlayerCount_2() > 1)
{
ResetTimer(&data->timer);
CloseLink();
data->state = ER_STATE_INCORRECT_LINK;
}
else if (ValidateEReaderConnection())
{
// Successful connection
PlaySE(SE_SELECT);
CloseLink();
ResetTimer(&data->timer);
data->state = ER_STATE_CONNECTING;
}
else if (UpdateTimer(&data->timer, 10))
{
// Retry connection
CloseLink();
OpenEReaderLink();
ResetTimer(&data->timer);
}
break;
case ER_STATE_INCORRECT_LINK:
if (PrintMysteryGiftMenuMessage(&data->textState, gJPText_LinkIsIncorrect))
data->state = ER_STATE_MSG_SELECT_CONNECT;
break;
case ER_STATE_CONNECTING:
AddTextPrinterToWindow1(gJPText_Connecting);
EReader_Load(&gEReaderData, gMultiBootProgram_EReader_End - gMultiBootProgram_EReader_Start, gMultiBootProgram_EReader_Start);
data->state = ER_STATE_TRANSFER;
break;
case ER_STATE_TRANSFER:
data->status = EReader_Transfer(&gEReaderData);
if (data->status != TRANSFER_ACTIVE)
data->state = ER_STATE_TRANSFER_END;
break;
case ER_STATE_TRANSFER_END:
EReader_Reset(&gEReaderData);
if (data->status == TRANSFER_TIMEOUT)
{
data->state = ER_STATE_LINK_ERROR;
}
else if (data->status == TRANSFER_SUCCESS)
{
ResetTimer(&data->timer);
AddTextPrinterToWindow1(gJPText_PleaseWaitAMoment);
data->state = ER_STATE_TRANSFER_SUCCESS;
}
else // TRANSFER_CANCELED
{
data->state = ER_STATE_START;
}
break;
case ER_STATE_TRANSFER_SUCCESS:
if (UpdateTimer(&data->timer, 840))
data->state = ER_STATE_LOAD_CARD_START;
break;
case ER_STATE_LOAD_CARD_START:
OpenEReaderLink();
AddTextPrinterToWindow1(gJPText_AllowEReaderToLoadCard);
data->state = ER_STATE_LOAD_CARD;
break;
case ER_STATE_LOAD_CARD:
switch (TryReceiveCard(&data->textState, &data->timer))
{
case RECV_ACTIVE:
// Running
break;
case RECV_SUCCESS:
AddTextPrinterToWindow1(gJPText_Connecting);
data->state = ER_STATE_WAIT_RECV_CARD;
break;
case RECV_CANCELED:
PlaySE(SE_SELECT);
CloseLink();
data->state = ER_STATE_CANCELED_CARD_READ;
break;
case RECV_TIMEOUT:
CloseLink();
data->state = ER_STATE_LINK_ERROR_TRY_AGAIN;
break;
case RECV_ERROR:
case RECV_DISCONNECTED:
CloseLink();
data->state = ER_STATE_LINK_ERROR;
break;
}
break;
case ER_STATE_WAIT_RECV_CARD:
if (HasLinkErrorOccurred())
{
CloseLink();
data->state = ER_STATE_LINK_ERROR;
}
else if (GetBlockReceivedStatus())
{
ResetBlockReceivedFlags();
data->state = ER_STATE_VALIDATE_CARD;
}
break;
case ER_STATE_VALIDATE_CARD:
data->status = ValidateTrainerTowerData((struct EReaderTrainerTowerSet *)gDecompressionBuffer);
SetCloseLinkCallbackAndType(data->status);
data->state = ER_STATE_WAIT_DISCONNECT;
break;
case ER_STATE_WAIT_DISCONNECT:
if (!gReceivedRemoteLinkPlayers)
{
if (data->status == TRUE) // Was data valid?
data->state = ER_STATE_SAVE;
else
data->state = ER_STATE_LINK_ERROR;
}
break;
case ER_STATE_SAVE:
if (CEReaderTool_SaveTrainerTower((struct EReaderTrainerTowerSet *)gDecompressionBuffer))
{
AddTextPrinterToWindow1(gJPText_ConnectionComplete);
ResetTimer(&data->timer);
data->state = ER_STATE_SUCCESS_MSG;
}
else
data->state = ER_STATE_SAVE_FAILED;
break;
case ER_STATE_SUCCESS_MSG:
if (UpdateTimer(&data->timer, 120))
{
AddTextPrinterToWindow1(gJPText_NewTrainerHasComeToSevii);
PlayFanfare(MUS_OBTAIN_ITEM);
data->state = ER_STATE_SUCCESS_END;
}
break;
case ER_STATE_SUCCESS_END:
if (IsFanfareTaskInactive() && JOY_NEW(A_BUTTON | B_BUTTON))
data->state = ER_STATE_END;
break;
case ER_STATE_CANCELED_CARD_READ:
if (PrintMysteryGiftMenuMessage(&data->textState, gJPText_CardReadingHasBeenHalted))
data->state = ER_STATE_END;
break;
case ER_STATE_LINK_ERROR:
if (PrintMysteryGiftMenuMessage(&data->textState, gJPText_ConnectionErrorCheckLink))
data->state = ER_STATE_START;
break;
case ER_STATE_LINK_ERROR_TRY_AGAIN:
if (PrintMysteryGiftMenuMessage(&data->textState, gJPText_ConnectionErrorTryAgain))
data->state = ER_STATE_START;
break;
case ER_STATE_SAVE_FAILED:
if (PrintMysteryGiftMenuMessage(&data->textState, gJPText_WriteErrorUnableToSaveData))
data->state = ER_STATE_START;
break;
case ER_STATE_END:
HelpSystem_Enable();
Free(data->unusedBuffer);
DestroyTask(taskId);
SetMainCallback2(MainCB_FreeAllBuffersAndReturnToInitTitleScreen);
break;
}
}
+1 -1
View File
@@ -481,7 +481,7 @@ static void Task_ExecuteMainMenuSelection(u8 taskId)
TrySetUpQuestLogScenes_ElseContinueFromSave(taskId);
break;
case MAIN_MENU_MYSTERYGIFT:
SetMainCallback2(c2_mystery_gift);
SetMainCallback2(CB2_InitMysteryGift);
HelpSystem_Disable();
FreeAllWindowBuffers();
DestroyTask(taskId);
-425
View File
@@ -3,17 +3,14 @@
#include "constants/songs.h"
#include "easy_chat.h"
#include "task.h"
#include "decompress.h"
#include "link.h"
#include "link_rfu.h"
#include "ereader_helpers.h"
#include "util.h"
#include "script.h"
#include "event_data.h"
#include "battle_tower.h"
#include "new_game.h"
#include "wonder_news.h"
#include "cereader_tool.h"
#include "mystery_gift_menu.h"
#include "help_system.h"
#include "mystery_gift.h"
@@ -21,23 +18,6 @@
#define CALC_CRC(data) CalcCRC16WithTable((void *)&(data), sizeof(data))
struct MEventTaskData1
{
u16 stateAdvanceDelay;
u16 t02;
u16 t04;
u16 t06;
u8 state;
u8 textOrReceiveState;
u8 t0A;
u8 t0B;
u8 t0C;
u8 t0D;
u8 initialSendResult;
struct MEvent_Str_2 *t10;
};
static void Task_EReaderComm(u8 taskId);
static bool32 ValidateWonderNews(const struct WonderNews * src);
static void ClearSavedWonderNews(void);
static void ClearSavedWonderNewsMetadata(void);
@@ -47,9 +27,6 @@ static void ClearSavedWonderCardMetadata(void);
static void IncrementCardStatForNewTrainer(u32 eventId, u32 trainerId, u32 *idsList, s32 count);
static void ClearSavedTrainerIds(void);
extern const u8 gMultiBootProgram_EReader_Start[];
extern const u8 gMultiBootProgram_EReader_End[];
static const u16 sReceivedGiftFlags[] = {
FLAG_RECEIVED_AURORA_TICKET,
FLAG_RECEIVED_MYSTIC_TICKET,
@@ -73,410 +50,8 @@ static const u16 sReceivedGiftFlags[] = {
FLAG_WONDER_CARD_UNUSED_17
};
struct MEvent_Str_1 sMEventSendToEReaderManager;
static EWRAM_DATA bool32 sStatsEnabled = FALSE;
void SendUnknownSerialData_Init(struct MEvent_Str_1 *mgr, size_t size, const void *data)
{
vu16 imeBak = REG_IME;
REG_IME = 0;
gIntrTable[1] = EReaderHelper_SerialCallback;
gIntrTable[2] = EReaderHelper_Timer3Callback;
EReaderHelper_SaveRegsState();
EReaderHelper_ClearsSendRecvMgr();
REG_IE |= INTR_FLAG_VCOUNT;
REG_IME = imeBak;
mgr->status = 0;
mgr->size = size;
mgr->data = data;
}
void SendUnknownSerialData_Teardown(struct MEvent_Str_1 *unused)
{
vu16 imeBak = REG_IME;
REG_IME = 0;
EReaderHelper_ClearsSendRecvMgr();
EReaderHelper_RestoreRegsState();
RestoreSerialTimer3IntrHandlers();
REG_IME = imeBak;
}
u8 SendUnknownSerialData_Run(struct MEvent_Str_1 *mgr)
{
u8 resp = 0;
mgr->status = EReaderHandleTransfer(1, mgr->size, mgr->data, 0);
if ((mgr->status & 0x13) == 0x10) // checksum OK and xfer off
resp = 1;
if (mgr->status & 8) // cancelled by player
resp = 2;
if (mgr->status & 4) // timed out
resp = 3;
gShouldAdvanceLinkState = 0;
return resp;
}
static void ResetTTDataBuffer(void)
{
memset(gDecompressionBuffer, 0, 0x2000);
gLinkType = 0x5502;
OpenLink();
SetSuppressLinkErrorMessage(TRUE);
}
bool32 sub_81436EC(void)
{
vu16 imeBak = REG_IME;
u16 data[4];
REG_IME = 0;
*(u64 *)data = *(u64 *)gLink.tempRecvBuffer;
REG_IME = imeBak;
if ( data[0] == 0xB9A0
&& data[1] == 0xCCD0
&& data[2] == 0xFFFF
&& data[3] == 0xFFFF
)
return TRUE;
return FALSE;
}
static bool32 IsEReaderConnectionSane(void)
{
if (IsLinkMaster() && GetLinkPlayerCount_2() == 2)
return TRUE;
return FALSE;
}
static u32 EReaderReceive(u8 * state_p, u16 * receiveDelay)
{
if ((*state_p == 3 || *state_p == 4 || *state_p == 5) && HasLinkErrorOccurred())
{
*state_p = 0;
return 3;
}
switch (*state_p)
{
case 0:
if (IsLinkMaster() && GetLinkPlayerCount_2() > 1)
{
*state_p = 1;
;
}
else if (JOY_NEW(B_BUTTON))
{
*state_p = 0;
return 1;
}
break;
case 1:
if (++(*receiveDelay) > 5)
{
*receiveDelay = 0;
*state_p = 2;
}
break;
case 2:
if (GetLinkPlayerCount_2() == 2)
{
PlaySE(SE_DING_DONG);
CheckShouldAdvanceLinkState();
*receiveDelay = 0;
*state_p = 3;
}
else if (JOY_NEW(B_BUTTON))
{
*state_p = 0;
return 1;
}
break;
case 3:
if (++(*receiveDelay) > 30)
{
*state_p = 0;
return 5;
}
else if (IsLinkConnectionEstablished())
{
if (gReceivedRemoteLinkPlayers)
{
if (IsLinkPlayerDataExchangeComplete())
{
*state_p = 0;
return 2;
}
else
*state_p = 4;
}
else
*state_p = 3;
}
break;
case 4:
SetCloseLinkCallbackAndType(0);
*state_p = 5;
break;
case 5:
if (!gReceivedRemoteLinkPlayers)
{
*state_p = 0;
return 4;
}
break;
}
return 0;
}
void task_add_00_ereader(void)
{
u8 taskId = CreateTask(Task_EReaderComm, 0);
struct MEventTaskData1 *data = (struct MEventTaskData1 *)gTasks[taskId].data;
data->state = 0;
data->textOrReceiveState = 0;
data->t0A = 0;
data->t0B = 0;
data->t0C = 0;
data->t0D = 0;
data->stateAdvanceDelay = 0;
data->t02 = 0;
data->t04 = 0;
data->t06 = 0;
data->initialSendResult = 0;
data->t10 = AllocZeroed(sizeof(struct MEvent_Str_2));
}
static void ResetDelayTimer(u16 *a0)
{
*a0 = 0;
}
static bool32 AdvanceDelayTimerCheckTimeout(u16 * a0, u16 a1)
{
if (++(*a0) > a1)
{
*a0 = 0;
return TRUE;
}
return FALSE;
}
static void Task_EReaderComm(u8 taskId)
{
struct MEventTaskData1 *data = (struct MEventTaskData1 *)gTasks[taskId].data;
switch (data->state)
{
case 0:
if (PrintMysteryGiftMenuMessage(&data->textOrReceiveState, gJPText_ReceiveMysteryGiftWithEReader))
data->state = 1;
break;
case 1:
ResetTTDataBuffer();
ResetDelayTimer(&data->stateAdvanceDelay);
data->state = 2;
break;
case 2:
if (AdvanceDelayTimerCheckTimeout(&data->stateAdvanceDelay, 10))
data->state = 3;
break;
case 3:
if (!IsEReaderConnectionSane())
{
CloseLink();
data->state = 4;
}
else
data->state = 13;
break;
case 4:
if (PrintMysteryGiftMenuMessage(&data->textOrReceiveState, gJPText_SelectConnectFromEReaderMenu))
{
AddTextPrinterToWindow1(gJPText_SelectConnectWithGBA);
ResetDelayTimer(&data->stateAdvanceDelay);
data->state = 5;
}
break;
case 5:
if (AdvanceDelayTimerCheckTimeout(&data->stateAdvanceDelay, 90))
{
ResetTTDataBuffer();
data->state = 6;
}
else if (JOY_NEW(B_BUTTON))
{
ResetDelayTimer(&data->stateAdvanceDelay);
PlaySE(SE_SELECT);
data->state = 23;
}
break;
case 6:
if (JOY_NEW(B_BUTTON))
{
PlaySE(SE_SELECT);
CloseLink();
ResetDelayTimer(&data->stateAdvanceDelay);
data->state = 23;
}
else if (GetLinkPlayerCount_2() > 1)
{
ResetDelayTimer(&data->stateAdvanceDelay);
CloseLink();
data->state = 7;
}
else if (sub_81436EC())
{
PlaySE(SE_SELECT);
CloseLink();
ResetDelayTimer(&data->stateAdvanceDelay);
data->state = 8;
}
else if (AdvanceDelayTimerCheckTimeout(&data->stateAdvanceDelay, 10))
{
CloseLink();
ResetTTDataBuffer();
ResetDelayTimer(&data->stateAdvanceDelay);
}
break;
case 7:
if (PrintMysteryGiftMenuMessage(&data->textOrReceiveState, gJPText_LinkIsIncorrect))
data->state = 4;
break;
case 8:
AddTextPrinterToWindow1(gJPText_Connecting);
SendUnknownSerialData_Init(&sMEventSendToEReaderManager, gMultiBootProgram_EReader_End - gMultiBootProgram_EReader_Start, gMultiBootProgram_EReader_Start);
data->state = 9;
break;
case 9:
data->initialSendResult = SendUnknownSerialData_Run(&sMEventSendToEReaderManager);
if (data->initialSendResult != 0)
data->state = 10;
break;
case 10:
SendUnknownSerialData_Teardown(&sMEventSendToEReaderManager);
if (data->initialSendResult == 3)
// Error
data->state = 20;
else if (data->initialSendResult == 1)
{
// OK
ResetDelayTimer(&data->stateAdvanceDelay);
AddTextPrinterToWindow1(gJPText_PleaseWaitAMoment);
data->state = 11;
}
else
// Try again
data->state = 0;
break;
case 11:
if (AdvanceDelayTimerCheckTimeout(&data->stateAdvanceDelay, 840))
data->state = 12;
break;
case 12:
ResetTTDataBuffer();
AddTextPrinterToWindow1(gJPText_AllowEReaderToLoadCard);
data->state = 13;
break;
case 13:
switch (EReaderReceive(&data->textOrReceiveState, &data->stateAdvanceDelay))
{
case 0:
// Running
break;
case 2:
// Done
AddTextPrinterToWindow1(gJPText_Connecting);
data->state = 14;
break;
case 1:
// Cancelled
PlaySE(SE_SELECT);
CloseLink();
data->state = 23;
break;
case 5:
// Error Try Again
CloseLink();
data->state = 21;
break;
case 3:
case 4:
// Error CheckLink
CloseLink();
data->state = 20;
break;
}
break;
case 14:
if (HasLinkErrorOccurred())
{
CloseLink();
data->state = 20;
}
else if (GetBlockReceivedStatus())
{
ResetBlockReceivedFlags();
data->state = 15;
}
break;
case 15:
data->initialSendResult = ValidateTrainerTowerData((struct EReaderTrainerTowerSet *)gDecompressionBuffer);
SetCloseLinkCallbackAndType(data->initialSendResult);
data->state = 16;
break;
case 16:
if (!gReceivedRemoteLinkPlayers)
{
if (data->initialSendResult == 1)
data->state = 17;
else
data->state = 20;
}
break;
case 17:
if (CEReaderTool_SaveTrainerTower((struct EReaderTrainerTowerSet *)gDecompressionBuffer))
{
AddTextPrinterToWindow1(gJPText_ConnectionComplete);
ResetDelayTimer(&data->stateAdvanceDelay);
data->state = 18;
}
else
data->state = 22;
break;
case 18:
if (AdvanceDelayTimerCheckTimeout(&data->stateAdvanceDelay, 120))
{
AddTextPrinterToWindow1(gJPText_NewTrainerHasComeToSevii);
PlayFanfare(MUS_OBTAIN_ITEM);
data->state = 19;
}
break;
case 19:
if (IsFanfareTaskInactive() && JOY_NEW(A_BUTTON | B_BUTTON))
data->state = 26;
break;
case 23:
if (PrintMysteryGiftMenuMessage(&data->textOrReceiveState, gJPText_CardReadingHasBeenHalted))
data->state = 26;
break;
case 20:
if (PrintMysteryGiftMenuMessage(&data->textOrReceiveState, gJPText_ConnectionErrorCheckLink))
data->state = 0;
break;
case 21:
if (PrintMysteryGiftMenuMessage(&data->textOrReceiveState, gJPText_ConnectionErrorTryAgain))
data->state = 0;
break;
case 22:
if (PrintMysteryGiftMenuMessage(&data->textOrReceiveState, gJPText_WriteErrorUnableToSaveData))
data->state = 0;
break;
case 26:
HelpSystem_Enable();
Free(data->t10);
DestroyTask(taskId);
SetMainCallback2(MainCB_FreeAllBuffersAndReturnToInitTitleScreen);
break;
}
}
void ClearMysteryGift(void)
{
CpuFill32(0, &gSaveBlock1Ptr->mysteryGift, sizeof(gSaveBlock1Ptr->mysteryGift));
+522 -547
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -40,7 +40,7 @@
.include "fame_checker.o"
.include "help_system_util.o"
.align 4
.include "mystery_gift.o"
.include "ereader_screen.o"
.align 4
.include "battle_controller_pokedude.o"
.align 4