Merge pull request #586 from GriffinRichards/sync-mevent

Sync mystery gift
This commit is contained in:
GriffinR
2022-11-26 11:34:59 -05:00
committed by GitHub
59 changed files with 3401 additions and 3126 deletions
+1 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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;
+520
View File
@@ -0,0 +1,520 @@
#include "global.h"
#include "malloc.h"
#include "decompress.h"
#include "ereader_helpers.h"
#include "link.h"
#include "main.h"
#include "mystery_gift_menu.h"
#include "mystery_gift_client.h"
#include "save.h"
#include "sound.h"
#include "sprite.h"
#include "task.h"
#include "strings.h"
#include "util.h"
#include "cereader_tool.h"
#include "help_system.h"
#include "constants/songs.h"
struct EReaderTaskData
{
u16 timer;
u16 unused1;
u16 unused2;
u16 unused3;
u8 state;
u8 textState;
u8 unused4;
u8 unused5;
u8 unused6;
u8 unused7;
u8 status;
u8 *unusedBuffer;
};
struct EReaderData
{
u16 status;
size_t size;
const void *data;
};
static void Task_EReader(u8);
struct EReaderData gEReaderData;
extern const u8 gMultiBootProgram_EReader_Start[];
extern const u8 gMultiBootProgram_EReader_End[];
static void EReader_Load(struct EReaderData *eReader, size_t size, const void *data)
{
vu16 imeBak = REG_IME;
REG_IME = 0;
gIntrTable[1] = EReaderHelper_SerialCallback;
gIntrTable[2] = EReaderHelper_Timer3Callback;
EReaderHelper_SaveRegsState();
EReaderHelper_ClearsSendRecvMgr();
REG_IE |= INTR_FLAG_VCOUNT;
REG_IME = imeBak;
eReader->status = 0;
eReader->size = size;
eReader->data = data;
}
static void EReader_Reset(struct EReaderData *eReader)
{
vu16 imeBak = REG_IME;
REG_IME = 0;
EReaderHelper_ClearsSendRecvMgr();
EReaderHelper_RestoreRegsState();
RestoreSerialTimer3IntrHandlers();
REG_IME = imeBak;
}
// Return values for EReader_Transfer
enum {
TRANSFER_ACTIVE,
TRANSFER_SUCCESS,
TRANSFER_CANCELED,
TRANSFER_TIMEOUT,
};
static u8 EReader_Transfer(struct EReaderData *eReader)
{
u8 transferStatus = TRANSFER_ACTIVE;
eReader->status = EReaderHandleTransfer(TRUE, eReader->size, eReader->data, NULL);
if ((eReader->status & EREADER_XFER_MASK) == 0 && eReader->status & EREADER_CHECKSUM_OK_MASK)
transferStatus = TRANSFER_SUCCESS;
if (eReader->status & EREADER_CANCEL_KEY_MASK)
transferStatus = TRANSFER_CANCELED;
if (eReader->status & EREADER_CANCEL_TIMEOUT_MASK)
transferStatus = TRANSFER_TIMEOUT;
gShouldAdvanceLinkState = 0;
return transferStatus;
}
static void OpenEReaderLink(void)
{
memset(gDecompressionBuffer, 0, 0x2000);
gLinkType = LINKTYPE_EREADER_FRLG;
OpenLink();
SetSuppressLinkErrorMessage(TRUE);
}
static bool32 ValidateEReaderConnection(void)
{
vu16 imeBak = REG_IME;
u16 handshakes[MAX_LINK_PLAYERS];
REG_IME = 0;
*(u64 *)handshakes = *(u64 *)gLink.tempRecvBuffer;
REG_IME = imeBak;
// Validate that we are player 1, the EReader is player 2,
// and that players 3 and 4 are empty.
if (handshakes[0] == SLAVE_HANDSHAKE
&& handshakes[1] == EREADER_HANDSHAKE
&& handshakes[2] == 0xFFFF
&& handshakes[3] == 0xFFFF)
return TRUE;
return FALSE;
}
static bool32 IsEReaderConnectionSane(void)
{
if (IsLinkMaster() && GetLinkPlayerCount_2() == 2)
return TRUE;
return FALSE;
}
// States for TryReceiveCard
enum {
RECV_STATE_INIT,
RECV_STATE_WAIT_START,
RECV_STATE_START,
RECV_STATE_EXCHANGE,
RECV_STATE_START_DISCONNECT,
RECV_STATE_WAIT_DISCONNECT,
};
// Return values for TryReceiveCard
enum {
RECV_ACTIVE,
RECV_CANCELED,
RECV_SUCCESS,
RECV_ERROR,
RECV_DISCONNECTED,
RECV_TIMEOUT,
};
static u32 TryReceiveCard(u8 * state, u16 * timer)
{
if ((*state == RECV_STATE_EXCHANGE
|| *state == RECV_STATE_START_DISCONNECT
|| *state == RECV_STATE_WAIT_DISCONNECT)
&& HasLinkErrorOccurred())
{
// Return error status if an error occurs
// during the link exchange.
*state = 0;
return RECV_ERROR;
}
switch (*state)
{
case RECV_STATE_INIT:
if (IsLinkMaster() && GetLinkPlayerCount_2() > 1)
{
*state = RECV_STATE_WAIT_START;
}
else if (JOY_NEW(B_BUTTON))
{
*state = 0;
return RECV_CANCELED;
}
break;
case RECV_STATE_WAIT_START:
if (++(*timer) > 5)
{
*timer = 0;
*state = RECV_STATE_START;
}
break;
case RECV_STATE_START:
if (GetLinkPlayerCount_2() == 2)
{
PlaySE(SE_DING_DONG);
CheckShouldAdvanceLinkState();
*timer = 0;
*state = RECV_STATE_EXCHANGE;
}
else if (JOY_NEW(B_BUTTON))
{
*state = 0;
return RECV_CANCELED;
}
break;
case RECV_STATE_EXCHANGE:
if (++(*timer) > 30)
{
*state = 0;
return RECV_TIMEOUT;
}
if (IsLinkConnectionEstablished())
{
if (gReceivedRemoteLinkPlayers)
{
if (IsLinkPlayerDataExchangeComplete())
{
*state = 0;
return RECV_SUCCESS;
}
else
*state = RECV_STATE_START_DISCONNECT;
}
else
*state = RECV_STATE_EXCHANGE;
}
break;
case RECV_STATE_START_DISCONNECT:
SetCloseLinkCallbackAndType(0);
*state = RECV_STATE_WAIT_DISCONNECT;
break;
case RECV_STATE_WAIT_DISCONNECT:
if (!gReceivedRemoteLinkPlayers)
{
*state = 0;
return RECV_DISCONNECTED;
}
break;
}
return RECV_ACTIVE;
}
void CreateEReaderTask(void)
{
u8 taskId = CreateTask(Task_EReader, 0);
struct EReaderTaskData *data = (struct EReaderTaskData *)gTasks[taskId].data;
data->state = 0;
data->textState = 0;
data->unused4 = 0;
data->unused5 = 0;
data->unused6 = 0;
data->unused7 = 0;
data->timer = 0;
data->unused1 = 0;
data->unused2 = 0;
data->unused3 = 0;
data->status = 0;
data->unusedBuffer = AllocZeroed(CLIENT_MAX_MSG_SIZE);
}
static void ResetTimer(u16 *timer)
{
*timer = 0;
}
static bool32 UpdateTimer(u16 * timer, u16 time)
{
if (++(*timer) > time)
{
// Timer has finished
*timer = 0;
return TRUE;
}
return FALSE;
}
// States for Task_EReader
enum {
ER_STATE_START,
ER_STATE_INIT_LINK,
ER_STATE_INIT_LINK_WAIT,
ER_STATE_INIT_LINK_CHECK,
ER_STATE_MSG_SELECT_CONNECT,
ER_STATE_MSG_SELECT_CONNECT_WAIT,
ER_STATE_TRY_LINK,
ER_STATE_INCORRECT_LINK,
ER_STATE_CONNECTING,
ER_STATE_TRANSFER,
ER_STATE_TRANSFER_END,
ER_STATE_TRANSFER_SUCCESS,
ER_STATE_LOAD_CARD_START,
ER_STATE_LOAD_CARD,
ER_STATE_WAIT_RECV_CARD,
ER_STATE_VALIDATE_CARD,
ER_STATE_WAIT_DISCONNECT,
ER_STATE_SAVE,
ER_STATE_SUCCESS_MSG,
ER_STATE_SUCCESS_END,
ER_STATE_LINK_ERROR,
ER_STATE_LINK_ERROR_TRY_AGAIN,
ER_STATE_SAVE_FAILED,
ER_STATE_CANCELED_CARD_READ,
ER_STATE_UNUSED_1,
ER_STATE_UNUSED_2,
ER_STATE_END,
};
static void Task_EReader(u8 taskId)
{
struct EReaderTaskData *data = (struct EReaderTaskData *)gTasks[taskId].data;
switch (data->state)
{
case ER_STATE_START:
if (PrintMysteryGiftMenuMessage(&data->textState, gJPText_ReceiveMysteryGiftWithEReader))
data->state = ER_STATE_INIT_LINK;
break;
case ER_STATE_INIT_LINK:
OpenEReaderLink();
ResetTimer(&data->timer);
data->state = ER_STATE_INIT_LINK_WAIT;
break;
case ER_STATE_INIT_LINK_WAIT:
if (UpdateTimer(&data->timer, 10))
data->state = ER_STATE_INIT_LINK_CHECK;
break;
case ER_STATE_INIT_LINK_CHECK:
if (!IsEReaderConnectionSane())
{
CloseLink();
data->state = ER_STATE_MSG_SELECT_CONNECT;
}
else
data->state = ER_STATE_LOAD_CARD;
break;
case ER_STATE_MSG_SELECT_CONNECT:
if (PrintMysteryGiftMenuMessage(&data->textState, gJPText_SelectConnectFromEReaderMenu))
{
AddTextPrinterToWindow1(gJPText_SelectConnectWithGBA);
ResetTimer(&data->timer);
data->state = ER_STATE_MSG_SELECT_CONNECT_WAIT;
}
break;
case ER_STATE_MSG_SELECT_CONNECT_WAIT:
if (UpdateTimer(&data->timer, 90))
{
OpenEReaderLink();
data->state = ER_STATE_TRY_LINK;
}
else if (JOY_NEW(B_BUTTON))
{
ResetTimer(&data->timer);
PlaySE(SE_SELECT);
data->state = ER_STATE_CANCELED_CARD_READ;
}
break;
case ER_STATE_TRY_LINK:
if (JOY_NEW(B_BUTTON))
{
// Canceled
PlaySE(SE_SELECT);
CloseLink();
ResetTimer(&data->timer);
data->state = ER_STATE_CANCELED_CARD_READ;
}
else if (GetLinkPlayerCount_2() > 1)
{
ResetTimer(&data->timer);
CloseLink();
data->state = ER_STATE_INCORRECT_LINK;
}
else if (ValidateEReaderConnection())
{
// Successful connection
PlaySE(SE_SELECT);
CloseLink();
ResetTimer(&data->timer);
data->state = ER_STATE_CONNECTING;
}
else if (UpdateTimer(&data->timer, 10))
{
// Retry connection
CloseLink();
OpenEReaderLink();
ResetTimer(&data->timer);
}
break;
case ER_STATE_INCORRECT_LINK:
if (PrintMysteryGiftMenuMessage(&data->textState, gJPText_LinkIsIncorrect))
data->state = ER_STATE_MSG_SELECT_CONNECT;
break;
case ER_STATE_CONNECTING:
AddTextPrinterToWindow1(gJPText_Connecting);
EReader_Load(&gEReaderData, gMultiBootProgram_EReader_End - gMultiBootProgram_EReader_Start, gMultiBootProgram_EReader_Start);
data->state = ER_STATE_TRANSFER;
break;
case ER_STATE_TRANSFER:
data->status = EReader_Transfer(&gEReaderData);
if (data->status != TRANSFER_ACTIVE)
data->state = ER_STATE_TRANSFER_END;
break;
case ER_STATE_TRANSFER_END:
EReader_Reset(&gEReaderData);
if (data->status == TRANSFER_TIMEOUT)
{
data->state = ER_STATE_LINK_ERROR;
}
else if (data->status == TRANSFER_SUCCESS)
{
ResetTimer(&data->timer);
AddTextPrinterToWindow1(gJPText_PleaseWaitAMoment);
data->state = ER_STATE_TRANSFER_SUCCESS;
}
else // TRANSFER_CANCELED
{
data->state = ER_STATE_START;
}
break;
case ER_STATE_TRANSFER_SUCCESS:
if (UpdateTimer(&data->timer, 840))
data->state = ER_STATE_LOAD_CARD_START;
break;
case ER_STATE_LOAD_CARD_START:
OpenEReaderLink();
AddTextPrinterToWindow1(gJPText_AllowEReaderToLoadCard);
data->state = ER_STATE_LOAD_CARD;
break;
case ER_STATE_LOAD_CARD:
switch (TryReceiveCard(&data->textState, &data->timer))
{
case RECV_ACTIVE:
// Running
break;
case RECV_SUCCESS:
AddTextPrinterToWindow1(gJPText_Connecting);
data->state = ER_STATE_WAIT_RECV_CARD;
break;
case RECV_CANCELED:
PlaySE(SE_SELECT);
CloseLink();
data->state = ER_STATE_CANCELED_CARD_READ;
break;
case RECV_TIMEOUT:
CloseLink();
data->state = ER_STATE_LINK_ERROR_TRY_AGAIN;
break;
case RECV_ERROR:
case RECV_DISCONNECTED:
CloseLink();
data->state = ER_STATE_LINK_ERROR;
break;
}
break;
case ER_STATE_WAIT_RECV_CARD:
if (HasLinkErrorOccurred())
{
CloseLink();
data->state = ER_STATE_LINK_ERROR;
}
else if (GetBlockReceivedStatus())
{
ResetBlockReceivedFlags();
data->state = ER_STATE_VALIDATE_CARD;
}
break;
case ER_STATE_VALIDATE_CARD:
data->status = ValidateTrainerTowerData((struct EReaderTrainerTowerSet *)gDecompressionBuffer);
SetCloseLinkCallbackAndType(data->status);
data->state = ER_STATE_WAIT_DISCONNECT;
break;
case ER_STATE_WAIT_DISCONNECT:
if (!gReceivedRemoteLinkPlayers)
{
if (data->status == TRUE) // Was data valid?
data->state = ER_STATE_SAVE;
else
data->state = ER_STATE_LINK_ERROR;
}
break;
case ER_STATE_SAVE:
if (CEReaderTool_SaveTrainerTower((struct EReaderTrainerTowerSet *)gDecompressionBuffer))
{
AddTextPrinterToWindow1(gJPText_ConnectionComplete);
ResetTimer(&data->timer);
data->state = ER_STATE_SUCCESS_MSG;
}
else
data->state = ER_STATE_SAVE_FAILED;
break;
case ER_STATE_SUCCESS_MSG:
if (UpdateTimer(&data->timer, 120))
{
AddTextPrinterToWindow1(gJPText_NewTrainerHasComeToSevii);
PlayFanfare(MUS_OBTAIN_ITEM);
data->state = ER_STATE_SUCCESS_END;
}
break;
case ER_STATE_SUCCESS_END:
if (IsFanfareTaskInactive() && JOY_NEW(A_BUTTON | B_BUTTON))
data->state = ER_STATE_END;
break;
case ER_STATE_CANCELED_CARD_READ:
if (PrintMysteryGiftMenuMessage(&data->textState, gJPText_CardReadingHasBeenHalted))
data->state = ER_STATE_END;
break;
case ER_STATE_LINK_ERROR:
if (PrintMysteryGiftMenuMessage(&data->textState, gJPText_ConnectionErrorCheckLink))
data->state = ER_STATE_START;
break;
case ER_STATE_LINK_ERROR_TRY_AGAIN:
if (PrintMysteryGiftMenuMessage(&data->textState, gJPText_ConnectionErrorTryAgain))
data->state = ER_STATE_START;
break;
case ER_STATE_SAVE_FAILED:
if (PrintMysteryGiftMenuMessage(&data->textState, gJPText_WriteErrorUnableToSaveData))
data->state = ER_STATE_START;
break;
case ER_STATE_END:
HelpSystem_Enable();
Free(data->unusedBuffer);
DestroyTask(taskId);
SetMainCallback2(MainCB_FreeAllBuffersAndReturnToInitTitleScreen);
break;
}
}
+2 -2
View File
@@ -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);
+2 -2
View File
@@ -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
View File
@@ -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
View File
@@ -481,7 +481,7 @@ static void Task_ExecuteMainMenuSelection(u8 taskId)
TrySetUpQuestLogScenes_ElseContinueFromSave(taskId);
break;
case MAIN_MENU_MYSTERYGIFT:
SetMainCallback2(c2_mystery_gift);
SetMainCallback2(CB2_InitMysteryGift);
HelpSystem_Disable();
FreeAllWindowBuffers();
DestroyTask(taskId);
-148
View File
@@ -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
View File
File diff suppressed because it is too large Load Diff
-290
View File
@@ -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);
}
-192
View File
@@ -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)
};
-279
View File
@@ -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;
}
-204
View File
@@ -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;
}
+634
View File
@@ -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);
}
+300
View File
@@ -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);
}
+215
View File
@@ -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
View File
File diff suppressed because it is too large Load Diff
+198
View File
@@ -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
};
+302
View File
@@ -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;
}
+1 -1
View File
@@ -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"
+1 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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}
};
+154
View File
@@ -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;
}
}