Merge pull request #586 from GriffinRichards/sync-mevent
Sync mystery gift
This commit is contained in:
+1
-1
@@ -10,7 +10,7 @@
|
||||
#include "link.h"
|
||||
#include "load_save.h"
|
||||
#include "m4a.h"
|
||||
#include "mevent.h"
|
||||
#include "mystery_gift.h"
|
||||
#include "new_menu_helpers.h"
|
||||
#include "overworld.h"
|
||||
#include "quest_log.h"
|
||||
|
||||
+4
-4
@@ -4,7 +4,7 @@
|
||||
#include "easy_chat.h"
|
||||
#include "event_data.h"
|
||||
#include "field_message_box.h"
|
||||
#include "mevent.h"
|
||||
#include "mystery_gift.h"
|
||||
#include "menu.h"
|
||||
#include "mail.h"
|
||||
#include "pokedex.h"
|
||||
@@ -472,11 +472,11 @@ void InitEasyChatPhrases(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
void EC_ResetMEventProfileMaybe(void)
|
||||
void InitQuestionnaireWords(void)
|
||||
{
|
||||
s32 i;
|
||||
u16 *ptr = GetMEventProfileECWordsMaybe();
|
||||
for (i = 0; i < 4; i++)
|
||||
u16 *ptr = GetQuestionnaireWordsPtr();
|
||||
for (i = 0; i < NUM_QUESTIONNAIRE_WORDS; i++)
|
||||
ptr[i] = EC_WORD_UNDEFINED;
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -3,7 +3,7 @@
|
||||
#include "easy_chat.h"
|
||||
#include "event_data.h"
|
||||
#include "menu.h"
|
||||
#include "mevent.h"
|
||||
#include "mystery_gift.h"
|
||||
#include "overworld.h"
|
||||
#include "strings.h"
|
||||
#include "task.h"
|
||||
@@ -271,7 +271,7 @@ void ShowEasyChatScreen(void)
|
||||
words = gSaveBlock1Ptr->easyChatBattleLost;
|
||||
break;
|
||||
case EASY_CHAT_TYPE_QUESTIONNAIRE:
|
||||
words = GetMEventProfileECWordsMaybe();
|
||||
words = GetQuestionnaireWordsPtr();
|
||||
break;
|
||||
case EASY_CHAT_TYPE_MAIL:
|
||||
words = gSaveBlock1Ptr->mail[gSpecialVar_0x8005].words;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -129,7 +129,7 @@ bool32 IsMysteryGiftEnabled(void)
|
||||
return FlagGet(FLAG_SYS_MYSTERY_GIFT_ENABLED);
|
||||
}
|
||||
|
||||
void ResetMysteryEventFlags(void)
|
||||
void ClearMysteryGiftFlags(void)
|
||||
{
|
||||
FlagClear(FLAG_MYSTERY_GIFT_DONE);
|
||||
FlagClear(FLAG_MYSTERY_GIFT_1);
|
||||
@@ -149,7 +149,7 @@ void ResetMysteryEventFlags(void)
|
||||
FlagClear(FLAG_MYSTERY_GIFT_15);
|
||||
}
|
||||
|
||||
void ResetMysteryEventVars(void)
|
||||
void ClearMysteryGiftVars(void)
|
||||
{
|
||||
VarSet(VAR_EVENT_PICHU_SLOT, 0);
|
||||
VarSet(VAR_MYSTERY_GIFT_1, 0);
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
#include "field_specials.h"
|
||||
#include "item_menu.h"
|
||||
#include "link.h"
|
||||
#include "menews_jisan.h"
|
||||
#include "wonder_news.h"
|
||||
#include "metatile_behavior.h"
|
||||
#include "overworld.h"
|
||||
#include "renewable_hidden_items.h"
|
||||
@@ -215,7 +215,7 @@ int ProcessPlayerFieldInput(struct FieldInput *input)
|
||||
if (input->tookStep)
|
||||
{
|
||||
IncrementGameStat(GAME_STAT_STEPS);
|
||||
MENewsJisanStepCounter();
|
||||
WonderNews_IncrementStepCounter();
|
||||
IncrementRenewableHiddenItemStepCounter();
|
||||
RunMassageCooldownStepCounter();
|
||||
IncrementResortGorgeousStepCounter();
|
||||
|
||||
+12
-12
@@ -28,7 +28,7 @@
|
||||
#include "pokedex.h"
|
||||
#include "text_window.h"
|
||||
#include "menu.h"
|
||||
#include "mevent.h"
|
||||
#include "mystery_gift.h"
|
||||
#include "naming_screen.h"
|
||||
#include "party_menu.h"
|
||||
#include "dynamic_placeholder_text_util.h"
|
||||
@@ -1950,20 +1950,20 @@ void QuestLog_TryRecordDepartedLocation(void)
|
||||
}
|
||||
}
|
||||
|
||||
u16 BattleCardAction(void)
|
||||
u16 GetMysteryGiftCardStat(void)
|
||||
{
|
||||
switch (gSpecialVar_Result)
|
||||
{
|
||||
case 0:
|
||||
return MEvent_GetBattleCardCount(3);
|
||||
case 1:
|
||||
return MEvent_GetBattleCardCount(4);
|
||||
case 2:
|
||||
return MEvent_GetBattleCardCount(0);
|
||||
case 3:
|
||||
return MEvent_GetBattleCardCount(1);
|
||||
case 4:
|
||||
return MEvent_GetBattleCardCount(2);
|
||||
case GET_NUM_STAMPS:
|
||||
return MysteryGift_GetCardStat(CARD_STAT_NUM_STAMPS);
|
||||
case GET_MAX_STAMPS:
|
||||
return MysteryGift_GetCardStat(CARD_STAT_MAX_STAMPS);
|
||||
case GET_CARD_BATTLES_WON:
|
||||
return MysteryGift_GetCardStat(CARD_STAT_BATTLES_WON);
|
||||
case GET_CARD_BATTLES_LOST:
|
||||
return MysteryGift_GetCardStat(CARD_STAT_BATTLES_LOST);
|
||||
case GET_CARD_NUM_TRADES:
|
||||
return MysteryGift_GetCardStat(CARD_STAT_NUM_TRADES);
|
||||
default:
|
||||
AGB_ASSERT_EX(0, ABSPATH("scr_tool.c"), 3873);
|
||||
return 0;
|
||||
|
||||
+1
-1
@@ -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);
|
||||
|
||||
@@ -1,148 +0,0 @@
|
||||
#include "global.h"
|
||||
#include "mevent.h"
|
||||
#include "random.h"
|
||||
#include "event_data.h"
|
||||
#include "menews_jisan.h"
|
||||
#include "constants/items.h"
|
||||
|
||||
static u32 GetMENewsJisanRewardItem(struct WonderNewsMetadata *);
|
||||
static void MENewsJisanIncrementCounterUnk0_5(struct WonderNewsMetadata *);
|
||||
static u32 GetMENewsJisanState(struct WonderNewsMetadata *);
|
||||
static void MENewsJisanIncrementCounterUnk0_2(struct WonderNewsMetadata *);
|
||||
static void MENewsJisanResetCounterUnk0_2(struct WonderNewsMetadata *);
|
||||
|
||||
void MENewsJisan_SetRandomReward(u32 a0)
|
||||
{
|
||||
struct WonderNewsMetadata *r5 = GetMENewsJisanStructPtr();
|
||||
|
||||
r5->unk_0_0 = a0;
|
||||
switch (a0)
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
case 2:
|
||||
r5->berry = (Random() % 15) + ITEM_TO_BERRY(ITEM_RAZZ_BERRY);
|
||||
break;
|
||||
case 3:
|
||||
r5->berry = (Random() % 15) + ITEM_TO_BERRY(ITEM_CHERI_BERRY);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void MENewsJisanReset(void)
|
||||
{
|
||||
struct WonderNewsMetadata *r5 = GetMENewsJisanStructPtr();
|
||||
|
||||
r5->unk_0_0 = 0;
|
||||
r5->unk_0_2 = 0;
|
||||
r5->unk_0_5 = 0;
|
||||
r5->berry = 0;
|
||||
VarSet(VAR_MENEWS_JISAN_STEP_COUNTER, 0);
|
||||
}
|
||||
|
||||
void MENewsJisanStepCounter(void)
|
||||
{
|
||||
u16 *r4 = GetVarPointer(VAR_MENEWS_JISAN_STEP_COUNTER);
|
||||
struct WonderNewsMetadata *r2 = GetMENewsJisanStructPtr();
|
||||
struct WonderNewsMetadata r0 = *r2;
|
||||
|
||||
if ((u8)r0.unk_0_5 > 4 && ++(*r4) >= 500)
|
||||
{
|
||||
r2->unk_0_5 = 0;
|
||||
*r4 = 0;
|
||||
}
|
||||
}
|
||||
|
||||
u16 GetMENewsJisanItemAndState(void)
|
||||
{
|
||||
u16 *r6 = &gSpecialVar_Result;
|
||||
struct WonderNewsMetadata *r4 = GetMENewsJisanStructPtr();
|
||||
u16 r5;
|
||||
|
||||
if (!IsMysteryGiftEnabled() || !ValidateReceivedWonderNews())
|
||||
return 0;
|
||||
|
||||
r5 = GetMENewsJisanState(r4);
|
||||
|
||||
switch (r5)
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
*r6 = GetMENewsJisanRewardItem(r4);
|
||||
break;
|
||||
case 2:
|
||||
*r6 = GetMENewsJisanRewardItem(r4);
|
||||
break;
|
||||
case 3:
|
||||
break;
|
||||
case 4:
|
||||
*r6 = GetMENewsJisanRewardItem(r4);
|
||||
MENewsJisanIncrementCounterUnk0_2(r4);
|
||||
break;
|
||||
case 5:
|
||||
*r6 = GetMENewsJisanRewardItem(r4);
|
||||
MENewsJisanResetCounterUnk0_2(r4);
|
||||
break;
|
||||
case 6:
|
||||
break;
|
||||
}
|
||||
|
||||
return r5;
|
||||
}
|
||||
|
||||
static u32 GetMENewsJisanRewardItem(struct WonderNewsMetadata *a0)
|
||||
{
|
||||
u32 r4;
|
||||
|
||||
a0->unk_0_0 = 0;
|
||||
r4 = a0->berry + FIRST_BERRY_INDEX - 1;
|
||||
a0->berry = 0;
|
||||
MENewsJisanIncrementCounterUnk0_5(a0);
|
||||
return r4;
|
||||
}
|
||||
|
||||
static void MENewsJisanResetCounterUnk0_2(struct WonderNewsMetadata *a0)
|
||||
{
|
||||
a0->unk_0_2 = 0;
|
||||
}
|
||||
|
||||
static void MENewsJisanIncrementCounterUnk0_2(struct WonderNewsMetadata *a0)
|
||||
{
|
||||
a0->unk_0_2++;
|
||||
if ((u8)a0->unk_0_2 > 4)
|
||||
a0->unk_0_2 = 4;
|
||||
}
|
||||
|
||||
static void MENewsJisanIncrementCounterUnk0_5(struct WonderNewsMetadata *a0)
|
||||
{
|
||||
a0->unk_0_5++;
|
||||
if ((u8)a0->unk_0_5 > 5)
|
||||
a0->unk_0_5 = 5;
|
||||
}
|
||||
|
||||
static u32 GetMENewsJisanState(struct WonderNewsMetadata *a0)
|
||||
{
|
||||
struct WonderNewsMetadata r0;
|
||||
if ((u8)a0->unk_0_5 == 5)
|
||||
return 6;
|
||||
|
||||
r0 = *a0;
|
||||
switch (r0.unk_0_0)
|
||||
{
|
||||
case 0:
|
||||
return 3;
|
||||
case 1:
|
||||
return 1;
|
||||
case 2:
|
||||
return 2;
|
||||
case 3:
|
||||
if ((u8)r0.unk_0_2 < 3)
|
||||
return 4;
|
||||
return 5;
|
||||
default:
|
||||
AGB_ASSERT_EX(0, ABSPATH("menews_jisan.c"), 383);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
-1029
File diff suppressed because it is too large
Load Diff
@@ -1,290 +0,0 @@
|
||||
#include "global.h"
|
||||
#include "gflib.h"
|
||||
#include "decompress.h"
|
||||
#include "overworld.h"
|
||||
#include "script.h"
|
||||
#include "battle_tower.h"
|
||||
#include "mystery_event_script.h"
|
||||
#include "mevent.h"
|
||||
#include "mevent_server.h"
|
||||
|
||||
static EWRAM_DATA struct mevent_client * s_mevent_client_ptr = NULL;
|
||||
|
||||
static void mevent_client_init(struct mevent_client *, u32, u32);
|
||||
static u32 mevent_client_exec(struct mevent_client *);
|
||||
static void mevent_client_free_resources(struct mevent_client *);
|
||||
|
||||
extern const struct mevent_client_cmd gMEventClientScript_InitialListen[];
|
||||
|
||||
void mevent_client_do_init(void)
|
||||
{
|
||||
s_mevent_client_ptr = AllocZeroed(sizeof(struct mevent_client));
|
||||
mevent_client_init(s_mevent_client_ptr, 1, 0);
|
||||
}
|
||||
|
||||
u32 mevent_client_do_exec(u16 * a0)
|
||||
{
|
||||
u32 result;
|
||||
if (s_mevent_client_ptr == NULL)
|
||||
return 6;
|
||||
result = mevent_client_exec(s_mevent_client_ptr);
|
||||
if (result == 6)
|
||||
{
|
||||
*a0 = s_mevent_client_ptr->param;
|
||||
mevent_client_free_resources(s_mevent_client_ptr);
|
||||
Free(s_mevent_client_ptr);
|
||||
s_mevent_client_ptr = NULL;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void mevent_client_inc_flag(void)
|
||||
{
|
||||
s_mevent_client_ptr->flag++;
|
||||
}
|
||||
|
||||
void *mevent_client_get_buffer(void)
|
||||
{
|
||||
return s_mevent_client_ptr->buffer;
|
||||
}
|
||||
|
||||
void mevent_client_set_param(u32 a0)
|
||||
{
|
||||
s_mevent_client_ptr->param = a0;
|
||||
}
|
||||
|
||||
static void mevent_client_init(struct mevent_client * svr, u32 sendPlayerNo, u32 recvPlayerNo)
|
||||
{
|
||||
svr->unk_00 = 0;
|
||||
svr->mainseqno = 0;
|
||||
svr->flag = 0;
|
||||
svr->sendBuffer = AllocZeroed(ME_SEND_BUF_SIZE);
|
||||
svr->recvBuffer = AllocZeroed(ME_SEND_BUF_SIZE);
|
||||
svr->cmdBuffer = AllocZeroed(ME_SEND_BUF_SIZE);
|
||||
svr->buffer = AllocZeroed(0x40);
|
||||
mevent_srv_sub_init(&svr->manager, sendPlayerNo, recvPlayerNo);
|
||||
}
|
||||
|
||||
static void mevent_client_free_resources(struct mevent_client * svr)
|
||||
{
|
||||
Free(svr->sendBuffer);
|
||||
Free(svr->recvBuffer);
|
||||
Free(svr->cmdBuffer);
|
||||
Free(svr->buffer);
|
||||
}
|
||||
|
||||
static void mevent_client_jmp_buffer(struct mevent_client * svr)
|
||||
{
|
||||
memcpy(svr->cmdBuffer, svr->recvBuffer, ME_SEND_BUF_SIZE);
|
||||
svr->cmdidx = 0;
|
||||
}
|
||||
|
||||
static void mevent_client_send_word(struct mevent_client * svr, u32 ident, u32 word)
|
||||
{
|
||||
CpuFill32(0, svr->sendBuffer, ME_SEND_BUF_SIZE);
|
||||
*(u32 *)svr->sendBuffer = word;
|
||||
mevent_srv_sub_init_send(&svr->manager, ident, svr->sendBuffer, sizeof(u32));
|
||||
}
|
||||
|
||||
static u32 client_mainseq_0(struct mevent_client * svr)
|
||||
{
|
||||
// init
|
||||
memcpy(svr->cmdBuffer, gMEventClientScript_InitialListen, ME_SEND_BUF_SIZE);
|
||||
svr->cmdidx = 0;
|
||||
svr->mainseqno = 4;
|
||||
svr->flag = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u32 client_mainseq_1(struct mevent_client * svr)
|
||||
{
|
||||
// done
|
||||
return 6;
|
||||
}
|
||||
|
||||
static u32 client_mainseq_2(struct mevent_client * svr)
|
||||
{
|
||||
// do recv
|
||||
if (mevent_srv_sub_recv(&svr->manager))
|
||||
{
|
||||
svr->mainseqno = 4;
|
||||
svr->flag = 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static u32 client_mainseq_3(struct mevent_client * svr)
|
||||
{
|
||||
// do send
|
||||
if (mevent_srv_sub_send(&svr->manager))
|
||||
{
|
||||
svr->mainseqno = 4;
|
||||
svr->flag = 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static u32 client_mainseq_4(struct mevent_client * svr)
|
||||
{
|
||||
// process command
|
||||
struct mevent_client_cmd * cmd = &svr->cmdBuffer[svr->cmdidx];
|
||||
++svr->cmdidx;
|
||||
switch (cmd->instr)
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
svr->param = cmd->parameter;
|
||||
svr->mainseqno = 1;
|
||||
svr->flag = 0;
|
||||
break;
|
||||
case 2:
|
||||
mevent_srv_sub_init_recv(&svr->manager, cmd->parameter, svr->recvBuffer);
|
||||
svr->mainseqno = 2;
|
||||
svr->flag = 0;
|
||||
break;
|
||||
case 3:
|
||||
svr->mainseqno = 3;
|
||||
svr->flag = 0;
|
||||
break;
|
||||
case 20:
|
||||
mevent_srv_sub_init_send(&svr->manager, 0x14, svr->sendBuffer, 0);
|
||||
svr->mainseqno = 3;
|
||||
svr->flag = 0;
|
||||
break;
|
||||
case 19:
|
||||
mevent_client_send_word(svr, 0x12, GetGameStat(cmd->parameter));
|
||||
svr->mainseqno = 3;
|
||||
svr->flag = 0;
|
||||
break;
|
||||
case 6:
|
||||
if (svr->param == 0)
|
||||
mevent_client_jmp_buffer(svr);
|
||||
break;
|
||||
case 7:
|
||||
if (svr->param == 1)
|
||||
mevent_client_jmp_buffer(svr);
|
||||
break;
|
||||
case 4:
|
||||
mevent_client_jmp_buffer(svr);
|
||||
break;
|
||||
case 5:
|
||||
memcpy(svr->buffer, svr->recvBuffer, 0x40);
|
||||
svr->mainseqno = 5;
|
||||
svr->flag = 0;
|
||||
return 2;
|
||||
case 11:
|
||||
memcpy(svr->buffer, svr->recvBuffer, 0x40);
|
||||
svr->mainseqno = 5;
|
||||
svr->flag = 0;
|
||||
return 3;
|
||||
case 12:
|
||||
memcpy(svr->buffer, svr->recvBuffer, 0x40);
|
||||
svr->mainseqno = 5;
|
||||
svr->flag = 0;
|
||||
return 5;
|
||||
case 13:
|
||||
svr->mainseqno = 5;
|
||||
svr->flag = 0;
|
||||
return 4;
|
||||
case 8:
|
||||
BuildMEventClientHeader(svr->sendBuffer);
|
||||
mevent_srv_sub_init_send(&svr->manager, 0x11, svr->sendBuffer, sizeof(struct MEventClientHeaderStruct));
|
||||
break;
|
||||
case 14:
|
||||
mevent_client_send_word(svr, 0x13, svr->param);
|
||||
break;
|
||||
case 10:
|
||||
OverwriteSavedWonderCardWithReceivedCard(svr->recvBuffer);
|
||||
break;
|
||||
case 9:
|
||||
if (!MEvent_HaveAlreadyReceivedWonderNews(svr->recvBuffer))
|
||||
{
|
||||
OverwriteSavedWonderNewsWithReceivedNews(svr->recvBuffer);
|
||||
mevent_client_send_word(svr, 0x13, 0);
|
||||
}
|
||||
else
|
||||
// Other trainer already has news
|
||||
mevent_client_send_word(svr, 0x13, 1);
|
||||
break;
|
||||
case 15:
|
||||
svr->mainseqno = 6;
|
||||
svr->flag = 0;
|
||||
break;
|
||||
case 16:
|
||||
MEvent_ReceiveDistributionMon(svr->recvBuffer);
|
||||
break;
|
||||
case 17:
|
||||
InitRamScript_NoObjectEvent(svr->recvBuffer, 1000);
|
||||
break;
|
||||
case 18:
|
||||
memcpy(&gSaveBlock2Ptr->battleTower.ereaderTrainer, svr->recvBuffer, sizeof(struct BattleTowerEReaderTrainer));
|
||||
ValidateEReaderTrainer();
|
||||
break;
|
||||
case 21:
|
||||
memcpy(gDecompressionBuffer, svr->recvBuffer, ME_SEND_BUF_SIZE);
|
||||
svr->mainseqno = 7;
|
||||
svr->flag = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static u32 client_mainseq_5(struct mevent_client * svr)
|
||||
{
|
||||
// wait flag
|
||||
if (svr->flag)
|
||||
{
|
||||
svr->mainseqno = 4;
|
||||
svr->flag = 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static u32 client_mainseq_6(struct mevent_client * svr)
|
||||
{
|
||||
// Run mevent buffer script
|
||||
switch (svr->flag)
|
||||
{
|
||||
case 0:
|
||||
MEventScript_InitContext(svr->recvBuffer);
|
||||
++svr->flag;
|
||||
break;
|
||||
case 1:
|
||||
if (!MEventScript_Run(&svr->param))
|
||||
{
|
||||
svr->mainseqno = 4;
|
||||
svr->flag = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static u32 client_mainseq_7(struct mevent_client * svr)
|
||||
{
|
||||
// exec arbitrary code
|
||||
u32 (*func)(u32 *, struct SaveBlock2 *, struct SaveBlock1 *) = (void *)gDecompressionBuffer;
|
||||
if (func(&svr->param, gSaveBlock2Ptr, gSaveBlock1Ptr) == 1)
|
||||
{
|
||||
svr->mainseqno = 4;
|
||||
svr->flag = 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static u32 mevent_client_exec(struct mevent_client * svr)
|
||||
{
|
||||
u32 (*funcs[])(struct mevent_client *) = {
|
||||
client_mainseq_0,
|
||||
client_mainseq_1,
|
||||
client_mainseq_2,
|
||||
client_mainseq_3,
|
||||
client_mainseq_4,
|
||||
client_mainseq_5,
|
||||
client_mainseq_6,
|
||||
client_mainseq_7
|
||||
};
|
||||
return funcs[svr->mainseqno](svr);
|
||||
}
|
||||
@@ -1,192 +0,0 @@
|
||||
#include "global.h"
|
||||
#include "mevent_server.h"
|
||||
|
||||
extern const struct mevent_server_cmd gServerScript_ClientCanceledCard[];
|
||||
|
||||
// Unreferenced
|
||||
const u8 gUnknown_84687A0[] = _("You have collected all STAMPs!\nWant to input a CARD as a prize?");
|
||||
|
||||
/* CLIENT SCRIPTS */
|
||||
|
||||
const struct mevent_client_cmd gMEventClientScript_InitialListen[] = { // 84687E0
|
||||
CLI_RECEIVE(0x10),
|
||||
CLI_JUMPBUF
|
||||
};
|
||||
|
||||
const struct mevent_client_cmd gMEventClientScript_Send1442CC[] = {
|
||||
CLI_SNDHEAD,
|
||||
CLI_WAITSND,
|
||||
CLI_RECEIVE(0x10),
|
||||
CLI_JUMPBUF
|
||||
};
|
||||
|
||||
const struct mevent_client_cmd gMEventClientScript_UnableToRecv[] = { // can't accept card or news
|
||||
CLI_SENDALL,
|
||||
CLI_RETURN(0x0a)
|
||||
};
|
||||
|
||||
const struct mevent_client_cmd gMEventClientScript_CommError[] = { // comm error
|
||||
CLI_SENDALL,
|
||||
CLI_RETURN(0x0b)
|
||||
};
|
||||
|
||||
const struct mevent_client_cmd gMEventClientScript_NothingSentOver[] = { // nothing sent
|
||||
CLI_SENDALL,
|
||||
CLI_RETURN(0x00)
|
||||
};
|
||||
|
||||
const struct mevent_client_cmd gMEventClientScript_ReceiveCardAndReturnSuccess[] = { // card success
|
||||
CLI_RECEIVE(0x16),
|
||||
CLI_RECVSAV,
|
||||
CLI_RECEIVE(0x19),
|
||||
CLI_RECVRAM,
|
||||
CLI_SENDALL,
|
||||
CLI_RETURN(0x02)
|
||||
};
|
||||
|
||||
const struct mevent_client_cmd gMEventClientScript_ReceiveNewsAndValidate[] = {
|
||||
CLI_RECEIVE(0x17),
|
||||
CLI_VLDNEWS,
|
||||
CLI_WAITSND,
|
||||
CLI_RECEIVE(0x10),
|
||||
CLI_JUMPBUF
|
||||
};
|
||||
|
||||
const struct mevent_client_cmd gMEventClientScript_AlreadyHadNews[] = { // already had news
|
||||
CLI_SENDALL,
|
||||
CLI_RETURN(0x07)
|
||||
};
|
||||
|
||||
const struct mevent_client_cmd gMEventClientScript_RecvNewsSuccess[] = { // news success
|
||||
CLI_SENDALL,
|
||||
CLI_RETURN(0x03)
|
||||
};
|
||||
|
||||
const struct mevent_client_cmd gMEventClientScript_AskWouldLikeToTossCard[] = {
|
||||
CLI_REQWORD,
|
||||
CLI_SNDWORD,
|
||||
CLI_WAITSND,
|
||||
CLI_RECEIVE(0x10),
|
||||
CLI_JUMPBUF
|
||||
};
|
||||
|
||||
const struct mevent_client_cmd gMEventClientScript_OtherTrainerCanceled[] = { // comm canceled
|
||||
CLI_SENDALL,
|
||||
CLI_RETURN(0x09)
|
||||
};
|
||||
|
||||
const struct mevent_client_cmd gMEventClientScript_AlreadyHadCard[] = { // already had card
|
||||
CLI_SENDALL,
|
||||
CLI_RETURN(0x05)
|
||||
};
|
||||
|
||||
const struct mevent_client_cmd gMEventClientScript_SuccessFromBuffer[] = { // success from buffer
|
||||
CLI_RECEIVE(0x15),
|
||||
CLI_RECVBUF,
|
||||
CLI_SENDALL,
|
||||
CLI_RETURN(0x0d)
|
||||
};
|
||||
|
||||
/* SERVER SCRIPTS */
|
||||
|
||||
const struct mevent_server_cmd gMEventSrvScript_UnableToSend[] = {
|
||||
SRV_SEND(0x10, gMEventClientScript_UnableToRecv),
|
||||
SRV_WAITSND,
|
||||
SRV_RECV(0x14),
|
||||
SRV_RETURN(0x0a)
|
||||
};
|
||||
|
||||
const struct mevent_server_cmd gUnknown_8468950[] = {
|
||||
SRV_SEND(0x10, gMEventClientScript_CommError),
|
||||
SRV_WAITSND,
|
||||
SRV_RECV(0x14),
|
||||
SRV_RETURN(0x0b)
|
||||
};
|
||||
|
||||
const struct mevent_server_cmd gUnknown_8468980[] = {
|
||||
SRV_SEND(0x10, gMEventClientScript_OtherTrainerCanceled),
|
||||
SRV_WAITSND,
|
||||
SRV_RECV(0x14),
|
||||
SRV_RETURN(0x09)
|
||||
};
|
||||
|
||||
const struct mevent_server_cmd gMEventSrvScript_OtherTrnHasNews[] = {
|
||||
SRV_SEND(0x10, gMEventClientScript_AlreadyHadNews),
|
||||
SRV_WAITSND,
|
||||
SRV_RECV(0x14),
|
||||
SRV_RETURN(0x07)
|
||||
};
|
||||
|
||||
const struct mevent_server_cmd gMEventSrvScript_SentNewsSuccess[] = {
|
||||
SRV_SEND(0x28, gMEventClientScript_ReceiveNewsAndValidate),
|
||||
SRV_WAITSND,
|
||||
SRV_SEND_NEWS,
|
||||
SRV_WAITSND,
|
||||
SRV_RECV(0x13),
|
||||
SRV_READWORD,
|
||||
SRV_BRANCHIF(0x01, gMEventSrvScript_OtherTrnHasNews),
|
||||
SRV_SEND(0x10, gMEventClientScript_RecvNewsSuccess),
|
||||
SRV_WAITSND,
|
||||
SRV_RECV(0x14),
|
||||
SRV_RETURN(0x03)
|
||||
};
|
||||
|
||||
const struct mevent_server_cmd gMEventSrvScript_SendCardSuccess[] = {
|
||||
SRV_SEND(0x30, gMEventClientScript_ReceiveCardAndReturnSuccess),
|
||||
SRV_WAITSND,
|
||||
SRV_SEND_CARD,
|
||||
SRV_WAITSND,
|
||||
SRV_BUFFER_SEND,
|
||||
SRV_WAITSND,
|
||||
SRV_RECV(0x14),
|
||||
SRV_RETURN(0x02)
|
||||
};
|
||||
|
||||
const struct mevent_server_cmd gMEventSrvScript_AskClientToOverwriteCard[] = {
|
||||
SRV_SEND(0x28, gMEventClientScript_AskWouldLikeToTossCard),
|
||||
SRV_WAITSND,
|
||||
SRV_RECV(0x13),
|
||||
SRV_READWORD,
|
||||
SRV_BRANCHIF(0x00, gMEventSrvScript_SendCardSuccess),
|
||||
SRV_BRANCH(gServerScript_ClientCanceledCard)
|
||||
};
|
||||
|
||||
const struct mevent_server_cmd gMEventSrvScript_OtherTrnHasCard[] = {
|
||||
SRV_SEND(0x10, gMEventClientScript_AlreadyHadCard),
|
||||
SRV_WAITSND,
|
||||
SRV_RECV(0x14),
|
||||
SRV_RETURN(0x05)
|
||||
};
|
||||
|
||||
const struct mevent_server_cmd gUnknown_8468B3C[] = {
|
||||
SRV_SEND(0x10, gMEventClientScript_NothingSentOver),
|
||||
SRV_WAITSND,
|
||||
SRV_RECV(0x14),
|
||||
SRV_RETURN(0x00)
|
||||
};
|
||||
|
||||
const struct mevent_server_cmd gMEventSrvScript_SendNews[] = {
|
||||
SRV_BUFFER_NEWS,
|
||||
SRV_SEND(0x20, gMEventClientScript_Send1442CC),
|
||||
SRV_WAITSND,
|
||||
SRV_RECV(0x11),
|
||||
SRV_READ_1442CC,
|
||||
SRV_VALID_1442CC,
|
||||
SRV_BRANCHIF(0x00, gMEventSrvScript_UnableToSend),
|
||||
SRV_BRANCH(gMEventSrvScript_SentNewsSuccess)
|
||||
};
|
||||
|
||||
const struct mevent_server_cmd gMEventSrvScript_SendCard[] = {
|
||||
SRV_BUFFER_CARD,
|
||||
SRV_RAM_SCRIPT_IF_VALID,
|
||||
SRV_SEND(0x20, gMEventClientScript_Send1442CC),
|
||||
SRV_WAITSND,
|
||||
SRV_RECV(0x11),
|
||||
SRV_READ_1442CC,
|
||||
SRV_VALID_1442CC,
|
||||
SRV_BRANCHIF(0x00, gMEventSrvScript_UnableToSend),
|
||||
SRV_CHECK_1442CC_14,
|
||||
SRV_BRANCHIF(0x02, gMEventSrvScript_AskClientToOverwriteCard),
|
||||
SRV_BRANCHIF(0x00, gMEventSrvScript_SendCardSuccess),
|
||||
SRV_BRANCH(gMEventSrvScript_OtherTrnHasCard)
|
||||
};
|
||||
@@ -1,279 +0,0 @@
|
||||
#include "global.h"
|
||||
#include "gflib.h"
|
||||
#include "script.h"
|
||||
#include "mevent.h"
|
||||
#include "mevent_server.h"
|
||||
|
||||
EWRAM_DATA struct mevent_srv_common * s_mevent_srv_common_ptr = NULL;
|
||||
|
||||
static void mevent_srv_init_common(struct mevent_srv_common *, const void *, u32, u32);
|
||||
static void mevent_srv_free_resources(struct mevent_srv_common *);
|
||||
static u32 mevent_srv_exec_common(struct mevent_srv_common *);
|
||||
|
||||
extern const struct mevent_server_cmd gMEventSrvScript_SendNews[];
|
||||
extern const struct mevent_server_cmd gMEventSrvScript_SendCard[];
|
||||
|
||||
void mevent_srv_init_wnews(void)
|
||||
{
|
||||
s_mevent_srv_common_ptr = AllocZeroed(sizeof(struct mevent_srv_common));
|
||||
mevent_srv_init_common(s_mevent_srv_common_ptr, gMEventSrvScript_SendNews, 0, 1);
|
||||
}
|
||||
|
||||
void mevent_srv_new_wcard(void)
|
||||
{
|
||||
s_mevent_srv_common_ptr = AllocZeroed(sizeof(struct mevent_srv_common));
|
||||
mevent_srv_init_common(s_mevent_srv_common_ptr, gMEventSrvScript_SendCard, 0, 1);
|
||||
}
|
||||
|
||||
u32 mevent_srv_common_do_exec(u16 * a0)
|
||||
{
|
||||
u32 result;
|
||||
if (s_mevent_srv_common_ptr == NULL)
|
||||
return 3;
|
||||
result = mevent_srv_exec_common(s_mevent_srv_common_ptr);
|
||||
if (result == 3)
|
||||
{
|
||||
*a0 = s_mevent_srv_common_ptr->param;
|
||||
mevent_srv_free_resources(s_mevent_srv_common_ptr);
|
||||
Free(s_mevent_srv_common_ptr);
|
||||
s_mevent_srv_common_ptr = NULL;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static void mevent_srv_init_common(struct mevent_srv_common * svr, const void *cmdBuffer, u32 sendPlayerNo, u32 recvPlayerNo)
|
||||
{
|
||||
svr->unk_00 = 0;
|
||||
svr->mainseqno = 0;
|
||||
svr->card = AllocZeroed(sizeof(struct WonderCard));
|
||||
svr->news = AllocZeroed(sizeof(struct WonderNews));
|
||||
svr->recvBuffer = AllocZeroed(ME_SEND_BUF_SIZE);
|
||||
svr->mevent_unk1442cc = AllocZeroed(sizeof(struct MEventClientHeaderStruct));
|
||||
svr->cmdBuffer = cmdBuffer;
|
||||
svr->cmdidx = 0;
|
||||
mevent_srv_sub_init(&svr->manager, sendPlayerNo, recvPlayerNo);
|
||||
}
|
||||
|
||||
static void mevent_srv_free_resources(struct mevent_srv_common * svr)
|
||||
{
|
||||
Free(svr->card);
|
||||
Free(svr->news);
|
||||
Free(svr->recvBuffer);
|
||||
Free(svr->mevent_unk1442cc);
|
||||
}
|
||||
|
||||
static void mevent_srv_common_init_send(struct mevent_srv_common * svr, u32 ident, const void *src, u32 size)
|
||||
{
|
||||
AGB_ASSERT_EX(size <= ME_SEND_BUF_SIZE, ABSPATH("mevent_server.c"), 257);
|
||||
mevent_srv_sub_init_send(&svr->manager, ident, src, size);
|
||||
}
|
||||
|
||||
static void *mevent_first_if_not_null_else_second(void *a0, void *a1)
|
||||
{
|
||||
if (a0 != NULL)
|
||||
return a0;
|
||||
else
|
||||
return a1;
|
||||
}
|
||||
|
||||
static u32 mevent_compare_pointers(void *a0, void *a1)
|
||||
{
|
||||
if (a1 < a0)
|
||||
return 0;
|
||||
else if (a1 == a0)
|
||||
return 1;
|
||||
else
|
||||
return 2;
|
||||
}
|
||||
|
||||
static u32 common_mainseq_0(struct mevent_srv_common * svr)
|
||||
{
|
||||
// start
|
||||
svr->mainseqno = 4;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u32 common_mainseq_1(struct mevent_srv_common * svr)
|
||||
{
|
||||
// done
|
||||
return 3;
|
||||
}
|
||||
|
||||
static u32 common_mainseq_2(struct mevent_srv_common * svr)
|
||||
{
|
||||
// do recv
|
||||
if (mevent_srv_sub_recv(&svr->manager))
|
||||
svr->mainseqno = 4;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static u32 common_mainseq_3(struct mevent_srv_common * svr)
|
||||
{
|
||||
// do send
|
||||
if (mevent_srv_sub_send(&svr->manager))
|
||||
svr->mainseqno = 4;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static u32 common_mainseq_4(struct mevent_srv_common * svr)
|
||||
{
|
||||
// process command
|
||||
const struct mevent_server_cmd * cmd = &svr->cmdBuffer[svr->cmdidx];
|
||||
void *ptr;
|
||||
svr->cmdidx++;
|
||||
|
||||
switch (cmd->instr)
|
||||
{
|
||||
case 0:
|
||||
AGB_ASSERT_EX(cmd->parameter == NULL, ABSPATH("mevent_server.c"), 354);
|
||||
svr->mainseqno = 1;
|
||||
svr->param = cmd->flag;
|
||||
break;
|
||||
case 1:
|
||||
svr->mainseqno = 3;
|
||||
break;
|
||||
case 2:
|
||||
AGB_ASSERT_EX(cmd->parameter == NULL, ABSPATH("mevent_server.c"), 364);
|
||||
mevent_srv_sub_init_recv(&svr->manager, cmd->flag, svr->recvBuffer);
|
||||
svr->mainseqno = 2;
|
||||
break;
|
||||
case 3:
|
||||
AGB_ASSERT_EX(cmd->flag == FALSE, ABSPATH("mevent_server.c"), 370);
|
||||
svr->cmdidx = 0;
|
||||
svr->cmdBuffer = cmd->parameter;
|
||||
break;
|
||||
case 5:
|
||||
AGB_ASSERT_EX(cmd->flag == FALSE, ABSPATH("mevent_server.c"), 376);
|
||||
AGB_ASSERT_EX(cmd->parameter == NULL, ABSPATH("mevent_server.c"), 377);
|
||||
memcpy(svr->mevent_unk1442cc, svr->recvBuffer, sizeof(struct MEventClientHeaderStruct));
|
||||
break;
|
||||
case 6:
|
||||
AGB_ASSERT_EX(cmd->flag == FALSE, ABSPATH("mevent_server.c"), 382);
|
||||
AGB_ASSERT_EX(cmd->parameter == NULL, ABSPATH("mevent_server.c"), 383);
|
||||
svr->param = ValidateMEventClientHeader(svr->mevent_unk1442cc);
|
||||
break;
|
||||
case 4:
|
||||
if (svr->param == cmd->flag)
|
||||
{
|
||||
svr->cmdidx = 0;
|
||||
svr->cmdBuffer = cmd->parameter;
|
||||
}
|
||||
break;
|
||||
case 7:
|
||||
AGB_ASSERT_EX(cmd->flag == FALSE, ABSPATH("mevent_server.c"), 396);
|
||||
ptr = mevent_first_if_not_null_else_second(cmd->parameter, svr->card);
|
||||
svr->param = sub_8144418(ptr, svr->mevent_unk1442cc, ptr);
|
||||
break;
|
||||
case 8:
|
||||
AGB_ASSERT_EX(cmd->flag == FALSE, ABSPATH("mevent_server.c"), 402);
|
||||
AGB_ASSERT_EX(cmd->parameter == NULL, ABSPATH("mevent_server.c"), 403);
|
||||
svr->param = *(u32 *)svr->recvBuffer;
|
||||
break;
|
||||
case 9:
|
||||
AGB_ASSERT_EX(cmd->flag == FALSE, ABSPATH("mevent_server.c"), 408);
|
||||
ptr = mevent_first_if_not_null_else_second(cmd->parameter, &svr->sendWord);
|
||||
svr->param = MEvent_CanPlayerReceiveDistributionMon(ptr, svr->mevent_unk1442cc, ptr);
|
||||
break;
|
||||
case 10:
|
||||
AGB_ASSERT_EX(cmd->parameter == NULL, ABSPATH("mevent_server.c"), 415);
|
||||
svr->param = sub_81444B0(svr->mevent_unk1442cc, cmd->flag);
|
||||
break;
|
||||
case 11:
|
||||
AGB_ASSERT_EX(cmd->flag == FALSE, ABSPATH("mevent_server.c"), 420);
|
||||
svr->param = sub_8144474(svr->mevent_unk1442cc, cmd->parameter);
|
||||
break;
|
||||
case 12:
|
||||
AGB_ASSERT_EX(cmd->flag == FALSE, ABSPATH("mevent_server.c"), 426);
|
||||
svr->param = mevent_compare_pointers(cmd->parameter, *(void **)svr->recvBuffer);
|
||||
break;
|
||||
case 14:
|
||||
AGB_ASSERT_EX(cmd->flag == FALSE, ABSPATH("mevent_server.c"), 432);
|
||||
mevent_srv_common_init_send(svr, 0x17, mevent_first_if_not_null_else_second(cmd->parameter, svr->news), sizeof(struct WonderNews));
|
||||
break;
|
||||
case 13:
|
||||
AGB_ASSERT_EX(cmd->flag == FALSE, ABSPATH("mevent_server.c"), 438);
|
||||
mevent_srv_common_init_send(svr, 0x16, mevent_first_if_not_null_else_second(cmd->parameter, svr->card), sizeof(struct WonderCard));
|
||||
break;
|
||||
case 16:
|
||||
AGB_ASSERT_EX(cmd->flag == FALSE, ABSPATH("mevent_server.c"), 444);
|
||||
mevent_srv_common_init_send(svr, 0x18, mevent_first_if_not_null_else_second(cmd->parameter, &svr->sendWord), 4);
|
||||
break;
|
||||
case 15:
|
||||
if (cmd->parameter == NULL)
|
||||
mevent_srv_common_init_send(svr, 0x19, svr->sendBuffer1, svr->sendBuffer1Size);
|
||||
else
|
||||
mevent_srv_common_init_send(svr, 0x19, cmd->parameter, cmd->flag);
|
||||
break;
|
||||
case 18:
|
||||
if (cmd->parameter == NULL)
|
||||
mevent_srv_common_init_send(svr, 0x10, svr->sendBuffer2, svr->sendBuffer2Size);
|
||||
else
|
||||
mevent_srv_common_init_send(svr, 0x10, cmd->parameter, cmd->flag);
|
||||
break;
|
||||
case 19:
|
||||
AGB_ASSERT_EX(cmd->flag == FALSE, ABSPATH("mevent_server.c"), 466);
|
||||
mevent_srv_common_init_send(svr, 0x1a, cmd->parameter, 188);
|
||||
break;
|
||||
case 20:
|
||||
mevent_srv_common_init_send(svr, 0x15, cmd->parameter, cmd->flag);
|
||||
break;
|
||||
case 17:
|
||||
mevent_srv_common_init_send(svr, 0x1c, cmd->parameter, cmd->flag);
|
||||
break;
|
||||
case 22:
|
||||
AGB_ASSERT_EX(cmd->flag == FALSE, ABSPATH("mevent_server.c"), 481);
|
||||
memcpy(svr->card, cmd->parameter, 332);
|
||||
break;
|
||||
case 23:
|
||||
AGB_ASSERT_EX(cmd->flag == FALSE, ABSPATH("mevent_server.c"), 486);
|
||||
memcpy(svr->news, cmd->parameter, 444);
|
||||
break;
|
||||
case 21:
|
||||
AGB_ASSERT_EX(cmd->flag == FALSE, ABSPATH("mevent_server.c"), 491);
|
||||
svr->sendWord = *(u32 *)cmd->parameter;
|
||||
break;
|
||||
case 24:
|
||||
svr->sendBuffer1 = cmd->parameter;
|
||||
svr->sendBuffer1Size = cmd->flag;
|
||||
break;
|
||||
case 25:
|
||||
svr->sendBuffer2 = cmd->parameter;
|
||||
svr->sendBuffer2Size = cmd->flag;
|
||||
break;
|
||||
case 26:
|
||||
AGB_ASSERT_EX(cmd->flag == FALSE && cmd->parameter == NULL, ABSPATH("mevent_server.c"), 506);
|
||||
memcpy(svr->card, GetSavedWonderCard(), 332);
|
||||
MEvent_WonderCardResetUnk08_6(svr->card);
|
||||
break;
|
||||
case 27:
|
||||
AGB_ASSERT_EX(cmd->flag == FALSE && cmd->parameter == NULL, ABSPATH("mevent_server.c"), 512);
|
||||
memcpy(svr->news, GetSavedWonderNews(), 444);
|
||||
break;
|
||||
case 28:
|
||||
AGB_ASSERT_EX(cmd->flag == FALSE && cmd->parameter == NULL, ABSPATH("mevent_server.c"), 517);
|
||||
svr->sendBuffer1 = GetSavedRamScriptIfValid();
|
||||
break;
|
||||
case 29:
|
||||
mevent_srv_common_init_send(svr, 0x1b, cmd->parameter, cmd->flag);
|
||||
break;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static u32 (*const func_tbl[])(struct mevent_srv_common *) = {
|
||||
common_mainseq_0,
|
||||
common_mainseq_1,
|
||||
common_mainseq_2,
|
||||
common_mainseq_3,
|
||||
common_mainseq_4
|
||||
};
|
||||
|
||||
static u32 mevent_srv_exec_common(struct mevent_srv_common * svr)
|
||||
{
|
||||
u32 response;
|
||||
AGB_ASSERT_EX(svr->mainseqno < NELEMS(func_tbl), ABSPATH("mevent_server.c"), 546);
|
||||
response = func_tbl[svr->mainseqno](svr);
|
||||
AGB_ASSERT_EX(svr->mainseqno < NELEMS(func_tbl), ABSPATH("mevent_server.c"), 548);
|
||||
return response;
|
||||
}
|
||||
@@ -1,204 +0,0 @@
|
||||
#include "global.h"
|
||||
#include "util.h"
|
||||
#include "link.h"
|
||||
#include "link_rfu.h"
|
||||
#include "mevent_server.h"
|
||||
|
||||
static u32 mevent_receive_func(struct mevent_srv_sub *);
|
||||
static u32 mevent_send_func(struct mevent_srv_sub *);
|
||||
|
||||
u32 mevent_srv_sub_recv(struct mevent_srv_sub * svr)
|
||||
{
|
||||
return svr->recvFunc(svr);
|
||||
}
|
||||
|
||||
u32 mevent_srv_sub_send(struct mevent_srv_sub * svr)
|
||||
{
|
||||
return svr->sendFunc(svr);
|
||||
}
|
||||
|
||||
void mevent_srv_sub_init(struct mevent_srv_sub * svr, u32 sendPlayerNo, u32 recvPlayerNo)
|
||||
{
|
||||
svr->sendPlayerNo = sendPlayerNo;
|
||||
svr->recvPlayerNo = recvPlayerNo;
|
||||
svr->seqno = 0;
|
||||
svr->sendCRC = 0;
|
||||
svr->sendSize = 0;
|
||||
svr->sendCounter = 0;
|
||||
svr->recvCRC = 0;
|
||||
svr->recvSize = 0;
|
||||
svr->recvCounter = 0;
|
||||
svr->sendBfr = NULL;
|
||||
svr->recvBfr = NULL;
|
||||
svr->sendFunc = mevent_send_func;
|
||||
svr->recvFunc = mevent_receive_func;
|
||||
}
|
||||
|
||||
void mevent_srv_sub_init_send(struct mevent_srv_sub * svr, u32 ident, const void *src, u32 size)
|
||||
{
|
||||
svr->seqno = 0;
|
||||
svr->sendIdent = ident;
|
||||
svr->sendCounter = 0;
|
||||
svr->sendCRC = 0;
|
||||
if (size != 0)
|
||||
svr->sendSize = size;
|
||||
else
|
||||
svr->sendSize = ME_SEND_BUF_SIZE;
|
||||
svr->sendBfr = src;
|
||||
}
|
||||
|
||||
void mevent_srv_sub_init_recv(struct mevent_srv_sub * svr, u32 ident, void *dest)
|
||||
{
|
||||
svr->seqno = 0;
|
||||
svr->recvIdent = ident;
|
||||
svr->recvCounter = 0;
|
||||
svr->recvCRC = 0;
|
||||
svr->recvSize = 0;
|
||||
svr->recvBfr = dest;
|
||||
}
|
||||
|
||||
static void mevent_recv_block(u32 recv_idx, void *dest, size_t size)
|
||||
{
|
||||
memcpy(dest, gBlockRecvBuffer[recv_idx], size);
|
||||
}
|
||||
|
||||
static bool32 mevent_has_received(u32 recv_idx)
|
||||
{
|
||||
if ((GetBlockReceivedStatus() >> recv_idx) & 1)
|
||||
return TRUE;
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void mevent_reset_recv(u32 recv_idx)
|
||||
{
|
||||
ResetBlockReceivedFlag(recv_idx);
|
||||
}
|
||||
|
||||
static bool32 mevent_receive_func(struct mevent_srv_sub * svr)
|
||||
{
|
||||
struct send_recv_header header;
|
||||
|
||||
switch (svr->seqno)
|
||||
{
|
||||
case 0:
|
||||
if (mevent_has_received(svr->recvPlayerNo))
|
||||
{
|
||||
mevent_recv_block(svr->recvPlayerNo, &header, sizeof(header));
|
||||
svr->recvSize = header.size;
|
||||
svr->recvCRC = header.crc;
|
||||
if (svr->recvSize > ME_SEND_BUF_SIZE)
|
||||
{
|
||||
LinkRfu_FatalError();
|
||||
return FALSE;
|
||||
}
|
||||
else if (svr->recvIdent != header.ident)
|
||||
{
|
||||
LinkRfu_FatalError();
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
svr->recvCounter = 0;
|
||||
mevent_reset_recv(svr->recvPlayerNo);
|
||||
++svr->seqno;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if (mevent_has_received(svr->recvPlayerNo))
|
||||
{
|
||||
size_t blocksiz = svr->recvCounter * 252;
|
||||
if (svr->recvSize - blocksiz <= 252)
|
||||
{
|
||||
mevent_recv_block(svr->recvPlayerNo, svr->recvBfr + blocksiz, svr->recvSize - blocksiz);
|
||||
++svr->recvCounter;
|
||||
++svr->seqno;
|
||||
}
|
||||
else
|
||||
{
|
||||
mevent_recv_block(svr->recvPlayerNo, svr->recvBfr + blocksiz, 252);
|
||||
++svr->recvCounter;
|
||||
}
|
||||
mevent_reset_recv(svr->recvPlayerNo);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if (CalcCRC16WithTable(svr->recvBfr, svr->recvSize) != svr->recvCRC)
|
||||
{
|
||||
LinkRfu_FatalError();
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
svr->seqno = 0;
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static bool32 mevent_send_func(struct mevent_srv_sub * svr)
|
||||
{
|
||||
struct send_recv_header header;
|
||||
|
||||
switch (svr->seqno)
|
||||
{
|
||||
case 0:
|
||||
if (IsLinkTaskFinished())
|
||||
{
|
||||
header.ident = svr->sendIdent;
|
||||
header.size = svr->sendSize;
|
||||
header.crc = CalcCRC16WithTable(svr->sendBfr, svr->sendSize);
|
||||
svr->sendCRC = header.crc;
|
||||
svr->sendCounter = 0;
|
||||
SendBlock(0, &header, sizeof(header));
|
||||
++svr->seqno;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if (IsLinkTaskFinished())
|
||||
{
|
||||
if (mevent_has_received(svr->sendPlayerNo))
|
||||
{
|
||||
size_t blocksiz;
|
||||
mevent_reset_recv(svr->sendPlayerNo);
|
||||
blocksiz = 252 * svr->sendCounter;
|
||||
if (svr->sendSize - blocksiz <= 252)
|
||||
{
|
||||
SendBlock(0, svr->sendBfr + blocksiz, svr->sendSize - blocksiz);
|
||||
++svr->sendCounter;
|
||||
++svr->seqno;
|
||||
}
|
||||
else
|
||||
{
|
||||
SendBlock(0, svr->sendBfr + blocksiz, 252);
|
||||
++svr->sendCounter;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if (IsLinkTaskFinished())
|
||||
{
|
||||
if (CalcCRC16WithTable(svr->sendBfr, svr->sendSize) != svr->sendCRC)
|
||||
LinkRfu_FatalError();
|
||||
else
|
||||
++svr->seqno;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
if (mevent_has_received(svr->sendPlayerNo))
|
||||
{
|
||||
mevent_reset_recv(svr->sendPlayerNo);
|
||||
svr->seqno = 0;
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
@@ -0,0 +1,634 @@
|
||||
#include "global.h"
|
||||
#include "gflib.h"
|
||||
#include "constants/songs.h"
|
||||
#include "easy_chat.h"
|
||||
#include "task.h"
|
||||
#include "link.h"
|
||||
#include "link_rfu.h"
|
||||
#include "util.h"
|
||||
#include "script.h"
|
||||
#include "event_data.h"
|
||||
#include "battle_tower.h"
|
||||
#include "new_game.h"
|
||||
#include "wonder_news.h"
|
||||
#include "mystery_gift_menu.h"
|
||||
#include "help_system.h"
|
||||
#include "mystery_gift.h"
|
||||
#include "strings.h"
|
||||
|
||||
#define CALC_CRC(data) CalcCRC16WithTable((void *)&(data), sizeof(data))
|
||||
|
||||
static bool32 ValidateWonderNews(const struct WonderNews * src);
|
||||
static void ClearSavedWonderNews(void);
|
||||
static void ClearSavedWonderNewsMetadata(void);
|
||||
static bool32 ValidateWonderCard(const struct WonderCard * src);
|
||||
static void ClearSavedWonderCard(void);
|
||||
static void ClearSavedWonderCardMetadata(void);
|
||||
static void IncrementCardStatForNewTrainer(u32 eventId, u32 trainerId, u32 *idsList, s32 count);
|
||||
static void ClearSavedTrainerIds(void);
|
||||
|
||||
static const u16 sReceivedGiftFlags[] = {
|
||||
FLAG_RECEIVED_AURORA_TICKET,
|
||||
FLAG_RECEIVED_MYSTIC_TICKET,
|
||||
FLAG_RECEIVED_OLD_SEA_MAP, // Not used until Emerald
|
||||
FLAG_WONDER_CARD_UNUSED_1,
|
||||
FLAG_WONDER_CARD_UNUSED_2,
|
||||
FLAG_WONDER_CARD_UNUSED_3,
|
||||
FLAG_WONDER_CARD_UNUSED_4,
|
||||
FLAG_WONDER_CARD_UNUSED_5,
|
||||
FLAG_WONDER_CARD_UNUSED_6,
|
||||
FLAG_WONDER_CARD_UNUSED_7,
|
||||
FLAG_WONDER_CARD_UNUSED_8,
|
||||
FLAG_WONDER_CARD_UNUSED_9,
|
||||
FLAG_WONDER_CARD_UNUSED_10,
|
||||
FLAG_WONDER_CARD_UNUSED_11,
|
||||
FLAG_WONDER_CARD_UNUSED_12,
|
||||
FLAG_WONDER_CARD_UNUSED_13,
|
||||
FLAG_WONDER_CARD_UNUSED_14,
|
||||
FLAG_WONDER_CARD_UNUSED_15,
|
||||
FLAG_WONDER_CARD_UNUSED_16,
|
||||
FLAG_WONDER_CARD_UNUSED_17
|
||||
};
|
||||
|
||||
static EWRAM_DATA bool32 sStatsEnabled = FALSE;
|
||||
|
||||
void ClearMysteryGift(void)
|
||||
{
|
||||
CpuFill32(0, &gSaveBlock1Ptr->mysteryGift, sizeof(gSaveBlock1Ptr->mysteryGift));
|
||||
ClearSavedWonderNewsMetadata();
|
||||
InitQuestionnaireWords();
|
||||
}
|
||||
|
||||
struct WonderNews * GetSavedWonderNews(void)
|
||||
{
|
||||
return &gSaveBlock1Ptr->mysteryGift.news;
|
||||
}
|
||||
|
||||
struct WonderCard * GetSavedWonderCard(void)
|
||||
{
|
||||
return &gSaveBlock1Ptr->mysteryGift.card;
|
||||
}
|
||||
|
||||
struct WonderCardMetadata * GetSavedWonderCardMetadata(void)
|
||||
{
|
||||
return &gSaveBlock1Ptr->mysteryGift.cardMetadata;
|
||||
}
|
||||
|
||||
struct WonderNewsMetadata * GetSavedWonderNewsMetadata(void)
|
||||
{
|
||||
return &gSaveBlock1Ptr->mysteryGift.newsMetadata;
|
||||
}
|
||||
|
||||
u16 * GetQuestionnaireWordsPtr(void)
|
||||
{
|
||||
return gSaveBlock1Ptr->mysteryGift.questionnaireWords;
|
||||
}
|
||||
|
||||
// Equivalent to ClearSavedWonderCardAndRelated, but nothing else to clear
|
||||
void ClearSavedWonderNewsAndRelated(void)
|
||||
{
|
||||
ClearSavedWonderNews();
|
||||
}
|
||||
|
||||
bool32 SaveWonderNews(const struct WonderNews * news)
|
||||
{
|
||||
if (!ValidateWonderNews(news))
|
||||
return FALSE;
|
||||
|
||||
ClearSavedWonderNews();
|
||||
gSaveBlock1Ptr->mysteryGift.news = *news;
|
||||
gSaveBlock1Ptr->mysteryGift.newsCrc = CALC_CRC(gSaveBlock1Ptr->mysteryGift.news);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool32 ValidateSavedWonderNews(void)
|
||||
{
|
||||
if (CALC_CRC(gSaveBlock1Ptr->mysteryGift.news) != gSaveBlock1Ptr->mysteryGift.newsCrc)
|
||||
return FALSE;
|
||||
if (!ValidateWonderNews(&gSaveBlock1Ptr->mysteryGift.news))
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static bool32 ValidateWonderNews(const struct WonderNews * news)
|
||||
{
|
||||
if (news->id == 0)
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool32 IsSendingSavedWonderNewsAllowed(void)
|
||||
{
|
||||
const struct WonderNews * news = &gSaveBlock1Ptr->mysteryGift.news;
|
||||
if (news->sendType == SEND_TYPE_DISALLOWED)
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void ClearSavedWonderNews(void)
|
||||
{
|
||||
CpuFill32(0, GetSavedWonderNews(), sizeof(gSaveBlock1Ptr->mysteryGift.news));
|
||||
gSaveBlock1Ptr->mysteryGift.newsCrc = 0;
|
||||
}
|
||||
|
||||
static void ClearSavedWonderNewsMetadata(void)
|
||||
{
|
||||
CpuFill32(0, GetSavedWonderNewsMetadata(), sizeof(gSaveBlock1Ptr->mysteryGift.newsMetadata));
|
||||
WonderNews_Reset();
|
||||
}
|
||||
|
||||
bool32 IsWonderNewsSameAsSaved(const u8 * news)
|
||||
{
|
||||
const u8 * savedNews = (const u8 *)&gSaveBlock1Ptr->mysteryGift.news;
|
||||
u32 i;
|
||||
if (!ValidateSavedWonderNews())
|
||||
return FALSE;
|
||||
|
||||
for (i = 0; i < sizeof(gSaveBlock1Ptr->mysteryGift.news); i++)
|
||||
{
|
||||
if (savedNews[i] != news[i])
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void ClearSavedWonderCardAndRelated(void)
|
||||
{
|
||||
ClearSavedWonderCard();
|
||||
ClearSavedWonderCardMetadata();
|
||||
ClearSavedTrainerIds();
|
||||
ClearRamScript();
|
||||
ClearMysteryGiftFlags();
|
||||
ClearMysteryGiftVars();
|
||||
ClearEReaderTrainer(&gSaveBlock2Ptr->battleTower.ereaderTrainer);
|
||||
}
|
||||
|
||||
bool32 SaveWonderCard(const struct WonderCard * card)
|
||||
{
|
||||
struct WonderCardMetadata * metadata;
|
||||
if (!ValidateWonderCard(card))
|
||||
return FALSE;
|
||||
|
||||
ClearSavedWonderCardAndRelated();
|
||||
memcpy(&gSaveBlock1Ptr->mysteryGift.card, card, sizeof(struct WonderCard));
|
||||
gSaveBlock1Ptr->mysteryGift.cardCrc = CALC_CRC(gSaveBlock1Ptr->mysteryGift.card);
|
||||
metadata = &gSaveBlock1Ptr->mysteryGift.cardMetadata;
|
||||
metadata->iconSpecies = (&gSaveBlock1Ptr->mysteryGift.card)->iconSpecies;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool32 ValidateSavedWonderCard(void)
|
||||
{
|
||||
if (gSaveBlock1Ptr->mysteryGift.cardCrc != CALC_CRC(gSaveBlock1Ptr->mysteryGift.card))
|
||||
return FALSE;
|
||||
if (!ValidateWonderCard(&gSaveBlock1Ptr->mysteryGift.card))
|
||||
return FALSE;
|
||||
if (!ValidateRamScript())
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static bool32 ValidateWonderCard(const struct WonderCard * card)
|
||||
{
|
||||
if (card->flagId == 0)
|
||||
return FALSE;
|
||||
if (card->type >= CARD_TYPE_COUNT)
|
||||
return FALSE;
|
||||
if (!(card->sendType == SEND_TYPE_DISALLOWED
|
||||
|| card->sendType == SEND_TYPE_ALLOWED
|
||||
|| card->sendType == SEND_TYPE_ALLOWED_ALWAYS))
|
||||
return FALSE;
|
||||
if (card->bgType >= NUM_WONDER_BGS)
|
||||
return FALSE;
|
||||
if (card->maxStamps > MAX_STAMP_CARD_STAMPS)
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool32 IsSendingSavedWonderCardAllowed(void)
|
||||
{
|
||||
const struct WonderCard * card = &gSaveBlock1Ptr->mysteryGift.card;
|
||||
if (card->sendType == SEND_TYPE_DISALLOWED)
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void ClearSavedWonderCard(void)
|
||||
{
|
||||
CpuFill32(0, &gSaveBlock1Ptr->mysteryGift.card, sizeof(gSaveBlock1Ptr->mysteryGift.card));
|
||||
gSaveBlock1Ptr->mysteryGift.cardCrc = 0;
|
||||
}
|
||||
|
||||
static void ClearSavedWonderCardMetadata(void)
|
||||
{
|
||||
CpuFill32(0, GetSavedWonderCardMetadata(), sizeof(gSaveBlock1Ptr->mysteryGift.cardMetadata));
|
||||
gSaveBlock1Ptr->mysteryGift.cardMetadataCrc = 0;
|
||||
}
|
||||
|
||||
u16 GetWonderCardFlagId(void)
|
||||
{
|
||||
if (ValidateSavedWonderCard())
|
||||
return gSaveBlock1Ptr->mysteryGift.card.flagId;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void DisableWonderCardSending(struct WonderCard * card)
|
||||
{
|
||||
if (card->sendType == SEND_TYPE_ALLOWED)
|
||||
card->sendType = SEND_TYPE_DISALLOWED;
|
||||
}
|
||||
|
||||
static bool32 IsWonderCardFlagIDInValidRange(u16 flagId)
|
||||
{
|
||||
if (flagId >= WONDER_CARD_FLAG_OFFSET && flagId < WONDER_CARD_FLAG_OFFSET + NUM_WONDER_CARD_FLAGS)
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bool32 IsSavedWonderCardGiftNotReceived(void)
|
||||
{
|
||||
u16 value = GetWonderCardFlagId();
|
||||
if (!IsWonderCardFlagIDInValidRange(value))
|
||||
return FALSE;
|
||||
|
||||
// If flag is set, player has received gift from this card
|
||||
if (FlagGet(sReceivedGiftFlags[value - WONDER_CARD_FLAG_OFFSET]) == TRUE)
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static s32 GetNumStampsInMetadata(const struct WonderCardMetadata * data, s32 size)
|
||||
{
|
||||
s32 numStamps = 0;
|
||||
s32 i;
|
||||
for (i = 0; i < size; i++)
|
||||
{
|
||||
if (data->stampData[STAMP_ID][i] && data->stampData[STAMP_SPECIES][i])
|
||||
numStamps++;
|
||||
}
|
||||
return numStamps;
|
||||
}
|
||||
|
||||
static bool32 IsStampInMetadata(const struct WonderCardMetadata * metadata, const u16 * stamp, s32 maxStamps)
|
||||
{
|
||||
s32 i;
|
||||
for (i = 0; i < maxStamps; i++)
|
||||
{
|
||||
if (metadata->stampData[STAMP_ID][i] == stamp[STAMP_ID])
|
||||
return TRUE;
|
||||
if (metadata->stampData[STAMP_SPECIES][i] == stamp[STAMP_SPECIES])
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static bool32 ValidateStamp(const u16 * stamp)
|
||||
{
|
||||
if (stamp[STAMP_ID] == 0)
|
||||
return FALSE;
|
||||
if (stamp[STAMP_SPECIES] == SPECIES_NONE)
|
||||
return FALSE;
|
||||
if (stamp[STAMP_SPECIES] >= NUM_SPECIES)
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static s32 GetNumStampsInSavedCard(void)
|
||||
{
|
||||
struct WonderCard * card;
|
||||
if (!ValidateSavedWonderCard())
|
||||
return 0;
|
||||
card = &gSaveBlock1Ptr->mysteryGift.card;
|
||||
if (card->type != CARD_TYPE_STAMP)
|
||||
return 0;
|
||||
return GetNumStampsInMetadata(&gSaveBlock1Ptr->mysteryGift.cardMetadata, card->maxStamps);
|
||||
}
|
||||
|
||||
bool32 MysteryGift_TrySaveStamp(const u16 * stamp)
|
||||
{
|
||||
struct WonderCard * card = &gSaveBlock1Ptr->mysteryGift.card;
|
||||
s32 maxStamps = card->maxStamps;
|
||||
s32 i;
|
||||
if (!ValidateStamp(stamp))
|
||||
return FALSE;
|
||||
if (IsStampInMetadata(&gSaveBlock1Ptr->mysteryGift.cardMetadata, stamp, maxStamps))
|
||||
return FALSE;
|
||||
for (i = 0; i < maxStamps; i++)
|
||||
{
|
||||
if (gSaveBlock1Ptr->mysteryGift.cardMetadata.stampData[STAMP_ID][i] == 0
|
||||
&& gSaveBlock1Ptr->mysteryGift.cardMetadata.stampData[STAMP_SPECIES][i] == SPECIES_NONE)
|
||||
{
|
||||
gSaveBlock1Ptr->mysteryGift.cardMetadata.stampData[STAMP_ID][i] = stamp[STAMP_ID];
|
||||
gSaveBlock1Ptr->mysteryGift.cardMetadata.stampData[STAMP_SPECIES][i] = stamp[STAMP_SPECIES];
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#define GAME_DATA_VALID_VAR 0x101
|
||||
|
||||
#if defined(FIRERED)
|
||||
#define VERSION_CODE 1
|
||||
#elif defined(LEAFGREEN)
|
||||
#define VERSION_CODE 2
|
||||
#endif
|
||||
|
||||
void MysteryGift_LoadLinkGameData(struct MysteryGiftLinkGameData * data)
|
||||
{
|
||||
s32 i;
|
||||
CpuFill32(0, data, sizeof(*data));
|
||||
// Magic
|
||||
data->unk_00 = GAME_DATA_VALID_VAR;
|
||||
data->unk_04 = 1;
|
||||
data->unk_08 = 1;
|
||||
data->unk_0C = 1;
|
||||
data->unk_10 = VERSION_CODE;
|
||||
|
||||
// Check whether a card already exists
|
||||
if (ValidateSavedWonderCard())
|
||||
{
|
||||
// Populate fields
|
||||
data->flagId = GetSavedWonderCard()->flagId;
|
||||
data->cardMetadata = *GetSavedWonderCardMetadata();
|
||||
data->maxStamps = GetSavedWonderCard()->maxStamps;
|
||||
}
|
||||
else
|
||||
{
|
||||
data->flagId = 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < NUM_QUESTIONNAIRE_WORDS; i++)
|
||||
data->questionnaireWords[i] = gSaveBlock1Ptr->mysteryGift.questionnaireWords[i];
|
||||
|
||||
CopyTrainerId(data->playerTrainerId, gSaveBlock2Ptr->playerTrainerId);
|
||||
StringCopy(data->playerName, gSaveBlock2Ptr->playerName);
|
||||
for (i = 0; i < EASY_CHAT_BATTLE_WORDS_COUNT; i++)
|
||||
data->easyChatProfile[i] = gSaveBlock1Ptr->easyChatProfile[i];
|
||||
|
||||
memcpy(data->gameCode, RomHeaderGameCode, GAME_CODE_LENGTH);
|
||||
data->version = RomHeaderSoftwareVersion;
|
||||
}
|
||||
|
||||
bool32 MysteryGift_ValidateLinkGameData(const struct MysteryGiftLinkGameData * data)
|
||||
{
|
||||
if (data->unk_00 != GAME_DATA_VALID_VAR)
|
||||
return FALSE;
|
||||
if (!(data->unk_04 & 1))
|
||||
return FALSE;
|
||||
if (!(data->unk_08 & 1))
|
||||
return FALSE;
|
||||
if (!(data->unk_0C & 1))
|
||||
return FALSE;
|
||||
if (!(data->unk_10 & 0x0F))
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
u32 MysteryGift_CompareCardFlags(const u16 * flagId, const struct MysteryGiftLinkGameData * data, const void *unused)
|
||||
{
|
||||
// Has a Wonder Card already?
|
||||
if (data->flagId == 0)
|
||||
return 0;
|
||||
|
||||
// Has this Wonder Card already?
|
||||
if (*flagId == data->flagId)
|
||||
return 1;
|
||||
|
||||
// Player has a different Wonder Card
|
||||
return 2;
|
||||
}
|
||||
|
||||
u32 MysteryGift_CheckStamps(const u16 * stamp, const struct MysteryGiftLinkGameData * data, const void *unused)
|
||||
{
|
||||
s32 stampsMissing = data->maxStamps - GetNumStampsInMetadata(&data->cardMetadata, data->maxStamps);
|
||||
|
||||
// Has full stamp card?
|
||||
if (stampsMissing == 0)
|
||||
return 1;
|
||||
|
||||
// Already has stamp?
|
||||
if (IsStampInMetadata(&data->cardMetadata, stamp, data->maxStamps))
|
||||
return 3;
|
||||
|
||||
// Only 1 empty stamp left?
|
||||
if (stampsMissing == 1)
|
||||
return 4;
|
||||
|
||||
// This is a new stamp
|
||||
return 2;
|
||||
}
|
||||
|
||||
bool32 MysteryGift_DoesQuestionnaireMatch(const struct MysteryGiftLinkGameData * data, const u16 * words)
|
||||
{
|
||||
s32 i;
|
||||
for (i = 0; i < NUM_QUESTIONNAIRE_WORDS; i++)
|
||||
{
|
||||
if (data->questionnaireWords[i] != words[i])
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static s32 GetNumStampsInLinkData(const struct MysteryGiftLinkGameData * data)
|
||||
{
|
||||
return GetNumStampsInMetadata(&data->cardMetadata, data->maxStamps);
|
||||
}
|
||||
|
||||
u16 MysteryGift_GetCardStatFromLinkData(const struct MysteryGiftLinkGameData * data, u32 stat)
|
||||
{
|
||||
switch (stat)
|
||||
{
|
||||
case CARD_STAT_BATTLES_WON:
|
||||
return data->cardMetadata.battlesWon;
|
||||
case CARD_STAT_BATTLES_LOST:
|
||||
return data->cardMetadata.battlesLost;
|
||||
case CARD_STAT_NUM_TRADES:
|
||||
return data->cardMetadata.numTrades;
|
||||
case CARD_STAT_NUM_STAMPS:
|
||||
return GetNumStampsInLinkData(data);
|
||||
case CARD_STAT_MAX_STAMPS:
|
||||
return data->maxStamps;
|
||||
default:
|
||||
AGB_ASSERT_EX(0, ABSPATH("mevent.c"), 825);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void IncrementCardStat(u32 statType)
|
||||
{
|
||||
struct WonderCard * card = &gSaveBlock1Ptr->mysteryGift.card;
|
||||
if (card->type == CARD_TYPE_LINK_STAT)
|
||||
{
|
||||
u16 * stat = NULL;
|
||||
switch (statType)
|
||||
{
|
||||
case CARD_STAT_BATTLES_WON:
|
||||
stat = &gSaveBlock1Ptr->mysteryGift.cardMetadata.battlesWon;
|
||||
break;
|
||||
case CARD_STAT_BATTLES_LOST:
|
||||
stat = &gSaveBlock1Ptr->mysteryGift.cardMetadata.battlesLost;
|
||||
break;
|
||||
case CARD_STAT_NUM_TRADES:
|
||||
stat = &gSaveBlock1Ptr->mysteryGift.cardMetadata.numTrades;
|
||||
break;
|
||||
case CARD_STAT_NUM_STAMPS:
|
||||
case CARD_STAT_MAX_STAMPS:
|
||||
break;
|
||||
}
|
||||
if (stat == NULL)
|
||||
{
|
||||
AGB_ASSERT_EX(0, ABSPATH("mevent.c"), 868);
|
||||
}
|
||||
else if (++(*stat) > MAX_WONDER_CARD_STAT)
|
||||
{
|
||||
*stat = MAX_WONDER_CARD_STAT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
u16 MysteryGift_GetCardStat(u32 stat)
|
||||
{
|
||||
switch (stat)
|
||||
{
|
||||
case CARD_STAT_BATTLES_WON:
|
||||
{
|
||||
struct WonderCard * card = &gSaveBlock1Ptr->mysteryGift.card;
|
||||
if (card->type == CARD_TYPE_LINK_STAT)
|
||||
{
|
||||
struct WonderCardMetadata * metadata = &gSaveBlock1Ptr->mysteryGift.cardMetadata;
|
||||
return metadata->battlesWon;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CARD_STAT_BATTLES_LOST:
|
||||
{
|
||||
struct WonderCard * card = &gSaveBlock1Ptr->mysteryGift.card;
|
||||
if (card->type == CARD_TYPE_LINK_STAT)
|
||||
{
|
||||
struct WonderCardMetadata * metadata = &gSaveBlock1Ptr->mysteryGift.cardMetadata;
|
||||
return metadata->battlesLost;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CARD_STAT_NUM_TRADES:
|
||||
{
|
||||
struct WonderCard * card = &gSaveBlock1Ptr->mysteryGift.card;
|
||||
if (card->type == CARD_TYPE_LINK_STAT)
|
||||
{
|
||||
struct WonderCardMetadata * metadata = &gSaveBlock1Ptr->mysteryGift.cardMetadata;
|
||||
return metadata->numTrades;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CARD_STAT_NUM_STAMPS:
|
||||
{
|
||||
struct WonderCard * card = &gSaveBlock1Ptr->mysteryGift.card;
|
||||
if (card->type == CARD_TYPE_STAMP)
|
||||
return GetNumStampsInSavedCard();
|
||||
break;
|
||||
}
|
||||
case CARD_STAT_MAX_STAMPS:
|
||||
{
|
||||
struct WonderCard * card = &gSaveBlock1Ptr->mysteryGift.card;
|
||||
if (card->type == CARD_TYPE_STAMP)
|
||||
return card->maxStamps;
|
||||
break;
|
||||
}
|
||||
}
|
||||
AGB_ASSERT_EX(0, ABSPATH("mevent.c"), 913);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void MysteryGift_DisableStats(void)
|
||||
{
|
||||
sStatsEnabled = FALSE;
|
||||
}
|
||||
|
||||
bool32 MysteryGift_TryEnableStatsByFlagId(u16 flagId)
|
||||
{
|
||||
sStatsEnabled = FALSE;
|
||||
if (flagId == 0)
|
||||
return FALSE;
|
||||
if (!ValidateSavedWonderCard())
|
||||
return FALSE;
|
||||
if (gSaveBlock1Ptr->mysteryGift.card.flagId != flagId)
|
||||
return FALSE;
|
||||
sStatsEnabled = TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void MysteryGift_TryIncrementStat(u32 stat, u32 trainerId)
|
||||
{
|
||||
if (sStatsEnabled)
|
||||
{
|
||||
switch (stat)
|
||||
{
|
||||
case CARD_STAT_NUM_TRADES:
|
||||
IncrementCardStatForNewTrainer(CARD_STAT_NUM_TRADES,
|
||||
trainerId,
|
||||
gSaveBlock1Ptr->mysteryGift.trainerIds[1],
|
||||
ARRAY_COUNT(gSaveBlock1Ptr->mysteryGift.trainerIds[1]));
|
||||
break;
|
||||
case CARD_STAT_BATTLES_WON:
|
||||
IncrementCardStatForNewTrainer(CARD_STAT_BATTLES_WON,
|
||||
trainerId,
|
||||
gSaveBlock1Ptr->mysteryGift.trainerIds[0],
|
||||
ARRAY_COUNT(gSaveBlock1Ptr->mysteryGift.trainerIds[0]));
|
||||
break;
|
||||
case CARD_STAT_BATTLES_LOST:
|
||||
IncrementCardStatForNewTrainer(CARD_STAT_BATTLES_LOST,
|
||||
trainerId,
|
||||
gSaveBlock1Ptr->mysteryGift.trainerIds[0],
|
||||
ARRAY_COUNT(gSaveBlock1Ptr->mysteryGift.trainerIds[0]));
|
||||
break;
|
||||
default:
|
||||
AGB_ASSERT_EX(0, ABSPATH("mevent.c"), 988);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ClearSavedTrainerIds(void)
|
||||
{
|
||||
CpuFill32(0, gSaveBlock1Ptr->mysteryGift.trainerIds, sizeof(gSaveBlock1Ptr->mysteryGift.trainerIds));
|
||||
}
|
||||
|
||||
// Returns TRUE if it's a new trainer id, FALSE if an existing one.
|
||||
// In either case the given trainerId is saved in element 0
|
||||
static bool32 RecordTrainerId(u32 trainerId, u32 * trainerIds, s32 size)
|
||||
{
|
||||
s32 i;
|
||||
s32 j;
|
||||
|
||||
for (i = 0; i < size; i++)
|
||||
{
|
||||
if (trainerIds[i] == trainerId)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == size)
|
||||
{
|
||||
// New trainer, shift array and insert new id at front
|
||||
for (j = size - 1; j > 0; j--)
|
||||
trainerIds[j] = trainerIds[j - 1];
|
||||
|
||||
trainerIds[0] = trainerId;
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Existing trainer, shift back to old slot and move id to front
|
||||
for (j = i; j > 0; j--)
|
||||
trainerIds[j] = trainerIds[j - 1];
|
||||
|
||||
trainerIds[0] = trainerId;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static void IncrementCardStatForNewTrainer(u32 stat, u32 trainerId, u32 * trainerIds, s32 size)
|
||||
{
|
||||
if (RecordTrainerId(trainerId, trainerIds, size))
|
||||
IncrementCardStat(stat);
|
||||
}
|
||||
@@ -0,0 +1,300 @@
|
||||
#include "global.h"
|
||||
#include "gflib.h"
|
||||
#include "decompress.h"
|
||||
#include "overworld.h"
|
||||
#include "script.h"
|
||||
#include "battle_tower.h"
|
||||
#include "mystery_event_script.h"
|
||||
#include "mystery_gift.h"
|
||||
#include "mystery_gift_client.h"
|
||||
#include "mystery_gift_server.h"
|
||||
|
||||
enum {
|
||||
FUNC_INIT,
|
||||
FUNC_DONE,
|
||||
FUNC_RECV,
|
||||
FUNC_SEND,
|
||||
FUNC_RUN,
|
||||
FUNC_WAIT,
|
||||
FUNC_RUN_MEVENT,
|
||||
FUNC_RUN_BUFFER,
|
||||
};
|
||||
|
||||
static EWRAM_DATA struct MysteryGiftClient * sClient = NULL;
|
||||
|
||||
static void MysteryGiftClient_Init(struct MysteryGiftClient *, u32, u32);
|
||||
static u32 MysteryGiftClient_CallFunc(struct MysteryGiftClient *);
|
||||
static void MysteryGiftClient_Free(struct MysteryGiftClient *);
|
||||
|
||||
extern const struct MysteryGiftClientCmd gMysteryGiftClientScript_Init[];
|
||||
|
||||
void MysteryGiftClient_Create(void)
|
||||
{
|
||||
sClient = AllocZeroed(sizeof(*sClient));
|
||||
MysteryGiftClient_Init(sClient, 1, 0);
|
||||
}
|
||||
|
||||
u32 MysteryGiftClient_Run(u16 * endVal)
|
||||
{
|
||||
u32 result;
|
||||
if (sClient == NULL)
|
||||
return CLI_RET_END;
|
||||
result = MysteryGiftClient_CallFunc(sClient);
|
||||
if (result == CLI_RET_END)
|
||||
{
|
||||
*endVal = sClient->param;
|
||||
MysteryGiftClient_Free(sClient);
|
||||
FREE_AND_SET_NULL(sClient);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void MysteryGiftClient_AdvanceState(void)
|
||||
{
|
||||
sClient->funcState++;
|
||||
}
|
||||
|
||||
void *MysteryGiftClient_GetMsg(void)
|
||||
{
|
||||
return sClient->msg;
|
||||
}
|
||||
|
||||
void MysteryGiftClient_SetParam(u32 val)
|
||||
{
|
||||
sClient->param = val;
|
||||
}
|
||||
|
||||
static void MysteryGiftClient_Init(struct MysteryGiftClient * client, u32 sendPlayerId, u32 recvPlayerId)
|
||||
{
|
||||
client->unused = 0;
|
||||
client->funcId = FUNC_INIT;
|
||||
client->funcState = 0;
|
||||
client->sendBuffer = AllocZeroed(MG_LINK_BUFFER_SIZE);
|
||||
client->recvBuffer = AllocZeroed(MG_LINK_BUFFER_SIZE);
|
||||
client->script = AllocZeroed(MG_LINK_BUFFER_SIZE);
|
||||
client->msg = AllocZeroed(CLIENT_MAX_MSG_SIZE);
|
||||
MysteryGiftLink_Init(&client->link, sendPlayerId, recvPlayerId);
|
||||
}
|
||||
|
||||
static void MysteryGiftClient_Free(struct MysteryGiftClient * client)
|
||||
{
|
||||
Free(client->sendBuffer);
|
||||
Free(client->recvBuffer);
|
||||
Free(client->script);
|
||||
Free(client->msg);
|
||||
}
|
||||
|
||||
static void MysteryGiftClient_CopyRecvScript(struct MysteryGiftClient * client)
|
||||
{
|
||||
memcpy(client->script, client->recvBuffer, MG_LINK_BUFFER_SIZE);
|
||||
client->cmdidx = 0;
|
||||
}
|
||||
|
||||
static void MysteryGiftClient_InitSendWord(struct MysteryGiftClient * client, u32 ident, u32 word)
|
||||
{
|
||||
CpuFill32(0, client->sendBuffer, MG_LINK_BUFFER_SIZE);
|
||||
*(u32 *)client->sendBuffer = word;
|
||||
MysteryGiftLink_InitSend(&client->link, ident, client->sendBuffer, sizeof(word));
|
||||
}
|
||||
|
||||
static u32 Client_Init(struct MysteryGiftClient * client)
|
||||
{
|
||||
memcpy(client->script, gMysteryGiftClientScript_Init, MG_LINK_BUFFER_SIZE);
|
||||
client->cmdidx = 0;
|
||||
client->funcId = FUNC_RUN;
|
||||
client->funcState = 0;
|
||||
return CLI_RET_INIT;
|
||||
}
|
||||
|
||||
static u32 Client_Done(struct MysteryGiftClient * client)
|
||||
{
|
||||
return CLI_RET_END;
|
||||
}
|
||||
|
||||
static u32 Client_Recv(struct MysteryGiftClient * client)
|
||||
{
|
||||
if (MysteryGiftLink_Recv(&client->link))
|
||||
{
|
||||
client->funcId = FUNC_RUN;
|
||||
client->funcState = 0;
|
||||
}
|
||||
return CLI_RET_ACTIVE;
|
||||
}
|
||||
|
||||
static u32 Client_Send(struct MysteryGiftClient * client)
|
||||
{
|
||||
if (MysteryGiftLink_Send(&client->link))
|
||||
{
|
||||
client->funcId = FUNC_RUN;
|
||||
client->funcState = 0;
|
||||
}
|
||||
return CLI_RET_ACTIVE;
|
||||
}
|
||||
|
||||
static u32 Client_Run(struct MysteryGiftClient * client)
|
||||
{
|
||||
// process command
|
||||
struct MysteryGiftClientCmd * cmd = &client->script[client->cmdidx];
|
||||
client->cmdidx++;
|
||||
switch (cmd->instr)
|
||||
{
|
||||
case CLI_NONE:
|
||||
break;
|
||||
case CLI_RETURN:
|
||||
client->param = cmd->parameter; // Set for endVal in MysteryGiftClient_Run
|
||||
client->funcId = FUNC_DONE;
|
||||
client->funcState = 0;
|
||||
break;
|
||||
case CLI_RECV:
|
||||
MysteryGiftLink_InitRecv(&client->link, cmd->parameter, client->recvBuffer);
|
||||
client->funcId = FUNC_RECV;
|
||||
client->funcState = 0;
|
||||
break;
|
||||
case CLI_SEND_LOADED:
|
||||
// Send without a MysteryGiftLink_InitSend
|
||||
// Sends whatever has been loaded already
|
||||
client->funcId = FUNC_SEND;
|
||||
client->funcState = 0;
|
||||
break;
|
||||
case CLI_SEND_READY_END:
|
||||
MysteryGiftLink_InitSend(&client->link, MG_LINKID_READY_END, client->sendBuffer, 0);
|
||||
client->funcId = FUNC_SEND;
|
||||
client->funcState = 0;
|
||||
break;
|
||||
case CLI_SEND_STAT:
|
||||
MysteryGiftClient_InitSendWord(client, MG_LINKID_GAME_STAT, GetGameStat(cmd->parameter));
|
||||
client->funcId = FUNC_SEND;
|
||||
client->funcState = 0;
|
||||
break;
|
||||
case CLI_COPY_RECV_IF_N:
|
||||
if (client->param == FALSE)
|
||||
MysteryGiftClient_CopyRecvScript(client);
|
||||
break;
|
||||
case CLI_COPY_RECV_IF:
|
||||
if (client->param == TRUE)
|
||||
MysteryGiftClient_CopyRecvScript(client);
|
||||
break;
|
||||
case CLI_COPY_RECV:
|
||||
MysteryGiftClient_CopyRecvScript(client);
|
||||
break;
|
||||
case CLI_YES_NO:
|
||||
memcpy(client->msg, client->recvBuffer, CLIENT_MAX_MSG_SIZE);
|
||||
client->funcId = FUNC_WAIT;
|
||||
client->funcState = 0;
|
||||
return CLI_RET_YES_NO;
|
||||
case CLI_PRINT_MSG:
|
||||
memcpy(client->msg, client->recvBuffer, CLIENT_MAX_MSG_SIZE);
|
||||
client->funcId = FUNC_WAIT;
|
||||
client->funcState = 0;
|
||||
return CLI_RET_PRINT_MSG;
|
||||
case CLI_COPY_MSG:
|
||||
memcpy(client->msg, client->recvBuffer, CLIENT_MAX_MSG_SIZE);
|
||||
client->funcId = FUNC_WAIT;
|
||||
client->funcState = 0;
|
||||
return CLI_RET_COPY_MSG;
|
||||
case CLI_ASK_TOSS:
|
||||
client->funcId = FUNC_WAIT;
|
||||
client->funcState = 0;
|
||||
return CLI_RET_ASK_TOSS;
|
||||
case CLI_LOAD_GAME_DATA:
|
||||
MysteryGift_LoadLinkGameData(client->sendBuffer);
|
||||
MysteryGiftLink_InitSend(&client->link, MG_LINKID_GAME_DATA, client->sendBuffer, sizeof(struct MysteryGiftLinkGameData));
|
||||
break;
|
||||
case CLI_LOAD_TOSS_RESPONSE:
|
||||
// param here is set by MG_STATE_CLIENT_ASK_TOSS or MG_STATE_CLIENT_ASK_TOSS_UNRECEIVED
|
||||
MysteryGiftClient_InitSendWord(client, MG_LINKID_RESPONSE, client->param);
|
||||
break;
|
||||
case CLI_SAVE_CARD:
|
||||
SaveWonderCard(client->recvBuffer);
|
||||
break;
|
||||
case CLI_SAVE_NEWS:
|
||||
if (!IsWonderNewsSameAsSaved(client->recvBuffer))
|
||||
{
|
||||
SaveWonderNews(client->recvBuffer);
|
||||
MysteryGiftClient_InitSendWord(client, MG_LINKID_RESPONSE, FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Wonder News has already been saved (or is invalid).
|
||||
// Prepare a signal to indicate it was not saved.
|
||||
MysteryGiftClient_InitSendWord(client, MG_LINKID_RESPONSE, TRUE);
|
||||
}
|
||||
break;
|
||||
case CLI_RUN_MEVENT_SCRIPT:
|
||||
client->funcId = FUNC_RUN_MEVENT;
|
||||
client->funcState = 0;
|
||||
break;
|
||||
case CLI_SAVE_STAMP:
|
||||
MysteryGift_TrySaveStamp(client->recvBuffer);
|
||||
break;
|
||||
case CLI_SAVE_RAM_SCRIPT:
|
||||
InitRamScript_NoObjectEvent(client->recvBuffer, sizeof(struct RamScriptData));
|
||||
break;
|
||||
case CLI_RECV_EREADER_TRAINER:
|
||||
memcpy(&gSaveBlock2Ptr->battleTower.ereaderTrainer, client->recvBuffer, sizeof(gSaveBlock2Ptr->battleTower.ereaderTrainer));
|
||||
ValidateEReaderTrainer();
|
||||
break;
|
||||
case CLI_RUN_BUFFER_SCRIPT:
|
||||
memcpy(gDecompressionBuffer, client->recvBuffer, MG_LINK_BUFFER_SIZE);
|
||||
client->funcId = FUNC_RUN_BUFFER;
|
||||
client->funcState = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return CLI_RET_ACTIVE;
|
||||
}
|
||||
|
||||
static u32 Client_Wait(struct MysteryGiftClient * client)
|
||||
{
|
||||
if (client->funcState)
|
||||
{
|
||||
client->funcId = FUNC_RUN;
|
||||
client->funcState = 0;
|
||||
}
|
||||
return CLI_RET_ACTIVE;
|
||||
}
|
||||
|
||||
static u32 Client_RunMysteryEventScript(struct MysteryGiftClient * client)
|
||||
{
|
||||
switch (client->funcState)
|
||||
{
|
||||
case 0:
|
||||
MEventScript_InitContext(client->recvBuffer);
|
||||
client->funcState++;
|
||||
break;
|
||||
case 1:
|
||||
if (!MEventScript_Run(&client->param))
|
||||
{
|
||||
client->funcId = FUNC_RUN;
|
||||
client->funcState = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return CLI_RET_ACTIVE;
|
||||
}
|
||||
|
||||
static u32 Client_RunBufferScript(struct MysteryGiftClient * client)
|
||||
{
|
||||
u32 (*func)(u32 *, struct SaveBlock2 *, struct SaveBlock1 *) = (void *)gDecompressionBuffer;
|
||||
if (func(&client->param, gSaveBlock2Ptr, gSaveBlock1Ptr) == 1)
|
||||
{
|
||||
client->funcId = FUNC_RUN;
|
||||
client->funcState = 0;
|
||||
}
|
||||
return CLI_RET_ACTIVE;
|
||||
}
|
||||
|
||||
static u32 MysteryGiftClient_CallFunc(struct MysteryGiftClient * client)
|
||||
{
|
||||
u32 (*funcs[])(struct MysteryGiftClient *) = {
|
||||
[FUNC_INIT] = Client_Init,
|
||||
[FUNC_DONE] = Client_Done,
|
||||
[FUNC_RECV] = Client_Recv,
|
||||
[FUNC_SEND] = Client_Send,
|
||||
[FUNC_RUN] = Client_Run,
|
||||
[FUNC_WAIT] = Client_Wait,
|
||||
[FUNC_RUN_MEVENT] = Client_RunMysteryEventScript,
|
||||
[FUNC_RUN_BUFFER] = Client_RunBufferScript
|
||||
};
|
||||
return funcs[client->funcId](client);
|
||||
}
|
||||
@@ -0,0 +1,215 @@
|
||||
#include "global.h"
|
||||
#include "util.h"
|
||||
#include "link.h"
|
||||
#include "link_rfu.h"
|
||||
#include "mystery_gift_server.h"
|
||||
|
||||
/*
|
||||
Handles the link connection functions used by the Mystery Gift client/server.
|
||||
Note: MysteryGiftLink is shortened to MGL for internal functions.
|
||||
*/
|
||||
|
||||
struct SendRecvHeader
|
||||
{
|
||||
u16 ident;
|
||||
u16 crc;
|
||||
u16 size;
|
||||
};
|
||||
|
||||
static u32 MGL_Receive(struct MysteryGiftLink *);
|
||||
static u32 MGL_Send(struct MysteryGiftLink *);
|
||||
|
||||
u32 MysteryGiftLink_Recv(struct MysteryGiftLink * link)
|
||||
{
|
||||
return link->recvFunc(link);
|
||||
}
|
||||
|
||||
u32 MysteryGiftLink_Send(struct MysteryGiftLink * link)
|
||||
{
|
||||
return link->sendFunc(link);
|
||||
}
|
||||
|
||||
void MysteryGiftLink_Init(struct MysteryGiftLink * link, u32 sendPlayerId, u32 recvPlayerId)
|
||||
{
|
||||
link->sendPlayerId = sendPlayerId;
|
||||
link->recvPlayerId = recvPlayerId;
|
||||
link->state = 0;
|
||||
link->sendCRC = 0;
|
||||
link->sendSize = 0;
|
||||
link->sendCounter = 0;
|
||||
link->recvCRC = 0;
|
||||
link->recvSize = 0;
|
||||
link->recvCounter = 0;
|
||||
link->sendBuffer = NULL;
|
||||
link->recvBuffer = NULL;
|
||||
link->sendFunc = MGL_Send;
|
||||
link->recvFunc = MGL_Receive;
|
||||
}
|
||||
|
||||
void MysteryGiftLink_InitSend(struct MysteryGiftLink * link, u32 ident, const void *src, u32 size)
|
||||
{
|
||||
link->state = 0;
|
||||
link->sendIdent = ident;
|
||||
link->sendCounter = 0;
|
||||
link->sendCRC = 0;
|
||||
if (size != 0)
|
||||
link->sendSize = size;
|
||||
else
|
||||
link->sendSize = MG_LINK_BUFFER_SIZE;
|
||||
link->sendBuffer = src;
|
||||
}
|
||||
|
||||
void MysteryGiftLink_InitRecv(struct MysteryGiftLink * link, u32 ident, void *dest)
|
||||
{
|
||||
link->state = 0;
|
||||
link->recvIdent = ident;
|
||||
link->recvCounter = 0;
|
||||
link->recvCRC = 0;
|
||||
link->recvSize = 0;
|
||||
link->recvBuffer = dest;
|
||||
}
|
||||
|
||||
static void MGL_ReceiveBlock(u32 playerId, void *dest, size_t size)
|
||||
{
|
||||
memcpy(dest, gBlockRecvBuffer[playerId], size);
|
||||
}
|
||||
|
||||
static bool32 MGL_HasReceived(u32 playerId)
|
||||
{
|
||||
if ((GetBlockReceivedStatus() >> playerId) & 1)
|
||||
return TRUE;
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void MGL_ResetReceived(u32 playerId)
|
||||
{
|
||||
ResetBlockReceivedFlag(playerId);
|
||||
}
|
||||
|
||||
static bool32 MGL_Receive(struct MysteryGiftLink * link)
|
||||
{
|
||||
struct SendRecvHeader header;
|
||||
|
||||
switch (link->state)
|
||||
{
|
||||
case 0:
|
||||
if (MGL_HasReceived(link->recvPlayerId))
|
||||
{
|
||||
MGL_ReceiveBlock(link->recvPlayerId, &header, sizeof(header));
|
||||
link->recvSize = header.size;
|
||||
link->recvCRC = header.crc;
|
||||
if (link->recvSize > MG_LINK_BUFFER_SIZE)
|
||||
{
|
||||
LinkRfu_FatalError();
|
||||
return FALSE;
|
||||
}
|
||||
else if (link->recvIdent != header.ident)
|
||||
{
|
||||
LinkRfu_FatalError();
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
link->recvCounter = 0;
|
||||
MGL_ResetReceived(link->recvPlayerId);
|
||||
link->state++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if (MGL_HasReceived(link->recvPlayerId))
|
||||
{
|
||||
size_t blocksize = link->recvCounter * 252;
|
||||
if (link->recvSize - blocksize <= 252)
|
||||
{
|
||||
MGL_ReceiveBlock(link->recvPlayerId, link->recvBuffer + blocksize, link->recvSize - blocksize);
|
||||
link->recvCounter++;
|
||||
link->state++;
|
||||
}
|
||||
else
|
||||
{
|
||||
MGL_ReceiveBlock(link->recvPlayerId, link->recvBuffer + blocksize, 252);
|
||||
link->recvCounter++;
|
||||
}
|
||||
MGL_ResetReceived(link->recvPlayerId);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if (CalcCRC16WithTable(link->recvBuffer, link->recvSize) != link->recvCRC)
|
||||
{
|
||||
LinkRfu_FatalError();
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
link->state = 0;
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static bool32 MGL_Send(struct MysteryGiftLink * link)
|
||||
{
|
||||
struct SendRecvHeader header;
|
||||
|
||||
switch (link->state)
|
||||
{
|
||||
case 0:
|
||||
if (IsLinkTaskFinished())
|
||||
{
|
||||
header.ident = link->sendIdent;
|
||||
header.size = link->sendSize;
|
||||
header.crc = CalcCRC16WithTable(link->sendBuffer, link->sendSize);
|
||||
link->sendCRC = header.crc;
|
||||
link->sendCounter = 0;
|
||||
SendBlock(0, &header, sizeof(header));
|
||||
link->state++;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if (IsLinkTaskFinished())
|
||||
{
|
||||
if (MGL_HasReceived(link->sendPlayerId))
|
||||
{
|
||||
size_t blocksize;
|
||||
MGL_ResetReceived(link->sendPlayerId);
|
||||
blocksize = 252 * link->sendCounter;
|
||||
if (link->sendSize - blocksize <= 252)
|
||||
{
|
||||
SendBlock(0, link->sendBuffer + blocksize, link->sendSize - blocksize);
|
||||
link->sendCounter++;
|
||||
link->state++;
|
||||
}
|
||||
else
|
||||
{
|
||||
SendBlock(0, link->sendBuffer + blocksize, 252);
|
||||
link->sendCounter++;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if (IsLinkTaskFinished())
|
||||
{
|
||||
if (CalcCRC16WithTable(link->sendBuffer, link->sendSize) != link->sendCRC)
|
||||
LinkRfu_FatalError();
|
||||
else
|
||||
link->state++;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
if (MGL_HasReceived(link->sendPlayerId))
|
||||
{
|
||||
MGL_ResetReceived(link->sendPlayerId);
|
||||
link->state = 0;
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
+548
-600
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,198 @@
|
||||
#include "global.h"
|
||||
#include "mystery_gift_server.h"
|
||||
#include "mystery_gift_client.h"
|
||||
#include "constants/mystery_gift.h"
|
||||
|
||||
extern const struct MysteryGiftServerCmd gServerScript_ClientCanceledCard[];
|
||||
|
||||
// Unreferenced
|
||||
static const u8 sText_CollectedAllStamps[] = _("You have collected all STAMPs!\nWant to input a CARD as a prize?");
|
||||
|
||||
//==================
|
||||
// Client scripts
|
||||
//==================
|
||||
|
||||
const struct MysteryGiftClientCmd gMysteryGiftClientScript_Init[] = {
|
||||
{CLI_RECV, MG_LINKID_CLIENT_SCRIPT},
|
||||
{CLI_COPY_RECV}
|
||||
};
|
||||
|
||||
static const struct MysteryGiftClientCmd sClientScript_SendGameData[] = {
|
||||
{CLI_LOAD_GAME_DATA},
|
||||
{CLI_SEND_LOADED},
|
||||
{CLI_RECV, MG_LINKID_CLIENT_SCRIPT},
|
||||
{CLI_COPY_RECV}
|
||||
};
|
||||
|
||||
static const struct MysteryGiftClientCmd sClientScript_CantAccept[] = {
|
||||
{CLI_SEND_READY_END},
|
||||
{CLI_RETURN, CLI_MSG_CANT_ACCEPT}
|
||||
};
|
||||
|
||||
static const struct MysteryGiftClientCmd sClientScript_CommError[] = {
|
||||
{CLI_SEND_READY_END},
|
||||
{CLI_RETURN, CLI_MSG_COMM_ERROR}
|
||||
};
|
||||
|
||||
static const struct MysteryGiftClientCmd sClientScript_NothingSent[] = {
|
||||
{CLI_SEND_READY_END},
|
||||
{CLI_RETURN, CLI_MSG_NOTHING_SENT}
|
||||
};
|
||||
|
||||
static const struct MysteryGiftClientCmd sClientScript_SaveCard[] = {
|
||||
{CLI_RECV, MG_LINKID_CARD},
|
||||
{CLI_SAVE_CARD},
|
||||
{CLI_RECV, MG_LINKID_RAM_SCRIPT},
|
||||
{CLI_SAVE_RAM_SCRIPT},
|
||||
{CLI_SEND_READY_END},
|
||||
{CLI_RETURN, CLI_MSG_CARD_RECEIVED}
|
||||
};
|
||||
|
||||
static const struct MysteryGiftClientCmd sClientScript_SaveNews[] = {
|
||||
{CLI_RECV, MG_LINKID_NEWS},
|
||||
{CLI_SAVE_NEWS},
|
||||
{CLI_SEND_LOADED}, // Send whether or not the News was saved (read by sServerScript_SendNews)
|
||||
{CLI_RECV, MG_LINKID_CLIENT_SCRIPT},
|
||||
{CLI_COPY_RECV}
|
||||
};
|
||||
|
||||
static const struct MysteryGiftClientCmd sClientScript_HadNews[] = {
|
||||
{CLI_SEND_READY_END},
|
||||
{CLI_RETURN, CLI_MSG_HAD_NEWS}
|
||||
};
|
||||
|
||||
static const struct MysteryGiftClientCmd sClientScript_NewsReceived[] = {
|
||||
{CLI_SEND_READY_END},
|
||||
{CLI_RETURN, CLI_MSG_NEWS_RECEIVED}
|
||||
};
|
||||
|
||||
static const struct MysteryGiftClientCmd sClientScript_AskToss[] = {
|
||||
{CLI_ASK_TOSS},
|
||||
{CLI_LOAD_TOSS_RESPONSE},
|
||||
{CLI_SEND_LOADED},
|
||||
{CLI_RECV, MG_LINKID_CLIENT_SCRIPT},
|
||||
{CLI_COPY_RECV}
|
||||
};
|
||||
|
||||
static const struct MysteryGiftClientCmd sClientScript_Canceled[] = {
|
||||
{CLI_SEND_READY_END},
|
||||
{CLI_RETURN, CLI_MSG_COMM_CANCELED}
|
||||
};
|
||||
|
||||
static const struct MysteryGiftClientCmd sClientScript_HadCard[] = {
|
||||
{CLI_SEND_READY_END},
|
||||
{CLI_RETURN, CLI_MSG_HAD_CARD}
|
||||
};
|
||||
|
||||
static const struct MysteryGiftClientCmd sClientScript_DynamicSuccess[] = {
|
||||
{CLI_RECV, MG_LINKID_DYNAMIC_MSG},
|
||||
{CLI_COPY_MSG},
|
||||
{CLI_SEND_READY_END},
|
||||
{CLI_RETURN, CLI_MSG_BUFFER_SUCCESS}
|
||||
};
|
||||
|
||||
//==================
|
||||
// Server scripts
|
||||
//==================
|
||||
|
||||
static const struct MysteryGiftServerCmd sServerScript_CantSend[] = {
|
||||
{SVR_LOAD_CLIENT_SCRIPT, PTR_ARG(sClientScript_CantAccept)},
|
||||
{SVR_SEND},
|
||||
{SVR_RECV, MG_LINKID_READY_END},
|
||||
{SVR_RETURN, SVR_MSG_CANT_SEND_GIFT_1}
|
||||
};
|
||||
|
||||
static const struct MysteryGiftServerCmd sServerScript_CommError[] = {
|
||||
{SVR_LOAD_CLIENT_SCRIPT, PTR_ARG(sClientScript_CommError)},
|
||||
{SVR_SEND},
|
||||
{SVR_RECV, MG_LINKID_READY_END},
|
||||
{SVR_RETURN, SVR_MSG_COMM_ERROR}
|
||||
};
|
||||
|
||||
static const struct MysteryGiftServerCmd sServerScript_ClientCanceledNews[] = {
|
||||
{SVR_LOAD_CLIENT_SCRIPT, PTR_ARG(sClientScript_Canceled)},
|
||||
{SVR_SEND},
|
||||
{SVR_RECV, MG_LINKID_READY_END},
|
||||
{SVR_RETURN, SVR_MSG_CLIENT_CANCELED}
|
||||
};
|
||||
|
||||
static const struct MysteryGiftServerCmd sServerScript_HasNews[] = {
|
||||
{SVR_LOAD_CLIENT_SCRIPT, PTR_ARG(sClientScript_HadNews)},
|
||||
{SVR_SEND},
|
||||
{SVR_RECV, MG_LINKID_READY_END},
|
||||
{SVR_RETURN, SVR_MSG_HAS_NEWS}
|
||||
};
|
||||
|
||||
static const struct MysteryGiftServerCmd sServerScript_SendNews[] = {
|
||||
{SVR_LOAD_CLIENT_SCRIPT, PTR_ARG(sClientScript_SaveNews)},
|
||||
{SVR_SEND},
|
||||
{SVR_LOAD_NEWS},
|
||||
{SVR_SEND},
|
||||
{SVR_RECV, MG_LINKID_RESPONSE},
|
||||
{SVR_READ_RESPONSE},
|
||||
{SVR_GOTO_IF_EQ, TRUE, sServerScript_HasNews}, // Wonder News was not saved
|
||||
{SVR_LOAD_CLIENT_SCRIPT, PTR_ARG(sClientScript_NewsReceived)},
|
||||
{SVR_SEND},
|
||||
{SVR_RECV, MG_LINKID_READY_END},
|
||||
{SVR_RETURN, SVR_MSG_NEWS_SENT}
|
||||
};
|
||||
|
||||
static const struct MysteryGiftServerCmd sServerScript_SendCard[] = {
|
||||
{SVR_LOAD_CLIENT_SCRIPT, PTR_ARG(sClientScript_SaveCard)},
|
||||
{SVR_SEND},
|
||||
{SVR_LOAD_CARD},
|
||||
{SVR_SEND},
|
||||
{SVR_LOAD_RAM_SCRIPT},
|
||||
{SVR_SEND},
|
||||
{SVR_RECV, MG_LINKID_READY_END},
|
||||
{SVR_RETURN, SVR_MSG_CARD_SENT}
|
||||
};
|
||||
|
||||
static const struct MysteryGiftServerCmd sServerScript_TossPrompt[] = {
|
||||
{SVR_LOAD_CLIENT_SCRIPT, PTR_ARG(sClientScript_AskToss)},
|
||||
{SVR_SEND},
|
||||
{SVR_RECV, MG_LINKID_RESPONSE},
|
||||
{SVR_READ_RESPONSE},
|
||||
{SVR_GOTO_IF_EQ, FALSE, sServerScript_SendCard}, // Tossed old card, send new one
|
||||
{SVR_GOTO, .ptr = gServerScript_ClientCanceledCard} // Kept old card, cancel new one
|
||||
};
|
||||
|
||||
static const struct MysteryGiftServerCmd sServerScript_HasCard[] = {
|
||||
{SVR_LOAD_CLIENT_SCRIPT, PTR_ARG(sClientScript_HadCard)},
|
||||
{SVR_SEND},
|
||||
{SVR_RECV, MG_LINKID_READY_END},
|
||||
{SVR_RETURN, SVR_MSG_HAS_CARD}
|
||||
};
|
||||
|
||||
static const struct MysteryGiftServerCmd sServerScript_NothingSent[] = {
|
||||
{SVR_LOAD_CLIENT_SCRIPT, PTR_ARG(sClientScript_NothingSent)},
|
||||
{SVR_SEND},
|
||||
{SVR_RECV, MG_LINKID_READY_END},
|
||||
{SVR_RETURN, SVR_MSG_NOTHING_SENT}
|
||||
};
|
||||
|
||||
const struct MysteryGiftServerCmd gMysteryGiftServerScript_SendWonderNews[] = {
|
||||
{SVR_COPY_SAVED_NEWS},
|
||||
{SVR_LOAD_CLIENT_SCRIPT, PTR_ARG(sClientScript_SendGameData)},
|
||||
{SVR_SEND},
|
||||
{SVR_RECV, MG_LINKID_GAME_DATA},
|
||||
{SVR_COPY_GAME_DATA},
|
||||
{SVR_CHECK_GAME_DATA},
|
||||
{SVR_GOTO_IF_EQ, FALSE, sServerScript_CantSend},
|
||||
{SVR_GOTO, .ptr = sServerScript_SendNews},
|
||||
};
|
||||
|
||||
const struct MysteryGiftServerCmd gMysteryGiftServerScript_SendWonderCard[] = {
|
||||
{SVR_COPY_SAVED_CARD},
|
||||
{SVR_COPY_SAVED_RAM_SCRIPT},
|
||||
{SVR_LOAD_CLIENT_SCRIPT, PTR_ARG(sClientScript_SendGameData)},
|
||||
{SVR_SEND},
|
||||
{SVR_RECV, MG_LINKID_GAME_DATA},
|
||||
{SVR_COPY_GAME_DATA},
|
||||
{SVR_CHECK_GAME_DATA},
|
||||
{SVR_GOTO_IF_EQ, FALSE, sServerScript_CantSend},
|
||||
{SVR_CHECK_EXISTING_CARD},
|
||||
{SVR_GOTO_IF_EQ, HAS_DIFF_CARD, sServerScript_TossPrompt},
|
||||
{SVR_GOTO_IF_EQ, HAS_NO_CARD, sServerScript_SendCard},
|
||||
{SVR_GOTO, .ptr = sServerScript_HasCard} // HAS_SAME_CARD
|
||||
};
|
||||
@@ -0,0 +1,302 @@
|
||||
#include "global.h"
|
||||
#include "gflib.h"
|
||||
#include "script.h"
|
||||
#include "mystery_gift.h"
|
||||
#include "mystery_gift_server.h"
|
||||
|
||||
// Assert statements use the original GF names, which are defined below.
|
||||
// Note that their name "flag" is especially misleading,
|
||||
// as it's not a boolean (for example it can contain a size argument).
|
||||
// 'parameter' is shortened to param explicitly to avoid a collision with
|
||||
// the original name for a different field.
|
||||
#define mainseqno funcId
|
||||
#define func_tbl sFuncTable
|
||||
#define parameter ptr
|
||||
#define flag param
|
||||
#define ME_SEND_BUF_SIZE MG_LINK_BUFFER_SIZE
|
||||
#define FILE ABSPATH("mevent_server.c")
|
||||
|
||||
#define ASSERT_PTR_EMPTY(lineNum) AGB_ASSERT_EX(cmd->parameter == NULL, FILE, (lineNum));
|
||||
#define ASSERT_PARAM_EMPTY(lineNum) AGB_ASSERT_EX(cmd->flag == FALSE, FILE, (lineNum));
|
||||
#define ASSERT_PTR_PARAM_EMPTY(lineNum) AGB_ASSERT_EX(cmd->flag == FALSE && cmd->parameter == NULL, FILE, (lineNum));
|
||||
#define ASSERT_VALID_FUNC(lineNum) AGB_ASSERT_EX(svr->mainseqno < NELEMS(func_tbl), FILE, (lineNum));
|
||||
#define ASSERT_SIZE_OK(lineNum) AGB_ASSERT_EX(size <= ME_SEND_BUF_SIZE, FILE, (lineNum));
|
||||
|
||||
enum {
|
||||
FUNC_INIT,
|
||||
FUNC_DONE,
|
||||
FUNC_RECV,
|
||||
FUNC_SEND,
|
||||
FUNC_RUN,
|
||||
};
|
||||
|
||||
static EWRAM_DATA struct MysteryGiftServer * sServer = NULL;
|
||||
|
||||
static void MysteryGiftServer_Init(struct MysteryGiftServer *, const void *, u32, u32);
|
||||
static void MysteryGiftServer_Free(struct MysteryGiftServer *);
|
||||
static u32 MysteryGiftServer_CallFunc(struct MysteryGiftServer *);
|
||||
|
||||
extern const struct MysteryGiftServerCmd gMysteryGiftServerScript_SendWonderNews[];
|
||||
extern const struct MysteryGiftServerCmd gMysteryGiftServerScript_SendWonderCard[];
|
||||
|
||||
void MysterGiftServer_CreateForNews(void)
|
||||
{
|
||||
sServer = AllocZeroed(sizeof(*sServer));
|
||||
MysteryGiftServer_Init(sServer, gMysteryGiftServerScript_SendWonderNews, 0, 1);
|
||||
}
|
||||
|
||||
void MysterGiftServer_CreateForCard(void)
|
||||
{
|
||||
sServer = AllocZeroed(sizeof(*sServer));
|
||||
MysteryGiftServer_Init(sServer, gMysteryGiftServerScript_SendWonderCard, 0, 1);
|
||||
}
|
||||
|
||||
u32 MysterGiftServer_Run(u16 * endVal)
|
||||
{
|
||||
u32 result;
|
||||
if (sServer == NULL)
|
||||
return SVR_RET_END;
|
||||
result = MysteryGiftServer_CallFunc(sServer);
|
||||
if (result == SVR_RET_END)
|
||||
{
|
||||
*endVal = sServer->param;
|
||||
MysteryGiftServer_Free(sServer);
|
||||
FREE_AND_SET_NULL(sServer);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static void MysteryGiftServer_Init(struct MysteryGiftServer * svr, const void *script, u32 sendPlayerId, u32 recvPlayerId)
|
||||
{
|
||||
svr->unused = 0;
|
||||
svr->funcId = FUNC_INIT;
|
||||
svr->card = AllocZeroed(sizeof(*svr->card));
|
||||
svr->news = AllocZeroed(sizeof(*svr->news));
|
||||
svr->recvBuffer = AllocZeroed(MG_LINK_BUFFER_SIZE);
|
||||
svr->linkGameData = AllocZeroed(sizeof(*svr->linkGameData));
|
||||
svr->script = script;
|
||||
svr->cmdidx = 0;
|
||||
MysteryGiftLink_Init(&svr->manager, sendPlayerId, recvPlayerId);
|
||||
}
|
||||
|
||||
static void MysteryGiftServer_Free(struct MysteryGiftServer * svr)
|
||||
{
|
||||
Free(svr->card);
|
||||
Free(svr->news);
|
||||
Free(svr->recvBuffer);
|
||||
Free(svr->linkGameData);
|
||||
}
|
||||
|
||||
static void MysteryGiftServer_InitSend(struct MysteryGiftServer * svr, u32 ident, const void *src, u32 size)
|
||||
{
|
||||
ASSERT_SIZE_OK(257);
|
||||
MysteryGiftLink_InitSend(&svr->manager, ident, src, size);
|
||||
}
|
||||
|
||||
// Given the command pointer parameter and the 'default' normal data.
|
||||
// If the command's pointer is not empty use that as the send data, otherwise use the default.
|
||||
static const void *MysteryGiftServer_GetSendData(const void *dynamicData, const void *defaultData)
|
||||
{
|
||||
if (dynamicData != NULL)
|
||||
return dynamicData;
|
||||
else
|
||||
return defaultData;
|
||||
}
|
||||
|
||||
static u32 MysteryGiftServer_Compare(const void *a, const void *b)
|
||||
{
|
||||
if (b < a)
|
||||
return 0;
|
||||
else if (b == a)
|
||||
return 1;
|
||||
else
|
||||
return 2;
|
||||
}
|
||||
|
||||
static u32 Server_Init(struct MysteryGiftServer * svr)
|
||||
{
|
||||
svr->funcId = FUNC_RUN;
|
||||
return SVR_RET_INIT;
|
||||
}
|
||||
|
||||
static u32 Server_Done(struct MysteryGiftServer * svr)
|
||||
{
|
||||
return SVR_RET_END;
|
||||
}
|
||||
|
||||
static u32 Server_Recv(struct MysteryGiftServer * svr)
|
||||
{
|
||||
if (MysteryGiftLink_Recv(&svr->manager))
|
||||
svr->funcId = FUNC_RUN;
|
||||
return SVR_RET_ACTIVE;
|
||||
}
|
||||
|
||||
static u32 Server_Send(struct MysteryGiftServer * svr)
|
||||
{
|
||||
if (MysteryGiftLink_Send(&svr->manager))
|
||||
svr->funcId = FUNC_RUN;
|
||||
return SVR_RET_ACTIVE;
|
||||
}
|
||||
|
||||
static u32 Server_Run(struct MysteryGiftServer * svr)
|
||||
{
|
||||
// process command
|
||||
const struct MysteryGiftServerCmd * cmd = &svr->script[svr->cmdidx];
|
||||
const void *ptr;
|
||||
svr->cmdidx++;
|
||||
|
||||
switch (cmd->instr)
|
||||
{
|
||||
case SVR_RETURN:
|
||||
ASSERT_PTR_EMPTY(354);
|
||||
svr->funcId = FUNC_DONE;
|
||||
svr->param = cmd->param; // Set for endVal in MysteryGiftServer_Run
|
||||
break;
|
||||
case SVR_SEND:
|
||||
svr->funcId = FUNC_SEND;
|
||||
break;
|
||||
case SVR_RECV:
|
||||
ASSERT_PTR_EMPTY(364);
|
||||
MysteryGiftLink_InitRecv(&svr->manager, cmd->param, svr->recvBuffer);
|
||||
svr->funcId = FUNC_RECV;
|
||||
break;
|
||||
case SVR_GOTO:
|
||||
ASSERT_PARAM_EMPTY(370);
|
||||
svr->cmdidx = 0;
|
||||
svr->script = cmd->ptr;
|
||||
break;
|
||||
case SVR_COPY_GAME_DATA:
|
||||
ASSERT_PARAM_EMPTY(376);
|
||||
ASSERT_PTR_EMPTY(377);
|
||||
memcpy(svr->linkGameData, svr->recvBuffer, sizeof(*svr->linkGameData));
|
||||
break;
|
||||
case SVR_CHECK_GAME_DATA:
|
||||
ASSERT_PARAM_EMPTY(382);
|
||||
ASSERT_PTR_EMPTY(383);
|
||||
svr->param = MysteryGift_ValidateLinkGameData(svr->linkGameData);
|
||||
break;
|
||||
case SVR_GOTO_IF_EQ:
|
||||
if (svr->param == cmd->param)
|
||||
{
|
||||
svr->cmdidx = 0;
|
||||
svr->script = cmd->ptr;
|
||||
}
|
||||
break;
|
||||
case SVR_CHECK_EXISTING_CARD:
|
||||
ASSERT_PARAM_EMPTY(396);
|
||||
ptr = MysteryGiftServer_GetSendData(cmd->ptr, svr->card);
|
||||
svr->param = MysteryGift_CompareCardFlags(ptr, svr->linkGameData, ptr);
|
||||
break;
|
||||
case SVR_READ_RESPONSE:
|
||||
ASSERT_PARAM_EMPTY(402);
|
||||
ASSERT_PTR_EMPTY(403);
|
||||
svr->param = *(u32 *)svr->recvBuffer;
|
||||
break;
|
||||
case SVR_CHECK_EXISTING_STAMPS:
|
||||
ASSERT_PARAM_EMPTY(408);
|
||||
ptr = MysteryGiftServer_GetSendData(cmd->ptr, &svr->stamp);
|
||||
svr->param = MysteryGift_CheckStamps(ptr, svr->linkGameData, ptr);
|
||||
break;
|
||||
case SVR_GET_CARD_STAT:
|
||||
ASSERT_PTR_EMPTY(415);
|
||||
svr->param = MysteryGift_GetCardStatFromLinkData(svr->linkGameData, cmd->param);
|
||||
break;
|
||||
case SVR_CHECK_QUESTIONNAIRE:
|
||||
ASSERT_PARAM_EMPTY(420);
|
||||
svr->param = MysteryGift_DoesQuestionnaireMatch(svr->linkGameData, cmd->ptr);
|
||||
break;
|
||||
case SVR_COMPARE:
|
||||
ASSERT_PARAM_EMPTY(426);
|
||||
svr->param = MysteryGiftServer_Compare(cmd->ptr, *(void **)svr->recvBuffer);
|
||||
break;
|
||||
case SVR_LOAD_NEWS:
|
||||
ASSERT_PARAM_EMPTY(432);
|
||||
MysteryGiftServer_InitSend(svr, MG_LINKID_NEWS, MysteryGiftServer_GetSendData(cmd->ptr, svr->news), sizeof(struct WonderNews));
|
||||
break;
|
||||
case SVR_LOAD_CARD:
|
||||
ASSERT_PARAM_EMPTY(438);
|
||||
MysteryGiftServer_InitSend(svr, MG_LINKID_CARD, MysteryGiftServer_GetSendData(cmd->ptr, svr->card), sizeof(struct WonderCard));
|
||||
break;
|
||||
case SVR_LOAD_STAMP:
|
||||
ASSERT_PARAM_EMPTY(444);
|
||||
MysteryGiftServer_InitSend(svr, MG_LINKID_STAMP, MysteryGiftServer_GetSendData(cmd->ptr, &svr->stamp), sizeof(svr->stamp));
|
||||
break;
|
||||
case SVR_LOAD_RAM_SCRIPT:
|
||||
if (cmd->ptr == NULL)
|
||||
MysteryGiftServer_InitSend(svr, MG_LINKID_RAM_SCRIPT, svr->ramScript, svr->ramScriptSize);
|
||||
else
|
||||
MysteryGiftServer_InitSend(svr, MG_LINKID_RAM_SCRIPT, cmd->ptr, cmd->param);
|
||||
break;
|
||||
case SVR_LOAD_CLIENT_SCRIPT:
|
||||
if (cmd->ptr == NULL)
|
||||
MysteryGiftServer_InitSend(svr, MG_LINKID_CLIENT_SCRIPT, svr->clientScript, svr->clientScriptSize);
|
||||
else
|
||||
MysteryGiftServer_InitSend(svr, MG_LINKID_CLIENT_SCRIPT, cmd->ptr, cmd->param);
|
||||
break;
|
||||
case SVR_LOAD_EREADER_TRAINER:
|
||||
ASSERT_PARAM_EMPTY(466);
|
||||
MysteryGiftServer_InitSend(svr, MG_LINKID_EREADER_TRAINER, cmd->ptr, sizeof(struct BattleTowerEReaderTrainer));
|
||||
break;
|
||||
case SVR_LOAD_MSG:
|
||||
MysteryGiftServer_InitSend(svr, MG_LINKID_DYNAMIC_MSG, cmd->ptr, cmd->param);
|
||||
break;
|
||||
case SVR_LOAD_UNK_2:
|
||||
MysteryGiftServer_InitSend(svr, MG_LINKID_UNK_2, cmd->ptr, cmd->param);
|
||||
break;
|
||||
case SVR_COPY_CARD:
|
||||
ASSERT_PARAM_EMPTY(481);
|
||||
memcpy(svr->card, cmd->ptr, sizeof(*svr->card));
|
||||
break;
|
||||
case SVR_COPY_NEWS:
|
||||
ASSERT_PARAM_EMPTY(486);
|
||||
memcpy(svr->news, cmd->ptr, sizeof(*svr->news));
|
||||
break;
|
||||
case SVR_COPY_STAMP:
|
||||
ASSERT_PARAM_EMPTY(491);
|
||||
svr->stamp = *(u32 *)cmd->ptr;
|
||||
break;
|
||||
case SVR_SET_RAM_SCRIPT:
|
||||
svr->ramScript = cmd->ptr;
|
||||
svr->ramScriptSize = cmd->param;
|
||||
break;
|
||||
case SVR_SET_CLIENT_SCRIPT:
|
||||
svr->clientScript = cmd->ptr;
|
||||
svr->clientScriptSize = cmd->param;
|
||||
break;
|
||||
case SVR_COPY_SAVED_CARD:
|
||||
ASSERT_PTR_PARAM_EMPTY(506);
|
||||
memcpy(svr->card, GetSavedWonderCard(), sizeof(*svr->card));
|
||||
DisableWonderCardSending(svr->card);
|
||||
break;
|
||||
case SVR_COPY_SAVED_NEWS:
|
||||
ASSERT_PTR_PARAM_EMPTY(512);
|
||||
memcpy(svr->news, GetSavedWonderNews(), sizeof(*svr->news));
|
||||
break;
|
||||
case SVR_COPY_SAVED_RAM_SCRIPT:
|
||||
ASSERT_PTR_PARAM_EMPTY(517);
|
||||
svr->ramScript = GetSavedRamScriptIfValid();
|
||||
break;
|
||||
case SVR_LOAD_UNK_1:
|
||||
MysteryGiftServer_InitSend(svr, MG_LINKID_UNK_1, cmd->ptr, cmd->param);
|
||||
break;
|
||||
}
|
||||
|
||||
return SVR_RET_ACTIVE;
|
||||
}
|
||||
|
||||
static u32 (*const sFuncTable[])(struct MysteryGiftServer *) = {
|
||||
[FUNC_INIT] = Server_Init,
|
||||
[FUNC_DONE] = Server_Done,
|
||||
[FUNC_RECV] = Server_Recv,
|
||||
[FUNC_SEND] = Server_Send,
|
||||
[FUNC_RUN] = Server_Run
|
||||
};
|
||||
|
||||
static u32 MysteryGiftServer_CallFunc(struct MysteryGiftServer * svr)
|
||||
{
|
||||
u32 response;
|
||||
ASSERT_VALID_FUNC(546)
|
||||
response = sFuncTable[svr->funcId](svr);
|
||||
ASSERT_VALID_FUNC(548)
|
||||
return response;
|
||||
}
|
||||
@@ -5,7 +5,7 @@
|
||||
#include "new_menu_helpers.h"
|
||||
#include "pokemon_icon.h"
|
||||
#include "mystery_gift_menu.h"
|
||||
#include "mevent.h"
|
||||
#include "mystery_gift.h"
|
||||
#include "battle_anim.h"
|
||||
#include "constants/mystery_gift.h"
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#include "gflib.h"
|
||||
#include "menu_indicators.h"
|
||||
#include "new_menu_helpers.h"
|
||||
#include "mevent.h"
|
||||
#include "mystery_gift.h"
|
||||
#include "mystery_gift_menu.h"
|
||||
#include "menu.h"
|
||||
#include "link_rfu.h"
|
||||
|
||||
+2
-2
@@ -22,7 +22,7 @@
|
||||
#include "berry.h"
|
||||
#include "easy_chat.h"
|
||||
#include "union_room_chat.h"
|
||||
#include "mevent.h"
|
||||
#include "mystery_gift.h"
|
||||
#include "renewable_hidden_items.h"
|
||||
#include "trainer_tower.h"
|
||||
#include "script.h"
|
||||
@@ -143,7 +143,7 @@ void NewGameInitData(void)
|
||||
ResetTrainerFanClub();
|
||||
UnionRoomChat_InitializeRegisteredTexts();
|
||||
ResetMiniGamesResults();
|
||||
InitMEventData();
|
||||
ClearMysteryGift();
|
||||
SetAllRenewableItemFlags();
|
||||
WarpToPlayersRoom();
|
||||
RunScriptImmediately(EventScript_ResetAllMapFlags);
|
||||
|
||||
+2
-2
@@ -2,12 +2,12 @@
|
||||
#include "script.h"
|
||||
#include "event_data.h"
|
||||
#include "quest_log.h"
|
||||
#include "mystery_gift.h"
|
||||
#include "constants/maps.h"
|
||||
#include "constants/map_scripts.h"
|
||||
|
||||
extern void ResetContextNpcTextColor(void); // field_specials
|
||||
extern u16 CalcCRC16WithTable(u8 *data, int length); // util
|
||||
extern bool32 ValidateReceivedWonderCard(void); // mevent
|
||||
|
||||
#define RAM_SCRIPT_MAGIC 51
|
||||
|
||||
@@ -554,7 +554,7 @@ bool32 ValidateRamScript(void)
|
||||
u8 *GetSavedRamScriptIfValid(void)
|
||||
{
|
||||
struct RamScriptData *scriptData = &gSaveBlock1Ptr->ramScript.data;
|
||||
if (!ValidateReceivedWonderCard())
|
||||
if (!ValidateSavedWonderCard())
|
||||
return NULL;
|
||||
if (scriptData->magic != RAM_SCRIPT_MAGIC)
|
||||
return NULL;
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
#include "trade.h"
|
||||
#include "link.h"
|
||||
#include "link_rfu.h"
|
||||
#include "mevent.h"
|
||||
#include "mystery_gift.h"
|
||||
#include "graphics.h"
|
||||
#include "strings.h"
|
||||
#include "menu.h"
|
||||
|
||||
+1
-1
@@ -20,7 +20,7 @@
|
||||
#include "list_menu.h"
|
||||
#include "load_save.h"
|
||||
#include "menu.h"
|
||||
#include "mevent.h"
|
||||
#include "mystery_gift.h"
|
||||
#include "mystery_gift_menu.h"
|
||||
#include "new_menu_helpers.h"
|
||||
#include "overworld.h"
|
||||
|
||||
+14
-13
@@ -1,6 +1,7 @@
|
||||
#include "global.h"
|
||||
#include "link_rfu.h"
|
||||
#include "mevent_server.h"
|
||||
#include "mystery_gift_server.h"
|
||||
#include "mystery_gift_client.h"
|
||||
#include "constants/union_room.h"
|
||||
|
||||
ALIGNED(4) const u8 gText_UR_EmptyString[] = _("");
|
||||
@@ -558,18 +559,18 @@ const u8 *const gTexts_UR_GladToMeetYou[GENDER_COUNT] = {
|
||||
ALIGNED(4) const u8 gText_UR_FinishedCheckingPlayersTrainerCard[] = _("Finished checking {SPECIAL_F7 0x01}'s\nTRAINER CARD.{PAUSE 60}");
|
||||
ALIGNED(4) static const u8 sText_CanceledReadingCard[] = _("Canceled reading the Card.");
|
||||
|
||||
static const struct mevent_client_cmd sClientScript_DynamicError[] = {
|
||||
CLI_RECEIVE(0x15),
|
||||
CLI_RECVBUF,
|
||||
CLI_SENDALL,
|
||||
CLI_RETURN(0x0e)
|
||||
static const struct MysteryGiftClientCmd sClientScript_DynamicError[] = {
|
||||
{CLI_RECV, MG_LINKID_DYNAMIC_MSG},
|
||||
{CLI_COPY_MSG},
|
||||
{CLI_SEND_READY_END},
|
||||
{CLI_RETURN, CLI_MSG_BUFFER_FAILURE}
|
||||
};
|
||||
|
||||
const struct mevent_server_cmd gServerScript_ClientCanceledCard[] = {
|
||||
SRV_SEND(0x20, sClientScript_DynamicError),
|
||||
SRV_WAITSND,
|
||||
SRV_SENDSTR(0x1b, sText_CanceledReadingCard),
|
||||
SRV_WAITSND,
|
||||
SRV_RECV(0x14),
|
||||
SRV_RETURN(0x09)
|
||||
const struct MysteryGiftServerCmd gServerScript_ClientCanceledCard[] = {
|
||||
{SVR_LOAD_CLIENT_SCRIPT, PTR_ARG(sClientScript_DynamicError)},
|
||||
{SVR_SEND},
|
||||
{SVR_LOAD_MSG, PTR_ARG(sText_CanceledReadingCard)},
|
||||
{SVR_SEND},
|
||||
{SVR_RECV, MG_LINKID_READY_END},
|
||||
{SVR_RETURN, SVR_MSG_CLIENT_CANCELED}
|
||||
};
|
||||
|
||||
@@ -0,0 +1,154 @@
|
||||
#include "global.h"
|
||||
#include "mystery_gift.h"
|
||||
#include "random.h"
|
||||
#include "event_data.h"
|
||||
#include "wonder_news.h"
|
||||
#include "constants/items.h"
|
||||
|
||||
// Every 4th reward for sending Wonder News to a link partner is a "big" reward.
|
||||
#define MAX_SENT_REWARD 4
|
||||
|
||||
// Only up to 5 rewards can be received in a short period. After this the player
|
||||
// must take 500 steps before any more rewards can be received.
|
||||
#define MAX_REWARD 5
|
||||
|
||||
static u32 GetRewardItem(struct WonderNewsMetadata *);
|
||||
static u32 GetRewardType(struct WonderNewsMetadata *);
|
||||
static void IncrementRewardCounter(struct WonderNewsMetadata *);
|
||||
static void IncrementSentRewardCounter(struct WonderNewsMetadata *);
|
||||
static void ResetSentRewardCounter(struct WonderNewsMetadata *);
|
||||
|
||||
void WonderNews_SetReward(u32 newsType)
|
||||
{
|
||||
struct WonderNewsMetadata *data = GetSavedWonderNewsMetadata();
|
||||
|
||||
data->newsType = newsType;
|
||||
switch (newsType)
|
||||
{
|
||||
case WONDER_NEWS_NONE:
|
||||
break;
|
||||
case WONDER_NEWS_RECV_FRIEND:
|
||||
case WONDER_NEWS_RECV_WIRELESS:
|
||||
// Random berry between ITEM_RAZZ_BERRY and ITEM_NOMEL_BERRY
|
||||
data->berry = (Random() % 15) + ITEM_TO_BERRY(ITEM_RAZZ_BERRY);
|
||||
break;
|
||||
case WONDER_NEWS_SENT:
|
||||
// Random berry between ITEM_CHERI_BERRY and ITEM_IAPAPA_BERRY
|
||||
data->berry = (Random() % 15) + ITEM_TO_BERRY(ITEM_CHERI_BERRY);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void WonderNews_Reset(void)
|
||||
{
|
||||
struct WonderNewsMetadata *data = GetSavedWonderNewsMetadata();
|
||||
|
||||
data->newsType = WONDER_NEWS_NONE;
|
||||
data->sentRewardCounter = 0;
|
||||
data->rewardCounter = 0;
|
||||
data->berry = 0;
|
||||
VarSet(VAR_WONDER_NEWS_STEP_COUNTER, 0);
|
||||
}
|
||||
|
||||
void WonderNews_IncrementStepCounter(void)
|
||||
{
|
||||
u16 *stepCounter = GetVarPointer(VAR_WONDER_NEWS_STEP_COUNTER);
|
||||
struct WonderNewsMetadata *data = GetSavedWonderNewsMetadata();
|
||||
|
||||
// If the player has reached the reward limit, start counting steps.
|
||||
// When they reach 500 steps reset the reward counter to allow them to
|
||||
// receive rewards again.
|
||||
if (data->rewardCounter >= MAX_REWARD && ++(*stepCounter) >= 500)
|
||||
{
|
||||
data->rewardCounter = 0;
|
||||
*stepCounter = 0;
|
||||
}
|
||||
}
|
||||
|
||||
u16 WonderNews_GetRewardInfo(void)
|
||||
{
|
||||
u16 *result = &gSpecialVar_Result;
|
||||
struct WonderNewsMetadata *data = GetSavedWonderNewsMetadata();
|
||||
u16 rewardType;
|
||||
|
||||
if (!IsMysteryGiftEnabled() || !ValidateSavedWonderNews())
|
||||
return NEWS_REWARD_NONE;
|
||||
|
||||
rewardType = GetRewardType(data);
|
||||
|
||||
switch (rewardType)
|
||||
{
|
||||
case NEWS_REWARD_RECV_SMALL:
|
||||
case NEWS_REWARD_RECV_BIG:
|
||||
*result = GetRewardItem(data);
|
||||
break;
|
||||
case NEWS_REWARD_SENT_SMALL:
|
||||
*result = GetRewardItem(data);
|
||||
IncrementSentRewardCounter(data);
|
||||
break;
|
||||
case NEWS_REWARD_SENT_BIG:
|
||||
*result = GetRewardItem(data);
|
||||
ResetSentRewardCounter(data);
|
||||
break;
|
||||
case NEWS_REWARD_NONE:
|
||||
case NEWS_REWARD_WAITING:
|
||||
case NEWS_REWARD_AT_MAX:
|
||||
break;
|
||||
}
|
||||
|
||||
return rewardType;
|
||||
}
|
||||
|
||||
static u32 GetRewardItem(struct WonderNewsMetadata *data)
|
||||
{
|
||||
u32 itemId;
|
||||
|
||||
data->newsType = WONDER_NEWS_NONE;
|
||||
itemId = data->berry + FIRST_BERRY_INDEX - 1;
|
||||
data->berry = 0;
|
||||
IncrementRewardCounter(data);
|
||||
return itemId;
|
||||
}
|
||||
|
||||
static void ResetSentRewardCounter(struct WonderNewsMetadata *data)
|
||||
{
|
||||
data->sentRewardCounter = 0;
|
||||
}
|
||||
|
||||
// Track number of times a reward was received (or attmepted to receive) for sending Wonder News to a link partner.
|
||||
static void IncrementSentRewardCounter(struct WonderNewsMetadata *data)
|
||||
{
|
||||
data->sentRewardCounter++;
|
||||
if (data->sentRewardCounter > MAX_SENT_REWARD)
|
||||
data->sentRewardCounter = MAX_SENT_REWARD;
|
||||
}
|
||||
|
||||
static void IncrementRewardCounter(struct WonderNewsMetadata *data)
|
||||
{
|
||||
data->rewardCounter++;
|
||||
if (data->rewardCounter > MAX_REWARD)
|
||||
data->rewardCounter = MAX_REWARD;
|
||||
}
|
||||
|
||||
static u32 GetRewardType(struct WonderNewsMetadata *data)
|
||||
{
|
||||
if (data->rewardCounter == MAX_REWARD)
|
||||
return NEWS_REWARD_AT_MAX;
|
||||
|
||||
switch (data->newsType)
|
||||
{
|
||||
case WONDER_NEWS_NONE:
|
||||
return NEWS_REWARD_WAITING;
|
||||
case WONDER_NEWS_RECV_FRIEND:
|
||||
return NEWS_REWARD_RECV_SMALL;
|
||||
case WONDER_NEWS_RECV_WIRELESS:
|
||||
return NEWS_REWARD_RECV_BIG;
|
||||
case WONDER_NEWS_SENT:
|
||||
if (data->sentRewardCounter < MAX_SENT_REWARD - 1)
|
||||
return NEWS_REWARD_SENT_SMALL;
|
||||
return NEWS_REWARD_SENT_BIG;
|
||||
default:
|
||||
AGB_ASSERT_EX(0, ABSPATH("menews_jisan.c"), 383);
|
||||
return NEWS_REWARD_NONE;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user