summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGriffinR <griffin.g.richards@gmail.com>2021-10-24 15:50:39 -0400
committerGitHub <noreply@github.com>2021-10-24 15:50:39 -0400
commitab802649218507237cd2c07e318ef65e1caca5fe (patch)
tree48104eb5c96c07611ba511f11fc56e9cce6404d6 /src
parent3834cc2957b27c771c59027935b0b3a86a19b273 (diff)
parent6067aa65b4d16649785f39fc2e8ff253abb34327 (diff)
Merge pull request #1519 from GriffinRichards/doc-mgift
Document Mystery Gift
Diffstat (limited to 'src')
-rw-r--r--src/cable_club.c12
-rw-r--r--src/crt0.s2
-rw-r--r--src/easy_chat.c2
-rwxr-xr-xsrc/ereader_screen.c32
-rw-r--r--src/event_data.c60
-rw-r--r--src/field_specials.c20
-rw-r--r--src/link_rfu_2.c4
-rw-r--r--src/main_menu.c8
-rwxr-xr-xsrc/mevent2.c630
-rw-r--r--src/mevent_801BAAC.c826
-rw-r--r--src/mevent_client.c291
-rw-r--r--src/mevent_news.c148
-rw-r--r--src/mevent_scripts.c191
-rw-r--r--src/mevent_server.c295
-rw-r--r--src/mevent_server_helpers.c211
-rw-r--r--src/mystery_event_msg.c22
-rw-r--r--src/mystery_event_script.c26
-rwxr-xr-x[-rw-r--r--]src/mystery_gift.c1966
-rw-r--r--src/mystery_gift_client.c303
-rw-r--r--src/mystery_gift_link.c222
-rw-r--r--src/mystery_gift_menu.c1618
-rw-r--r--src/mystery_gift_scripts.c217
-rw-r--r--src/mystery_gift_server.c291
-rw-r--r--src/mystery_gift_view.c936
-rw-r--r--src/new_game.c4
-rw-r--r--src/scrcmd.c2
-rw-r--r--src/script.c15
-rw-r--r--src/trade.c7
-rwxr-xr-xsrc/trainer_card.c34
-rw-r--r--src/union_room.c50
-rw-r--r--src/wonder_news.c160
31 files changed, 4378 insertions, 4227 deletions
diff --git a/src/cable_club.c b/src/cable_club.c
index 8db583989..3083ed9c0 100644
--- a/src/cable_club.c
+++ b/src/cable_club.c
@@ -18,7 +18,7 @@
#include "overworld.h"
#include "palette.h"
#include "union_room.h"
-#include "mevent2.h"
+#include "mystery_gift.h"
#include "script.h"
#include "script_pokemon_util.h"
#include "sound.h"
@@ -372,7 +372,7 @@ static void Task_LinkupExchangeDataWithLeader(u8 taskId)
gLocalLinkPlayerId = GetMultiplayerId();
SaveLinkPlayers(gFieldLinkPlayerCount);
card = (struct TrainerCard *)gBlockSendBuffer;
- TrainerCard_GenerateCardForPlayer(card);
+ TrainerCard_GenerateCardForLinkPlayer(card);
card->monSpecies[0] = GetMonData(&gPlayerParty[gSelectedOrderFromParty[0] - 1], MON_DATA_SPECIES, NULL);
card->monSpecies[1] = GetMonData(&gPlayerParty[gSelectedOrderFromParty[1] - 1], MON_DATA_SPECIES, NULL);
gTasks[taskId].func = Task_LinkupAwaitTrainerCardData;
@@ -420,7 +420,7 @@ static void Task_LinkupCheckStatusAfterConfirm(u8 taskId)
gLocalLinkPlayerId = GetMultiplayerId();
SaveLinkPlayers(gFieldLinkPlayerCount);
card = (struct TrainerCard *)gBlockSendBuffer;
- TrainerCard_GenerateCardForPlayer(card);
+ TrainerCard_GenerateCardForLinkPlayer(card);
card->monSpecies[0] = GetMonData(&gPlayerParty[gSelectedOrderFromParty[0] - 1], MON_DATA_SPECIES, NULL);
card->monSpecies[1] = GetMonData(&gPlayerParty[gSelectedOrderFromParty[1] - 1], MON_DATA_SPECIES, NULL);
gTasks[taskId].func = Task_LinkupAwaitTrainerCardData;
@@ -518,7 +518,7 @@ static void Task_LinkupAwaitTrainerCardData(u8 taskId)
for (index = 0; index < GetLinkPlayerCount(); index++)
{
- CopyTrainerCardData(&gTrainerCards[index], gBlockRecvBuffer[index], gLinkPlayers[index].version);
+ CopyTrainerCardData(&gTrainerCards[index], (struct TrainerCard *)gBlockRecvBuffer[index], gLinkPlayers[index].version);
}
SetSuppressLinkErrorMessage(FALSE);
@@ -1004,10 +1004,10 @@ void CB2_ReturnFromCableClubBattle(void)
switch (gBattleOutcome)
{
case B_OUTCOME_WON:
- RecordIdOfWonderCardSenderByEventType(0, gLinkPlayers[GetMultiplayerId() ^ 1].trainerId);
+ MysteryGift_TryIncrementStat(CARD_STAT_BATTLES_WON, gLinkPlayers[GetMultiplayerId() ^ 1].trainerId);
break;
case B_OUTCOME_LOST:
- RecordIdOfWonderCardSenderByEventType(1, gLinkPlayers[GetMultiplayerId() ^ 1].trainerId);
+ MysteryGift_TryIncrementStat(CARD_STAT_BATTLES_LOST, gLinkPlayers[GetMultiplayerId() ^ 1].trainerId);
break;
}
}
diff --git a/src/crt0.s b/src/crt0.s
index 835522589..672fc94f2 100644
--- a/src/crt0.s
+++ b/src/crt0.s
@@ -94,7 +94,7 @@ GPIOPortReadEnable: @ 80000C8
.byte 0x1e, 0x1e, 0x10, 0x40
- .4byte 0x0000322e @ offsetof(struct SaveBlock1, ? part-way into unk_322C)
+ .4byte 0x0000322e @ offsetof(struct SaveBlock1, ? part-way into mysteryGift)
.4byte 0x00000498 @ offsetof(struct SaveBlock1, pcItems)
.4byte 0x000031a8 @ offsetof(struct SaveBlock1, giftRibbons)
.4byte 0x000031f8 @ offsetof(struct SaveBlock1, enigmaBerry)
diff --git a/src/easy_chat.c b/src/easy_chat.c
index 79300bd52..b18d09b83 100644
--- a/src/easy_chat.c
+++ b/src/easy_chat.c
@@ -15,7 +15,7 @@
#include "graphics.h"
#include "international_string_util.h"
#include "main.h"
-#include "mevent.h"
+#include "mystery_gift.h"
#include "menu.h"
#include "overworld.h"
#include "palette.h"
diff --git a/src/ereader_screen.c b/src/ereader_screen.c
index f5edbc628..73a1b870e 100755
--- a/src/ereader_screen.c
+++ b/src/ereader_screen.c
@@ -4,7 +4,7 @@
#include "ereader_helpers.h"
#include "link.h"
#include "main.h"
-#include "mystery_gift.h"
+#include "mystery_gift_menu.h"
#include "save.h"
#include "sound.h"
#include "sprite.h"
@@ -13,7 +13,7 @@
#include "util.h"
#include "constants/songs.h"
-struct Unk81D5014
+struct EReaderTaskData
{
u16 unk0;
u16 unk2;
@@ -36,7 +36,7 @@ struct Unk03006370
u32 *unk8;
};
-static void sub_81D5084(u8);
+static void Task_EReader(u8);
struct Unk03006370 gUnknown_03006370;
@@ -209,11 +209,11 @@ static u32 sub_81D4EE4(u8 *arg0, u16 *arg1)
return 0;
}
-void task_add_00_ereader(void)
+void CreateEReaderTask(void)
{
- struct Unk81D5014 *data;
- u8 taskId = CreateTask(sub_81D5084, 0);
- data = (struct Unk81D5014 *)gTasks[taskId].data;
+ struct EReaderTaskData *data;
+ u8 taskId = CreateTask(Task_EReader, 0);
+ data = (struct EReaderTaskData *)gTasks[taskId].data;
data->unk8 = 0;
data->unk9 = 0;
data->unkA = 0;
@@ -244,13 +244,13 @@ static bool32 sub_81D5064(u16 *arg0, u16 arg1)
return FALSE;
}
-static void sub_81D5084(u8 taskId)
+static void Task_EReader(u8 taskId)
{
- struct Unk81D5014 *data = (struct Unk81D5014 *)gTasks[taskId].data;
+ struct EReaderTaskData *data = (struct EReaderTaskData *)gTasks[taskId].data;
switch (data->unk8)
{
case 0:
- if (MG_PrintTextOnWindow1AndWaitButton(&data->unk9, gJPText_ReceiveMysteryGiftWithEReader))
+ if (PrintMysteryGiftMenuMessage(&data->unk9, gJPText_ReceiveMysteryGiftWithEReader))
data->unk8 = 1;
break;
case 1:
@@ -274,7 +274,7 @@ static void sub_81D5084(u8 taskId)
}
break;
case 4:
- if (MG_PrintTextOnWindow1AndWaitButton(&data->unk9, gJPText_SelectConnectFromEReaderMenu))
+ if (PrintMysteryGiftMenuMessage(&data->unk9, gJPText_SelectConnectFromEReaderMenu))
{
AddTextPrinterToWindow1(gJPText_SelectConnectWithGBA);
sub_81D505C(&data->unk0);
@@ -323,7 +323,7 @@ static void sub_81D5084(u8 taskId)
}
break;
case 7:
- if (MG_PrintTextOnWindow1AndWaitButton(&data->unk9, gJPText_LinkIsIncorrect))
+ if (PrintMysteryGiftMenuMessage(&data->unk9, gJPText_LinkIsIncorrect))
data->unk8 = 4;
break;
case 8:
@@ -439,19 +439,19 @@ static void sub_81D5084(u8 taskId)
data->unk8 = 26;
break;
case 23:
- if (MG_PrintTextOnWindow1AndWaitButton(&data->unk9, gJPText_CardReadingHasBeenHalted))
+ if (PrintMysteryGiftMenuMessage(&data->unk9, gJPText_CardReadingHasBeenHalted))
data->unk8 = 26;
break;
case 20:
- if (MG_PrintTextOnWindow1AndWaitButton(&data->unk9, gJPText_ConnectionErrorCheckLink))
+ if (PrintMysteryGiftMenuMessage(&data->unk9, gJPText_ConnectionErrorCheckLink))
data->unk8 = 0;
break;
case 21:
- if (MG_PrintTextOnWindow1AndWaitButton(&data->unk9, gJPText_ConnectionErrorTryAgain))
+ if (PrintMysteryGiftMenuMessage(&data->unk9, gJPText_ConnectionErrorTryAgain))
data->unk8 = 0;
break;
case 22:
- if (MG_PrintTextOnWindow1AndWaitButton(&data->unk9, gJPText_WriteErrorUnableToSaveData))
+ if (PrintMysteryGiftMenuMessage(&data->unk9, gJPText_WriteErrorUnableToSaveData))
data->unk8 = 0;
break;
case 26:
diff --git a/src/event_data.c b/src/event_data.c
index 2bde09012..e2af6c3d0 100644
--- a/src/event_data.c
+++ b/src/event_data.c
@@ -114,36 +114,36 @@ bool32 IsMysteryGiftEnabled(void)
return FlagGet(FLAG_SYS_MYSTERY_GIFT_ENABLE);
}
-void ClearMysteryEventFlags(void)
-{
- FlagClear(FLAG_MYSTERY_EVENT_DONE);
- FlagClear(FLAG_MYSTERY_EVENT_1);
- FlagClear(FLAG_MYSTERY_EVENT_2);
- FlagClear(FLAG_MYSTERY_EVENT_3);
- FlagClear(FLAG_MYSTERY_EVENT_4);
- FlagClear(FLAG_MYSTERY_EVENT_5);
- FlagClear(FLAG_MYSTERY_EVENT_6);
- FlagClear(FLAG_MYSTERY_EVENT_7);
- FlagClear(FLAG_MYSTERY_EVENT_8);
- FlagClear(FLAG_MYSTERY_EVENT_9);
- FlagClear(FLAG_MYSTERY_EVENT_10);
- FlagClear(FLAG_MYSTERY_EVENT_11);
- FlagClear(FLAG_MYSTERY_EVENT_12);
- FlagClear(FLAG_MYSTERY_EVENT_13);
- FlagClear(FLAG_MYSTERY_EVENT_14);
- FlagClear(FLAG_MYSTERY_EVENT_15);
-}
-
-void ClearMysteryEventVars(void)
-{
- VarSet(VAR_EVENT_PICHU_SLOT, 0);
- VarSet(VAR_NEVER_READ_0x40DE, 0);
- VarSet(VAR_NEVER_READ_0x40DF, 0);
- VarSet(VAR_NEVER_READ_0x40E0, 0);
- VarSet(VAR_NEVER_READ_0x40E1, 0);
- VarSet(VAR_NEVER_READ_0x40E2, 0);
- VarSet(VAR_NEVER_READ_0x40E3, 0);
- VarSet(VAR_NEVER_READ_0x40E4, 0);
+void ClearMysteryGiftFlags(void)
+{
+ FlagClear(FLAG_MYSTERY_GIFT_DONE);
+ FlagClear(FLAG_MYSTERY_GIFT_1);
+ FlagClear(FLAG_MYSTERY_GIFT_2);
+ FlagClear(FLAG_MYSTERY_GIFT_3);
+ FlagClear(FLAG_MYSTERY_GIFT_4);
+ FlagClear(FLAG_MYSTERY_GIFT_5);
+ FlagClear(FLAG_MYSTERY_GIFT_6);
+ FlagClear(FLAG_MYSTERY_GIFT_7);
+ FlagClear(FLAG_MYSTERY_GIFT_8);
+ FlagClear(FLAG_MYSTERY_GIFT_9);
+ FlagClear(FLAG_MYSTERY_GIFT_10);
+ FlagClear(FLAG_MYSTERY_GIFT_11);
+ FlagClear(FLAG_MYSTERY_GIFT_12);
+ FlagClear(FLAG_MYSTERY_GIFT_13);
+ FlagClear(FLAG_MYSTERY_GIFT_14);
+ FlagClear(FLAG_MYSTERY_GIFT_15);
+}
+
+void ClearMysteryGiftVars(void)
+{
+ VarSet(VAR_GIFT_PICHU_SLOT, 0);
+ VarSet(VAR_GIFT_UNUSED_1, 0);
+ VarSet(VAR_GIFT_UNUSED_2, 0);
+ VarSet(VAR_GIFT_UNUSED_3, 0);
+ VarSet(VAR_GIFT_UNUSED_4, 0);
+ VarSet(VAR_GIFT_UNUSED_5, 0);
+ VarSet(VAR_GIFT_UNUSED_6, 0);
+ VarSet(VAR_GIFT_UNUSED_7, 0);
}
void DisableResetRTC(void)
diff --git a/src/field_specials.c b/src/field_specials.c
index ab02f9938..97fba6b10 100644
--- a/src/field_specials.c
+++ b/src/field_specials.c
@@ -22,7 +22,7 @@
#include "link.h"
#include "list_menu.h"
#include "main.h"
-#include "mevent.h"
+#include "mystery_gift.h"
#include "match_call.h"
#include "menu.h"
#include "overworld.h"
@@ -56,7 +56,7 @@
#include "constants/heal_locations.h"
#include "constants/map_types.h"
#include "constants/maps.h"
-#include "constants/mevent.h"
+#include "constants/mystery_gift.h"
#include "constants/script_menu.h"
#include "constants/slot_machine.h"
#include "constants/songs.h"
@@ -1655,20 +1655,20 @@ void BufferLottoTicketNumber(void)
}
}
-u16 GetMysteryEventCardVal(void)
+u16 GetMysteryGiftCardStat(void)
{
switch (gSpecialVar_Result)
{
case GET_NUM_STAMPS:
- return mevent_081445C0(GET_NUM_STAMPS_INTERNAL);
+ return MysteryGift_GetCardStat(CARD_STAT_NUM_STAMPS);
case GET_MAX_STAMPS:
- return mevent_081445C0(GET_MAX_STAMPS_INTERNAL);
+ return MysteryGift_GetCardStat(CARD_STAT_MAX_STAMPS);
case GET_CARD_BATTLES_WON:
- return mevent_081445C0(GET_CARD_BATTLES_WON_INTERNAL);
- case 3: // Never occurs
- return mevent_081445C0(1);
- case 4: // Never occurs
- return mevent_081445C0(2);
+ return MysteryGift_GetCardStat(CARD_STAT_BATTLES_WON);
+ case GET_CARD_BATTLES_LOST: // Never occurs
+ return MysteryGift_GetCardStat(CARD_STAT_BATTLES_LOST);
+ case GET_CARD_NUM_TRADES: // Never occurs
+ return MysteryGift_GetCardStat(CARD_STAT_NUM_TRADES);
default:
return 0;
}
diff --git a/src/link_rfu_2.c b/src/link_rfu_2.c
index f2caef949..87e9f8e9d 100644
--- a/src/link_rfu_2.c
+++ b/src/link_rfu_2.c
@@ -16,7 +16,7 @@
#include "task.h"
#include "text.h"
#include "save.h"
-#include "mystery_gift.h"
+#include "mystery_gift_menu.h"
enum {
RFUSTATE_INIT,
@@ -1981,7 +1981,7 @@ static void RfuCheckErrorStatus(void)
{
if (gRfu.errorState == RFU_ERROR_STATE_OCCURRED && lman.childClockSlave_flag == 0)
{
- if (gMain.callback2 == c2_mystery_gift_e_reader_run || lman.init_param->mboot_flag)
+ if (gMain.callback2 == CB2_MysteryGiftEReader || lman.init_param->mboot_flag)
gWirelessCommType = 2;
SetMainCallback2(CB2_LinkError);
gMain.savedCallback = CB2_LinkError;
diff --git a/src/main_menu.c b/src/main_menu.c
index f6dff3d44..a74ba9ec3 100644
--- a/src/main_menu.c
+++ b/src/main_menu.c
@@ -35,7 +35,7 @@
#include "text_window.h"
#include "title_screen.h"
#include "window.h"
-#include "mystery_gift.h"
+#include "mystery_gift_menu.h"
/*
* Main menu state machine
@@ -90,7 +90,7 @@
* - If the user selected New Game, advance to Task_NewGameBirchSpeech_Init.
* - If the user selected Continue, advance to CB2_ContinueSavedGame.
* - If the user selected the Options menu, advance to CB2_InitOptionMenu.
- * - If the user selected Mystery Gift, advance to CB2_MysteryGift. However,
+ * - If the user selected Mystery Gift, advance to CB2_InitMysteryGift. However,
* if the wireless adapter was removed, instead advance to
* Task_DisplayMainMenuInvalidActionError.
* - Code to start a Mystery Event is present here, but is unreachable in this
@@ -1070,7 +1070,7 @@ static void Task_HandleMainMenuAPressed(u8 taskId)
DestroyTask(taskId);
break;
case ACTION_MYSTERY_GIFT:
- SetMainCallback2(c2_mystery_gift);
+ SetMainCallback2(CB2_InitMysteryGift);
DestroyTask(taskId);
break;
case ACTION_MYSTERY_EVENTS:
@@ -1078,7 +1078,7 @@ static void Task_HandleMainMenuAPressed(u8 taskId)
DestroyTask(taskId);
break;
case ACTION_EREADER:
- SetMainCallback2(c2_ereader);
+ SetMainCallback2(CB2_InitEReader);
DestroyTask(taskId);
break;
case ACTION_INVALID:
diff --git a/src/mevent2.c b/src/mevent2.c
deleted file mode 100755
index d2c020858..000000000
--- a/src/mevent2.c
+++ /dev/null
@@ -1,630 +0,0 @@
-#include "global.h"
-#include "util.h"
-#include "main.h"
-#include "event_data.h"
-#include "easy_chat.h"
-#include "script.h"
-#include "battle_tower.h"
-#include "mevent_news.h"
-#include "string_util.h"
-#include "new_game.h"
-#include "mevent.h"
-#include "constants/mevent.h"
-
-static EWRAM_DATA bool32 gUnknown_02022C70 = FALSE;
-
-static void sub_801B180(void);
-static void s_DestroyWonderNews(void);
-static bool32 sub_801B114(const struct WonderNews *data);
-static bool32 sub_801B2CC(const struct WonderCard *data);
-static void sub_801B330(void);
-static void sub_801B368(void);
-static void sub_801B9F8(void);
-static void sub_801BA8C(u32 a0, u32 a1, u32 *a2, int a3);
-
-void sub_801AFD8(void)
-{
- CpuFill32(0, &gSaveBlock1Ptr->unk_322C, sizeof(gSaveBlock1Ptr->unk_322C));
- sub_801B180();
- InitQuestionnaireWords();
-}
-
-struct WonderNews *GetSavedWonderNews(void)
-{
- return &gSaveBlock1Ptr->unk_322C.wonderNews.data;
-}
-
-struct WonderCard *GetSavedWonderCard(void)
-{
- return &gSaveBlock1Ptr->unk_322C.wonderCard.data;
-}
-
-struct MEventBuffer_3430_Sub *sav1_get_mevent_buffer_2(void)
-{
- return &gSaveBlock1Ptr->unk_322C.buffer_310.data;
-}
-
-struct MysteryEventStruct *sub_801B044(void)
-{
- return &gSaveBlock1Ptr->unk_322C.unk_340;
-}
-
-u16 *GetQuestionnaireWordsPtr(void)
-{
- return gSaveBlock1Ptr->unk_322C.questionnaireWords;
-}
-
-void DestroyWonderNews(void)
-{
- s_DestroyWonderNews();
-}
-
-bool32 sub_801B078(const struct WonderNews *src)
-{
- if (!sub_801B114(src))
- return FALSE;
-
- s_DestroyWonderNews();
- gSaveBlock1Ptr->unk_322C.wonderNews.data = *src;
- gSaveBlock1Ptr->unk_322C.wonderNews.crc = CalcCRC16WithTable((void *)&gSaveBlock1Ptr->unk_322C.wonderNews.data, sizeof(struct WonderNews));
- return TRUE;
-}
-
-bool32 ValidateReceivedWonderNews(void)
-{
- if (CalcCRC16WithTable((void *)&gSaveBlock1Ptr->unk_322C.wonderNews.data, sizeof(struct WonderNews)) != gSaveBlock1Ptr->unk_322C.wonderNews.crc)
- return FALSE;
- if (!sub_801B114(&gSaveBlock1Ptr->unk_322C.wonderNews.data))
- return FALSE;
-
- return TRUE;
-}
-
-static bool32 sub_801B114(const struct WonderNews *data)
-{
- if (data->unk_00 == 0)
- return FALSE;
-
- return TRUE;
-}
-
-bool32 WonderNews_Test_Unk_02(void)
-{
- const struct WonderNews *data = &gSaveBlock1Ptr->unk_322C.wonderNews.data;
- if (data->unk_02 == 0)
- return FALSE;
-
- return TRUE;
-}
-
-static void s_DestroyWonderNews(void)
-{
- CpuFill32(0, GetSavedWonderNews(), sizeof(gSaveBlock1Ptr->unk_322C.wonderNews.data));
- gSaveBlock1Ptr->unk_322C.wonderNews.crc = 0;
-}
-
-static void sub_801B180(void)
-{
- CpuFill32(0, sub_801B044(), sizeof(struct MysteryEventStruct));
- sub_801DBC0();
-}
-
-bool32 sub_801B1A4(const u8 *src)
-{
- const u8 *r5 = (const u8 *)&gSaveBlock1Ptr->unk_322C.wonderNews.data;
- u32 i;
- if (!ValidateReceivedWonderNews())
- return FALSE;
-
- for (i = 0; i < sizeof(struct WonderNews); i++)
- {
- if (r5[i] != src[i])
- return FALSE;
- }
-
- return TRUE;
-}
-
-void DestroyWonderCard(void)
-{
- sub_801B330();
- sub_801B368();
- sub_801B9F8();
- ClearRamScript();
- ClearMysteryEventFlags();
- ClearMysteryEventVars();
- ClearEReaderTrainer(&gSaveBlock2Ptr->frontier.ereaderTrainer);
-}
-
-bool32 sub_801B21C(const struct WonderCard *data)
-{
- struct MEventBuffer_3430_Sub *r2;
- struct WonderCard *r1;
- if (!sub_801B2CC(data))
- return FALSE;
-
- DestroyWonderCard();
- memcpy(&gSaveBlock1Ptr->unk_322C.wonderCard.data, data, sizeof(struct WonderCard));
- gSaveBlock1Ptr->unk_322C.wonderCard.crc = CalcCRC16WithTable((void *)&gSaveBlock1Ptr->unk_322C.wonderCard.data, sizeof(struct WonderCard));
- r2 = &gSaveBlock1Ptr->unk_322C.buffer_310.data;
- r1 = &gSaveBlock1Ptr->unk_322C.wonderCard.data;
- r2->unk_06 = r1->unk_02;
- return TRUE;
-}
-
-bool32 ValidateReceivedWonderCard(void)
-{
- if (gSaveBlock1Ptr->unk_322C.wonderCard.crc != CalcCRC16WithTable((void *)&gSaveBlock1Ptr->unk_322C.wonderCard.data, sizeof(struct WonderCard)))
- return FALSE;
- if (!sub_801B2CC(&gSaveBlock1Ptr->unk_322C.wonderCard.data))
- return FALSE;
- if (!ValidateSavedRamScript())
- return FALSE;
-
- return TRUE;
-}
-
-static bool32 sub_801B2CC(const struct WonderCard *data)
-{
- if (data->unk_00 == 0)
- return FALSE;
- if (data->unk_08_0 > 2)
- return FALSE;
- if (!(data->unk_08_6 == 0 || data->unk_08_6 == 1 || data->unk_08_6 == 2))
- return FALSE;
- if (data->unk_08_2 > 7)
- return FALSE;
- if (data->unk_09 > 7)
- return FALSE;
-
- return TRUE;
-}
-
-bool32 WonderCard_Test_Unk_08_6(void)
-{
- const struct WonderCard *data = &gSaveBlock1Ptr->unk_322C.wonderCard.data;
- if (data->unk_08_6 == 0)
- return FALSE;
-
- return TRUE;
-}
-
-static void sub_801B330(void)
-{
- CpuFill32(0, &gSaveBlock1Ptr->unk_322C.wonderCard.data, sizeof(struct WonderCard));
- gSaveBlock1Ptr->unk_322C.wonderCard.crc = 0;
-}
-
-static void sub_801B368(void)
-{
- CpuFill32(0, sav1_get_mevent_buffer_2(), 18 *sizeof(u16));
- gSaveBlock1Ptr->unk_322C.buffer_310.crc = 0;
-}
-
-u16 GetWonderCardFlagID(void)
-{
- if (ValidateReceivedWonderCard())
- return gSaveBlock1Ptr->unk_322C.wonderCard.data.unk_00;
-
- return 0;
-}
-
-void WonderCard_ResetInternalReceivedFlag(struct WonderCard *buffer)
-{
- if (buffer->unk_08_6 == 1)
- buffer->unk_08_6 = 0;
-}
-
-static bool32 IsWonderCardFlagIDInValidRange(u16 a0)
-{
- if (a0 >= 1000 && a0 < 1020)
- return TRUE;
-
- return FALSE;
-}
-
-static const u16 sMysteryGiftFlags[] =
-{
- FLAG_RECEIVED_AURORA_TICKET,
- FLAG_RECEIVED_MYSTIC_TICKET,
- FLAG_RECEIVED_OLD_SEA_MAP,
- FLAG_UNUSED_MYSTERY_GIFT_0x13D,
- FLAG_UNUSED_MYSTERY_GIFT_0x13E,
- FLAG_UNUSED_MYSTERY_GIFT_0x13F,
- FLAG_UNUSED_MYSTERY_GIFT_0x140,
- FLAG_UNUSED_MYSTERY_GIFT_0x141,
- FLAG_UNUSED_MYSTERY_GIFT_0x142,
- FLAG_UNUSED_MYSTERY_GIFT_0x143,
- FLAG_UNUSED_MYSTERY_GIFT_0x144,
- FLAG_UNUSED_MYSTERY_GIFT_0x145,
- FLAG_UNUSED_MYSTERY_GIFT_0x146,
- FLAG_UNUSED_MYSTERY_GIFT_0x147,
- FLAG_UNUSED_MYSTERY_GIFT_0x148,
- FLAG_UNUSED_MYSTERY_GIFT_0x149,
- FLAG_UNUSED_MYSTERY_GIFT_0x14A,
- FLAG_UNUSED_MYSTERY_GIFT_0x14B,
- FLAG_UNUSED_MYSTERY_GIFT_0x14C,
- FLAG_UNUSED_MYSTERY_GIFT_0x14D,
-};
-
-bool32 CheckReceivedGiftFromWonderCard(void)
-{
- u16 value = GetWonderCardFlagID();
- if (!IsWonderCardFlagIDInValidRange(value))
- return FALSE;
-
- if (FlagGet(sMysteryGiftFlags[value - 1000]) == TRUE)
- return FALSE;
-
- return TRUE;
-}
-
-static int sub_801B438(const struct MEventBuffer_3430_Sub *data, int size)
-{
- int r3 = 0;
- int i;
- for (i = 0; i < size; i++)
- {
- if (data->unk_08[1][i] && data->unk_08[0][i])
- r3++;
- }
-
- return r3;
-}
-
-static bool32 sub_801B460(const struct MEventBuffer_3430_Sub *data1, const u16 *data2, int size)
-{
- int i;
- for (i = 0; i < size; i++)
- {
- if (data1->unk_08[1][i] == data2[1])
- return TRUE;
- if (data1->unk_08[0][i] == data2[0])
- return TRUE;
- }
-
- return FALSE;
-}
-
-static bool32 sub_801B4A4(const u16 *data)
-{
- if (data[1] == 0)
- return FALSE;
- if (data[0] == 0)
- return FALSE;
- if (data[0] >= NUM_SPECIES)
- return FALSE;
- return TRUE;
-}
-
-static int sub_801B4CC(void)
-{
- struct WonderCard *data;
- if (!ValidateReceivedWonderCard())
- return 0;
-
- data = &gSaveBlock1Ptr->unk_322C.wonderCard.data;
- if (data->unk_08_0 != 1)
- return 0;
-
- return sub_801B438(&gSaveBlock1Ptr->unk_322C.buffer_310.data, data->unk_09);
-}
-
-bool32 sub_801B508(const u16 *data)
-{
- struct WonderCard *buffer = &gSaveBlock1Ptr->unk_322C.wonderCard.data;
- int size = buffer->unk_09;
- int i;
- if (!sub_801B4A4(data))
- return FALSE;
-
- if (sub_801B460(&gSaveBlock1Ptr->unk_322C.buffer_310.data, data, size))
- return FALSE;
-
- for (i = 0; i < size; i++)
- {
- if (gSaveBlock1Ptr->unk_322C.buffer_310.data.unk_08[1][i] == 0 && gSaveBlock1Ptr->unk_322C.buffer_310.data.unk_08[0][i] == 0)
- {
- gSaveBlock1Ptr->unk_322C.buffer_310.data.unk_08[1][i] = data[1];
- gSaveBlock1Ptr->unk_322C.buffer_310.data.unk_08[0][i] = data[0];
- return TRUE;
- }
- }
-
- return FALSE;
-}
-
-void sub_801B580(struct MEventStruct_Unk1442CC *data, bool32 a1)
-{
- int i;
- CpuFill32(0, data, sizeof(struct MEventStruct_Unk1442CC));
- data->unk_00 = 0x101;
- data->unk_04 = 1;
- data->unk_08 = 1;
-
- if (a1)
- {
- data->unk_0C = 5;
- data->unk_10 = 0x0201;
- }
- else
- {
- data->unk_0C = 4;
- data->unk_10 = 0x0200;
- }
-
- if (ValidateReceivedWonderCard())
- {
- data->unk_14 = GetSavedWonderCard()->unk_00;
- data->unk_20 = *sav1_get_mevent_buffer_2();
- data->unk_44 = GetSavedWonderCard()->unk_09;
- }
- else
- {
- data->unk_14 = 0;
- }
-
- for (i = 0; i < NUM_QUESTIONNAIRE_WORDS; i++)
- data->unk_16[i] = gSaveBlock1Ptr->unk_322C.questionnaireWords[i];
-
- CopyTrainerId(data->unk_4C, gSaveBlock2Ptr->playerTrainerId);
- StringCopy(data->unk_45, gSaveBlock2Ptr->playerName);
- for (i = 0; i < 6; i++)
- data->unk_50[i] = gSaveBlock1Ptr->easyChatProfile[i];
-
- memcpy(data->unk_5C, RomHeaderGameCode, 4);
- data->unk_60 = RomHeaderSoftwareVersion;
-}
-
-bool32 sub_801B6A0(const struct MEventStruct_Unk1442CC *data, bool32 a1)
-{
- if (data->unk_00 != 0x101)
- return FALSE;
-
- if (!(data->unk_04 & 1))
- return FALSE;
-
- if (!(data->unk_08 & 1))
- return FALSE;
-
- if (!a1)
- {
- if (!(data->unk_0C & 4))
- return FALSE;
-
- if (!(data->unk_10 & 0x380))
- return FALSE;
- }
-
- return TRUE;
-}
-
-u32 sub_801B6EC(const u16 *a0, const struct MEventStruct_Unk1442CC *a1, const void *unused)
-{
- if (a1->unk_14 == 0)
- return 0;
-
- if (*a0 == a1->unk_14)
- return 1;
-
- return 2;
-}
-
-u32 sub_801B708(const u16 *a0, const struct MEventStruct_Unk1442CC *a1, const void *unused)
-{
- int r4 = a1->unk_44 - sub_801B438(&a1->unk_20, a1->unk_44);
- if (r4 == 0)
- return 1;
- if (sub_801B460(&a1->unk_20, a0, a1->unk_44))
- return 3;
- if (r4 == 1)
- return 4;
- return 2;
-}
-
-bool32 MEventStruct_Unk1442CC_CompareField_unk_16(const struct MEventStruct_Unk1442CC *a0, const u16 *a1)
-{
- int i;
- for (i = 0; i < NUM_QUESTIONNAIRE_WORDS; i++)
- {
- if (a0->unk_16[i] != a1[i])
- return FALSE;
- }
-
- return TRUE;
-}
-
-static int sub_801B770(const struct MEventStruct_Unk1442CC *a0)
-{
- return sub_801B438(&a0->unk_20, a0->unk_44);
-}
-
-u16 MEventStruct_Unk1442CC_GetValueNFrom_unk_20(const struct MEventStruct_Unk1442CC *a0, u32 command)
-{
- switch (command)
- {
- case 0:
- return a0->unk_20.unk_00;
- case 1:
- return a0->unk_20.unk_02;
- case 2:
- return a0->unk_20.unk_04;
- case 3:
- return sub_801B770(a0);
- case 4:
- return a0->unk_44;
- default:
- AGB_ASSERT(0);
- return 0;
- }
-}
-
-static void sub_801B7D8(u32 command)
-{
- struct WonderCard *data = &gSaveBlock1Ptr->unk_322C.wonderCard.data;
- if (data->unk_08_0 == 2)
- {
- u16 *dest = NULL;
- switch (command)
- {
- case 0:
- dest = &gSaveBlock1Ptr->unk_322C.buffer_310.data.unk_00;
- break;
- case 1:
- dest = &gSaveBlock1Ptr->unk_322C.buffer_310.data.unk_02;
- break;
- case 2:
- dest = &gSaveBlock1Ptr->unk_322C.buffer_310.data.unk_04;
- break;
- case 3:
- break;
- case 4:
- break;
- }
-
- if (dest == NULL)
- {
- AGB_ASSERT(0);
- }
- else if (++(*dest) > 999)
- {
- *dest = 999;
- }
- }
-}
-
-u16 mevent_081445C0(u32 command)
-{
- switch (command)
- {
- case GET_CARD_BATTLES_WON_INTERNAL:
- {
- struct WonderCard *data = &gSaveBlock1Ptr->unk_322C.wonderCard.data;
- if (data->unk_08_0 == 2)
- {
- struct MEventBuffer_3430_Sub *buffer = &gSaveBlock1Ptr->unk_322C.buffer_310.data;
- return buffer->unk_00;
- }
- break;
- }
- case 1: // Never occurs
- {
- struct WonderCard *data = &gSaveBlock1Ptr->unk_322C.wonderCard.data;
- if (data->unk_08_0 == 2)
- {
- struct MEventBuffer_3430_Sub *buffer = &gSaveBlock1Ptr->unk_322C.buffer_310.data;
- return buffer->unk_02;
- }
- break;
- }
- case 2: // Never occurs
- {
- struct WonderCard *data = &gSaveBlock1Ptr->unk_322C.wonderCard.data;
- if (data->unk_08_0 == 2)
- {
- struct MEventBuffer_3430_Sub *buffer = &gSaveBlock1Ptr->unk_322C.buffer_310.data;
- return buffer->unk_04;
- }
- break;
- }
- case GET_NUM_STAMPS_INTERNAL:
- {
- struct WonderCard *data = &gSaveBlock1Ptr->unk_322C.wonderCard.data;
- if (data->unk_08_0 == 1)
- return sub_801B4CC();
- break;
- }
- case GET_MAX_STAMPS_INTERNAL:
- {
- struct WonderCard *data = &gSaveBlock1Ptr->unk_322C.wonderCard.data;
- if (data->unk_08_0 == 1)
- return data->unk_09;
- break;
- }
- }
-
- AGB_ASSERT(0);
- return 0;
-}
-
-void ResetReceivedWonderCardFlag(void)
-{
- gUnknown_02022C70 = FALSE;
-}
-
-bool32 MEventHandleReceivedWonderCard(u16 a0)
-{
- gUnknown_02022C70 = FALSE;
- if (a0 == 0)
- return FALSE;
-
- if (!ValidateReceivedWonderCard())
- return FALSE;
-
- if (gSaveBlock1Ptr->unk_322C.wonderCard.data.unk_00 != a0)
- return FALSE;
-
- gUnknown_02022C70 = TRUE;
- return TRUE;
-}
-
-void RecordIdOfWonderCardSenderByEventType(u32 a0, u32 a1)
-{
- if (gUnknown_02022C70)
- {
- switch (a0)
- {
- case 2:
- sub_801BA8C(2, a1, gSaveBlock1Ptr->unk_322C.unk_344[1], 5);
- break;
- case 0:
- sub_801BA8C(0, a1, gSaveBlock1Ptr->unk_322C.unk_344[0], 5);
- break;
- case 1:
- sub_801BA8C(1, a1, gSaveBlock1Ptr->unk_322C.unk_344[0], 5);
- break;
- default:
- AGB_ASSERT(0);
- }
- }
-}
-
-static void sub_801B9F8(void)
-{
- CpuFill32(0, gSaveBlock1Ptr->unk_322C.unk_344, sizeof(gSaveBlock1Ptr->unk_322C.unk_344));
-}
-
-static bool32 sub_801BA24(u32 a0, u32 *a1, int size)
-{
- int i;
- int j;
-
- for (i = 0; i < size; i++)
- {
- if (a1[i] == a0)
- break;
- }
-
- if (i == size)
- {
- for (j = size - 1; j > 0; j--)
- a1[j] = a1[j - 1];
-
- a1[0] = a0;
- return TRUE;
- }
- else
- {
- for (j = i; j > 0; j--)
- a1[j] = a1[j - 1];
-
- a1[0] = a0;
- return FALSE;
- }
-}
-
-static void sub_801BA8C(u32 a0, u32 a1, u32 *a2, int a3)
-{
- if (sub_801BA24(a1, a2, a3))
- sub_801B7D8(a0);
-}
diff --git a/src/mevent_801BAAC.c b/src/mevent_801BAAC.c
deleted file mode 100644
index a3e6ee0b6..000000000
--- a/src/mevent_801BAAC.c
+++ /dev/null
@@ -1,826 +0,0 @@
-#include "global.h"
-#include "bg.h"
-#include "gpu_regs.h"
-#include "palette.h"
-#include "decompress.h"
-#include "malloc.h"
-#include "menu.h"
-#include "pokemon_icon.h"
-#include "union_room.h"
-#include "list_menu.h"
-#include "text_window.h"
-#include "string_util.h"
-#include "link_rfu.h"
-#include "mevent.h"
-#include "mystery_gift.h"
-#include "constants/rgb.h"
-
-struct UnkStruct_8467FB8
-{
- u8 textPal1:4;
- u8 textPal2:4;
- u8 textPal3:4;
- u8 textPal4:4;
- const u32 * tiles;
- const u32 * map;
- const u16 * pal;
-};
-
-struct UnkStruct_203F3C8_02DC
-{
- u8 unk_00;
- u8 unk_01[41];
- u8 unk_42[4];
-};
-
-struct UnkStruct_203F3C8
-{
- /*0000*/ struct WonderCard unk_0000;
- /*014c*/ struct MEventBuffer_3430_Sub unk_014C;
- /*0170*/ const struct UnkStruct_8467FB8 * unk_0170;
- /*0174*/ u8 unk_0174;
- /*0175*/ u8 unk_0175;
- /*0176*/ u16 unk_0176[3];
- /*017C*/ u8 unk_017C;
- /*017D*/ u8 unk_017D[7][2];
- /*018B*/ u8 unk_018B[41];
- /*01B4*/ u8 unk_01B4[41];
- /*01DD*/ u8 unk_01DD[7];
- /*01E4*/ u8 unk_01E4[4][41];
- /*0288*/ u8 unk_0288[41];
- /*02B1*/ u8 unk_02B1[41];
- /*02DC*/ struct UnkStruct_203F3C8_02DC unk_02DC[8];
- /*045C*/ u8 buffer_045C[0x1000];
-};
-
-EWRAM_DATA struct UnkStruct_203F3C8 * sWonderCardData = NULL;
-
-void sub_801BEF8(void);
-void sub_801C178(u8 whichWindow);
-void sub_801C4C0(void);
-void sub_801C61C(void);
-
-extern const struct OamData gOamData_AffineOff_ObjNormal_32x16;
-
-const u8 sTextColorTable[][3] = {
- {TEXT_COLOR_TRANSPARENT, TEXT_COLOR_DARK_GRAY, TEXT_COLOR_LIGHT_GRAY},
- {TEXT_COLOR_TRANSPARENT, TEXT_COLOR_WHITE, TEXT_COLOR_DARK_GRAY}
-};
-const u8 ALIGNED(4) gUnknown_082F0E18[3] = {7, 4, 7};
-const struct WindowTemplate gUnknown_082F0E1C[] = {
- {
- .bg = 1,
- .tilemapLeft = 1,
- .tilemapTop = 1,
- .width = 25,
- .height = 4,
- .paletteNum = 2,
- .baseBlock = 0x029c
- }, {
- .bg = 1,
- .tilemapLeft = 1,
- .tilemapTop = 6,
- .width = 28,
- .height = 8,
- .paletteNum = 2,
- .baseBlock = 0x01bc
- }, {
- .bg = 1,
- .tilemapLeft = 1,
- .tilemapTop = 14,
- .width = 28,
- .height = 5,
- .paletteNum = 2,
- .baseBlock = 0x0130
- }
-};
-
-const u16 gWonderCardBgPal1[] = INCBIN_U16("graphics/wonder_transfers/wonder_card_1.gbapal");
-const u16 gWonderCardBgPal2[] = INCBIN_U16("graphics/wonder_transfers/wonder_card_2.gbapal");
-const u16 gWonderCardBgPal3[] = INCBIN_U16("graphics/wonder_transfers/wonder_card_3.gbapal");
-const u16 gWonderCardBgPal4[] = INCBIN_U16("graphics/wonder_transfers/wonder_card_4.gbapal");
-const u16 gWonderCardBgPal5[] = INCBIN_U16("graphics/wonder_transfers/wonder_card_5.gbapal");
-const u16 gWonderCardBgPal6[] = INCBIN_U16("graphics/wonder_transfers/wonder_card_6.gbapal");
-const u16 gWonderCardBgPal7[] = INCBIN_U16("graphics/wonder_transfers/wonder_card_7.gbapal");
-const u16 gWonderCardBgPal8[] = INCBIN_U16("graphics/wonder_transfers/wonder_card_8.gbapal");
-const u32 gWonderCardBgGfx1[] = INCBIN_U32("graphics/wonder_transfers/wonder_card_1.4bpp.lz");
-const u32 gWonderCardBgTilemap1[] = INCBIN_U32("graphics/wonder_transfers/wonder_card_1.bin.lz");
-const u32 gWonderCardBgGfx2[] = INCBIN_U32("graphics/wonder_transfers/wonder_card_2.4bpp.lz");
-const u32 gWonderCardBgTilemap2[] = INCBIN_U32("graphics/wonder_transfers/wonder_card_2.bin.lz");
-const u32 gWonderCardBgGfx3[] = INCBIN_U32("graphics/wonder_transfers/wonder_card_3.4bpp.lz");
-const u32 gWonderCardBgTilemap3[] = INCBIN_U32("graphics/wonder_transfers/wonder_card_3.bin.lz");
-const u32 gWonderCardBgGfx7[] = INCBIN_U32("graphics/wonder_transfers/wonder_card_7.4bpp.lz");
-const u32 gWonderCardBgTilemap7[] = INCBIN_U32("graphics/wonder_transfers/wonder_card_7.bin.lz");
-const u32 gWonderCardBgGfx8[] = INCBIN_U32("graphics/wonder_transfers/wonder_card_8.4bpp.lz");
-const u32 gWonderCardBgTilemap8[] = INCBIN_U32("graphics/wonder_transfers/wonder_card_8.bin.lz");
-const u16 gWonderCardShadowPal1[] = INCBIN_U16("graphics/wonder_transfers/wonder_card_shadow_1.gbapal");
-const u16 gWonderCardShadowPal2[] = INCBIN_U16("graphics/wonder_transfers/wonder_card_shadow_2.gbapal");
-const u16 gWonderCardShadowPal3[] = INCBIN_U16("graphics/wonder_transfers/wonder_card_shadow_3.gbapal");
-const u16 gWonderCardShadowPal4[] = INCBIN_U16("graphics/wonder_transfers/wonder_card_shadow_4.gbapal");
-const u16 gWonderCardShadowPal5[] = INCBIN_U16("graphics/wonder_transfers/wonder_card_shadow_5.gbapal");
-const u16 gWonderCardShadowPal6[] = INCBIN_U16("graphics/wonder_transfers/wonder_card_shadow_6.gbapal");
-const u16 gWonderCardShadowPal7[] = INCBIN_U16("graphics/wonder_transfers/wonder_card_shadow_7.gbapal");
-const u16 gWonderCardShadowPal8[] = INCBIN_U16("graphics/wonder_transfers/wonder_card_shadow_8.gbapal");
-const u32 gWonderCardShadowGfx[] = INCBIN_U32("graphics/wonder_transfers/wonder_card_shadow.4bpp.lz");
-
-const struct CompressedSpriteSheet gUnknown_082F1D00 = {
- gWonderCardShadowGfx, 0x100, 0x8000
-};
-const struct SpritePalette gUnknown_082F1D08[] = {
- {gWonderCardShadowPal1, 0x8000},
- {gWonderCardShadowPal2, 0x8000},
- {gWonderCardShadowPal3, 0x8000},
- {gWonderCardShadowPal4, 0x8000},
- {gWonderCardShadowPal5, 0x8000},
- {gWonderCardShadowPal6, 0x8000},
- {gWonderCardShadowPal7, 0x8000},
- {gWonderCardShadowPal8, 0x8000}
-};
-const struct SpriteTemplate gUnknown_082F1D48 = {
- 0x8000, 0x8000, &gOamData_AffineOff_ObjNormal_32x16, gDummySpriteAnimTable, NULL, gDummySpriteAffineAnimTable, SpriteCallbackDummy
-};
-const struct UnkStruct_8467FB8 gUnknown_082F1D60[8] = {
- {1, 0, 0, 0, gWonderCardBgGfx1, gWonderCardBgTilemap1, gWonderCardBgPal1},
- {1, 0, 0, 1, gWonderCardBgGfx2, gWonderCardBgTilemap2, gWonderCardBgPal2},
- {1, 0, 0, 2, gWonderCardBgGfx3, gWonderCardBgTilemap3, gWonderCardBgPal3},
- {1, 0, 0, 3, gWonderCardBgGfx3, gWonderCardBgTilemap3, gWonderCardBgPal4},
- {1, 0, 0, 4, gWonderCardBgGfx3, gWonderCardBgTilemap3, gWonderCardBgPal5},
- {1, 0, 0, 5, gWonderCardBgGfx3, gWonderCardBgTilemap3, gWonderCardBgPal6},
- {1, 0, 0, 6, gWonderCardBgGfx7, gWonderCardBgTilemap7, gWonderCardBgPal7},
- {1, 0, 0, 7, gWonderCardBgGfx8, gWonderCardBgTilemap8, gWonderCardBgPal8}
-};
-
-bool32 InitWonderCardResources(struct WonderCard * r5, struct MEventBuffer_3430_Sub * r6)
-{
- if (r5 == NULL || r6 == NULL)
- return FALSE;
- sWonderCardData = AllocZeroed(sizeof(struct UnkStruct_203F3C8));
- if (sWonderCardData == NULL)
- return FALSE;
- sWonderCardData->unk_0000 = *r5;
- sWonderCardData->unk_014C = *r6;
- if (sWonderCardData->unk_0000.unk_08_2 >= ARRAY_COUNT(gUnknown_082F1D60))
- sWonderCardData->unk_0000.unk_08_2 = 0;
- if (sWonderCardData->unk_0000.unk_08_0 >= ARRAY_COUNT(gUnknown_082F0E18))
- sWonderCardData->unk_0000.unk_08_0 = 0;
- if (sWonderCardData->unk_0000.unk_09 > ARRAY_COUNT(sWonderCardData->unk_017D))
- sWonderCardData->unk_0000.unk_09 = 0;
- sWonderCardData->unk_0170 = &gUnknown_082F1D60[sWonderCardData->unk_0000.unk_08_2];
- return TRUE;
-}
-
-void DestroyWonderCardResources(void)
-{
- if (sWonderCardData != NULL)
- {
- *sWonderCardData = (struct UnkStruct_203F3C8){};
- Free(sWonderCardData);
- sWonderCardData = NULL;
- }
-}
-
-s32 FadeToWonderCardMenu(void)
-{
- if (sWonderCardData == NULL)
- return -1;
- switch(sWonderCardData->unk_0174)
- {
- case 0:
- BeginNormalPaletteFade(PALETTES_ALL, 0, 0, 16, RGB_BLACK);
- break;
- case 1:
- if (UpdatePaletteFade())
- return 0;
- break;
- case 2:
- FillBgTilemapBufferRect_Palette0(0, 0x000, 0, 0, 30, 20);
- FillBgTilemapBufferRect_Palette0(1, 0x000, 0, 0, 30, 20);
- FillBgTilemapBufferRect_Palette0(2, 0x000, 0, 0, 30, 20);
- CopyBgTilemapBufferToVram(0);
- CopyBgTilemapBufferToVram(1);
- CopyBgTilemapBufferToVram(2);
- DecompressAndCopyTileDataToVram(2, sWonderCardData->unk_0170->tiles, 0, 0x008, 0);
- sWonderCardData->unk_0176[0] = AddWindow(&gUnknown_082F0E1C[0]);
- sWonderCardData->unk_0176[1] = AddWindow(&gUnknown_082F0E1C[1]);
- sWonderCardData->unk_0176[2] = AddWindow(&gUnknown_082F0E1C[2]);
- break;
- case 3:
- if (FreeTempTileDataBuffersIfPossible())
- return 0;
- LoadPalette(GetTextWindowPalette(1), 0x20, 0x20);
- gPaletteFade.bufferTransferDisabled = TRUE;
- LoadPalette(sWonderCardData->unk_0170->pal, 0x10, 0x20);
- LZ77UnCompWram(sWonderCardData->unk_0170->map, sWonderCardData->buffer_045C);
- CopyRectToBgTilemapBufferRect(2, sWonderCardData->buffer_045C, 0, 0, 30, 20, 0, 0, 30, 20, 1, 0x008, 0);
- CopyBgTilemapBufferToVram(2);
- break;
- case 4:
- sub_801BEF8();
- break;
- case 5:
- sub_801C178(0);
- sub_801C178(1);
- sub_801C178(2);
- CopyBgTilemapBufferToVram(1);
- break;
- case 6:
- LoadMonIconPalettes();
- break;
- case 7:
- ShowBg(1);
- ShowBg(2);
- gPaletteFade.bufferTransferDisabled = FALSE;
- sub_801C4C0();
- BeginNormalPaletteFade(PALETTES_ALL, 0, 16, 0, RGB_BLACK);
- UpdatePaletteFade();
- break;
- default:
- if (UpdatePaletteFade())
- return 0;
- sWonderCardData->unk_0174 = 0;
- return 1;
- }
- ++sWonderCardData->unk_0174;
- return 0;
-}
-
-s32 FadeOutFromWonderCard(bool32 flag)
-{
- if (sWonderCardData == NULL)
- return -1;
- switch (sWonderCardData->unk_0174)
- {
- case 0:
- BeginNormalPaletteFade(PALETTES_ALL, 0, 0, 16, RGB_BLACK);
- break;
- case 1:
- if (UpdatePaletteFade())
- return 0;
- break;
- case 2:
- FillBgTilemapBufferRect_Palette0(0, 0x000, 0, 0, 30, 20);
- FillBgTilemapBufferRect_Palette0(1, 0x000, 0, 0, 30, 20);
- FillBgTilemapBufferRect_Palette0(2, 0x000, 0, 0, 30, 20);
- CopyBgTilemapBufferToVram(0);
- CopyBgTilemapBufferToVram(1);
- CopyBgTilemapBufferToVram(2);
- break;
- case 3:
- HideBg(1);
- HideBg(2);
- RemoveWindow(sWonderCardData->unk_0176[2]);
- RemoveWindow(sWonderCardData->unk_0176[1]);
- RemoveWindow(sWonderCardData->unk_0176[0]);
- break;
- case 4:
- sub_801C61C();
- FreeMonIconPalettes();
- break;
- case 5:
- PrintMysteryGiftOrEReaderTopMenu(gGiftIsFromEReader, flag);
- CopyBgTilemapBufferToVram(0);
- BeginNormalPaletteFade(PALETTES_ALL, 0, 16, 0, RGB_BLACK);
- break;
- default:
- if (UpdatePaletteFade())
- return 0;
- sWonderCardData->unk_0174 = 0;
- return 1;
- }
- ++sWonderCardData->unk_0174;
- return 0;
-}
-
-void sub_801BEF8(void)
-{
- u16 i = 0;
- u16 r6;
- u16 sp0[3] = {0, 0, 0};
-
- memcpy(sWonderCardData->unk_018B, sWonderCardData->unk_0000.unk_0A, 40);
- sWonderCardData->unk_018B[40] = EOS;
- memcpy(sWonderCardData->unk_01B4, sWonderCardData->unk_0000.unk_32, 40);
- sWonderCardData->unk_01B4[40] = EOS;
- if (sWonderCardData->unk_0000.unk_04 > 999999)
- sWonderCardData->unk_0000.unk_04 = 999999;
- ConvertIntToDecimalStringN(sWonderCardData->unk_01DD, sWonderCardData->unk_0000.unk_04, STR_CONV_MODE_LEFT_ALIGN, 6);
- for (i = 0; i < 4; i++)
- {
- memcpy(sWonderCardData->unk_01E4[i], sWonderCardData->unk_0000.unk_5A[i], 40);
- sWonderCardData->unk_01E4[i][40] = EOS;
- }
- memcpy(sWonderCardData->unk_0288, sWonderCardData->unk_0000.unk_FA, 40);
- sWonderCardData->unk_0288[40] = EOS;
- switch (sWonderCardData->unk_0000.unk_08_0)
- {
- case 0:
- memcpy(sWonderCardData->unk_02B1, sWonderCardData->unk_0000.unk_122, 40);
- sWonderCardData->unk_02B1[40] = EOS;
- break;
- case 1:
- sWonderCardData->unk_02B1[00] = EOS;
- break;
- case 2:
- sWonderCardData->unk_02B1[00] = EOS;
- sp0[0] = sWonderCardData->unk_014C.unk_00 < 999 ? sWonderCardData->unk_014C.unk_00 : 999;
- sp0[1] = sWonderCardData->unk_014C.unk_02 < 999 ? sWonderCardData->unk_014C.unk_02 : 999;
- sp0[2] = sWonderCardData->unk_014C.unk_04 < 999 ? sWonderCardData->unk_014C.unk_04 : 999;
- for (i = 0; i < 8; i++)
- {
- memset(sWonderCardData->unk_02DC[i].unk_42, EOS, 4);
- memset(sWonderCardData->unk_02DC[i].unk_01, EOS, 41);
- }
- for (i = 0, r6 = 0; i < 40; i++)
- {
- if (sWonderCardData->unk_0000.unk_122[i] != 0xF7)
- {
- sWonderCardData->unk_02DC[sWonderCardData->unk_0175].unk_01[r6] = sWonderCardData->unk_0000.unk_122[i];
- r6++;
- }
- else
- {
- u8 r3 = sWonderCardData->unk_0000.unk_122[i + 1];
- if (r3 > 2)
- {
- i += 2;
- }
- else
- {
- ConvertIntToDecimalStringN(sWonderCardData->unk_02DC[sWonderCardData->unk_0175].unk_42, sp0[r3], STR_CONV_MODE_LEADING_ZEROS, 3);
- sWonderCardData->unk_02DC[sWonderCardData->unk_0175].unk_00 = sWonderCardData->unk_0000.unk_122[i + 2];
- sWonderCardData->unk_0175++;
- if (sWonderCardData->unk_0175 > 7)
- break;
- r6 = 0;
- i += 2;
- }
- }
- }
- }
-}
-
-void sub_801C178(u8 whichWindow)
-{
- s8 sp0C = 0;
- s32 windowId = sWonderCardData->unk_0176[whichWindow];
- PutWindowTilemap(windowId);
- FillWindowPixelBuffer(windowId, 0);
- switch (whichWindow)
- {
- case 0:
- {
- s32 x;
- AddTextPrinterParameterized3(windowId, 3, 0, 1, sTextColorTable[sWonderCardData->unk_0170->textPal1], 0, sWonderCardData->unk_018B);
- x = 160 - GetStringWidth(3, sWonderCardData->unk_01B4, GetFontAttribute(3, 2));
- if (x < 0)
- x = 0;
- AddTextPrinterParameterized3(windowId, 3, x, 17, sTextColorTable[sWonderCardData->unk_0170->textPal1], 0, sWonderCardData->unk_01B4);
- if (sWonderCardData->unk_0000.unk_04 != 0)
- {
- AddTextPrinterParameterized3(windowId, 1, 166, 17, sTextColorTable[sWonderCardData->unk_0170->textPal1], 0, sWonderCardData->unk_01DD);
- }
- break;
- }
- case 1:
- for (; sp0C < 4; sp0C++)
- {
- AddTextPrinterParameterized3(windowId, 3, 0, 16 * sp0C + 2, sTextColorTable[sWonderCardData->unk_0170->textPal2], 0, sWonderCardData->unk_01E4[sp0C]);
- }
- break;
- case 2:
- AddTextPrinterParameterized3(windowId, 3, 0, gUnknown_082F0E18[sWonderCardData->unk_0000.unk_08_0], sTextColorTable[sWonderCardData->unk_0170->textPal3], 0, sWonderCardData->unk_0288);
- if (sWonderCardData->unk_0000.unk_08_0 != 2)
- {
- AddTextPrinterParameterized3(windowId, 3, 0, 16 + gUnknown_082F0E18[sWonderCardData->unk_0000.unk_08_0], sTextColorTable[sWonderCardData->unk_0170->textPal3], 0, sWonderCardData->unk_02B1);
- }
- else
- {
- s32 x = 0;
- s32 y = gUnknown_082F0E18[sWonderCardData->unk_0000.unk_08_0] + 16;
- s32 spacing = GetFontAttribute(3, 2);
- for (; sp0C < sWonderCardData->unk_0175; sp0C++)
- {
- AddTextPrinterParameterized3(windowId, 3, x, y, sTextColorTable[sWonderCardData->unk_0170->textPal3], 0, sWonderCardData->unk_02DC[sp0C].unk_01);
- if (sWonderCardData->unk_02DC[sp0C].unk_42[0] != EOS)
- {
- x += GetStringWidth(3, sWonderCardData->unk_02DC[sp0C].unk_01, spacing);
- AddTextPrinterParameterized3(windowId, 3, x, y, sTextColorTable[sWonderCardData->unk_0170->textPal3], 0, sWonderCardData->unk_02DC[sp0C].unk_42);
- x += GetStringWidth(3, sWonderCardData->unk_02DC[sp0C].unk_42, spacing) + sWonderCardData->unk_02DC[sp0C].unk_00;
- }
- }
- }
- break;
- }
- CopyWindowToVram(windowId, 3);
-}
-
-void sub_801C4C0(void)
-{
- u8 r7 = 0;
- sWonderCardData->unk_017C = 0xFF;
- if (sWonderCardData->unk_014C.unk_06 != SPECIES_NONE)
- {
- sWonderCardData->unk_017C = CreateMonIconNoPersonality(GetIconSpeciesNoPersonality(sWonderCardData->unk_014C.unk_06), SpriteCallbackDummy, 0xDC, 0x14, 0, FALSE);
- gSprites[sWonderCardData->unk_017C].oam.priority = 2;
- }
- if (sWonderCardData->unk_0000.unk_09 != 0 && sWonderCardData->unk_0000.unk_08_0 == 1)
- {
- LoadCompressedSpriteSheetUsingHeap(&gUnknown_082F1D00);
- LoadSpritePalette(&gUnknown_082F1D08[sWonderCardData->unk_0170->textPal4]);
- for (; r7 < sWonderCardData->unk_0000.unk_09; r7++)
- {
- sWonderCardData->unk_017D[r7][0] = 0xFF;
- sWonderCardData->unk_017D[r7][1] = 0xFF;
- sWonderCardData->unk_017D[r7][0] = CreateSprite(&gUnknown_082F1D48, 0xd8 - 32 * r7, 0x90, 8);
- if (sWonderCardData->unk_014C.unk_08[0][r7] != 0)
- {
- sWonderCardData->unk_017D[r7][1] = CreateMonIconNoPersonality(GetIconSpeciesNoPersonality(sWonderCardData->unk_014C.unk_08[0][r7]), SpriteCallbackDummy, 0xd8 - 32 * r7, 0x88, 0, 0);
- }
- }
- }
-}
-
-void sub_801C61C(void)
-{
- u8 r6 = 0;
- if (sWonderCardData->unk_017C != 0xFF)
- FreeAndDestroyMonIconSprite(&gSprites[sWonderCardData->unk_017C]);
- if (sWonderCardData->unk_0000.unk_09 != 0 && sWonderCardData->unk_0000.unk_08_0 == 1)
- {
- for (; r6 < sWonderCardData->unk_0000.unk_09; r6++)
- {
- if (sWonderCardData->unk_017D[r6][0] != 0xFF)
- {
- DestroySprite(&gSprites[sWonderCardData->unk_017D[r6][0]]);
- }
- if (sWonderCardData->unk_017D[r6][1] != 0xFF)
- {
- FreeAndDestroyMonIconSprite(&gSprites[sWonderCardData->unk_017D[r6][1]]);
- }
- }
- FreeSpriteTilesByTag(0x8000);
- FreeSpritePaletteByTag(0x8000);
- }
-}
-
-struct UnkStruct_203F3CC
-{
- /*0000*/ struct WonderNews unk_0000;
- /*01bc*/ const struct UnkStruct_8467FB8 * unk_01BC;
- /*01c0*/ u8 unk_01C0_0:1;
- u8 unk_01C0_1:7;
- /*01c1*/ u8 unk_01C1;
- /*01c2*/ u8 unk_01C2_0:1;
- u8 unk_01C2_1:7;
- /*01c3*/ u8 unk_01C3_0:1;
- u8 unk_01C3_1:7;
- /*01c4*/ u16 unk_01C4;
- /*01c6*/ u16 unk_01C6;
- /*01c8*/ u16 unk_01C8[2];
- /*01cc*/ u8 filler_01CC[2];
- /*01ce*/ u8 unk_01CE[41];
- /*01f7*/ u8 unk_01F7[10][41];
- /*0394*/ struct ScrollArrowsTemplate unk_0394;
- /*03a4*/ u8 buffer_03A4[0x1000];
-};
-
-EWRAM_DATA struct UnkStruct_203F3CC * sWonderNewsData = NULL;
-
-void sub_801CDCC(void);
-void sub_801CE7C(void);
-void sub_801CFA4(void);
-
-const u8 gUnknown_082F1DE0[][3] = {
- {0, 2, 3},
- {0, 1, 2}
-};
-const struct WindowTemplate gUnknown_082F1DE8[] = {
- {
- .bg = 0,
- .tilemapLeft = 1,
- .tilemapTop = 0,
- .width = 28,
- .height = 3,
- .paletteNum = 2,
- .baseBlock = 0x2AC
- }, {
- .bg = 2,
- .tilemapLeft = 1,
- .tilemapTop = 3,
- .width = 28,
- .height = 20,
- .paletteNum = 2,
- .baseBlock = 0x07C
- }
-};
-const struct ScrollArrowsTemplate gUnknown_082F1DF8 = {
- 0x02, 0xe8, 0x18, 0x03, 0xe8, 0x98,
- 0x0000, 0x0002, 0x1000, 0x1000, 0x0
-};
-const u16 gWonderNewsPal1[] = INCBIN_U16("graphics/wonder_transfers/wonder_news_1.gbapal");
-const u16 gWonderNewsPal7[] = INCBIN_U16("graphics/wonder_transfers/wonder_news_7.gbapal");
-const u16 gWonderNewsPal8[] = INCBIN_U16("graphics/wonder_transfers/wonder_news_8.gbapal");
-const u32 gWonderNewsGfx1[] = INCBIN_U32("graphics/wonder_transfers/wonder_news_1.4bpp.lz");
-const u32 gWonderNewsTilemap1[] = INCBIN_U32("graphics/wonder_transfers/wonder_news_1.bin.lz");
-const u32 gWonderNewsGfx2[] = INCBIN_U32("graphics/wonder_transfers/wonder_news_2.4bpp.lz");
-const u32 gWonderNewsTilemap2[] = INCBIN_U32("graphics/wonder_transfers/wonder_news_2.bin.lz");
-const u32 gWonderNewsGfx3[] = INCBIN_U32("graphics/wonder_transfers/wonder_news_3.4bpp.lz");
-const u32 gWonderNewsTilemap3[] = INCBIN_U32("graphics/wonder_transfers/wonder_news_3.bin.lz");
-const u32 gWonderNewsGfx7[] = INCBIN_U32("graphics/wonder_transfers/wonder_news_7.4bpp.lz");
-const u32 gWonderNewsTilemap7[] = INCBIN_U32("graphics/wonder_transfers/wonder_news_7.bin.lz");
-const u32 gWonderNewsGfx8[] = INCBIN_U32("graphics/wonder_transfers/wonder_news_8.4bpp.lz");
-const u32 gWonderNewsTilemap8[] = INCBIN_U32("graphics/wonder_transfers/wonder_news_8.bin.lz");
-
-const struct UnkStruct_8467FB8 gUnknown_082F24C8[] = {
- {1, 0, 0, 0, gWonderNewsGfx1, gWonderNewsTilemap1, gWonderNewsPal1},
- {1, 0, 0, 0, gWonderNewsGfx2, gWonderNewsTilemap2, gWonderCardBgPal2},
- {1, 0, 0, 0, gWonderNewsGfx3, gWonderNewsTilemap3, gWonderCardBgPal3},
- {1, 0, 0, 0, gWonderNewsGfx3, gWonderNewsTilemap3, gWonderCardBgPal4},
- {1, 0, 0, 0, gWonderNewsGfx3, gWonderNewsTilemap3, gWonderCardBgPal5},
- {1, 0, 0, 0, gWonderNewsGfx3, gWonderNewsTilemap3, gWonderCardBgPal6},
- {1, 0, 0, 0, gWonderNewsGfx7, gWonderNewsTilemap7, gWonderNewsPal7},
- {1, 0, 0, 0, gWonderNewsGfx8, gWonderNewsTilemap8, gWonderNewsPal8}
-};
-
-bool32 InitWonderNewsResources(const struct WonderNews * a0)
-{
- if (a0 == NULL)
- return FALSE;
- sWonderNewsData = AllocZeroed(sizeof(struct UnkStruct_203F3CC));
- if (sWonderNewsData == NULL)
- return FALSE;
- sWonderNewsData->unk_0000 = *a0;
- if (sWonderNewsData->unk_0000.unk_03 >= ARRAY_COUNT(gUnknown_082F24C8))
- sWonderNewsData->unk_0000.unk_03 = 0;
- sWonderNewsData->unk_01BC = &gUnknown_082F24C8[sWonderNewsData->unk_0000.unk_03];
- sWonderNewsData->unk_01C1 = 0xFF;
- return TRUE;
-}
-
-void DestroyWonderNewsResources(void)
-{
- if (sWonderNewsData != NULL)
- {
- *sWonderNewsData = (struct UnkStruct_203F3CC){};
- Free(sWonderNewsData);
- sWonderNewsData = NULL;
- }
-}
-
-s32 FadeToWonderNewsMenu(void)
-{
- if (sWonderNewsData == NULL)
- return -1;
-
- switch (sWonderNewsData->unk_01C0_1)
- {
- case 0:
- BeginNormalPaletteFade(PALETTES_ALL, 0, 0, 16, RGB_BLACK);
- break;
- case 1:
- if (UpdatePaletteFade())
- return 0;
- ChangeBgY(0, 0, 0);
- ChangeBgY(1, 0, 0);
- ChangeBgY(2, 0, 0);
- ChangeBgY(3, 0, 0);
- SetGpuReg(REG_OFFSET_WIN0H, WIN_RANGE(0, DISPLAY_WIDTH));
- SetGpuReg(REG_OFFSET_WIN0V, WIN_RANGE(26, 152));
- SetGpuReg(REG_OFFSET_WININ, WININ_WIN0_BG_ALL | WININ_WIN0_OBJ);
- SetGpuReg(REG_OFFSET_WINOUT, WINOUT_WIN01_BG0 | WINOUT_WIN01_BG1 | WINOUT_WIN01_BG3 | WINOUT_WIN01_OBJ);
- SetGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_WIN0_ON);
- break;
- case 2:
- FillBgTilemapBufferRect_Palette0(0, 0x000, 0, 0, 30, 20);
- FillBgTilemapBufferRect_Palette0(1, 0x000, 0, 0, 30, 20);
- FillBgTilemapBufferRect_Palette0(2, 0x000, 0, 0, 30, 20);
- FillBgTilemapBufferRect_Palette0(3, 0x000, 0, 0, 30, 20);
- CopyBgTilemapBufferToVram(0);
- CopyBgTilemapBufferToVram(1);
- CopyBgTilemapBufferToVram(2);
- CopyBgTilemapBufferToVram(3);
- DecompressAndCopyTileDataToVram(3, sWonderNewsData->unk_01BC->tiles, 0, 8, 0);
- sWonderNewsData->unk_01C8[0] = AddWindow(&gUnknown_082F1DE8[0]);
- sWonderNewsData->unk_01C8[1] = AddWindow(&gUnknown_082F1DE8[1]);
- break;
- case 3:
- if (FreeTempTileDataBuffersIfPossible())
- return 0;
- LoadPalette(GetTextWindowPalette(1), 0x20, 0x20);
- gPaletteFade.bufferTransferDisabled = TRUE;
- LoadPalette(sWonderNewsData->unk_01BC->pal, 0x10, 0x20);
- LZ77UnCompWram(sWonderNewsData->unk_01BC->map, sWonderNewsData->buffer_03A4);
- CopyRectToBgTilemapBufferRect(1, sWonderNewsData->buffer_03A4, 0, 0, 30, 3, 0, 0, 30, 3, 1, 8, 0);
- CopyRectToBgTilemapBufferRect(3, sWonderNewsData->buffer_03A4, 0, 3, 30, 23, 0, 3, 30, 23, 1, 8, 0);
- CopyBgTilemapBufferToVram(1);
- CopyBgTilemapBufferToVram(3);
- break;
- case 4:
- sub_801CDCC();
- break;
- case 5:
- sub_801CE7C();
- CopyBgTilemapBufferToVram(0);
- CopyBgTilemapBufferToVram(2);
- break;
- case 6:
- ShowBg(1);
- ShowBg(2);
- ShowBg(3);
- gPaletteFade.bufferTransferDisabled = FALSE;
- sWonderNewsData->unk_01C1 = AddScrollIndicatorArrowPair(&sWonderNewsData->unk_0394, &sWonderNewsData->unk_01C6);
- BeginNormalPaletteFade(PALETTES_ALL, 0, 16, 0, RGB_BLACK);
- UpdatePaletteFade();
- break;
- default:
- if (UpdatePaletteFade())
- return 0;
- sWonderNewsData->unk_01C0_1 = 0;
- return 1;
- }
-
- ++sWonderNewsData->unk_01C0_1;
- return 0;
-}
-
-s32 FadeOutFromWonderNews(bool32 flag)
-{
- if (sWonderNewsData == NULL)
- return -1;
- switch (sWonderNewsData->unk_01C0_1)
- {
- case 0:
- BeginNormalPaletteFade(PALETTES_ALL, 0, 0, 16, RGB_BLACK);
- break;
- case 1:
- if (UpdatePaletteFade())
- return 0;
- ChangeBgY(2, 0, 0);
- SetGpuReg(REG_OFFSET_WIN0H, 0);
- SetGpuReg(REG_OFFSET_WIN0V, 0);
- SetGpuReg(REG_OFFSET_WININ, 0);
- SetGpuReg(REG_OFFSET_WINOUT, 0);
- ClearGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_WIN0_ON);
- break;
- case 2:
- FillBgTilemapBufferRect_Palette0(0, 0x000, 0, 0, 30, 20);
- FillBgTilemapBufferRect_Palette0(1, 0x000, 0, 0, 30, 20);
- FillBgTilemapBufferRect_Palette0(2, 0x000, 0, 0, 30, 24);
- FillBgTilemapBufferRect_Palette0(3, 0x000, 0, 0, 30, 24);
- CopyBgTilemapBufferToVram(0);
- CopyBgTilemapBufferToVram(1);
- CopyBgTilemapBufferToVram(2);
- CopyBgTilemapBufferToVram(3);
- break;
- case 3:
- HideBg(1);
- HideBg(2);
- RemoveWindow(sWonderNewsData->unk_01C8[1]);
- RemoveWindow(sWonderNewsData->unk_01C8[0]);
- break;
- case 4:
- ChangeBgY(2, 0, 0);
- ChangeBgY(3, 0, 0);
- if (sWonderNewsData->unk_01C1 != 0xFF)
- {
- RemoveScrollIndicatorArrowPair(sWonderNewsData->unk_01C1);
- sWonderNewsData->unk_01C1 = 0xFF;
- }
- break;
- case 5:
- PrintMysteryGiftOrEReaderTopMenu(gGiftIsFromEReader, flag);
- MG_DrawCheckerboardPattern(3);
- CopyBgTilemapBufferToVram(0);
- CopyBgTilemapBufferToVram(3);
- BeginNormalPaletteFade(PALETTES_ALL, 0, 16, 0, RGB_BLACK);
- break;
- default:
- if (UpdatePaletteFade())
- return 0;
- sWonderNewsData->unk_01C0_1 = 0;
- return 1;
- }
- ++sWonderNewsData->unk_01C0_1;
- return 0;
-}
-
-void MENews_RemoveScrollIndicatorArrowPair(void)
-{
- if (!sWonderNewsData->unk_01C0_0 && sWonderNewsData->unk_01C1 != 0xFF)
- {
- RemoveScrollIndicatorArrowPair(sWonderNewsData->unk_01C1);
- sWonderNewsData->unk_01C1 = 0xFF;
- sWonderNewsData->unk_01C0_0 = TRUE;
- }
-}
-
-
-void MENews_AddScrollIndicatorArrowPair(void)
-{
- if (sWonderNewsData->unk_01C0_0)
- {
- sWonderNewsData->unk_01C1 = AddScrollIndicatorArrowPair(&sWonderNewsData->unk_0394, &sWonderNewsData->unk_01C6);
- sWonderNewsData->unk_01C0_0 = FALSE;
- }
-}
-
-u32 MENews_GetInput(u16 input)
-{
- if (sWonderNewsData->unk_01C2_0)
- {
- sub_801CFA4();
- return 0xFF;
- }
- switch (input)
- {
- case A_BUTTON:
- return 0;
- case B_BUTTON:
- return 1;
- case DPAD_UP:
- if (sWonderNewsData->unk_01C6 == 0)
- return 0xFF;
- if (sWonderNewsData->unk_01C0_0)
- return 0xFF;
- sWonderNewsData->unk_01C3_0 = FALSE;
- break;
- case DPAD_DOWN:
- if (sWonderNewsData->unk_01C6 == sWonderNewsData->unk_01C4)
- return 0xFF;
- if (sWonderNewsData->unk_01C0_0)
- return 0xFF;
- sWonderNewsData->unk_01C3_0 = TRUE;
- break;
- default:
- return 0xFF;
- }
- sWonderNewsData->unk_01C2_0 = TRUE;
- sWonderNewsData->unk_01C2_1 = 2;
- sWonderNewsData->unk_01C3_1 = 0;
- if (sWonderNewsData->unk_01C3_0 == FALSE)
- return 2;
- else
- return 3;
-}
-
-void sub_801CDCC(void)
-{
- u8 i = 0;
- memcpy(sWonderNewsData->unk_01CE, sWonderNewsData->unk_0000.unk_04, 40);
- sWonderNewsData->unk_01CE[40] = EOS;
- for (; i < 10; ++i)
- {
- memcpy(sWonderNewsData->unk_01F7[i], sWonderNewsData->unk_0000.unk_2C[i], 40);
- sWonderNewsData->unk_01F7[i][40] = EOS;
- if (i > 7 && sWonderNewsData->unk_01F7[i][0] != EOS)
- ++sWonderNewsData->unk_01C4;
- }
- sWonderNewsData->unk_0394 = gUnknown_082F1DF8;
- sWonderNewsData->unk_0394.fullyDownThreshold = sWonderNewsData->unk_01C4;
-}
-
-void sub_801CE7C(void)
-{
- u8 i = 0;
- s32 x;
- PutWindowTilemap(sWonderNewsData->unk_01C8[0]);
- PutWindowTilemap(sWonderNewsData->unk_01C8[1]);
- FillWindowPixelBuffer(sWonderNewsData->unk_01C8[0], 0);
- FillWindowPixelBuffer(sWonderNewsData->unk_01C8[1], 0);
- x = (0xe0 - GetStringWidth(3, sWonderNewsData->unk_01CE, GetFontAttribute(3, 2))) / 2;
- if (x < 0)
- x = 0;
- AddTextPrinterParameterized3(sWonderNewsData->unk_01C8[0], 3, x, 6, gUnknown_082F1DE0[sWonderNewsData->unk_01BC->textPal1], 0, sWonderNewsData->unk_01CE);
- for (; i < 10; ++i)
- {
- AddTextPrinterParameterized3(sWonderNewsData->unk_01C8[1], 3, 0, 16 * i + 2, gUnknown_082F1DE0[sWonderNewsData->unk_01BC->textPal2], 0, sWonderNewsData->unk_01F7[i]);
- }
- CopyWindowToVram(sWonderNewsData->unk_01C8[0], 3);
- CopyWindowToVram(sWonderNewsData->unk_01C8[1], 3);
-}
-
-void sub_801CFA4(void)
-{
- u16 r4 = sWonderNewsData->unk_01C2_1;
- r4 <<= 8;
- if (sWonderNewsData->unk_01C3_0)
- {
- ChangeBgY(2, r4, 1);
- ChangeBgY(3, r4, 1);
- }
- else
- {
- ChangeBgY(2, r4, 2);
- ChangeBgY(3, r4, 2);
- }
- sWonderNewsData->unk_01C3_1 += sWonderNewsData->unk_01C2_1;
- if (sWonderNewsData->unk_01C3_1 > 15)
- {
- if (sWonderNewsData->unk_01C3_0)
- ++sWonderNewsData->unk_01C6;
- else
- --sWonderNewsData->unk_01C6;
- sWonderNewsData->unk_01C2_0 = FALSE;
- sWonderNewsData->unk_01C3_1 = 0;
- }
-}
diff --git a/src/mevent_client.c b/src/mevent_client.c
deleted file mode 100644
index 9a62bf18e..000000000
--- a/src/mevent_client.c
+++ /dev/null
@@ -1,291 +0,0 @@
-#include "global.h"
-#include "malloc.h"
-#include "decompress.h"
-#include "overworld.h"
-#include "script.h"
-#include "battle_tower.h"
-#include "mevent.h"
-#include "mystery_event_script.h"
-#include "mevent_client.h"
-
-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 gUnknown_082F2598[];
-
-void mevent_client_do_init(u32 arg)
-{
- s_mevent_client_ptr = AllocZeroed(sizeof(struct mevent_client));
- mevent_client_init(s_mevent_client_ptr, 1, 0);
- s_mevent_client_ptr->unk_4C = arg;
-}
-
-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 mainseq_0(struct mevent_client * svr)
-{
- // init
- memcpy(svr->cmdBuffer, gUnknown_082F2598, ME_SEND_BUF_SIZE);
- svr->cmdidx = 0;
- svr->mainseqno = 4;
- svr->flag = 0;
- return 0;
-}
-
-static u32 mainseq_1(struct mevent_client * svr)
-{
- // done
- return 6;
-}
-
-
-static u32 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 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 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:
- sub_801B580(svr->sendBuffer, svr->unk_4C);
- mevent_srv_sub_init_send(&svr->manager, 0x11, svr->sendBuffer, sizeof(struct MEventStruct_Unk1442CC));
- break;
- case 14:
- mevent_client_send_word(svr, 0x13, svr->param);
- break;
- case 10:
- sub_801B21C(svr->recvBuffer);
- break;
- case 9:
- if (!sub_801B1A4(svr->recvBuffer))
- {
- sub_801B078(svr->recvBuffer);
- mevent_client_send_word(svr, 0x13, 0);
- }
- else
- mevent_client_send_word(svr, 0x13, 1);
- break;
- case 15:
- svr->mainseqno = 6;
- svr->flag = 0;
- break;
- case 16:
- sub_801B508(svr->recvBuffer);
- break;
- case 17:
- InitRamScript_NoObjectEvent(svr->recvBuffer, 1000);
- break;
- case 18:
- memcpy(&gSaveBlock2Ptr->frontier.ereaderTrainer, svr->recvBuffer, 0xbc);
- ValidateEReaderTrainer();
- break;
- case 21:
- memcpy(gDecompressionBuffer, svr->recvBuffer, ME_SEND_BUF_SIZE);
- svr->mainseqno = 7;
- svr->flag = 0;
- break;
- }
-
- return 1;
-}
-
-static u32 mainseq_5(struct mevent_client * svr)
-{
- // wait flag
- if (svr->flag)
- {
- svr->mainseqno = 4;
- svr->flag = 0;
- }
- return 1;
-}
-
-static u32 mainseq_6(struct mevent_client * svr)
-{
- // ???
- switch (svr->flag)
- {
- case 0:
- sub_8153870(svr->recvBuffer);
- ++svr->flag;
- break;
- case 1:
- if (!sub_8153884(&svr->param))
- {
- svr->mainseqno = 4;
- svr->flag = 0;
- }
- break;
- }
- return 1;
-}
-
-static u32 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 *) = {
- mainseq_0,
- mainseq_1,
- mainseq_2,
- mainseq_3,
- mainseq_4,
- mainseq_5,
- mainseq_6,
- mainseq_7
- };
- return funcs[svr->mainseqno](svr);
-}
diff --git a/src/mevent_news.c b/src/mevent_news.c
deleted file mode 100644
index 9e78cf406..000000000
--- a/src/mevent_news.c
+++ /dev/null
@@ -1,148 +0,0 @@
-#include "global.h"
-#include "mevent.h"
-#include "random.h"
-#include "event_data.h"
-#include "mevent_news.h"
-
-static u32 sub_801DCAC(struct MysteryEventStruct *);
-static void sub_801DD10(struct MysteryEventStruct *);
-static u32 sub_801DD44(struct MysteryEventStruct *);
-static void sub_801DCD8(struct MysteryEventStruct *);
-static void sub_801DCCC(struct MysteryEventStruct *);
-
-void GenerateRandomNews(u32 a0)
-{
- struct MysteryEventStruct *r5 = sub_801B044();
-
- r5->unk_0_0 = a0;
- switch (a0)
- {
- case 0:
- break;
- case 1:
- case 2:
- r5->unk_1 = (Random() % 15) + 16;
- break;
- case 3:
- r5->unk_1 = (Random() % 15) + 1;
- break;
- }
-}
-
-void sub_801DBC0(void)
-{
- struct MysteryEventStruct *r5 = sub_801B044();
-
- r5->unk_0_0 = 0;
- r5->unk_0_2 = 0;
- r5->unk_0_5 = 0;
- r5->unk_1 = 0;
- VarSet(VAR_0x402E, 0);
-}
-
-void sub_801DBDC(void)
-{
- u16 *r4 = GetVarPointer(VAR_0x402E);
- struct MysteryEventStruct *r2 = sub_801B044();
- struct MysteryEventStruct r0 = *r2;
-
- if ((u8)r0.unk_0_5 > 4 && ++(*r4) > 0x1f3)
- {
- r2->unk_0_5 = 0;
- *r4 = 0;
- }
-}
-
-// Unused
-u16 sub_801DC20(void)
-{
- u16 *r6 = &gSpecialVar_Result;
- struct MysteryEventStruct *r4 = sub_801B044();
- u16 r5;
-
- if (!IsMysteryEventEnabled() || !ValidateReceivedWonderNews())
- return 0;
-
- r5 = sub_801DD44(r4);
-
- switch (r5)
- {
- case 0:
- break;
- case 1:
- *r6 = sub_801DCAC(r4);
- break;
- case 2:
- *r6 = sub_801DCAC(r4);
- break;
- case 3:
- break;
- case 4:
- *r6 = sub_801DCAC(r4);
- sub_801DCD8(r4);
- break;
- case 5:
- *r6 = sub_801DCAC(r4);
- sub_801DCCC(r4);
- break;
- case 6:
- break;
- }
-
- return r5;
-}
-
-static u32 sub_801DCAC(struct MysteryEventStruct *a0)
-{
- u32 r4;
-
- a0->unk_0_0 = 0;
- r4 = a0->unk_1 + 0x84;
- a0->unk_1 = 0;
- sub_801DD10(a0);
- return r4;
-}
-
-static void sub_801DCCC(struct MysteryEventStruct *a0)
-{
- a0->unk_0_2 = 0;
-}
-
-static void sub_801DCD8(struct MysteryEventStruct *a0)
-{
- a0->unk_0_2++;
- if ((u8)a0->unk_0_2 > 4)
- a0->unk_0_2 = 4;
-}
-
-static void sub_801DD10(struct MysteryEventStruct *a0)
-{
- a0->unk_0_5++;
- if ((u8)a0->unk_0_5 > 5)
- a0->unk_0_5 = 5;
-}
-
-static u32 sub_801DD44(struct MysteryEventStruct *a0)
-{
- struct MysteryEventStruct 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(0);
- return 0;
- }
-}
diff --git a/src/mevent_scripts.c b/src/mevent_scripts.c
deleted file mode 100644
index 41a5ddd51..000000000
--- a/src/mevent_scripts.c
+++ /dev/null
@@ -1,191 +0,0 @@
-#include "global.h"
-#include "mevent_client.h"
-#include "mevent_server.h"
-
-const u8 gText_CanceledReadingCard[] = _("Canceled reading\nthe Card.");
-
-
-const struct mevent_client_cmd gUnknown_082F2598[] = {
- {.instr = 2, .parameter = 16},
- {.instr = 4, .parameter = 0}
-};
-
-const struct mevent_client_cmd gUnknown_082F25A8[] = {
- {.instr = 8, .parameter = 0},
- {.instr = 3, .parameter = 0},
- {.instr = 2, .parameter = 16},
- {.instr = 4, .parameter = 0}
-};
-
-const struct mevent_client_cmd gUnknown_082F25C8[] = {
- {.instr = 20, .parameter = 0},
- {.instr = 1, .parameter = 10}
-};
-
-const struct mevent_client_cmd gUnknown_082F25D8[] = {
- {.instr = 20, .parameter = 0},
- {.instr = 1, .parameter = 11}
-};
-
-const struct mevent_client_cmd gUnknown_082F25E8[] = {
- {.instr = 20, .parameter = 0},
- {.instr = 1, .parameter = 0}
-};
-
-const struct mevent_client_cmd gUnknown_082F25F8[] = {
- {.instr = 2, .parameter = 22},
- {.instr = 10, .parameter = 0},
- {.instr = 2, .parameter = 25},
- {.instr = 17, .parameter = 0},
- {.instr = 20, .parameter = 0},
- {.instr = 1, .parameter = 2}
-};
-
-const struct mevent_client_cmd gUnknown_082F2628[] = {
- {.instr = 2, .parameter = 23},
- {.instr = 9, .parameter = 0},
- {.instr = 3, .parameter = 0},
- {.instr = 2, .parameter = 16},
- {.instr = 4, .parameter = 0}
-};
-
-const struct mevent_client_cmd gUnknown_082F2650[] = {
- {.instr = 20, .parameter = 0},
- {.instr = 1, .parameter = 7}
-};
-
-const struct mevent_client_cmd gUnknown_082F2660[] = {
- {.instr = 20, .parameter = 0},
- {.instr = 1, .parameter = 3}
-};
-
-const struct mevent_client_cmd gUnknown_082F2670[] = {
- {.instr = 13, .parameter = 0},
- {.instr = 14, .parameter = 0},
- {.instr = 3, .parameter = 0},
- {.instr = 2, .parameter = 16},
- {.instr = 4, .parameter = 0}
-};
-
-const struct mevent_client_cmd gUnknown_082F2698[] = {
- {.instr = 20, .parameter = 0},
- {.instr = 1, .parameter = 9}
-};
-
-const struct mevent_client_cmd gUnknown_082F26A8[] = {
- {.instr = 20, .parameter = 0},
- {.instr = 1, .parameter = 5}
-};
-
-const struct mevent_client_cmd gUnknown_082F26B8[] = {
- {.instr = 2, .parameter = 21},
- {.instr = 12, .parameter = 0},
- {.instr = 20, .parameter = 0},
- {.instr = 1, .parameter = 14},
- {.instr = 2, .parameter = 21},
- {.instr = 12, .parameter = 0},
- {.instr = 20, .parameter = 0},
- {.instr = 1, .parameter = 13}
-};
-
-const struct mevent_cmd gUnknown_082F26F8[] = {
- {.instr = 18, .flag = 0x10, .parameter = gUnknown_082F25C8},
- {.instr = 1, .flag = 0x00, .parameter = NULL},
- {.instr = 2, .flag = 0x14, .parameter = NULL},
- {.instr = 0, .flag = 0x0a, .parameter = NULL},
- {.instr = 18, .flag = 0x10, .parameter = gUnknown_082F25D8},
- {.instr = 1, .flag = 0x00, .parameter = NULL},
- {.instr = 2, .flag = 0x14, .parameter = NULL},
- {.instr = 0, .flag = 0x0b, .parameter = NULL},
- {.instr = 18, .flag = 0x10, .parameter = gUnknown_082F2698},
- {.instr = 1, .flag = 0x00, .parameter = NULL},
- {.instr = 2, .flag = 0x14, .parameter = NULL},
- {.instr = 0, .flag = 0x09, .parameter = NULL}
-};
-
-const struct mevent_cmd gUnknown_082F2788[] = {
- {.instr = 18, .flag = 0x20, .parameter = gUnknown_082F26B8},
- {.instr = 1, .flag = 0x00, .parameter = NULL},
- {.instr = 20, .flag = 0x1b, .parameter = gText_CanceledReadingCard},
- {.instr = 1, .flag = 0x00, .parameter = NULL},
- {.instr = 2, .flag = 0x14, .parameter = NULL},
- {.instr = 0, .flag = 0x09, .parameter = NULL}
-};
-
-const struct mevent_cmd gUnknown_082F27D0[] = {
- {.instr = 18, .flag = 0x10, .parameter = gUnknown_082F2650},
- {.instr = 1, .flag = 0x00, .parameter = NULL},
- {.instr = 2, .flag = 0x14, .parameter = NULL},
- {.instr = 0, .flag = 0x07, .parameter = NULL}
-};
-
-const struct mevent_cmd gUnknown_082F2800[] = {
- {.instr = 18, .flag = 0x28, .parameter = gUnknown_082F2628},
- {.instr = 1, .flag = 0x00, .parameter = NULL},
- {.instr = 14, .flag = 0x00, .parameter = NULL},
- {.instr = 1, .flag = 0x00, .parameter = NULL},
- {.instr = 2, .flag = 0x13, .parameter = NULL},
- {.instr = 8, .flag = 0x00, .parameter = NULL},
- {.instr = 4, .flag = 0x01, .parameter = gUnknown_082F27D0},
- {.instr = 18, .flag = 0x10, .parameter = gUnknown_082F2660},
- {.instr = 1, .flag = 0x00, .parameter = NULL},
- {.instr = 2, .flag = 0x14, .parameter = NULL},
- {.instr = 0, .flag = 0x03, .parameter = NULL}
-};
-
-const struct mevent_cmd gUnknown_082F2884[] = {
- {.instr = 18, .flag = 0x30, .parameter = gUnknown_082F25F8},
- {.instr = 1, .flag = 0x00, .parameter = NULL},
- {.instr = 13, .flag = 0x00, .parameter = NULL},
- {.instr = 1, .flag = 0x00, .parameter = NULL},
- {.instr = 15, .flag = 0x00, .parameter = NULL},
- {.instr = 1, .flag = 0x00, .parameter = NULL},
- {.instr = 2, .flag = 0x14, .parameter = NULL},
- {.instr = 0, .flag = 0x02, .parameter = NULL}
-};
-
-const struct mevent_cmd gUnknown_082F28E4[] = {
- {.instr = 18, .flag = 0x28, .parameter = gUnknown_082F2670},
- {.instr = 1, .flag = 0x00, .parameter = NULL},
- {.instr = 2, .flag = 0x13, .parameter = NULL},
- {.instr = 8, .flag = 0x00, .parameter = NULL},
- {.instr = 4, .flag = 0x00, .parameter = gUnknown_082F2884},
- {.instr = 3, .flag = 0x00, .parameter = gUnknown_082F2788}
-};
-
-const struct mevent_cmd gUnknown_082F292C[] = {
- {.instr = 18, .flag = 0x10, .parameter = gUnknown_082F26A8},
- {.instr = 1, .flag = 0x00, .parameter = NULL},
- {.instr = 2, .flag = 0x14, .parameter = NULL},
- {.instr = 0, .flag = 0x05, .parameter = NULL},
- {.instr = 18, .flag = 0x10, .parameter = gUnknown_082F25E8},
- {.instr = 1, .flag = 0x00, .parameter = NULL},
- {.instr = 2, .flag = 0x14, .parameter = NULL},
- {.instr = 0, .flag = 0x00, .parameter = NULL}
-};
-
-const struct mevent_cmd s_mevent_wonder_news[] = {
- {.instr = 27, .flag = 0x00, .parameter = NULL},
- {.instr = 18, .flag = 0x20, .parameter = gUnknown_082F25A8},
- {.instr = 1, .flag = 0x00, .parameter = NULL},
- {.instr = 2, .flag = 0x11, .parameter = NULL},
- {.instr = 5, .flag = 0x00, .parameter = NULL},
- {.instr = 30, .flag = 0x00, .parameter = NULL},
- {.instr = 4, .flag = 0x00, .parameter = gUnknown_082F26F8},
- {.instr = 3, .flag = 0x00, .parameter = gUnknown_082F2800}
-};
-
-const struct mevent_cmd s_mevent_wonder_card[] = {
- {.instr = 26, .flag = 0x00, .parameter = NULL},
- {.instr = 28, .flag = 0x00, .parameter = NULL},
- {.instr = 18, .flag = 0x20, .parameter = gUnknown_082F25A8},
- {.instr = 1, .flag = 0x00, .parameter = NULL},
- {.instr = 2, .flag = 0x11, .parameter = NULL},
- {.instr = 5, .flag = 0x00, .parameter = NULL},
- {.instr = 6, .flag = 0x00, .parameter = NULL},
- {.instr = 4, .flag = 0x00, .parameter = gUnknown_082F26F8},
- {.instr = 7, .flag = 0x00, .parameter = NULL},
- {.instr = 4, .flag = 0x02, .parameter = gUnknown_082F28E4},
- {.instr = 4, .flag = 0x00, .parameter = gUnknown_082F2884},
- {.instr = 3, .flag = 0x00, .parameter = gUnknown_082F292C}
-};
diff --git a/src/mevent_server.c b/src/mevent_server.c
deleted file mode 100644
index 2e7b3d89a..000000000
--- a/src/mevent_server.c
+++ /dev/null
@@ -1,295 +0,0 @@
-#include "global.h"
-#include "malloc.h"
-#include "script.h"
-#include "mevent.h"
-#include "mevent_server.h"
-#include "mevent_server_helpers.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_cmd s_mevent_wonder_news[];
-extern const struct mevent_cmd s_mevent_wonder_card[];
-
-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, s_mevent_wonder_news, 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, s_mevent_wonder_card, 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->wonder_card = AllocZeroed(sizeof(struct WonderCard));
- svr->wonder_news = AllocZeroed(sizeof(struct WonderNews));
- svr->recvBuffer = AllocZeroed(ME_SEND_BUF_SIZE);
- svr->mevent_unk1442cc = AllocZeroed(sizeof(struct MEventStruct_Unk1442CC));
- 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->wonder_card);
- Free(svr->wonder_news);
- Free(svr->recvBuffer);
- Free(svr->mevent_unk1442cc);
-}
-
-void mevent_srv_common_init_send(struct mevent_srv_common * svr, u32 ident, const void * src, u32 size)
-{
- AGB_ASSERT(size <= ME_SEND_BUF_SIZE);
- mevent_srv_sub_init_send(&svr->manager, ident, src, size);
-}
-
-static const void * mevent_first_if_not_null_else_second(const void * a0, const void * a1)
-{
- if (a0 != NULL)
- return a0;
- else
- return a1;
-}
-
-static u32 mevent_compare_pointers(const void * a0, const 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_cmd * cmd = &svr->cmdBuffer[svr->cmdidx];
- const void * ptr;
- svr->cmdidx++;
-
- switch (cmd->instr)
- {
- case 0:
- // end
- AGB_ASSERT(cmd->parameter == NULL);
- svr->mainseqno = 1;
- svr->param = cmd->flag;
- break;
- case 1:
- // wait_send
- svr->mainseqno = 3;
- break;
- case 2:
- // receive
- AGB_ASSERT(cmd->parameter == NULL);
- mevent_srv_sub_init_recv(&svr->manager, cmd->flag, svr->recvBuffer);
- svr->mainseqno = 2;
- break;
- case 3:
- // jump
- AGB_ASSERT(cmd->flag == FALSE);
- svr->cmdidx = 0;
- svr->cmdBuffer = cmd->parameter;
- break;
- case 5:
- // get_1442CC
- AGB_ASSERT(cmd->flag == FALSE);
- AGB_ASSERT(cmd->parameter == NULL);
- memcpy(svr->mevent_unk1442cc, svr->recvBuffer, sizeof(struct MEventStruct_Unk1442CC));
- break;
- case 6:
- // check_header__pass_false
- AGB_ASSERT(cmd->flag == FALSE);
- AGB_ASSERT(cmd->parameter == NULL);
- svr->param = sub_801B6A0(svr->mevent_unk1442cc, FALSE);
- break;
- case 30:
- // check_header__pass_true
- AGB_ASSERT(cmd->flag == FALSE);
- AGB_ASSERT(cmd->parameter == NULL);
- svr->param = sub_801B6A0(svr->mevent_unk1442cc, TRUE);
- break;
- case 4:
- // jump_if_eq
- if (svr->param == cmd->flag)
- {
- svr->cmdidx = 0;
- svr->cmdBuffer = cmd->parameter;
- }
- break;
- case 7:
- // check_crc
- AGB_ASSERT(cmd->flag == FALSE);
- ptr = mevent_first_if_not_null_else_second(cmd->parameter, svr->wonder_card);
- svr->param = sub_801B6EC(ptr, svr->mevent_unk1442cc, ptr);
- break;
- case 8:
- // read_word
- AGB_ASSERT(cmd->flag == FALSE);
- AGB_ASSERT(cmd->parameter == NULL);
- svr->param = *(u32 *)svr->recvBuffer;
- break;
- case 9:
- AGB_ASSERT(cmd->flag == FALSE);
- ptr = mevent_first_if_not_null_else_second(cmd->parameter, &svr->sendWord);
- svr->param = sub_801B708(ptr, svr->mevent_unk1442cc, ptr);
- break;
- case 10:
- AGB_ASSERT(cmd->parameter == NULL);
- svr->param = MEventStruct_Unk1442CC_GetValueNFrom_unk_20(svr->mevent_unk1442cc, cmd->flag);
- break;
- case 11:
- AGB_ASSERT(cmd->flag == FALSE);
- svr->param = MEventStruct_Unk1442CC_CompareField_unk_16(svr->mevent_unk1442cc, cmd->parameter);
- break;
- case 12:
- AGB_ASSERT(cmd->flag == FALSE);
- svr->param = mevent_compare_pointers(cmd->parameter, *(void **)svr->recvBuffer);
- break;
- case 14:
- AGB_ASSERT(cmd->flag == FALSE);
- mevent_srv_common_init_send(svr, 0x17, mevent_first_if_not_null_else_second(cmd->parameter, svr->wonder_news), sizeof(struct WonderNews));
- break;
- case 13:
- AGB_ASSERT(cmd->flag == FALSE);
- mevent_srv_common_init_send(svr, 0x16, mevent_first_if_not_null_else_second(cmd->parameter, svr->wonder_card), sizeof(struct WonderCard));
- break;
- case 16:
- AGB_ASSERT(cmd->flag == FALSE);
- 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(cmd->flag == FALSE);
- 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(cmd->flag == FALSE);
- memcpy(svr->wonder_card, cmd->parameter, 332);
- break;
- case 23:
- AGB_ASSERT(cmd->flag == FALSE);
- memcpy(svr->wonder_news, cmd->parameter, 444);
- break;
- case 21:
- AGB_ASSERT(cmd->flag == FALSE);
- 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(cmd->flag == FALSE && cmd->parameter == NULL);
- memcpy(svr->wonder_card, GetSavedWonderCard(), 332);
- WonderCard_ResetInternalReceivedFlag(svr->wonder_card);
- break;
- case 27:
- AGB_ASSERT(cmd->flag == FALSE && cmd->parameter == NULL);
- memcpy(svr->wonder_news, GetSavedWonderNews(), 444);
- break;
- case 28:
- AGB_ASSERT(cmd->flag == FALSE && cmd->parameter == NULL);
- 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(svr->mainseqno < ARRAY_COUNT(func_tbl));
- response = func_tbl[svr->mainseqno](svr);
- AGB_ASSERT(svr->mainseqno < ARRAY_COUNT(func_tbl));
- return response;
-}
diff --git a/src/mevent_server_helpers.c b/src/mevent_server_helpers.c
deleted file mode 100644
index 616f394f7..000000000
--- a/src/mevent_server_helpers.c
+++ /dev/null
@@ -1,211 +0,0 @@
-#include "global.h"
-#include "malloc.h"
-#include "decompress.h"
-#include "util.h"
-#include "link.h"
-#include "link_rfu.h"
-#include "overworld.h"
-#include "script.h"
-#include "battle_tower.h"
-#include "mystery_event_script.h"
-#include "mevent.h"
-#include "mevent_server_helpers.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;
-}
diff --git a/src/mystery_event_msg.c b/src/mystery_event_msg.c
index e0e70a218..51141bb77 100644
--- a/src/mystery_event_msg.c
+++ b/src/mystery_event_msg.c
@@ -1,13 +1,13 @@
#include "global.h"
-const u8 gText_MysteryGiftBerry[] = _("Obtained a {STR_VAR_2} BERRY!\nDad has it at PETALBURG GYM.");
-const u8 gText_MysteryGiftBerryTransform[] = _("The {STR_VAR_1} BERRY transformed into\none {STR_VAR_2} BERRY.");
-const u8 gText_MysteryGiftBerryObtained[] = _("The {STR_VAR_1} BERRY has already been\nobtained.");
-const u8 gText_MysteryGiftSpecialRibbon[] = _("A special RIBBON was awarded to\nyour party POKéMON.");
-const u8 gText_MysteryGiftNationalDex[] = _("The POKéDEX has been upgraded\nwith the NATIONAL MODE.");
-const u8 gText_MysteryGiftRareWord[] = _("A rare word has been added.");
-const u8 gText_MysteryGiftSentOver[] = _("{STR_VAR_1} was sent over!");
-const u8 gText_MysteryGiftFullParty[] = _("Your party is full.\n{STR_VAR_1} could not be sent over.");
-const u8 gText_MysteryGiftNewTrainer[] = _("A new TRAINER has arrived in\nHOENN.");
-const u8 gText_MysteryGiftNewAdversaryInBattleTower[] = _("A new adversary has arrived in the\nBATTLE TOWER.");
-const u8 gText_MysteryGiftCantBeUsed[] = _("This data can't be used in\nthis version.");
+const u8 gText_MysteryEventBerry[] = _("Obtained a {STR_VAR_2} BERRY!\nDad has it at PETALBURG GYM.");
+const u8 gText_MysteryEventBerryTransform[] = _("The {STR_VAR_1} BERRY transformed into\none {STR_VAR_2} BERRY.");
+const u8 gText_MysteryEventBerryObtained[] = _("The {STR_VAR_1} BERRY has already been\nobtained.");
+const u8 gText_MysteryEventSpecialRibbon[] = _("A special RIBBON was awarded to\nyour party POKéMON.");
+const u8 gText_MysteryEventNationalDex[] = _("The POKéDEX has been upgraded\nwith the NATIONAL MODE.");
+const u8 gText_MysteryEventRareWord[] = _("A rare word has been added.");
+const u8 gText_MysteryEventSentOver[] = _("{STR_VAR_1} was sent over!");
+const u8 gText_MysteryEventFullParty[] = _("Your party is full.\n{STR_VAR_1} could not be sent over.");
+const u8 gText_MysteryEventNewTrainer[] = _("A new TRAINER has arrived in\nHOENN.");
+const u8 gText_MysteryEventNewAdversaryInBattleTower[] = _("A new adversary has arrived in the\nBATTLE TOWER.");
+const u8 gText_MysteryEventCantBeUsed[] = _("This data can't be used in\nthis version.");
diff --git a/src/mystery_event_script.c b/src/mystery_event_script.c
index 176eab7fc..f80240006 100644
--- a/src/mystery_event_script.c
+++ b/src/mystery_event_script.c
@@ -43,7 +43,7 @@ static bool32 CheckCompatibility(u16 a1, u32 a2, u16 a3, u32 a4)
static void SetIncompatible(void)
{
- StringExpandPlaceholders(gStringVar4, gText_MysteryGiftCantBeUsed);
+ StringExpandPlaceholders(gStringVar4, gText_MysteryEventCantBeUsed);
SetMysteryEventScriptStatus(3);
}
@@ -65,15 +65,15 @@ static bool32 RunMysteryEventScriptCommand(struct ScriptContext *ctx)
return FALSE;
}
-void sub_8153870(u8 *script)
+void InitMysteryEventScriptContext(u8 *script)
{
InitMysteryEventScript(&sMysteryEventScriptContext, script);
}
-bool32 sub_8153884(u32 *a0)
+bool32 RunMysteryEventScriptContextCommand(u32 *script)
{
bool32 ret = RunMysteryEventScriptCommand(&sMysteryEventScriptContext);
- *a0 = sMysteryEventScriptContext.data[2];
+ *script = sMysteryEventScriptContext.data[2];
return ret;
}
@@ -229,17 +229,17 @@ bool8 MEScrCmd_setenigmaberry(struct ScriptContext *ctx)
if (!haveBerry)
{
str = gStringVar4;
- message = gText_MysteryGiftBerry;
+ message = gText_MysteryEventBerry;
}
else if (StringCompare(gStringVar1, gStringVar2))
{
str = gStringVar4;
- message = gText_MysteryGiftBerryTransform;
+ message = gText_MysteryEventBerryTransform;
}
else
{
str = gStringVar4;
- message = gText_MysteryGiftBerryObtained;
+ message = gText_MysteryEventBerryObtained;
}
StringExpandPlaceholders(str, message);
@@ -259,7 +259,7 @@ bool8 MEScrCmd_giveribbon(struct ScriptContext *ctx)
u8 index = ScriptReadByte(ctx);
u8 ribbonId = ScriptReadByte(ctx);
GiveGiftRibbonToParty(index, ribbonId);
- StringExpandPlaceholders(gStringVar4, gText_MysteryGiftSpecialRibbon);
+ StringExpandPlaceholders(gStringVar4, gText_MysteryEventSpecialRibbon);
ctx->data[2] = 2;
return FALSE;
}
@@ -278,7 +278,7 @@ bool8 MEScrCmd_initramscript(struct ScriptContext *ctx)
bool8 MEScrCmd_givenationaldex(struct ScriptContext *ctx)
{
EnableNationalPokedex();
- StringExpandPlaceholders(gStringVar4, gText_MysteryGiftNationalDex);
+ StringExpandPlaceholders(gStringVar4, gText_MysteryEventNationalDex);
ctx->data[2] = 2;
return FALSE;
}
@@ -286,7 +286,7 @@ bool8 MEScrCmd_givenationaldex(struct ScriptContext *ctx)
bool8 MEScrCmd_addrareword(struct ScriptContext *ctx)
{
UnlockAdditionalPhrase(ScriptReadByte(ctx));
- StringExpandPlaceholders(gStringVar4, gText_MysteryGiftRareWord);
+ StringExpandPlaceholders(gStringVar4, gText_MysteryEventRareWord);
ctx->data[2] = 2;
return FALSE;
}
@@ -320,7 +320,7 @@ bool8 MEScrCmd_givepokemon(struct ScriptContext *ctx)
if (gPlayerPartyCount == PARTY_SIZE)
{
- StringExpandPlaceholders(gStringVar4, gText_MysteryGiftFullParty);
+ StringExpandPlaceholders(gStringVar4, gText_MysteryEventFullParty);
ctx->data[2] = 3;
}
else
@@ -340,7 +340,7 @@ bool8 MEScrCmd_givepokemon(struct ScriptContext *ctx)
GiveMailToMon2(&gPlayerParty[PARTY_SIZE - 1], &mail);
CompactPartySlots();
CalculatePlayerPartyCount();
- StringExpandPlaceholders(gStringVar4, gText_MysteryGiftSentOver);
+ StringExpandPlaceholders(gStringVar4, gText_MysteryEventSentOver);
ctx->data[2] = 2;
}
@@ -352,7 +352,7 @@ bool8 MEScrCmd_addtrainer(struct ScriptContext *ctx)
u32 data = ScriptReadWord(ctx) - ctx->data[1] + ctx->data[0];
memcpy(&gSaveBlock2Ptr->frontier.ereaderTrainer, (void *)data, sizeof(gSaveBlock2Ptr->frontier.ereaderTrainer));
ValidateEReaderTrainer();
- StringExpandPlaceholders(gStringVar4, gText_MysteryGiftNewTrainer);
+ StringExpandPlaceholders(gStringVar4, gText_MysteryEventNewTrainer);
ctx->data[2] = 2;
return FALSE;
}
diff --git a/src/mystery_gift.c b/src/mystery_gift.c
index 6ae6a9534..1df6533d9 100644..100755
--- a/src/mystery_gift.c
+++ b/src/mystery_gift.c
@@ -1,1672 +1,662 @@
#include "global.h"
+#include "util.h"
#include "main.h"
-#include "text.h"
-#include "task.h"
-#include "malloc.h"
-#include "gpu_regs.h"
-#include "scanline_effect.h"
-#include "text_window.h"
-#include "bg.h"
-#include "window.h"
-#include "strings.h"
-#include "text_window.h"
-#include "menu.h"
-#include "palette.h"
-#include "constants/songs.h"
-#include "sound.h"
-#include "mystery_gift.h"
-#include "union_room.h"
-#include "title_screen.h"
-#include "ereader_screen.h"
-#include "international_string_util.h"
-#include "list_menu.h"
-#include "string_util.h"
-#include "mevent.h"
-#include "mevent_801BAAC.h"
-#include "save.h"
-#include "link.h"
-#include "mevent_client.h"
#include "event_data.h"
-#include "link_rfu.h"
-#include "mevent_news.h"
-#include "mevent_server.h"
-#include "constants/cable_club.h"
+#include "easy_chat.h"
+#include "script.h"
+#include "battle_tower.h"
+#include "wonder_news.h"
+#include "string_util.h"
+#include "new_game.h"
+#include "mystery_gift.h"
+#include "constants/mystery_gift.h"
-void bgid_upload_textbox_1(u8 bgId);
-void task_add_00_mystery_gift(void);
-void task00_mystery_gift(u8 taskId);
+static EWRAM_DATA bool32 sStatsEnabled = FALSE;
-EWRAM_DATA u8 sDownArrowCounterAndYCoordIdx[8] = {};
-EWRAM_DATA bool8 gGiftIsFromEReader = FALSE;
+static void ClearSavedWonderNewsMetadata(void);
+static void ClearSavedWonderNews(void);
+static void ClearSavedWonderCard(void);
+static bool32 ValidateWonderNews(const struct WonderNews *);
+static bool32 ValidateWonderCard(const struct WonderCard *);
+static void ClearSavedWonderCardMetadata(void);
+static void ClearSavedTrainerIds(void);
+static void IncrementCardStatForNewTrainer(u32, u32, u32 *, int);
-static const u16 gUnkTextboxBorderPal[] = INCBIN_U16("graphics/interface/unk_textbox_border.gbapal");
-static const u32 gUnkTextboxBorderGfx[] = INCBIN_U32("graphics/interface/unk_textbox_border.4bpp.lz");
+#define CALC_CRC(data) CalcCRC16WithTable((void *)&(data), sizeof(data))
-struct MysteryGiftTaskData
+void ClearMysteryGift(void)
{
- u16 curPromptWindowId;
- u16 unk2;
- u16 unk4;
- u16 unk6;
- u8 state;
- u8 textState;
- u8 unkA;
- u8 unkB;
- u8 IsCardOrNews;
- u8 source;
- u8 prevPromptWindowId;
- u8 * buffer;
-};
-
-static const struct BgTemplate sBGTemplates[] = {
- {
- .bg = 0,
- .charBaseIndex = 2,
- .mapBaseIndex = 15,
- .screenSize = 0,
- .paletteMode = 0,
- .priority = 0,
- .baseTile = 0x000
- }, {
- .bg = 1,
- .charBaseIndex = 0,
- .mapBaseIndex = 14,
- .screenSize = 0,
- .paletteMode = 0,
- .priority = 1,
- .baseTile = 0x000
- }, {
- .bg = 2,
- .charBaseIndex = 0,
- .mapBaseIndex = 13,
- .screenSize = 0,
- .paletteMode = 0,
- .priority = 2,
- .baseTile = 0x000
- }, {
- .bg = 3,
- .charBaseIndex = 0,
- .mapBaseIndex = 12,
- .screenSize = 0,
- .paletteMode = 0,
- .priority = 3,
- .baseTile = 0x000
- }
-};
-
-static const struct WindowTemplate sMainWindows[] = {
- {
- .bg = 0x00,
- .tilemapLeft = 0x00,
- .tilemapTop = 0x00,
- .width = 0x1e,
- .height = 0x02,
- .paletteNum = 0x0c,
- .baseBlock = 0x0013
- }, {
- .bg = 0x00,
- .tilemapLeft = 0x01,
- .tilemapTop = 0x0f,
- .width = 0x1c,
- .height = 0x04,
- .paletteNum = 0x0c,
- .baseBlock = 0x004f
- }, {
- .bg = 0x00,
- .tilemapLeft = 0x00,
- .tilemapTop = 0x0f,
- .width = 0x1e,
- .height = 0x05,
- .paletteNum = 0x0d,
- .baseBlock = 0x004f
- }, {
- 0xFF
- }
-};
-
-static const struct WindowTemplate sWindowTemplate_PromptYesOrNo_Width28 = {
- .bg = 0x00,
- .tilemapLeft = 0x01,
- .tilemapTop = 0x0f,
- .width = 0x1c,
- .height = 0x04,
- .paletteNum = 0x0c,
- .baseBlock = 0x00e5
-};
-
-static const struct WindowTemplate sWindowTemplate_PromptYesOrNo_Width20 = {
- .bg = 0x00,
- .tilemapLeft = 0x01,
- .tilemapTop = 0x0f,
- .width = 0x14,
- .height = 0x04,
- .paletteNum = 0x0c,
- .baseBlock = 0x00e5
-};
-
-static const struct WindowTemplate sMysteryGiftMenuWindowTemplate = {
- .bg = 0x00,
- .tilemapLeft = 0x01,
- .tilemapTop = 0x0f,
- .width = 0x13,
- .height = 0x04,
- .paletteNum = 0x0c,
- .baseBlock = 0x00e5
-};
-
-static const struct WindowTemplate sWindowTemplate_ThreeOptions = {
- .bg = 0x00,
- .tilemapLeft = 0x08,
- .tilemapTop = 0x06,
- .width = 0x0e,
- .height = 0x06,
- .paletteNum = 0x0c,
- .baseBlock = 0x0155
-};
-
-static const struct WindowTemplate sWindowTemplate_YesNoBox = {
- .bg = 0x00,
- .tilemapLeft = 0x17,
- .tilemapTop = 0x0f,
- .width = 0x06,
- .height = 0x04,
- .paletteNum = 0x0c,
- .baseBlock = 0x0155
-};
-
-static const struct WindowTemplate sWindowTemplate_7by8 = {
- .bg = 0x00,
- .tilemapLeft = 0x16,
- .tilemapTop = 0x0b,
- .width = 0x07,
- .height = 0x08,
- .paletteNum = 0x0c,
- .baseBlock = 0x0155
-};
-
-static const struct WindowTemplate sWindowTemplate_7by6 = {
- .bg = 0x00,
- .tilemapLeft = 0x16,
- .tilemapTop = 0x0d,
- .width = 0x07,
- .height = 0x06,
- .paletteNum = 0x0c,
- .baseBlock = 0x0155
-};
+ CpuFill32(0, &gSaveBlock1Ptr->mysteryGift, sizeof(gSaveBlock1Ptr->mysteryGift));
+ ClearSavedWonderNewsMetadata(); // Clear is redundant, InitSavedWonderNews would be sufficient
+ InitQuestionnaireWords();
+}
-static const struct WindowTemplate sWindowTemplate_7by4 = {
- .bg = 0x00,
- .tilemapLeft = 0x16,
- .tilemapTop = 0x0f,
- .width = 0x07,
- .height = 0x04,
- .paletteNum = 0x0c,
- .baseBlock = 0x0155
-};
+struct WonderNews *GetSavedWonderNews(void)
+{
+ return &gSaveBlock1Ptr->mysteryGift.news;
+}
-static const struct ListMenuItem sListMenuItems_CardsOrNews[] = {
- { gText_WonderCards, 0 },
- { gText_WonderNews, 1 },
- { gText_Exit3, -2 }
-};
+struct WonderCard *GetSavedWonderCard(void)
+{
+ return &gSaveBlock1Ptr->mysteryGift.card;
+}
-static const struct ListMenuItem sListMenuItems_WirelessOrFriend[] = {
- { gText_WirelessCommunication, 0 },
- { gText_Friend2, 1 },
- { gText_Cancel2, -2 }
-};
+struct WonderCardMetadata *GetSavedWonderCardMetadata(void)
+{
+ return &gSaveBlock1Ptr->mysteryGift.cardMetadata;
+}
-static const struct ListMenuTemplate sListMenuTemplate_ThreeOptions = {
- .items = NULL,
- .moveCursorFunc = ListMenuDefaultCursorMoveFunc,
- .itemPrintFunc = NULL,
- .totalItems = 3,
- .maxShowed = 3,
- .windowId = 0,
- .header_X = 0,
- .item_X = 8,
- .cursor_X = 0,
- .upText_Y = 1,
- .cursorPal = 2,
- .fillValue = 1,
- .cursorShadowPal = 3,
- .lettersSpacing = 0,
- .itemVerticalPadding = 0,
- .scrollMultiple = 0,
- .fontId = 1,
- .cursorKind = 0
-};
+struct WonderNewsMetadata *GetSavedWonderNewsMetadata(void)
+{
+ return &gSaveBlock1Ptr->mysteryGift.newsMetadata;
+}
-static const struct ListMenuItem sListMenuItems_ReceiveSendToss[] = {
- { gText_Receive, 0 },
- { gText_Send, 1 },
- { gText_Toss, 2 },
- { gText_Cancel2, -2 }
-};
+u16 *GetQuestionnaireWordsPtr(void)
+{
+ return gSaveBlock1Ptr->mysteryGift.questionnaireWords;
+}
-static const struct ListMenuItem sListMenuItems_ReceiveToss[] = {
- { gText_Receive, 0 },
- { gText_Toss, 2 },
- { gText_Cancel2, -2 }
-};
+// Equivalent to ClearSavedWonderCardAndRelated, but nothing else to clear
+void ClearSavedWonderNewsAndRelated(void)
+{
+ ClearSavedWonderNews();
+}
-static const struct ListMenuItem sListMenuItems_ReceiveSend[] = {
- { gText_Receive, 0 },
- { gText_Send, 1 },
- { gText_Cancel2, -2 }
-};
+bool32 SaveWonderNews(const struct WonderNews *news)
+{
+ if (!ValidateWonderNews(news))
+ return FALSE;
-static const struct ListMenuItem sListMenuItems_Receive[] = {
- { gText_Receive, 0 },
- { gText_Cancel2, -2 }
-};
+ ClearSavedWonderNews();
+ gSaveBlock1Ptr->mysteryGift.news = *news;
+ gSaveBlock1Ptr->mysteryGift.newsCrc = CALC_CRC(gSaveBlock1Ptr->mysteryGift.news);
+ return TRUE;
+}
-static const struct ListMenuTemplate sListMenu_ReceiveSendToss = {
- .items = sListMenuItems_ReceiveSendToss,
- .moveCursorFunc = ListMenuDefaultCursorMoveFunc,
- .itemPrintFunc = NULL,
- .totalItems = 4,
- .maxShowed = 4,
- .windowId = 0,
- .header_X = 0,
- .item_X = 8,
- .cursor_X = 0,
- .upText_Y = 1,
- .cursorPal = 2,
- .fillValue = 1,
- .cursorShadowPal = 3,
- .lettersSpacing = 0,
- .itemVerticalPadding = 0,
- .scrollMultiple = 0,
- .fontId = 1,
- .cursorKind = 0
-};
+bool32 ValidateSavedWonderNews(void)
+{
+ if (CALC_CRC(gSaveBlock1Ptr->mysteryGift.news) != gSaveBlock1Ptr->mysteryGift.newsCrc)
+ return FALSE;
+ if (!ValidateWonderNews(&gSaveBlock1Ptr->mysteryGift.news))
+ return FALSE;
-static const struct ListMenuTemplate sListMenu_ReceiveToss = {
- .items = sListMenuItems_ReceiveToss,
- .moveCursorFunc = ListMenuDefaultCursorMoveFunc,
- .itemPrintFunc = NULL,
- .totalItems = 3,
- .maxShowed = 3,
- .windowId = 0,
- .header_X = 0,
- .item_X = 8,
- .cursor_X = 0,
- .upText_Y = 1,
- .cursorPal = 2,
- .fillValue = 1,
- .cursorShadowPal = 3,
- .lettersSpacing = 0,
- .itemVerticalPadding = 0,
- .scrollMultiple = 0,
- .fontId = 1,
- .cursorKind = 0
-};
+ return TRUE;
+}
-static const struct ListMenuTemplate sListMenu_ReceiveSend = {
- .items = sListMenuItems_ReceiveSend,
- .moveCursorFunc = ListMenuDefaultCursorMoveFunc,
- .itemPrintFunc = NULL,
- .totalItems = 3,
- .maxShowed = 3,
- .windowId = 0,
- .header_X = 0,
- .item_X = 8,
- .cursor_X = 0,
- .upText_Y = 1,
- .cursorPal = 2,
- .fillValue = 1,
- .cursorShadowPal = 3,
- .lettersSpacing = 0,
- .itemVerticalPadding = 0,
- .scrollMultiple = 0,
- .fontId = 1,
- .cursorKind = 0
-};
+static bool32 ValidateWonderNews(const struct WonderNews *news)
+{
+ if (news->id == 0)
+ return FALSE;
-static const struct ListMenuTemplate sListMenu_Receive = {
- .items = sListMenuItems_Receive,
- .moveCursorFunc = ListMenuDefaultCursorMoveFunc,
- .itemPrintFunc = NULL,
- .totalItems = 2,
- .maxShowed = 2,
- .windowId = 0,
- .header_X = 0,
- .item_X = 8,
- .cursor_X = 0,
- .upText_Y = 1,
- .cursorPal = 2,
- .fillValue = 1,
- .cursorShadowPal = 3,
- .lettersSpacing = 0,
- .itemVerticalPadding = 0,
- .scrollMultiple = 0,
- .fontId = 1,
- .cursorKind = 0
-};
+ return TRUE;
+}
-static const u8 *const Unref_082F0710[] = {
- gText_VarietyOfEventsImportedWireless,
- gText_WonderCardsInPossession,
- gText_ReadNewsThatArrived,
- gText_ReturnToTitle
-};
+bool32 IsSendingSavedWonderNewsAllowed(void)
+{
+ const struct WonderNews *news = &gSaveBlock1Ptr->mysteryGift.news;
+ if (news->sendType == SEND_TYPE_DISALLOWED)
+ return FALSE;
-ALIGNED(2) const u8 sMG_Ereader_TextColor_1[] = { 0, 1, 2 };
-ALIGNED(2) const u8 sMG_Ereader_TextColor_1_Copy[] = { 0, 1, 2 };
-ALIGNED(2) const u8 sMG_Ereader_TextColor_2[] = { 1, 2, 3 };
+ return TRUE;
+}
-void vblankcb_mystery_gift_e_reader_run(void)
+static void ClearSavedWonderNews(void)
{
- ProcessSpriteCopyRequests();
- LoadOam();
- TransferPlttBuffer();
+ CpuFill32(0, GetSavedWonderNews(), sizeof(gSaveBlock1Ptr->mysteryGift.news));
+ gSaveBlock1Ptr->mysteryGift.newsCrc = 0;
}
-void c2_mystery_gift_e_reader_run(void)
+static void ClearSavedWonderNewsMetadata(void)
{
- RunTasks();
- RunTextPrinters();
- AnimateSprites();
- BuildOamBuffer();
+ CpuFill32(0, GetSavedWonderNewsMetadata(), sizeof(gSaveBlock1Ptr->mysteryGift.newsMetadata));
+ InitSavedWonderNews();
}
-bool32 HandleMysteryGiftOrEReaderSetup(s32 mg_or_ereader)
+bool32 IsWonderNewsSameAsSaved(const u8 *news)
{
- switch (gMain.state)
+ const u8 *savedNews = (const u8 *)&gSaveBlock1Ptr->mysteryGift.news;
+ u32 i;
+ if (!ValidateSavedWonderNews())
+ return FALSE;
+
+ for (i = 0; i < sizeof(gSaveBlock1Ptr->mysteryGift.news); i++)
{
- case 0:
- SetVBlankCallback(NULL);
- ResetPaletteFade();
- ResetSpriteData();
- FreeAllSpritePalettes();
- ResetTasks();
- ScanlineEffect_Stop();
- ResetBgsAndClearDma3BusyFlags(0);
-
- InitBgsFromTemplates(0, sBGTemplates, ARRAY_COUNT(sBGTemplates));
- ChangeBgX(0, 0, 0);
- ChangeBgY(0, 0, 0);
- ChangeBgX(1, 0, 0);
- ChangeBgY(1, 0, 0);
- ChangeBgX(2, 0, 0);
- ChangeBgY(2, 0, 0);
- ChangeBgX(3, 0, 0);
- ChangeBgY(3, 0, 0);
-
- SetBgTilemapBuffer(3, Alloc(BG_SCREEN_SIZE));
- SetBgTilemapBuffer(2, Alloc(BG_SCREEN_SIZE));
- SetBgTilemapBuffer(1, Alloc(BG_SCREEN_SIZE));
- SetBgTilemapBuffer(0, Alloc(BG_SCREEN_SIZE));
-
- bgid_upload_textbox_1(3);
- InitWindows(sMainWindows);
- DeactivateAllTextPrinters();
- ClearGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_WIN0_ON | DISPCNT_WIN1_ON);
- SetGpuReg(REG_OFFSET_BLDCNT, 0);
- SetGpuReg(REG_OFFSET_BLDALPHA, 0);
- SetGpuReg(REG_OFFSET_BLDY, 0);
- gMain.state++;
- break;
- case 1:
- LoadPalette(gUnkTextboxBorderPal, 0, 0x20);
- LoadPalette(GetTextWindowPalette(2), 0xd0, 0x20);
- Menu_LoadStdPalAt(0xC0);
- LoadUserWindowBorderGfx(0, 0xA, 0xE0);
- LoadUserWindowBorderGfx_(0, 0x1, 0xF0);
- FillBgTilemapBufferRect(0, 0x000, 0, 0, 32, 32, 0x11);
- FillBgTilemapBufferRect(1, 0x000, 0, 0, 32, 32, 0x11);
- FillBgTilemapBufferRect(2, 0x000, 0, 0, 32, 32, 0x11);
- MG_DrawCheckerboardPattern(3);
- PrintMysteryGiftOrEReaderTopMenu(mg_or_ereader, 0);
- gMain.state++;
- break;
- case 2:
- CopyBgTilemapBufferToVram(3);
- CopyBgTilemapBufferToVram(2);
- CopyBgTilemapBufferToVram(1);
- CopyBgTilemapBufferToVram(0);
- gMain.state++;
- break;
- case 3:
- ShowBg(0);
- ShowBg(3);
- PlayBGM(MUS_RG_MYSTERY_GIFT);
- SetVBlankCallback(vblankcb_mystery_gift_e_reader_run);
- EnableInterrupts(INTR_FLAG_VBLANK | INTR_FLAG_VCOUNT | INTR_FLAG_TIMER3 | INTR_FLAG_SERIAL);
- return TRUE;
+ if (savedNews[i] != news[i])
+ return FALSE;
}
- return FALSE;
+ return TRUE;
}
-void c2_mystery_gift(void)
+void ClearSavedWonderCardAndRelated(void)
{
- if (HandleMysteryGiftOrEReaderSetup(0))
- {
- SetMainCallback2(c2_mystery_gift_e_reader_run);
- gGiftIsFromEReader = FALSE;
- task_add_00_mystery_gift();
- }
- RunTasks();
+ ClearSavedWonderCard();
+ ClearSavedWonderCardMetadata();
+ ClearSavedTrainerIds();
+ ClearRamScript();
+ ClearMysteryGiftFlags();
+ ClearMysteryGiftVars();
+ ClearEReaderTrainer(&gSaveBlock2Ptr->frontier.ereaderTrainer);
}
-void c2_ereader(void)
+bool32 SaveWonderCard(const struct WonderCard *card)
{
- if (HandleMysteryGiftOrEReaderSetup(1))
- {
- SetMainCallback2(c2_mystery_gift_e_reader_run);
- gGiftIsFromEReader = TRUE;
- task_add_00_ereader();
- }
-}
+ struct WonderCardMetadata *metadata;
+ if (!ValidateWonderCard(card))
+ return FALSE;
-void MainCB_FreeAllBuffersAndReturnToInitTitleScreen(void)
-{
- gGiftIsFromEReader = FALSE;
- FreeAllWindowBuffers();
- Free(GetBgTilemapBuffer(0));
- Free(GetBgTilemapBuffer(1));
- Free(GetBgTilemapBuffer(2));
- Free(GetBgTilemapBuffer(3));
- SetMainCallback2(CB2_InitTitleScreen);
+ 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;
}
-void PrintMysteryGiftOrEReaderTopMenu(bool8 mg_or_ereader, bool32 usePickOkCancel)
+bool32 ValidateSavedWonderCard(void)
{
- const u8 * header;
- const u8 * options;
- FillWindowPixelBuffer(0, 0);
- if (mg_or_ereader == 0)
- {
- header = gText_MysteryGift;
- options = !usePickOkCancel ? gText_PickOKExit : gText_PickOKCancel;
- }
- else
- {
- header = gJPText_MysteryGift;
- options = gJPText_DecideStop;
- }
+ if (gSaveBlock1Ptr->mysteryGift.cardCrc != CALC_CRC(gSaveBlock1Ptr->mysteryGift.card))
+ return FALSE;
+ if (!ValidateWonderCard(&gSaveBlock1Ptr->mysteryGift.card))
+ return FALSE;
+ if (!ValidateSavedRamScript())
+ return FALSE;
- AddTextPrinterParameterized4(0, 1, 4, 1, 0, 0, sMG_Ereader_TextColor_1, -1, header);
- AddTextPrinterParameterized4(0, 0, GetStringRightAlignXOffset(0, options, 0xDE), 1, 0, 0, sMG_Ereader_TextColor_1, -1, options);
- CopyWindowToVram(0, 2);
- PutWindowTilemap(0);
+ return TRUE;
}
-void MG_DrawTextBorder(u8 windowId)
+static bool32 ValidateWonderCard(const struct WonderCard *card)
{
- DrawTextBorderOuter(windowId, 0x01, 0xF);
+ 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;
}
-void MG_DrawCheckerboardPattern(u32 bg)
+bool32 IsSendingSavedWonderCardAllowed(void)
{
- s32 i = 0, j;
+ const struct WonderCard *card = &gSaveBlock1Ptr->mysteryGift.card;
+ if (card->sendType == SEND_TYPE_DISALLOWED)
+ return FALSE;
- FillBgTilemapBufferRect(bg, 0x003, 0, 0, 32, 2, 0x11);
+ return TRUE;
+}
- for (i = 0; i < 18; i++)
- {
- for (j = 0; j < 32; j++)
- {
- if ((i & 1) != (j & 1))
- FillBgTilemapBufferRect(bg, 1, j, i + 2, 1, 1, 0x11);
- else
- FillBgTilemapBufferRect(bg, 2, j, i + 2, 1, 1, 0x11);
- }
- }
+static void ClearSavedWonderCard(void)
+{
+ CpuFill32(0, &gSaveBlock1Ptr->mysteryGift.card, sizeof(gSaveBlock1Ptr->mysteryGift.card));
+ gSaveBlock1Ptr->mysteryGift.cardCrc = 0;
}
-void ClearScreenInBg0(bool32 ignoreTopTwoRows)
+static void ClearSavedWonderCardMetadata(void)
{
- switch (ignoreTopTwoRows)
- {
- case 0:
- FillBgTilemapBufferRect(0, 0, 0, 0, 32, 32, 0x11);
- break;
- case 1:
- FillBgTilemapBufferRect(0, 0, 0, 2, 32, 30, 0x11);
- break;
- }
- CopyBgTilemapBufferToVram(0);
+ CpuFill32(0, GetSavedWonderCardMetadata(), sizeof(gSaveBlock1Ptr->mysteryGift.cardMetadata));
+ gSaveBlock1Ptr->mysteryGift.cardMetadataCrc = 0;
}
-void AddTextPrinterToWindow1(const u8 *str)
+u16 GetWonderCardFlagID(void)
{
- StringExpandPlaceholders(gStringVar4, str);
- FillWindowPixelBuffer(1, 0x11);
- AddTextPrinterParameterized4(1, 1, 0, 1, 0, 0, sMG_Ereader_TextColor_2, 0, gStringVar4);
- DrawTextBorderOuter(1, 0x001, 0xF);
- PutWindowTilemap(1);
- CopyWindowToVram(1, 3);
+ if (ValidateSavedWonderCard())
+ return gSaveBlock1Ptr->mysteryGift.card.flagId;
+
+ return 0;
}
-static void ClearTextWindow(void)
+void DisableWonderCardSending(struct WonderCard *card)
{
- rbox_fill_rectangle(1);
- ClearWindowTilemap(1);
- CopyWindowToVram(1, 1);
+ if (card->sendType == SEND_TYPE_ALLOWED)
+ card->sendType = SEND_TYPE_DISALLOWED;
}
-bool32 MG_PrintTextOnWindow1AndWaitButton(u8 *textState, const u8 *str)
+static bool32 IsWonderCardFlagIDInValidRange(u16 flagId)
{
- switch (*textState)
- {
- case 0:
- AddTextPrinterToWindow1(str);
- (*textState)++;
- break;
- case 1:
- DrawDownArrow(1, 0xD0, 0x14, 1, FALSE, &sDownArrowCounterAndYCoordIdx[0], &sDownArrowCounterAndYCoordIdx[1]);
- if (({JOY_NEW(A_BUTTON | B_BUTTON);}))
- (*textState)++;
- break;
- case 2:
- DrawDownArrow(1, 0xD0, 0x14, 1, TRUE, &sDownArrowCounterAndYCoordIdx[0], &sDownArrowCounterAndYCoordIdx[1]);
- *textState = 0;
- ClearTextWindow();
+ if (flagId >= WONDER_CARD_FLAG_OFFSET && flagId < WONDER_CARD_FLAG_OFFSET + NUM_WONDER_CARD_FLAGS)
return TRUE;
- case 0xFF:
- *textState = 2;
- return FALSE;
- }
+
return FALSE;
}
-static void HideDownArrow(void)
+static const u16 sReceivedGiftFlags[] =
+{
+ FLAG_RECEIVED_AURORA_TICKET,
+ FLAG_RECEIVED_MYSTIC_TICKET,
+ FLAG_RECEIVED_OLD_SEA_MAP,
+ 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,
+};
+
+bool32 IsSavedWonderCardGiftNotReceived(void)
{
- DrawDownArrow(1, 0xD0, 0x14, 1, FALSE, &sDownArrowCounterAndYCoordIdx[0], &sDownArrowCounterAndYCoordIdx[1]);
+ 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 void ShowDownArrow(void)
+static int GetNumStampsInMetadata(const struct WonderCardMetadata *data, int size)
{
- DrawDownArrow(1, 0xD0, 0x14, 1, TRUE, &sDownArrowCounterAndYCoordIdx[0], &sDownArrowCounterAndYCoordIdx[1]);
+ int numStamps = 0;
+ int i;
+ for (i = 0; i < size; i++)
+ {
+ if (data->stampData[STAMP_ID][i] && data->stampData[STAMP_SPECIES][i] != SPECIES_NONE)
+ numStamps++;
+ }
+
+ return numStamps;
}
-bool32 unref_HideDownArrowAndWaitButton(u8 * textState)
+static bool32 IsStampInMetadata(const struct WonderCardMetadata *metadata, const u16 *stamp, int maxStamps)
{
- switch (*textState)
+ int i;
+ for (i = 0; i < maxStamps; i++)
{
- case 0:
- HideDownArrow();
- if (JOY_NEW(A_BUTTON | B_BUTTON))
- (*textState)++;
- break;
- case 1:
- ShowDownArrow();
- *textState = 0;
- return TRUE;
+ 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 PrintStringAndWait2Seconds(u8 * counter, const u8 * str)
+static bool32 ValidateStamp(const u16 *stamp)
{
- if (*counter == 0)
- AddTextPrinterToWindow1(str);
-
- if (++(*counter) > 120)
- {
- *counter = 0;
- ClearTextWindow();
- return TRUE;
- }
- else
- {
+ 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 u32 MysteryGift_HandleThreeOptionMenu(u8 * unused0, u16 * unused1, u8 whichMenu)
+static int GetNumStampsInSavedCard(void)
{
- struct ListMenuTemplate listMenuTemplate = sListMenuTemplate_ThreeOptions;
- struct WindowTemplate windowTemplate = sWindowTemplate_ThreeOptions;
- s32 width;
- s32 response;
+ struct WonderCard *card;
+ if (!ValidateSavedWonderCard())
+ return 0;
- if (whichMenu == 0)
- listMenuTemplate.items = sListMenuItems_CardsOrNews;
- else
- listMenuTemplate.items = sListMenuItems_WirelessOrFriend;
-
- width = Intl_GetListMenuWidth(&listMenuTemplate);
- if (width & 1)
- width++;
-
- windowTemplate.width = width;
- if (width < 30)
- windowTemplate.tilemapLeft = (30 - width) / 2;
- else
- windowTemplate.tilemapLeft = 0;
+ card = &gSaveBlock1Ptr->mysteryGift.card;
+ if (card->type != CARD_TYPE_STAMP)
+ return 0;
- response = DoMysteryGiftListMenu(&windowTemplate, &listMenuTemplate, 1, 0x00A, 0xE0);
- if (response != -1)
- {
- ClearWindowTilemap(2);
- CopyWindowToVram(2, 1);
- }
- return response;
+ return GetNumStampsInMetadata(&gSaveBlock1Ptr->mysteryGift.cardMetadata, card->maxStamps);
}
-s8 mevent_message_print_and_prompt_yes_no(u8 * textState, u16 * windowId, bool8 yesNoBoxPlacement, const u8 * str)
+bool32 MysteryGift_TrySaveStamp(const u16 *stamp)
{
- struct WindowTemplate windowTemplate;
- s8 input;
+ struct WonderCard *card = &gSaveBlock1Ptr->mysteryGift.card;
+ int maxStamps = card->maxStamps;
+ int i;
+ if (!ValidateStamp(stamp))
+ return FALSE;
+
+ if (IsStampInMetadata(&gSaveBlock1Ptr->mysteryGift.cardMetadata, stamp, maxStamps))
+ return FALSE;
- switch (*textState)
+ for (i = 0; i < maxStamps; i++)
{
- case 0:
- StringExpandPlaceholders(gStringVar4, str);
- if (yesNoBoxPlacement == 0)
- *windowId = AddWindow(&sWindowTemplate_PromptYesOrNo_Width28);
- else
- *windowId = AddWindow(&sWindowTemplate_PromptYesOrNo_Width20);
- FillWindowPixelBuffer(*windowId, 0x11);
- AddTextPrinterParameterized4(*windowId, 1, 0, 1, 0, 0, sMG_Ereader_TextColor_2, 0, gStringVar4);
- DrawTextBorderOuter(*windowId, 0x001, 0x0F);
- CopyWindowToVram(*windowId, 2);
- PutWindowTilemap(*windowId);
- (*textState)++;
- break;
- case 1:
- windowTemplate = sWindowTemplate_YesNoBox;
- if (yesNoBoxPlacement == 0)
- windowTemplate.tilemapTop = 9;
- else
- windowTemplate.tilemapTop = 15;
- CreateYesNoMenu(&windowTemplate, 10, 14, 0);
- (*textState)++;
- break;
- case 2:
- input = Menu_ProcessInputNoWrapClearOnChoose();
- if (input == MENU_B_PRESSED || input == 0 || input == 1)
+ if (gSaveBlock1Ptr->mysteryGift.cardMetadata.stampData[STAMP_ID][i] == 0
+ && gSaveBlock1Ptr->mysteryGift.cardMetadata.stampData[STAMP_SPECIES][i] == SPECIES_NONE)
{
- *textState = 0;
- rbox_fill_rectangle(*windowId);
- ClearWindowTilemap(*windowId);
- CopyWindowToVram(*windowId, 1);
- RemoveWindow(*windowId);
- return input;
+ gSaveBlock1Ptr->mysteryGift.cardMetadata.stampData[STAMP_ID][i] = stamp[STAMP_ID];
+ gSaveBlock1Ptr->mysteryGift.cardMetadata.stampData[STAMP_SPECIES][i] = stamp[STAMP_SPECIES];
+ return TRUE;
}
- break;
- case (u8)MENU_B_PRESSED:
- *textState = 0;
- rbox_fill_rectangle(*windowId);
- ClearWindowTilemap(*windowId);
- CopyWindowToVram(*windowId, 1);
- RemoveWindow(*windowId);
- return MENU_B_PRESSED;
}
- return MENU_NOTHING_CHOSEN;
+ return FALSE;
}
-static s32 HandleMysteryGiftListMenu(u8 * textState, u16 * windowId, bool32 cannotToss, bool32 cannotSend)
+#define GAME_DATA_VALID_VAR 0x101
+#define GAME_DATA_VALID_GIFT_TYPE_1 (1 << 2)
+#define GAME_DATA_VALID_GIFT_TYPE_2 (1 << 9)
+
+void MysteryGift_LoadLinkGameData(struct MysteryGiftLinkGameData *data, bool32 isWonderNews)
{
- struct WindowTemplate windowTemplate;
- s32 input;
+ int i;
+ CpuFill32(0, data, sizeof(*data));
+ data->validationVar = GAME_DATA_VALID_VAR;
+ data->validationFlag1 = 1;
+ data->validationFlag2 = 1;
- switch (*textState)
+ if (isWonderNews)
{
- case 0:
- if (cannotToss == 0)
- {
- StringExpandPlaceholders(gStringVar4, gText_WhatToDoWithCards);
- }
- else
- {
- StringExpandPlaceholders(gStringVar4, gText_WhatToDoWithNews);
- }
- *windowId = AddWindow(&sMysteryGiftMenuWindowTemplate);
- FillWindowPixelBuffer(*windowId, 0x11);
- AddTextPrinterParameterized4(*windowId, 1, 0, 1, 0, 0, sMG_Ereader_TextColor_2, 0, gStringVar4);
- DrawTextBorderOuter(*windowId, 0x001, 0x0F);
- CopyWindowToVram(*windowId, 2);
- PutWindowTilemap(*windowId);
- (*textState)++;
- break;
- case 1:
- windowTemplate = sWindowTemplate_YesNoBox;
- if (cannotSend)
- {
- if (cannotToss == 0)
- {
- input = DoMysteryGiftListMenu(&sWindowTemplate_7by6, &sListMenu_ReceiveToss, 1, 0x00A, 0xE0);
- }
- else
- {
- input = DoMysteryGiftListMenu(&sWindowTemplate_7by4, &sListMenu_Receive, 1, 0x00A, 0xE0);
- }
- }
- else
- {
- if (cannotToss == 0)
- {
- input = DoMysteryGiftListMenu(&sWindowTemplate_7by8, &sListMenu_ReceiveSendToss, 1, 0x00A, 0xE0);
- }
- else
- {
- input = DoMysteryGiftListMenu(&sWindowTemplate_7by6, &sListMenu_ReceiveSend, 1, 0x00A, 0xE0);
- }
- }
- if (input != -1)
- {
- *textState = 0;
- rbox_fill_rectangle(*windowId);
- ClearWindowTilemap(*windowId);
- CopyWindowToVram(*windowId, 1);
- RemoveWindow(*windowId);
- return input;
- }
- break;
- case 0xFF:
- *textState = 0;
- rbox_fill_rectangle(*windowId);
- ClearWindowTilemap(*windowId);
- CopyWindowToVram(*windowId, 1);
- RemoveWindow(*windowId);
- return -2;
+ // Despite setting these for News, they are
+ // only ever checked for Cards
+ data->validationGiftType1 = GAME_DATA_VALID_GIFT_TYPE_1 | 1;
+ data->validationGiftType2 = GAME_DATA_VALID_GIFT_TYPE_2 | 1;
+ }
+ else // Wonder Card
+ {
+ data->validationGiftType1 = GAME_DATA_VALID_GIFT_TYPE_1;
+ data->validationGiftType2 = GAME_DATA_VALID_GIFT_TYPE_2;
}
- return -1;
-}
-
-static bool32 ValidateCardOrNews(bool32 cardOrNews)
-{
- if (cardOrNews == 0)
+ if (ValidateSavedWonderCard())
{
- return ValidateReceivedWonderCard();
+ data->flagId = GetSavedWonderCard()->flagId;
+ data->cardMetadata = *GetSavedWonderCardMetadata();
+ data->maxStamps = GetSavedWonderCard()->maxStamps;
}
else
{
- return ValidateReceivedWonderNews();
+ 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->romHeaderGameCode, RomHeaderGameCode, GAME_CODE_LENGTH);
+ data->romHeaderSoftwareVersion = RomHeaderSoftwareVersion;
}
-static bool32 HandleLoadWonderCardOrNews(u8 * state, bool32 cardOrNews)
+bool32 MysteryGift_ValidateLinkGameData(const struct MysteryGiftLinkGameData *data, bool32 isWonderNews)
{
- switch (*state)
+ if (data->validationVar != GAME_DATA_VALID_VAR)
+ return FALSE;
+
+ if (!(data->validationFlag1 & 1))
+ return FALSE;
+
+ if (!(data->validationFlag2 & 1))
+ return FALSE;
+
+ if (!isWonderNews)
{
- case 0:
- if (cardOrNews == 0)
- {
- InitWonderCardResources(GetSavedWonderCard(), sav1_get_mevent_buffer_2());
- }
- else
- {
- InitWonderNewsResources(GetSavedWonderNews());
- }
- (*state)++;
- break;
- case 1:
- if (cardOrNews == 0)
- {
- if (!FadeToWonderCardMenu())
- {
- return FALSE;
- }
- }
- else
- {
- if (!FadeToWonderNewsMenu())
- {
- return FALSE;
- }
- }
- *state = 0;
- return TRUE;
+ if (!(data->validationGiftType1 & GAME_DATA_VALID_GIFT_TYPE_1))
+ return FALSE;
+
+ if (!(data->validationGiftType2 & (GAME_DATA_VALID_GIFT_TYPE_2 | 0x180)))
+ return FALSE;
}
- return FALSE;
+ return TRUE;
}
-static bool32 DestroyNewsOrCard(bool32 cardOrNews)
+u32 MysteryGift_CompareCardFlags(const u16 *flagId, const struct MysteryGiftLinkGameData *data, const void *unused)
{
- if (cardOrNews == 0)
- {
- DestroyWonderCard();
- }
- else
- {
- DestroyWonderNews();
- }
- return TRUE;
+ // Has a Wonder Card already?
+ if (data->flagId == 0)
+ return HAS_NO_CARD;
+
+ // Has this Wonder Card already?
+ if (*flagId == data->flagId)
+ return HAS_SAME_CARD;
+
+ // Player has a different Wonder Card
+ return HAS_DIFF_CARD;
}
-static bool32 TearDownCardOrNews_ReturnToTopMenu(bool32 cardOrNews, bool32 arg1)
+// This is referenced by the Mystery Gift server, but the instruction it's referenced in is never used,
+// so the return values here are never checked by anything.
+u32 MysteryGift_CheckStamps(const u16 *stamp, const struct MysteryGiftLinkGameData *data, const void *unused)
{
- if (cardOrNews == 0)
- {
- if (FadeOutFromWonderCard(arg1) != 0)
- {
- DestroyWonderCardResources();
- return TRUE;
- }
- else
- {
- return FALSE;
- }
- }
- else
+ int 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)
+{
+ int i;
+ for (i = 0; i < NUM_QUESTIONNAIRE_WORDS; i++)
{
- if (FadeOutFromWonderNews(arg1) != 0)
- {
- DestroyWonderNewsResources();
- return TRUE;
- }
- else
- {
+ if (data->questionnaireWords[i] != words[i])
return FALSE;
- }
}
+
+ return TRUE;
}
-static s32 mevent_message_prompt_discard(u8 * textState, u16 * windowId, bool32 cardOrNews)
+static int GetNumStampsInLinkData(const struct MysteryGiftLinkGameData *data)
{
- if (cardOrNews == 0)
- {
- return mevent_message_print_and_prompt_yes_no(textState, windowId, TRUE, gText_IfThrowAwayCardEventWontHappen);
- }
- else
- {
- return mevent_message_print_and_prompt_yes_no(textState, windowId, TRUE, gText_OkayToDiscardNews);
- }
+ return GetNumStampsInMetadata(&data->cardMetadata, data->maxStamps);
}
-static bool32 mevent_message_was_thrown_away(u8 * textState, bool32 cardOrNews)
+u16 MysteryGift_GetCardStatFromLinkData(const struct MysteryGiftLinkGameData *data, u32 stat)
{
- if (cardOrNews == 0)
- {
- return MG_PrintTextOnWindow1AndWaitButton(textState, gText_WonderCardThrownAway);
- }
- else
+ switch (stat)
{
- return MG_PrintTextOnWindow1AndWaitButton(textState, gText_WonderNewsThrownAway);
+ 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(0);
+ return 0;
}
}
-static bool32 mevent_save_game(u8 * state)
+static void IncrementCardStat(u32 statType)
{
- switch (*state)
+ struct WonderCard *card = &gSaveBlock1Ptr->mysteryGift.card;
+ if (card->type == CARD_TYPE_LINK_STAT)
{
- case 0:
- AddTextPrinterToWindow1(gText_DataWillBeSaved);
- (*state)++;
- break;
- case 1:
- TrySavingData(SAVE_NORMAL);
- (*state)++;
- break;
- case 2:
- AddTextPrinterToWindow1(gText_SaveCompletedPressA);
- (*state)++;
- break;
- case 3:
- if (({JOY_NEW(A_BUTTON | B_BUTTON);}))
+ u16 *stat = NULL;
+ switch (statType)
{
- (*state)++;
+ 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: // Unused
+ case CARD_STAT_MAX_STAMPS: // Unused
+ break;
}
- break;
- case 4:
- *state = 0;
- ClearTextWindow();
- return TRUE;
- }
-
- return FALSE;
-}
-
-static const u8 * mevent_message(u32 * a0, u8 a1, u8 cardOrNews, u32 msgId)
-{
- const u8 * msg = NULL;
- *a0 = 0;
- switch (msgId)
- {
- case 0:
- *a0 = 0;
- msg = gText_NothingSentOver;
- break;
- case 1:
- *a0 = 0;
- msg = gText_RecordUploadedViaWireless;
- break;
- case 2:
- *a0 = 1;
- msg = cardOrNews == 0 ? gText_WonderCardReceived : gText_WonderCardReceivedFrom;
- break;
- case 3:
- *a0 = 1;
- msg = cardOrNews == 0 ? gText_WonderNewsReceived : gText_WonderNewsReceivedFrom;
- break;
- case 4:
- *a0 = 1;
- msg = gText_NewStampReceived;
- break;
- case 5:
- *a0 = 0;
- msg = gText_AlreadyHadCard;
- break;
- case 6:
- *a0 = 0;
- msg = gText_AlreadyHadStamp;
- break;
- case 7:
- *a0 = 0;
- msg = gText_AlreadyHadNews;
- break;
- case 8:
- *a0 = 0;
- msg = gText_NoMoreRoomForStamps;
- break;
- case 9:
- *a0 = 0;
- msg = gText_CommunicationCanceled;
- break;
- case 10:
- *a0 = 0;
- msg = a1 == 0 ? gText_CantAcceptCardFromTrainer : gText_CantAcceptNewsFromTrainer;
- break;
- case 11:
- *a0 = 0;
- msg = gText_CommunicationError;
- break;
- case 12:
- *a0 = 1;
- msg = gText_NewTrainerReceived;
- break;
- case 13:
- *a0 = 1;
- break;
- case 14:
- *a0 = 0;
- break;
+ if (stat == NULL)
+ AGB_ASSERT(0);
+ else if (++(*stat) > MAX_WONDER_CARD_STAT)
+ *stat = MAX_WONDER_CARD_STAT;
}
-
- return msg;
}
-static bool32 PrintMGSuccessMessage(u8 * state, const u8 * arg1, u16 * arg2)
+u16 MysteryGift_GetCardStat(u32 stat)
{
- switch (*state)
+ switch (stat)
{
- case 0:
- if (arg1 != NULL)
+ case CARD_STAT_BATTLES_WON:
+ {
+ struct WonderCard *card = &gSaveBlock1Ptr->mysteryGift.card;
+ if (card->type == CARD_TYPE_LINK_STAT)
{
- AddTextPrinterToWindow1(arg1);
+ struct WonderCardMetadata *metadata = &gSaveBlock1Ptr->mysteryGift.cardMetadata;
+ return metadata->battlesWon;
}
- PlayFanfare(MUS_OBTAIN_ITEM);
- *arg2 = 0;
- (*state)++;
break;
- case 1:
- if (++(*arg2) > 0xF0)
+ }
+ case CARD_STAT_BATTLES_LOST:
+ {
+ struct WonderCard *card = &gSaveBlock1Ptr->mysteryGift.card;
+ if (card->type == CARD_TYPE_LINK_STAT)
{
- (*state)++;
+ struct WonderCardMetadata *metadata = &gSaveBlock1Ptr->mysteryGift.cardMetadata;
+ return metadata->battlesLost;
}
break;
- case 2:
- if (IsFanfareTaskInactive())
+ }
+ case CARD_STAT_NUM_TRADES:
+ {
+ struct WonderCard *card = &gSaveBlock1Ptr->mysteryGift.card;
+ if (card->type == CARD_TYPE_LINK_STAT)
{
- *state = 0;
- ClearTextWindow();
- return TRUE;
+ struct WonderCardMetadata *metadata = &gSaveBlock1Ptr->mysteryGift.cardMetadata;
+ return metadata->numTrades;
}
break;
}
- return FALSE;
-}
-
-static const u8 * mevent_message_stamp_card_etc_send_status(u32 * a0, u8 unused, u32 msgId)
-{
- const u8 * result = gText_CommunicationError;
- *a0 = 0;
- switch (msgId)
+ case CARD_STAT_NUM_STAMPS:
{
- case 0:
- result = gText_NothingSentOver;
- break;
- case 1:
- result = gText_RecordUploadedViaWireless;
- break;
- case 2:
- result = gText_WonderCardSentTo;
- *a0 = 1;
- break;
- case 3:
- result = gText_WonderNewsSentTo;
- *a0 = 1;
- break;
- case 4:
- result = gText_StampSentTo;
- break;
- case 5:
- result = gText_OtherTrainerHasCard;
- break;
- case 6:
- result = gText_OtherTrainerHasStamp;
- break;
- case 7:
- result = gText_OtherTrainerHasNews;
- break;
- case 8:
- result = gText_NoMoreRoomForStamps;
- break;
- case 9:
- result = gText_OtherTrainerCanceled;
- break;
- case 10:
- result = gText_CantSendGiftToTrainer;
- break;
- case 11:
- result = gText_CommunicationError;
- break;
- case 12:
- result = gText_GiftSentTo;
- break;
- case 13:
- result = gText_GiftSentTo;
- break;
- case 14:
- result = gText_CantSendGiftToTrainer;
+ struct WonderCard *card = &gSaveBlock1Ptr->mysteryGift.card;
+ if (card->type == CARD_TYPE_STAMP)
+ return GetNumStampsInSavedCard();
break;
}
- return result;
-}
-
-static bool32 PrintMGSendStatus(u8 * state, u16 * arg1, u8 arg2, u32 msgId)
-{
- u32 flag;
- const u8 * str = mevent_message_stamp_card_etc_send_status(&flag, arg2, msgId);
- if (flag)
+ case CARD_STAT_MAX_STAMPS:
{
- return PrintMGSuccessMessage(state, str, arg1);
+ struct WonderCard *card = &gSaveBlock1Ptr->mysteryGift.card;
+ if (card->type == CARD_TYPE_STAMP)
+ return card->maxStamps;
+ break;
}
- else
- {
- return MG_PrintTextOnWindow1AndWaitButton(state, str);
}
+
+ AGB_ASSERT(0);
+ return 0;
}
-void task_add_00_mystery_gift(void)
+void MysteryGift_DisableStats(void)
{
- u8 taskId = CreateTask(task00_mystery_gift, 0);
- struct MysteryGiftTaskData * data = (void *)gTasks[taskId].data;
- data->state = 0;
- data->textState = 0;
- data->unkA = 0;
- data->unkB = 0;
- data->IsCardOrNews = 0;
- data->source = 0;
- data->curPromptWindowId = 0;
- data->unk2 = 0;
- data->unk4 = 0;
- data->unk6 = 0;
- data->prevPromptWindowId = 0;
- data->buffer = AllocZeroed(0x40);
+ sStatsEnabled = FALSE;
}
-void task00_mystery_gift(u8 taskId)
+bool32 MysteryGift_TryEnableStatsByFlagId(u16 flagId)
{
- struct MysteryGiftTaskData *data = (void *)gTasks[taskId].data;
- u32 sp0, flag;
- const u8 *r1;
+ sStatsEnabled = FALSE;
+ if (flagId == 0)
+ return FALSE;
+
+ if (!ValidateSavedWonderCard())
+ return FALSE;
+
+ if (gSaveBlock1Ptr->mysteryGift.card.flagId != flagId)
+ return FALSE;
- switch (data->state)
+ sStatsEnabled = TRUE;
+ return TRUE;
+}
+
+void MysteryGift_TryIncrementStat(u32 stat, u32 trainerId)
+{
+ if (sStatsEnabled)
{
- case 0:
- data->state = 1;
- break;
- case 1:
- switch (MysteryGift_HandleThreeOptionMenu(&data->textState, &data->curPromptWindowId, FALSE))
+ switch (stat)
{
- case 0:
- data->IsCardOrNews = 0;
- if (ValidateReceivedWonderCard() == TRUE)
- {
- data->state = 18;
- }
- else
- {
- data->state = 2;
- }
- break;
- case 1:
- data->IsCardOrNews = 1;
- if (ValidateReceivedWonderNews() == TRUE)
- {
- data->state = 18;
- }
- else
- {
- data->state = 2;
- }
- break;
- case -2u:
- data->state = 37;
+ case CARD_STAT_NUM_TRADES:
+ IncrementCardStatForNewTrainer(CARD_STAT_NUM_TRADES,
+ trainerId,
+ gSaveBlock1Ptr->mysteryGift.trainerIds[1],
+ ARRAY_COUNT(gSaveBlock1Ptr->mysteryGift.trainerIds[1]));
break;
- }
- break;
- case 2:
- {
- if (data->IsCardOrNews == 0)
- {
- if (MG_PrintTextOnWindow1AndWaitButton(&data->textState, gText_DontHaveCardNewOneInput))
- {
- data->state = 3;
- PrintMysteryGiftOrEReaderTopMenu(0, 1);
- }
- }
- else
- {
- if (MG_PrintTextOnWindow1AndWaitButton(&data->textState, gText_DontHaveNewsNewOneInput))
- {
- data->state = 3;
- PrintMysteryGiftOrEReaderTopMenu(0, 1);
- }
- }
- break;
- }
- case 3:
- if (data->IsCardOrNews == 0)
- {
- AddTextPrinterToWindow1(gText_WhereShouldCardBeAccessed);
- }
- else
- {
- AddTextPrinterToWindow1(gText_WhereShouldNewsBeAccessed);
- }
- data->state = 4;
- break;
- case 4:
- switch (MysteryGift_HandleThreeOptionMenu(&data->textState, &data->curPromptWindowId, TRUE))
- {
- case 0:
- ClearTextWindow();
- data->state = 5;
- data->source = 0;
+ case CARD_STAT_BATTLES_WON:
+ IncrementCardStatForNewTrainer(CARD_STAT_BATTLES_WON,
+ trainerId,
+ gSaveBlock1Ptr->mysteryGift.trainerIds[0],
+ ARRAY_COUNT(gSaveBlock1Ptr->mysteryGift.trainerIds[0]));
break;
- case 1:
- ClearTextWindow();
- data->state = 5;
- data->source = 1;
+ case CARD_STAT_BATTLES_LOST:
+ IncrementCardStatForNewTrainer(CARD_STAT_BATTLES_LOST,
+ trainerId,
+ gSaveBlock1Ptr->mysteryGift.trainerIds[0],
+ ARRAY_COUNT(gSaveBlock1Ptr->mysteryGift.trainerIds[0]));
break;
- case -2u:
- ClearTextWindow();
- if (ValidateCardOrNews(data->IsCardOrNews))
- {
- data->state = 18;
- }
- else
- {
- data->state = 0;
- PrintMysteryGiftOrEReaderTopMenu(0, 0);
- }
+ default:
+ AGB_ASSERT(0);
break;
}
- break;
- case 5:
- *gStringVar1 = EOS;
- *gStringVar2 = EOS;
- *gStringVar3 = EOS;
+ }
+}
- switch (data->IsCardOrNews)
- {
- case 0:
- if (data->source == 1)
- {
- MEvent_CreateTask_CardOrNewsWithFriend(ACTIVITY_WONDER_CARD);
- }
- else if (data->source == 0)
- {
- MEvent_CreateTask_CardOrNewsOverWireless(ACTIVITY_WONDER_CARD);
- }
- break;
- case 1:
- if (data->source == 1)
- {
- MEvent_CreateTask_CardOrNewsWithFriend(ACTIVITY_WONDER_NEWS);
- }
- else if (data->source == 0)
- {
- MEvent_CreateTask_CardOrNewsOverWireless(ACTIVITY_WONDER_NEWS);
- }
- break;
- }
- data->state = 6;
- break;
- case 6:
- if (gReceivedRemoteLinkPlayers != 0)
- {
- ClearScreenInBg0(TRUE);
- data->state = 7;
- mevent_client_do_init(data->IsCardOrNews);
- }
- else if (gSpecialVar_Result == LINKUP_FAILED)
- {
- ClearScreenInBg0(TRUE);
- data->state = 3;
- }
- break;
- case 7:
- AddTextPrinterToWindow1(gText_Communicating);
- data->state = 8;
- break;
- case 8:
- switch (mevent_client_do_exec(&data->curPromptWindowId))
- {
- case 6:
- Rfu_SetCloseLinkCallback();
- data->prevPromptWindowId = data->curPromptWindowId;
- data->state = 13;
- break;
- case 5:
- memcpy(data->buffer, mevent_client_get_buffer(), 0x40);
- mevent_client_inc_flag();
- break;
- case 3:
- data->state = 10;
- break;
- case 2:
- data->state = 9;
- break;
- case 4:
- data->state = 11;
- StringCopy(gStringVar1, gLinkPlayers[0].name);
- break;
- }
- break;
- case 9:
- flag = mevent_message_print_and_prompt_yes_no(&data->textState, &data->curPromptWindowId, FALSE, mevent_client_get_buffer());
- switch (flag)
- {
- case 0:
- mevent_client_set_param(0);
- mevent_client_inc_flag();
- data->state = 7;
- break;
- case 1:
- mevent_client_set_param(1);
- mevent_client_inc_flag();
- data->state = 7;
- break;
- case -1u:
- mevent_client_set_param(1);
- mevent_client_inc_flag();
- data->state = 7;
- break;
- }
- break;
- case 10:
- if (MG_PrintTextOnWindow1AndWaitButton(&data->textState, mevent_client_get_buffer()))
- {
- mevent_client_inc_flag();
- data->state = 7;
- }
- break;
- case 11:
- flag = mevent_message_print_and_prompt_yes_no(&data->textState, &data->curPromptWindowId, FALSE, gText_ThrowAwayWonderCard);
- switch (flag)
- {
- case 0:
- if (CheckReceivedGiftFromWonderCard() == TRUE)
- {
- data->state = 12;
- }
- else
- {
- mevent_client_set_param(0);
- mevent_client_inc_flag();
- data->state = 7;
- }
- break;
- case 1:
- mevent_client_set_param(1);
- mevent_client_inc_flag();
- data->state = 7;
- break;
- case -1u:
- mevent_client_set_param(1);
- mevent_client_inc_flag();
- data->state = 7;
- break;
- }
- break;
- case 12:
- flag = mevent_message_print_and_prompt_yes_no(&data->textState, &data->curPromptWindowId, FALSE, gText_HaventReceivedCardsGift);
- switch (flag)
- {
- case 0:
- mevent_client_set_param(0);
- mevent_client_inc_flag();
- data->state = 7;
- break;
- case 1:
- mevent_client_set_param(1);
- mevent_client_inc_flag();
- data->state = 7;
- break;
- case -1u:
- mevent_client_set_param(1);
- mevent_client_inc_flag();
- data->state = 7;
- break;
- }
- break;
- case 13:
- if (gReceivedRemoteLinkPlayers == 0)
- {
- DestroyWirelessStatusIndicatorSprite();
- data->state = 14;
- }
- break;
- case 14:
- if (PrintStringAndWait2Seconds(&data->textState, gText_CommunicationCompleted))
- {
- if (data->source == 1)
- {
- StringCopy(gStringVar1, gLinkPlayers[0].name);
- }
- data->state = 15;
- }
- break;
- case 15:
- r1 = mevent_message(&sp0, data->IsCardOrNews, data->source, data->prevPromptWindowId);
- if (r1 == NULL)
- {
- r1 = data->buffer;
- }
- if (sp0)
- {
- flag = PrintMGSuccessMessage(&data->textState, r1, &data->curPromptWindowId);
- }
- else
- {
- flag = MG_PrintTextOnWindow1AndWaitButton(&data->textState, r1);
- }
- if (flag)
- {
- if (data->prevPromptWindowId == 3)
- {
- if (data->source == 1)
- {
- GenerateRandomNews(1);
- }
- else
- {
- GenerateRandomNews(2);
- }
- }
- if (!sp0)
- {
- data->state = 0;
- PrintMysteryGiftOrEReaderTopMenu(0, 0);
- }
- else
- {
- data->state = 17;
- }
- }
- break;
- case 16:
- if (MG_PrintTextOnWindow1AndWaitButton(&data->textState, gText_CommunicationError))
- {
- data->state = 0;
- PrintMysteryGiftOrEReaderTopMenu(0, 0);
- }
- break;
- case 17:
- if (mevent_save_game(&data->textState))
- {
- data->state = 18;
- }
- break;
- case 18:
- if (HandleLoadWonderCardOrNews(&data->textState, data->IsCardOrNews))
- {
- data->state = 20;
- }
- break;
- case 20:
- if (data->IsCardOrNews == 0)
- {
- if (({JOY_NEW(A_BUTTON);}))
- {
- data->state = 21;
- }
- if (({JOY_NEW(B_BUTTON);}))
- {
- data->state = 27;
- }
- }
- else
- {
- switch (MENews_GetInput(gMain.newKeys))
- {
- case 0:
- MENews_RemoveScrollIndicatorArrowPair();
- data->state = 21;
- break;
- case 1:
- data->state = 27;
- break;
- }
- }
- break;
- case 21:
+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, int size)
+{
+ int i, j;
+
+ for (i = 0; i < size; i++)
{
- u32 result;
- if (data->IsCardOrNews == 0)
- {
- if (WonderCard_Test_Unk_08_6())
- {
- result = HandleMysteryGiftListMenu(&data->textState, &data->curPromptWindowId, data->IsCardOrNews, FALSE);
- }
- else
- {
- result = HandleMysteryGiftListMenu(&data->textState, &data->curPromptWindowId, data->IsCardOrNews, TRUE);
- }
- }
- else
- {
- if (WonderNews_Test_Unk_02())
- {
- result = HandleMysteryGiftListMenu(&data->textState, &data->curPromptWindowId, data->IsCardOrNews, FALSE);
- }
- else
- {
- result = HandleMysteryGiftListMenu(&data->textState, &data->curPromptWindowId, data->IsCardOrNews, TRUE);
- }
- }
- switch (result)
- {
- case 0:
- data->state = 28;
- break;
- case 1:
- data->state = 29;
+ if (trainerIds[i] == trainerId)
break;
- case 2:
- data->state = 22;
- break;
- case -2u:
- if (data->IsCardOrNews == 1)
- {
- MENews_AddScrollIndicatorArrowPair();
- }
- data->state = 20;
- break;
- }
- break;
}
- case 22:
- switch (mevent_message_prompt_discard(&data->textState, &data->curPromptWindowId, data->IsCardOrNews))
- {
- case 0:
- if (data->IsCardOrNews == 0 && CheckReceivedGiftFromWonderCard() == TRUE)
- {
- data->state = 23;
- }
- else
- {
- data->state = 24;
- }
- break;
- case 1:
- data->state = 21;
- break;
- case -1:
- data->state = 21;
- break;
- }
- break;
- case 23:
- switch ((u32)mevent_message_print_and_prompt_yes_no(&data->textState, &data->curPromptWindowId, TRUE, gText_HaventReceivedGiftOkayToDiscard))
- {
- case 0:
- data->state = 24;
- break;
- case 1:
- data->state = 21;
- break;
- case -1u:
- data->state = 21;
- break;
- }
- break;
- case 24:
- if (TearDownCardOrNews_ReturnToTopMenu(data->IsCardOrNews, 1))
- {
- DestroyNewsOrCard(data->IsCardOrNews);
- data->state = 25;
- }
- break;
- case 25:
- if (mevent_save_game(&data->textState))
- {
- data->state = 26;
- }
- break;
- case 26:
- if (mevent_message_was_thrown_away(&data->textState, data->IsCardOrNews))
- {
- data->state = 0;
- PrintMysteryGiftOrEReaderTopMenu(0, 0);
- }
- break;
- case 27:
- if (TearDownCardOrNews_ReturnToTopMenu(data->IsCardOrNews, 0))
- {
- data->state = 0;
- }
- break;
- case 28:
- if (TearDownCardOrNews_ReturnToTopMenu(data->IsCardOrNews, 1))
- {
- data->state = 3;
- }
- break;
- case 29:
- if (TearDownCardOrNews_ReturnToTopMenu(data->IsCardOrNews, 1))
- {
- switch (data->IsCardOrNews)
- {
- case 0:
- MEvent_CreateTask_Leader(ACTIVITY_WONDER_CARD);
- break;
- case 1:
- MEvent_CreateTask_Leader(ACTIVITY_WONDER_NEWS);
- break;
- }
- data->source = 1;
- data->state = 30;
- }
- break;
- case 30:
- if (gReceivedRemoteLinkPlayers != 0)
- {
- ClearScreenInBg0(1);
- data->state = 31;
- }
- else if (gSpecialVar_Result == LINKUP_FAILED)
- {
- ClearScreenInBg0(1);
- data->state = 18;
- }
- break;
- case 31:
- *gStringVar1 = EOS;
- *gStringVar2 = EOS;
- *gStringVar3 = EOS;
- if (data->IsCardOrNews == 0)
- {
- AddTextPrinterToWindow1(gText_SendingWonderCard);
- mevent_srv_new_wcard();
- }
- else
- {
- AddTextPrinterToWindow1(gText_SendingWonderNews);
- mevent_srv_init_wnews();
- }
- data->state = 32;
- break;
- case 32:
- if (mevent_srv_common_do_exec(&data->curPromptWindowId) == 3)
- {
- data->prevPromptWindowId = data->curPromptWindowId;
- data->state = 33;
- }
- break;
- case 33:
- Rfu_SetCloseLinkCallback();
- StringCopy(gStringVar1, gLinkPlayers[1].name);
- data->state = 34;
- break;
- case 34:
- if (gReceivedRemoteLinkPlayers == 0)
- {
- DestroyWirelessStatusIndicatorSprite();
- data->state = 35;
- }
- break;
- case 35:
- if (PrintMGSendStatus(&data->textState, &data->curPromptWindowId, data->source, data->prevPromptWindowId))
- {
- if (data->source == 1 && data->prevPromptWindowId == 3)
- {
- GenerateRandomNews(3);
- data->state = 17;
- }
- else
- {
- data->state = 0;
- PrintMysteryGiftOrEReaderTopMenu(0, 0);
- }
- }
- break;
- case 36:
- if (MG_PrintTextOnWindow1AndWaitButton(&data->textState, gText_CommunicationError))
- {
- data->state = 0;
- PrintMysteryGiftOrEReaderTopMenu(0, 0);
- }
- break;
- case 37:
- CloseLink();
- Free(data->buffer);
- DestroyTask(taskId);
- SetMainCallback2(MainCB_FreeAllBuffersAndReturnToInitTitleScreen);
- 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];
-u16 GetMysteryGiftBaseBlock(void)
-{
- return 0x1A9;
+ trainerIds[0] = trainerId;
+ return FALSE;
+ }
}
-void bgid_upload_textbox_1(u8 bgId)
+static void IncrementCardStatForNewTrainer(u32 stat, u32 trainerId, u32 *trainerIds, int size)
{
- DecompressAndLoadBgGfxUsingHeap(bgId, gUnkTextboxBorderGfx, 0x100, 0, 0);
+ if (RecordTrainerId(trainerId, trainerIds, size))
+ IncrementCardStat(stat);
}
diff --git a/src/mystery_gift_client.c b/src/mystery_gift_client.c
new file mode 100644
index 000000000..adf3ce8a6
--- /dev/null
+++ b/src/mystery_gift_client.c
@@ -0,0 +1,303 @@
+#include "global.h"
+#include "malloc.h"
+#include "decompress.h"
+#include "overworld.h"
+#include "script.h"
+#include "battle_tower.h"
+#include "mystery_gift.h"
+#include "mystery_event_script.h"
+#include "mystery_gift_client.h"
+
+enum {
+ FUNC_INIT,
+ FUNC_DONE,
+ FUNC_RECV,
+ FUNC_SEND,
+ FUNC_RUN,
+ FUNC_WAIT,
+ FUNC_RUN_MEVENT,
+ FUNC_RUN_BUFFER,
+};
+
+EWRAM_DATA static 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(bool32 isWonderNews)
+{
+ sClient = AllocZeroed(sizeof(*sClient));
+ MysteryGiftClient_Init(sClient, 1, 0);
+ sClient->isWonderNews = isWonderNews;
+}
+
+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(sClient);
+ sClient = NULL;
+ }
+ 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, client->isWonderNews);
+ 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_LINK_ASK_TOSS or MG_STATE_LINK_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, 1000);
+ break;
+ case CLI_RECV_EREADER_TRAINER:
+ memcpy(&gSaveBlock2Ptr->frontier.ereaderTrainer, client->recvBuffer, sizeof(gSaveBlock2Ptr->frontier.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:
+ InitMysteryEventScriptContext(client->recvBuffer);
+ client->funcState++;
+ break;
+ case 1:
+ if (!RunMysteryEventScriptContextCommand(&client->param))
+ {
+ client->funcId = FUNC_RUN;
+ client->funcState = 0;
+ }
+ break;
+ }
+ return CLI_RET_ACTIVE;
+}
+
+static u32 Client_RunBufferScript(struct MysteryGiftClient * client)
+{
+ // exec arbitrary code
+ 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);
+}
diff --git a/src/mystery_gift_link.c b/src/mystery_gift_link.c
new file mode 100644
index 000000000..55f4b7852
--- /dev/null
+++ b/src/mystery_gift_link.c
@@ -0,0 +1,222 @@
+#include "global.h"
+#include "malloc.h"
+#include "decompress.h"
+#include "util.h"
+#include "link.h"
+#include "link_rfu.h"
+#include "overworld.h"
+#include "script.h"
+#include "battle_tower.h"
+#include "mystery_event_script.h"
+#include "mystery_gift.h"
+#include "mystery_gift_link.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;
+}
diff --git a/src/mystery_gift_menu.c b/src/mystery_gift_menu.c
new file mode 100644
index 000000000..e1236adfd
--- /dev/null
+++ b/src/mystery_gift_menu.c
@@ -0,0 +1,1618 @@
+#include "global.h"
+#include "main.h"
+#include "text.h"
+#include "task.h"
+#include "malloc.h"
+#include "gpu_regs.h"
+#include "scanline_effect.h"
+#include "text_window.h"
+#include "bg.h"
+#include "window.h"
+#include "strings.h"
+#include "text_window.h"
+#include "menu.h"
+#include "palette.h"
+#include "constants/songs.h"
+#include "sound.h"
+#include "mystery_gift_menu.h"
+#include "union_room.h"
+#include "title_screen.h"
+#include "ereader_screen.h"
+#include "international_string_util.h"
+#include "list_menu.h"
+#include "string_util.h"
+#include "mystery_gift.h"
+#include "mystery_gift_view.h"
+#include "save.h"
+#include "link.h"
+#include "mystery_gift_client.h"
+#include "mystery_gift_server.h"
+#include "event_data.h"
+#include "link_rfu.h"
+#include "wonder_news.h"
+#include "constants/cable_club.h"
+
+#define LIST_MENU_TILE_NUM 10
+#define LIST_MENU_PAL_NUM 224
+
+static void LoadMysteryGiftTextboxBorder(u8 bgId);
+static void CreateMysteryGiftTask(void);
+static void Task_MysteryGift(u8 taskId);
+
+EWRAM_DATA static u8 sDownArrowCounterAndYCoordIdx[8] = {};
+EWRAM_DATA bool8 gGiftIsFromEReader = FALSE;
+
+static const u16 sTextboxBorder_Pal[] = INCBIN_U16("graphics/interface/mystery_gift_textbox_border.gbapal");
+static const u32 sTextboxBorder_Gfx[] = INCBIN_U32("graphics/interface/mystery_gift_textbox_border.4bpp.lz");
+
+struct MysteryGiftTaskData
+{
+ u16 var; // Multipurpose
+ u16 unused1;
+ u16 unused2;
+ u16 unused3;
+ u8 state;
+ u8 textState;
+ u8 unused4;
+ u8 unused5;
+ bool8 isWonderNews;
+ bool8 sourceIsFriend;
+ u8 msgId;
+ u8 * clientMsg;
+};
+
+static const struct BgTemplate sBGTemplates[] = {
+ {
+ .bg = 0,
+ .charBaseIndex = 2,
+ .mapBaseIndex = 15,
+ .screenSize = 0,
+ .paletteMode = 0,
+ .priority = 0,
+ .baseTile = 0x000
+ }, {
+ .bg = 1,
+ .charBaseIndex = 0,
+ .mapBaseIndex = 14,
+ .screenSize = 0,
+ .paletteMode = 0,
+ .priority = 1,
+ .baseTile = 0x000
+ }, {
+ .bg = 2,
+ .charBaseIndex = 0,
+ .mapBaseIndex = 13,
+ .screenSize = 0,
+ .paletteMode = 0,
+ .priority = 2,
+ .baseTile = 0x000
+ }, {
+ .bg = 3,
+ .charBaseIndex = 0,
+ .mapBaseIndex = 12,
+ .screenSize = 0,
+ .paletteMode = 0,
+ .priority = 3,
+ .baseTile = 0x000
+ }
+};
+
+static const struct WindowTemplate sMainWindows[] = {
+ {
+ .bg = 0,
+ .tilemapLeft = 0,
+ .tilemapTop = 0,
+ .width = 30,
+ .height = 2,
+ .paletteNum = 12,
+ .baseBlock = 0x0013
+ }, {
+ .bg = 0,
+ .tilemapLeft = 1,
+ .tilemapTop = 15,
+ .width = 28,
+ .height = 4,
+ .paletteNum = 12,
+ .baseBlock = 0x004f
+ }, {
+ .bg = 0,
+ .tilemapLeft = 0,
+ .tilemapTop = 15,
+ .width = 30,
+ .height = 5,
+ .paletteNum = 13,
+ .baseBlock = 0x004f
+ },
+ DUMMY_WIN_TEMPLATE
+};
+
+static const struct WindowTemplate sWindowTemplate_YesNoMsg_Wide = {
+ .bg = 0,
+ .tilemapLeft = 1,
+ .tilemapTop = 15,
+ .width = 28,
+ .height = 4,
+ .paletteNum = 12,
+ .baseBlock = 0x00e5
+};
+
+static const struct WindowTemplate sWindowTemplate_YesNoMsg = {
+ .bg = 0,
+ .tilemapLeft = 1,
+ .tilemapTop = 15,
+ .width = 20,
+ .height = 4,
+ .paletteNum = 12,
+ .baseBlock = 0x00e5
+};
+
+static const struct WindowTemplate sWindowTemplate_GiftSelect = {
+ .bg = 0,
+ .tilemapLeft = 1,
+ .tilemapTop = 15,
+ .width = 19,
+ .height = 4,
+ .paletteNum = 12,
+ .baseBlock = 0x00e5
+};
+
+static const struct WindowTemplate sWindowTemplate_ThreeOptions = {
+ .bg = 0,
+ .tilemapLeft = 8,
+ .tilemapTop = 6,
+ .width = 14,
+ .height = 6,
+ .paletteNum = 12,
+ .baseBlock = 0x0155
+};
+
+static const struct WindowTemplate sWindowTemplate_YesNoBox = {
+ .bg = 0,
+ .tilemapLeft = 23,
+ .tilemapTop = 15,
+ .width = 6,
+ .height = 4,
+ .paletteNum = 12,
+ .baseBlock = 0x0155
+};
+
+static const struct WindowTemplate sWindowTemplate_GiftSelect_3Options = {
+ .bg = 0,
+ .tilemapLeft = 22,
+ .tilemapTop = 11,
+ .width = 7,
+ .height = 8,
+ .paletteNum = 12,
+ .baseBlock = 0x0155
+};
+
+static const struct WindowTemplate sWindowTemplate_GiftSelect_2Options = {
+ .bg = 0,
+ .tilemapLeft = 22,
+ .tilemapTop = 13,
+ .width = 7,
+ .height = 6,
+ .paletteNum = 12,
+ .baseBlock = 0x0155
+};
+
+static const struct WindowTemplate sWindowTemplate_GiftSelect_1Option = {
+ .bg = 0,
+ .tilemapLeft = 22,
+ .tilemapTop = 15,
+ .width = 7,
+ .height = 4,
+ .paletteNum = 12,
+ .baseBlock = 0x0155
+};
+
+static const struct ListMenuItem sListMenuItems_CardsOrNews[] = {
+ { gText_WonderCards, 0 },
+ { gText_WonderNews, 1 },
+ { gText_Exit3, LIST_CANCEL }
+};
+
+static const struct ListMenuItem sListMenuItems_WirelessOrFriend[] = {
+ { gText_WirelessCommunication, 0 },
+ { gText_Friend2, 1 },
+ { gText_Cancel2, LIST_CANCEL }
+};
+
+static const struct ListMenuTemplate sListMenuTemplate_ThreeOptions = {
+ .items = NULL,
+ .moveCursorFunc = ListMenuDefaultCursorMoveFunc,
+ .itemPrintFunc = NULL,
+ .totalItems = 3,
+ .maxShowed = 3,
+ .windowId = 0,
+ .header_X = 0,
+ .item_X = 8,
+ .cursor_X = 0,
+ .upText_Y = 1,
+ .cursorPal = 2,
+ .fillValue = 1,
+ .cursorShadowPal = 3,
+ .lettersSpacing = 0,
+ .itemVerticalPadding = 0,
+ .scrollMultiple = 0,
+ .fontId = 1,
+ .cursorKind = 0
+};
+
+static const struct ListMenuItem sListMenuItems_ReceiveSendToss[] = {
+ { gText_Receive, 0 },
+ { gText_Send, 1 },
+ { gText_Toss, 2 },
+ { gText_Cancel2, LIST_CANCEL }
+};
+
+static const struct ListMenuItem sListMenuItems_ReceiveToss[] = {
+ { gText_Receive, 0 },
+ { gText_Toss, 2 },
+ { gText_Cancel2, LIST_CANCEL }
+};
+
+static const struct ListMenuItem sListMenuItems_ReceiveSend[] = {
+ { gText_Receive, 0 },
+ { gText_Send, 1 },
+ { gText_Cancel2, LIST_CANCEL }
+};
+
+static const struct ListMenuItem sListMenuItems_Receive[] = {
+ { gText_Receive, 0 },
+ { gText_Cancel2, LIST_CANCEL }
+};
+
+static const struct ListMenuTemplate sListMenu_ReceiveSendToss = {
+ .items = sListMenuItems_ReceiveSendToss,
+ .moveCursorFunc = ListMenuDefaultCursorMoveFunc,
+ .itemPrintFunc = NULL,
+ .totalItems = 4,
+ .maxShowed = 4,
+ .windowId = 0,
+ .header_X = 0,
+ .item_X = 8,
+ .cursor_X = 0,
+ .upText_Y = 1,
+ .cursorPal = 2,
+ .fillValue = 1,
+ .cursorShadowPal = 3,
+ .lettersSpacing = 0,
+ .itemVerticalPadding = 0,
+ .scrollMultiple = 0,
+ .fontId = 1,
+ .cursorKind = 0
+};
+
+static const struct ListMenuTemplate sListMenu_ReceiveToss = {
+ .items = sListMenuItems_ReceiveToss,
+ .moveCursorFunc = ListMenuDefaultCursorMoveFunc,
+ .itemPrintFunc = NULL,
+ .totalItems = 3,
+ .maxShowed = 3,
+ .windowId = 0,
+ .header_X = 0,
+ .item_X = 8,
+ .cursor_X = 0,
+ .upText_Y = 1,
+ .cursorPal = 2,
+ .fillValue = 1,
+ .cursorShadowPal = 3,
+ .lettersSpacing = 0,
+ .itemVerticalPadding = 0,
+ .scrollMultiple = 0,
+ .fontId = 1,
+ .cursorKind = 0
+};
+
+static const struct ListMenuTemplate sListMenu_ReceiveSend = {
+ .items = sListMenuItems_ReceiveSend,
+ .moveCursorFunc = ListMenuDefaultCursorMoveFunc,
+ .itemPrintFunc = NULL,
+ .totalItems = 3,
+ .maxShowed = 3,
+ .windowId = 0,
+ .header_X = 0,
+ .item_X = 8,
+ .cursor_X = 0,
+ .upText_Y = 1,
+ .cursorPal = 2,
+ .fillValue = 1,
+ .cursorShadowPal = 3,
+ .lettersSpacing = 0,
+ .itemVerticalPadding = 0,
+ .scrollMultiple = 0,
+ .fontId = 1,
+ .cursorKind = 0
+};
+
+static const struct ListMenuTemplate sListMenu_Receive = {
+ .items = sListMenuItems_Receive,
+ .moveCursorFunc = ListMenuDefaultCursorMoveFunc,
+ .itemPrintFunc = NULL,
+ .totalItems = 2,
+ .maxShowed = 2,
+ .windowId = 0,
+ .header_X = 0,
+ .item_X = 8,
+ .cursor_X = 0,
+ .upText_Y = 1,
+ .cursorPal = 2,
+ .fillValue = 1,
+ .cursorShadowPal = 3,
+ .lettersSpacing = 0,
+ .itemVerticalPadding = 0,
+ .scrollMultiple = 0,
+ .fontId = 1,
+ .cursorKind = 0
+};
+
+static const u8 *const Unref_082F0710[] = {
+ gText_VarietyOfEventsImportedWireless,
+ gText_WonderCardsInPossession,
+ gText_ReadNewsThatArrived,
+ gText_ReturnToTitle
+};
+
+ALIGNED(2) static const u8 sTextColors_TopMenu[] = { TEXT_COLOR_TRANSPARENT, TEXT_COLOR_WHITE, TEXT_COLOR_DARK_GRAY };
+ALIGNED(2) static const u8 sTextColors_TopMenu_Copy[] = { TEXT_COLOR_TRANSPARENT, TEXT_COLOR_WHITE, TEXT_COLOR_DARK_GRAY };
+ALIGNED(2) static const u8 sMG_Ereader_TextColor_2[] = { TEXT_COLOR_WHITE, TEXT_COLOR_DARK_GRAY, TEXT_COLOR_LIGHT_GRAY };
+
+static void VBlankCB_MysteryGiftEReader(void)
+{
+ ProcessSpriteCopyRequests();
+ LoadOam();
+ TransferPlttBuffer();
+}
+
+void CB2_MysteryGiftEReader(void)
+{
+ RunTasks();
+ RunTextPrinters();
+ AnimateSprites();
+ BuildOamBuffer();
+}
+
+static bool32 HandleMysteryGiftOrEReaderSetup(s32 isEReader)
+{
+ switch (gMain.state)
+ {
+ case 0:
+ SetVBlankCallback(NULL);
+ ResetPaletteFade();
+ ResetSpriteData();
+ FreeAllSpritePalettes();
+ ResetTasks();
+ ScanlineEffect_Stop();
+ ResetBgsAndClearDma3BusyFlags(0);
+
+ InitBgsFromTemplates(0, sBGTemplates, ARRAY_COUNT(sBGTemplates));
+ ChangeBgX(0, 0, 0);
+ ChangeBgY(0, 0, 0);
+ ChangeBgX(1, 0, 0);
+ ChangeBgY(1, 0, 0);
+ ChangeBgX(2, 0, 0);
+ ChangeBgY(2, 0, 0);
+ ChangeBgX(3, 0, 0);
+ ChangeBgY(3, 0, 0);
+
+ SetBgTilemapBuffer(3, Alloc(BG_SCREEN_SIZE));
+ SetBgTilemapBuffer(2, Alloc(BG_SCREEN_SIZE));
+ SetBgTilemapBuffer(1, Alloc(BG_SCREEN_SIZE));
+ SetBgTilemapBuffer(0, Alloc(BG_SCREEN_SIZE));
+
+ LoadMysteryGiftTextboxBorder(3);
+ InitWindows(sMainWindows);
+ DeactivateAllTextPrinters();
+ ClearGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_WIN0_ON | DISPCNT_WIN1_ON);
+ SetGpuReg(REG_OFFSET_BLDCNT, 0);
+ SetGpuReg(REG_OFFSET_BLDALPHA, 0);
+ SetGpuReg(REG_OFFSET_BLDY, 0);
+ gMain.state++;
+ break;
+ case 1:
+ LoadPalette(sTextboxBorder_Pal, 0, 0x20);
+ LoadPalette(GetTextWindowPalette(2), 0xd0, 0x20);
+ Menu_LoadStdPalAt(0xC0);
+ LoadUserWindowBorderGfx(0, 0xA, 0xE0);
+ LoadUserWindowBorderGfx_(0, 0x1, 0xF0);
+ FillBgTilemapBufferRect(0, 0x000, 0, 0, 32, 32, 0x11);
+ FillBgTilemapBufferRect(1, 0x000, 0, 0, 32, 32, 0x11);
+ FillBgTilemapBufferRect(2, 0x000, 0, 0, 32, 32, 0x11);
+ MG_DrawCheckerboardPattern(3);
+ PrintMysteryGiftOrEReaderTopMenu(isEReader, FALSE);
+ gMain.state++;
+ break;
+ case 2:
+ CopyBgTilemapBufferToVram(3);
+ CopyBgTilemapBufferToVram(2);
+ CopyBgTilemapBufferToVram(1);
+ CopyBgTilemapBufferToVram(0);
+ gMain.state++;
+ break;
+ case 3:
+ ShowBg(0);
+ ShowBg(3);
+ PlayBGM(MUS_RG_MYSTERY_GIFT);
+ SetVBlankCallback(VBlankCB_MysteryGiftEReader);
+ EnableInterrupts(INTR_FLAG_VBLANK | INTR_FLAG_VCOUNT | INTR_FLAG_TIMER3 | INTR_FLAG_SERIAL);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+void CB2_InitMysteryGift(void)
+{
+ if (HandleMysteryGiftOrEReaderSetup(FALSE))
+ {
+ SetMainCallback2(CB2_MysteryGiftEReader);
+ gGiftIsFromEReader = FALSE;
+ CreateMysteryGiftTask();
+ }
+ RunTasks();
+}
+
+void CB2_InitEReader(void)
+{
+ if (HandleMysteryGiftOrEReaderSetup(TRUE))
+ {
+ SetMainCallback2(CB2_MysteryGiftEReader);
+ gGiftIsFromEReader = TRUE;
+ CreateEReaderTask();
+ }
+}
+
+void MainCB_FreeAllBuffersAndReturnToInitTitleScreen(void)
+{
+ gGiftIsFromEReader = FALSE;
+ FreeAllWindowBuffers();
+ Free(GetBgTilemapBuffer(0));
+ Free(GetBgTilemapBuffer(1));
+ Free(GetBgTilemapBuffer(2));
+ Free(GetBgTilemapBuffer(3));
+ SetMainCallback2(CB2_InitTitleScreen);
+}
+
+void PrintMysteryGiftOrEReaderTopMenu(bool8 isEReader, bool32 useCancel)
+{
+ const u8 * header;
+ const u8 * options;
+ FillWindowPixelBuffer(0, 0);
+ if (!isEReader)
+ {
+ header = gText_MysteryGift;
+ options = !useCancel ? gText_PickOKExit : gText_PickOKCancel;
+ }
+ else
+ {
+ header = gJPText_MysteryGift;
+ options = gJPText_DecideStop;
+ }
+
+ AddTextPrinterParameterized4(0, 1, 4, 1, 0, 0, sTextColors_TopMenu, TEXT_SPEED_FF, header);
+ AddTextPrinterParameterized4(0, 0, GetStringRightAlignXOffset(0, options, 0xDE), 1, 0, 0, sTextColors_TopMenu, TEXT_SPEED_FF, options);
+ CopyWindowToVram(0, 2);
+ PutWindowTilemap(0);
+}
+
+void MG_DrawTextBorder(u8 windowId)
+{
+ DrawTextBorderOuter(windowId, 0x01, 0xF);
+}
+
+void MG_DrawCheckerboardPattern(u32 bg)
+{
+ s32 i = 0, j;
+
+ FillBgTilemapBufferRect(bg, 0x003, 0, 0, 32, 2, 0x11);
+
+ for (i = 0; i < 18; i++)
+ {
+ for (j = 0; j < 32; j++)
+ {
+ if ((i & 1) != (j & 1))
+ FillBgTilemapBufferRect(bg, 1, j, i + 2, 1, 1, 0x11);
+ else
+ FillBgTilemapBufferRect(bg, 2, j, i + 2, 1, 1, 0x11);
+ }
+ }
+}
+
+static void ClearScreenInBg0(bool32 ignoreTopTwoRows)
+{
+ switch (ignoreTopTwoRows)
+ {
+ case 0:
+ FillBgTilemapBufferRect(0, 0, 0, 0, 32, 32, 0x11);
+ break;
+ case 1:
+ FillBgTilemapBufferRect(0, 0, 0, 2, 32, 30, 0x11);
+ break;
+ }
+ CopyBgTilemapBufferToVram(0);
+}
+
+void AddTextPrinterToWindow1(const u8 *str)
+{
+ StringExpandPlaceholders(gStringVar4, str);
+ FillWindowPixelBuffer(1, 0x11);
+ AddTextPrinterParameterized4(1, 1, 0, 1, 0, 0, sMG_Ereader_TextColor_2, 0, gStringVar4);
+ DrawTextBorderOuter(1, 0x001, 0xF);
+ PutWindowTilemap(1);
+ CopyWindowToVram(1, 3);
+}
+
+static void ClearTextWindow(void)
+{
+ rbox_fill_rectangle(1);
+ ClearWindowTilemap(1);
+ CopyWindowToVram(1, 1);
+}
+
+#define DOWN_ARROW_X 208
+#define DOWN_ARROW_Y 20
+
+bool32 PrintMysteryGiftMenuMessage(u8 *textState, const u8 *str)
+{
+ switch (*textState)
+ {
+ case 0:
+ AddTextPrinterToWindow1(str);
+ (*textState)++;
+ break;
+ case 1:
+ DrawDownArrow(1, DOWN_ARROW_X, DOWN_ARROW_Y, 1, FALSE, &sDownArrowCounterAndYCoordIdx[0], &sDownArrowCounterAndYCoordIdx[1]);
+ if (({JOY_NEW(A_BUTTON | B_BUTTON);}))
+ (*textState)++;
+ break;
+ case 2:
+ DrawDownArrow(1, DOWN_ARROW_X, DOWN_ARROW_Y, 1, TRUE, &sDownArrowCounterAndYCoordIdx[0], &sDownArrowCounterAndYCoordIdx[1]);
+ *textState = 0;
+ ClearTextWindow();
+ return TRUE;
+ case 0xFF:
+ *textState = 2;
+ return FALSE;
+ }
+ return FALSE;
+}
+
+static void HideDownArrow(void)
+{
+ DrawDownArrow(1, DOWN_ARROW_X, DOWN_ARROW_Y, 1, FALSE, &sDownArrowCounterAndYCoordIdx[0], &sDownArrowCounterAndYCoordIdx[1]);
+}
+
+static void ShowDownArrow(void)
+{
+ DrawDownArrow(1, DOWN_ARROW_X, DOWN_ARROW_Y, 1, TRUE, &sDownArrowCounterAndYCoordIdx[0], &sDownArrowCounterAndYCoordIdx[1]);
+}
+
+// Unused
+static bool32 HideDownArrowAndWaitButton(u8 * textState)
+{
+ switch (*textState)
+ {
+ case 0:
+ HideDownArrow();
+ if (JOY_NEW(A_BUTTON | B_BUTTON))
+ (*textState)++;
+ break;
+ case 1:
+ ShowDownArrow();
+ *textState = 0;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static bool32 PrintStringAndWait2Seconds(u8 * counter, const u8 * str)
+{
+ if (*counter == 0)
+ AddTextPrinterToWindow1(str);
+
+ if (++(*counter) > 120)
+ {
+ *counter = 0;
+ ClearTextWindow();
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+
+static u32 MysteryGift_HandleThreeOptionMenu(u8 * unused0, u16 * unused1, u8 whichMenu)
+{
+ struct ListMenuTemplate listMenuTemplate = sListMenuTemplate_ThreeOptions;
+ struct WindowTemplate windowTemplate = sWindowTemplate_ThreeOptions;
+ s32 width;
+ s32 response;
+
+ if (whichMenu == 0)
+ listMenuTemplate.items = sListMenuItems_CardsOrNews;
+ else
+ listMenuTemplate.items = sListMenuItems_WirelessOrFriend;
+
+ width = Intl_GetListMenuWidth(&listMenuTemplate);
+ if (width & 1)
+ width++;
+
+ windowTemplate.width = width;
+ if (width < 30)
+ windowTemplate.tilemapLeft = (30 - width) / 2;
+ else
+ windowTemplate.tilemapLeft = 0;
+
+ response = DoMysteryGiftListMenu(&windowTemplate, &listMenuTemplate, 1, LIST_MENU_TILE_NUM, LIST_MENU_PAL_NUM);
+ if (response != LIST_NOTHING_CHOSEN)
+ {
+ ClearWindowTilemap(2);
+ CopyWindowToVram(2, 1);
+ }
+ return response;
+}
+
+s8 DoMysteryGiftYesNo(u8 * textState, u16 * windowId, bool8 yesNoBoxPlacement, const u8 * str)
+{
+ struct WindowTemplate windowTemplate;
+ s8 input;
+
+ switch (*textState)
+ {
+ case 0:
+ // Print question message
+ StringExpandPlaceholders(gStringVar4, str);
+ if (yesNoBoxPlacement == 0)
+ *windowId = AddWindow(&sWindowTemplate_YesNoMsg_Wide);
+ else
+ *windowId = AddWindow(&sWindowTemplate_YesNoMsg);
+ FillWindowPixelBuffer(*windowId, 0x11);
+ AddTextPrinterParameterized4(*windowId, 1, 0, 1, 0, 0, sMG_Ereader_TextColor_2, 0, gStringVar4);
+ DrawTextBorderOuter(*windowId, 0x001, 0x0F);
+ CopyWindowToVram(*windowId, 2);
+ PutWindowTilemap(*windowId);
+ (*textState)++;
+ break;
+ case 1:
+ // Create Yes/No
+ windowTemplate = sWindowTemplate_YesNoBox;
+ if (yesNoBoxPlacement == 0)
+ windowTemplate.tilemapTop = 9;
+ else
+ windowTemplate.tilemapTop = 15;
+ CreateYesNoMenu(&windowTemplate, 10, 14, 0);
+ (*textState)++;
+ break;
+ case 2:
+ // Handle Yes/No input
+ input = Menu_ProcessInputNoWrapClearOnChoose();
+ if (input == MENU_B_PRESSED || input == 0 || input == 1)
+ {
+ *textState = 0;
+ rbox_fill_rectangle(*windowId);
+ ClearWindowTilemap(*windowId);
+ CopyWindowToVram(*windowId, 1);
+ RemoveWindow(*windowId);
+ return input;
+ }
+ break;
+ case 0xFF:
+ *textState = 0;
+ rbox_fill_rectangle(*windowId);
+ ClearWindowTilemap(*windowId);
+ CopyWindowToVram(*windowId, 1);
+ RemoveWindow(*windowId);
+ return MENU_B_PRESSED;
+ }
+
+ return MENU_NOTHING_CHOSEN;
+}
+
+// Handle the "Receive/Send/Toss" menu that appears when selecting Wonder Card/News
+static s32 HandleGiftSelectMenu(u8 * textState, u16 * windowId, bool32 cannotToss, bool32 cannotSend)
+{
+ struct WindowTemplate windowTemplate;
+ s32 input;
+
+ switch (*textState)
+ {
+ case 0:
+ // Print menu message
+ if (!cannotToss)
+ StringExpandPlaceholders(gStringVar4, gText_WhatToDoWithCards);
+ else
+ StringExpandPlaceholders(gStringVar4, gText_WhatToDoWithNews);
+ *windowId = AddWindow(&sWindowTemplate_GiftSelect);
+ FillWindowPixelBuffer(*windowId, 0x11);
+ AddTextPrinterParameterized4(*windowId, 1, 0, 1, 0, 0, sMG_Ereader_TextColor_2, 0, gStringVar4);
+ DrawTextBorderOuter(*windowId, 0x001, 0x0F);
+ CopyWindowToVram(*windowId, 2);
+ PutWindowTilemap(*windowId);
+ (*textState)++;
+ break;
+ case 1:
+ windowTemplate = sWindowTemplate_YesNoBox;
+ if (cannotSend)
+ {
+ if (!cannotToss)
+ input = DoMysteryGiftListMenu(&sWindowTemplate_GiftSelect_2Options, &sListMenu_ReceiveToss, 1, LIST_MENU_TILE_NUM, LIST_MENU_PAL_NUM);
+ else
+ input = DoMysteryGiftListMenu(&sWindowTemplate_GiftSelect_1Option, &sListMenu_Receive, 1, LIST_MENU_TILE_NUM, LIST_MENU_PAL_NUM);
+ }
+ else
+ {
+ if (!cannotToss)
+ input = DoMysteryGiftListMenu(&sWindowTemplate_GiftSelect_3Options, &sListMenu_ReceiveSendToss, 1, LIST_MENU_TILE_NUM, LIST_MENU_PAL_NUM);
+ else
+ input = DoMysteryGiftListMenu(&sWindowTemplate_GiftSelect_2Options, &sListMenu_ReceiveSend, 1, LIST_MENU_TILE_NUM, LIST_MENU_PAL_NUM);
+ }
+ if (input != LIST_NOTHING_CHOSEN)
+ {
+ *textState = 0;
+ rbox_fill_rectangle(*windowId);
+ ClearWindowTilemap(*windowId);
+ CopyWindowToVram(*windowId, 1);
+ RemoveWindow(*windowId);
+ return input;
+ }
+ break;
+ case 0xFF:
+ *textState = 0;
+ rbox_fill_rectangle(*windowId);
+ ClearWindowTilemap(*windowId);
+ CopyWindowToVram(*windowId, 1);
+ RemoveWindow(*windowId);
+ return LIST_CANCEL;
+ }
+
+ return LIST_NOTHING_CHOSEN;
+}
+
+static bool32 ValidateCardOrNews(bool32 isWonderNews)
+{
+ if (!isWonderNews)
+ return ValidateSavedWonderCard();
+ else
+ return ValidateSavedWonderNews();
+}
+
+static bool32 HandleLoadWonderCardOrNews(u8 * state, bool32 isWonderNews)
+{
+ switch (*state)
+ {
+ case 0:
+ if (!isWonderNews)
+ WonderCard_Init(GetSavedWonderCard(), GetSavedWonderCardMetadata());
+ else
+ WonderNews_Init(GetSavedWonderNews());
+ (*state)++;
+ break;
+ case 1:
+ if (!isWonderNews)
+ {
+ if (!WonderCard_Enter())
+ return FALSE;
+ }
+ else
+ {
+ if (!WonderNews_Enter())
+ return FALSE;
+ }
+ *state = 0;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static bool32 ClearSavedNewsOrCard(bool32 isWonderNews)
+{
+ if (!isWonderNews)
+ ClearSavedWonderCardAndRelated();
+ else
+ ClearSavedWonderNewsAndRelated();
+ return TRUE;
+}
+
+static bool32 ExitWonderCardOrNews(bool32 isWonderNews, bool32 useCancel)
+{
+ if (!isWonderNews)
+ {
+ if (WonderCard_Exit(useCancel))
+ {
+ WonderCard_Destroy();
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+ }
+ else
+ {
+ if (WonderNews_Exit(useCancel))
+ {
+ WonderNews_Destroy();
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+ }
+}
+
+static s32 AskDiscardGift(u8 * textState, u16 * windowId, bool32 isWonderNews)
+{
+ if (!isWonderNews)
+ return DoMysteryGiftYesNo(textState, windowId, TRUE, gText_IfThrowAwayCardEventWontHappen);
+ else
+ return DoMysteryGiftYesNo(textState, windowId, TRUE, gText_OkayToDiscardNews);
+}
+
+static bool32 PrintThrownAway(u8 * textState, bool32 isWonderNews)
+{
+ if (!isWonderNews)
+ return PrintMysteryGiftMenuMessage(textState, gText_WonderCardThrownAway);
+ else
+ return PrintMysteryGiftMenuMessage(textState, gText_WonderNewsThrownAway);
+}
+
+static bool32 SaveOnMysteryGiftMenu(u8 * state)
+{
+ switch (*state)
+ {
+ case 0:
+ AddTextPrinterToWindow1(gText_DataWillBeSaved);
+ (*state)++;
+ break;
+ case 1:
+ TrySavingData(SAVE_NORMAL);
+ (*state)++;
+ break;
+ case 2:
+ AddTextPrinterToWindow1(gText_SaveCompletedPressA);
+ (*state)++;
+ break;
+ case 3:
+ if (JOY_NEW(A_BUTTON | B_BUTTON))
+ (*state)++;
+ break;
+ case 4:
+ *state = 0;
+ ClearTextWindow();
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static const u8 * GetClientResultMessage(bool32 * successMsg, bool8 isWonderNews, bool8 sourceIsFriend, u32 msgId)
+{
+ const u8 * msg = NULL;
+ *successMsg = FALSE;
+
+ switch (msgId)
+ {
+ case CLI_MSG_NOTHING_SENT:
+ *successMsg = FALSE;
+ msg = gText_NothingSentOver;
+ break;
+ case CLI_MSG_RECORD_UPLOADED:
+ *successMsg = FALSE;
+ msg = gText_RecordUploadedViaWireless;
+ break;
+ case CLI_MSG_CARD_RECEIVED:
+ *successMsg = TRUE;
+ msg = !sourceIsFriend ? gText_WonderCardReceived : gText_WonderCardReceivedFrom;
+ break;
+ case CLI_MSG_NEWS_RECEIVED:
+ *successMsg = TRUE;
+ msg = !sourceIsFriend ? gText_WonderNewsReceived : gText_WonderNewsReceivedFrom;
+ break;
+ case CLI_MSG_STAMP_RECEIVED:
+ *successMsg = TRUE;
+ msg = gText_NewStampReceived;
+ break;
+ case CLI_MSG_HAD_CARD:
+ *successMsg = FALSE;
+ msg = gText_AlreadyHadCard;
+ break;
+ case CLI_MSG_HAD_STAMP:
+ *successMsg = FALSE;
+ msg = gText_AlreadyHadStamp;
+ break;
+ case CLI_MSG_HAD_NEWS:
+ *successMsg = FALSE;
+ msg = gText_AlreadyHadNews;
+ break;
+ case CLI_MSG_NO_ROOM_STAMPS:
+ *successMsg = FALSE;
+ msg = gText_NoMoreRoomForStamps;
+ break;
+ case CLI_MSG_COMM_CANCELED:
+ *successMsg = FALSE;
+ msg = gText_CommunicationCanceled;
+ break;
+ case CLI_MSG_CANT_ACCEPT:
+ *successMsg = FALSE;
+ msg = !isWonderNews ? gText_CantAcceptCardFromTrainer : gText_CantAcceptNewsFromTrainer;
+ break;
+ case CLI_MSG_COMM_ERROR:
+ *successMsg = FALSE;
+ msg = gText_CommunicationError;
+ break;
+ case CLI_MSG_TRAINER_RECEIVED:
+ *successMsg = TRUE;
+ msg = gText_NewTrainerReceived;
+ break;
+ case CLI_MSG_BUFFER_SUCCESS:
+ *successMsg = TRUE;
+ // msg is NULL, use buffer
+ break;
+ case CLI_MSG_BUFFER_FAILURE:
+ *successMsg = FALSE;
+ // msg is NULL, use buffer
+ break;
+ }
+
+ return msg;
+}
+
+static bool32 PrintSuccessMessage(u8 * state, const u8 * msg, u16 * timer)
+{
+ switch (*state)
+ {
+ case 0:
+ if (msg != NULL)
+ AddTextPrinterToWindow1(msg);
+ PlayFanfare(MUS_OBTAIN_ITEM);
+ *timer = 0;
+ (*state)++;
+ break;
+ case 1:
+ if (++(*timer) > 240)
+ (*state)++;
+ break;
+ case 2:
+ if (IsFanfareTaskInactive())
+ {
+ *state = 0;
+ ClearTextWindow();
+ return TRUE;
+ }
+ break;
+ }
+ return FALSE;
+}
+
+static const u8 * GetServerResultMessage(bool32 * wonderSuccess, bool8 sourceIsFriend, u32 msgId)
+{
+ const u8 * result = gText_CommunicationError;
+ *wonderSuccess = FALSE;
+ switch (msgId)
+ {
+ case SVR_MSG_NOTHING_SENT:
+ result = gText_NothingSentOver;
+ break;
+ case SVR_MSG_RECORD_UPLOADED:
+ result = gText_RecordUploadedViaWireless;
+ break;
+ case SVR_MSG_CARD_SENT:
+ result = gText_WonderCardSentTo;
+ *wonderSuccess = TRUE;
+ break;
+ case SVR_MSG_NEWS_SENT:
+ result = gText_WonderNewsSentTo;
+ *wonderSuccess = TRUE;
+ break;
+ case SVR_MSG_STAMP_SENT:
+ result = gText_StampSentTo;
+ break;
+ case SVR_MSG_HAS_CARD:
+ result = gText_OtherTrainerHasCard;
+ break;
+ case SVR_MSG_HAS_STAMP:
+ result = gText_OtherTrainerHasStamp;
+ break;
+ case SVR_MSG_HAS_NEWS:
+ result = gText_OtherTrainerHasNews;
+ break;
+ case SVR_MSG_NO_ROOM_STAMPS:
+ result = gText_NoMoreRoomForStamps;
+ break;
+ case SVR_MSG_CLIENT_CANCELED:
+ result = gText_OtherTrainerCanceled;
+ break;
+ case SVR_MSG_CANT_SEND_GIFT_1:
+ result = gText_CantSendGiftToTrainer;
+ break;
+ case SVR_MSG_COMM_ERROR:
+ result = gText_CommunicationError;
+ break;
+ case SVR_MSG_GIFT_SENT_1:
+ result = gText_GiftSentTo;
+ break;
+ case SVR_MSG_GIFT_SENT_2:
+ result = gText_GiftSentTo;
+ break;
+ case SVR_MSG_CANT_SEND_GIFT_2:
+ result = gText_CantSendGiftToTrainer;
+ break;
+ }
+ return result;
+}
+
+static bool32 PrintServerResultMessage(u8 * state, u16 * timer, bool8 sourceIsFriend, u32 msgId)
+{
+ bool32 wonderSuccess;
+ const u8 * str = GetServerResultMessage(&wonderSuccess, sourceIsFriend, msgId);
+ if (wonderSuccess)
+ return PrintSuccessMessage(state, str, timer);
+ else
+ return PrintMysteryGiftMenuMessage(state, str);
+}
+
+// States for Task_MysteryGift.
+// CLIENT states are for when the player is receiving a gift, and use mystery_gift_client.c link functions.
+// SERVER states are for when the player is sending a gift, and use mystery_gift_server.c link functions.
+// Other states handle the general Mystery Gift menu usage.
+enum {
+ MG_STATE_TO_MAIN_MENU,
+ MG_STATE_MAIN_MENU,
+ MG_STATE_DONT_HAVE_ANY,
+ MG_STATE_SOURCE_PROMPT,
+ MG_STATE_SOURCE_PROMPT_INPUT,
+ MG_STATE_CLIENT_LINK_START,
+ MG_STATE_CLIENT_LINK_WAIT,
+ MG_STATE_CLIENT_COMMUNICATING,
+ MG_STATE_CLIENT_LINK,
+ MG_STATE_CLIENT_YES_NO,
+ MG_STATE_CLIENT_MESSAGE,
+ MG_STATE_CLIENT_ASK_TOSS,
+ MG_STATE_CLIENT_ASK_TOSS_UNRECEIVED,
+ MG_STATE_CLIENT_LINK_END,
+ MG_STATE_CLIENT_COMM_COMPLETED,
+ MG_STATE_CLIENT_RESULT_MSG,
+ MG_STATE_CLIENT_ERROR,
+ MG_STATE_SAVE_LOAD_GIFT,
+ MG_STATE_LOAD_GIFT,
+ MG_STATE_UNUSED,
+ MG_STATE_HANDLE_GIFT_INPUT,
+ MG_STATE_HANDLE_GIFT_SELECT,
+ MG_STATE_ASK_TOSS,
+ MG_STATE_ASK_TOSS_UNRECEIVED,
+ MG_STATE_TOSS,
+ MG_STATE_TOSS_SAVE,
+ MG_STATE_TOSSED,
+ MG_STATE_GIFT_INPUT_EXIT,
+ MG_STATE_RECEIVE,
+ MG_STATE_SEND,
+ MG_STATE_SERVER_LINK_WAIT,
+ MG_STATE_SERVER_LINK_START,
+ MG_STATE_SERVER_LINK,
+ MG_STATE_SERVER_LINK_END,
+ MG_STATE_SERVER_LINK_END_WAIT,
+ MG_STATE_SERVER_RESULT_MSG,
+ MG_STATE_SERVER_ERROR,
+ MG_STATE_EXIT,
+};
+
+static void CreateMysteryGiftTask(void)
+{
+ u8 taskId = CreateTask(Task_MysteryGift, 0);
+ struct MysteryGiftTaskData * data = (void *)gTasks[taskId].data;
+ data->state = MG_STATE_TO_MAIN_MENU;
+ data->textState = 0;
+ data->unused4 = 0;
+ data->unused5 = 0;
+ data->isWonderNews = 0;
+ data->sourceIsFriend = 0;
+ data->var = 0;
+ data->unused1 = 0;
+ data->unused2 = 0;
+ data->unused3 = 0;
+ data->msgId = 0;
+ data->clientMsg = AllocZeroed(CLIENT_MAX_MSG_SIZE);
+}
+
+static void Task_MysteryGift(u8 taskId)
+{
+ struct MysteryGiftTaskData *data = (void *)gTasks[taskId].data;
+ u32 successMsg, input;
+ const u8 *msg;
+
+ switch (data->state)
+ {
+ case MG_STATE_TO_MAIN_MENU:
+ data->state = MG_STATE_MAIN_MENU;
+ break;
+ case MG_STATE_MAIN_MENU:
+ // Main Mystery Gift menu, player can select Wonder Cards or News (or exit)
+ switch (MysteryGift_HandleThreeOptionMenu(&data->textState, &data->var, FALSE))
+ {
+ case 0: // "Wonder Cards"
+ data->isWonderNews = FALSE;
+ if (ValidateSavedWonderCard() == TRUE)
+ data->state = MG_STATE_LOAD_GIFT;
+ else
+ data->state = MG_STATE_DONT_HAVE_ANY;
+ break;
+ case 1: // "Wonder News"
+ data->isWonderNews = TRUE;
+ if (ValidateSavedWonderNews() == TRUE)
+ data->state = MG_STATE_LOAD_GIFT;
+ else
+ data->state = MG_STATE_DONT_HAVE_ANY;
+ break;
+ case LIST_CANCEL:
+ data->state = MG_STATE_EXIT;
+ break;
+ }
+ break;
+ case MG_STATE_DONT_HAVE_ANY:
+ {
+ // Player doesn't have any Wonder Card/News
+ // Start prompt to ask where to read one from
+ if (!data->isWonderNews)
+ {
+ if (PrintMysteryGiftMenuMessage(&data->textState, gText_DontHaveCardNewOneInput))
+ {
+ data->state = MG_STATE_SOURCE_PROMPT;
+ PrintMysteryGiftOrEReaderTopMenu(FALSE, TRUE);
+ }
+ }
+ else
+ {
+ if (PrintMysteryGiftMenuMessage(&data->textState, gText_DontHaveNewsNewOneInput))
+ {
+ data->state = MG_STATE_SOURCE_PROMPT;
+ PrintMysteryGiftOrEReaderTopMenu(FALSE, TRUE);
+ }
+ }
+ break;
+ }
+ case MG_STATE_SOURCE_PROMPT:
+ if (!data->isWonderNews)
+ AddTextPrinterToWindow1(gText_WhereShouldCardBeAccessed);
+ else
+ AddTextPrinterToWindow1(gText_WhereShouldNewsBeAccessed);
+ data->state = MG_STATE_SOURCE_PROMPT_INPUT;
+ break;
+ case MG_STATE_SOURCE_PROMPT_INPUT:
+ // Choose where to access the Wonder Card/News from
+ switch (MysteryGift_HandleThreeOptionMenu(&data->textState, &data->var, TRUE))
+ {
+ case 0: // "Wireless Communication"
+ ClearTextWindow();
+ data->state = MG_STATE_CLIENT_LINK_START;
+ data->sourceIsFriend = FALSE;
+ break;
+ case 1: // "Friend"
+ ClearTextWindow();
+ data->state = MG_STATE_CLIENT_LINK_START;
+ data->sourceIsFriend = TRUE;
+ break;
+ case LIST_CANCEL:
+ ClearTextWindow();
+ if (ValidateCardOrNews(data->isWonderNews))
+ {
+ data->state = MG_STATE_LOAD_GIFT;
+ }
+ else
+ {
+ data->state = MG_STATE_TO_MAIN_MENU;
+ PrintMysteryGiftOrEReaderTopMenu(FALSE, FALSE);
+ }
+ break;
+ }
+ break;
+ case MG_STATE_CLIENT_LINK_START:
+ *gStringVar1 = EOS;
+ *gStringVar2 = EOS;
+ *gStringVar3 = EOS;
+
+ switch (data->isWonderNews)
+ {
+ case FALSE:
+ if (data->sourceIsFriend == TRUE)
+ CreateTask_LinkMysteryGiftWithFriend(ACTIVITY_WONDER_CARD);
+ else if (data->sourceIsFriend == FALSE)
+ CreateTask_LinkMysteryGiftOverWireless(ACTIVITY_WONDER_CARD);
+ break;
+ case TRUE:
+ if (data->sourceIsFriend == TRUE)
+ CreateTask_LinkMysteryGiftWithFriend(ACTIVITY_WONDER_NEWS);
+ else if (data->sourceIsFriend == FALSE)
+ CreateTask_LinkMysteryGiftOverWireless(ACTIVITY_WONDER_NEWS);
+ break;
+ }
+ data->state = MG_STATE_CLIENT_LINK_WAIT;
+ break;
+ case MG_STATE_CLIENT_LINK_WAIT:
+ if (gReceivedRemoteLinkPlayers != 0)
+ {
+ ClearScreenInBg0(TRUE);
+ data->state = MG_STATE_CLIENT_COMMUNICATING;
+ MysteryGiftClient_Create(data->isWonderNews);
+ }
+ else if (gSpecialVar_Result == LINKUP_FAILED)
+ {
+ // Link failed, return to link start menu
+ ClearScreenInBg0(TRUE);
+ data->state = MG_STATE_SOURCE_PROMPT;
+ }
+ break;
+ case MG_STATE_CLIENT_COMMUNICATING:
+ AddTextPrinterToWindow1(gText_Communicating);
+ data->state = MG_STATE_CLIENT_LINK;
+ break;
+ case MG_STATE_CLIENT_LINK:
+ switch (MysteryGiftClient_Run(&data->var))
+ {
+ case CLI_RET_END:
+ Rfu_SetCloseLinkCallback();
+ data->msgId = data->var;
+ data->state = MG_STATE_CLIENT_LINK_END;
+ break;
+ case CLI_RET_COPY_MSG:
+ memcpy(data->clientMsg, MysteryGiftClient_GetMsg(), 0x40);
+ MysteryGiftClient_AdvanceState();
+ break;
+ case CLI_RET_PRINT_MSG:
+ data->state = MG_STATE_CLIENT_MESSAGE;
+ break;
+ case CLI_RET_YES_NO:
+ data->state = MG_STATE_CLIENT_YES_NO;
+ break;
+ case CLI_RET_ASK_TOSS:
+ data->state = MG_STATE_CLIENT_ASK_TOSS;
+ StringCopy(gStringVar1, gLinkPlayers[0].name);
+ break;
+ }
+ break;
+ case MG_STATE_CLIENT_YES_NO:
+ input = DoMysteryGiftYesNo(&data->textState, &data->var, FALSE, MysteryGiftClient_GetMsg());
+ switch (input)
+ {
+ case 0: // Yes
+ MysteryGiftClient_SetParam(FALSE);
+ MysteryGiftClient_AdvanceState();
+ data->state = MG_STATE_CLIENT_COMMUNICATING;
+ break;
+ case 1: // No
+ case MENU_B_PRESSED:
+ MysteryGiftClient_SetParam(TRUE);
+ MysteryGiftClient_AdvanceState();
+ data->state = MG_STATE_CLIENT_COMMUNICATING;
+ break;
+ }
+ break;
+ case MG_STATE_CLIENT_MESSAGE:
+ if (PrintMysteryGiftMenuMessage(&data->textState, MysteryGiftClient_GetMsg()))
+ {
+ MysteryGiftClient_AdvanceState();
+ data->state = MG_STATE_CLIENT_COMMUNICATING;
+ }
+ break;
+ case MG_STATE_CLIENT_ASK_TOSS:
+ // Player is receiving a new Wonder Card/News but needs to toss an existing one to make room.
+ // Ask for confirmation.
+ input = DoMysteryGiftYesNo(&data->textState, &data->var, FALSE, gText_ThrowAwayWonderCard);
+ switch (input)
+ {
+ case 0: // Yes
+ if (IsSavedWonderCardGiftNotReceived() == TRUE)
+ {
+ data->state = MG_STATE_CLIENT_ASK_TOSS_UNRECEIVED;
+ }
+ else
+ {
+ MysteryGiftClient_SetParam(FALSE);
+ MysteryGiftClient_AdvanceState();
+ data->state = MG_STATE_CLIENT_COMMUNICATING;
+ }
+ break;
+ case 1: // No
+ case MENU_B_PRESSED:
+ MysteryGiftClient_SetParam(TRUE);
+ MysteryGiftClient_AdvanceState();
+ data->state = MG_STATE_CLIENT_COMMUNICATING;
+ break;
+ }
+ break;
+ case MG_STATE_CLIENT_ASK_TOSS_UNRECEIVED:
+ // Player has selected to toss a Wonder Card that they haven't received the gift for.
+ // Ask for confirmation again.
+ input = DoMysteryGiftYesNo(&data->textState, &data->var, FALSE, gText_HaventReceivedCardsGift);
+ switch (input)
+ {
+ case 0: // Yes
+ MysteryGiftClient_SetParam(FALSE);
+ MysteryGiftClient_AdvanceState();
+ data->state = MG_STATE_CLIENT_COMMUNICATING;
+ break;
+ case 1: // No
+ case MENU_B_PRESSED:
+ MysteryGiftClient_SetParam(TRUE);
+ MysteryGiftClient_AdvanceState();
+ data->state = MG_STATE_CLIENT_COMMUNICATING;
+ break;
+ }
+ break;
+ case MG_STATE_CLIENT_LINK_END:
+ if (gReceivedRemoteLinkPlayers == 0)
+ {
+ DestroyWirelessStatusIndicatorSprite();
+ data->state = MG_STATE_CLIENT_COMM_COMPLETED;
+ }
+ break;
+ case MG_STATE_CLIENT_COMM_COMPLETED:
+ if (PrintStringAndWait2Seconds(&data->textState, gText_CommunicationCompleted))
+ {
+ if (data->sourceIsFriend == TRUE)
+ StringCopy(gStringVar1, gLinkPlayers[0].name);
+ data->state = MG_STATE_CLIENT_RESULT_MSG;
+ }
+ break;
+ case MG_STATE_CLIENT_RESULT_MSG:
+ msg = GetClientResultMessage(&successMsg, data->isWonderNews, data->sourceIsFriend, data->msgId);
+ if (msg == NULL)
+ msg = data->clientMsg;
+ if (successMsg)
+ input = PrintSuccessMessage(&data->textState, msg, &data->var);
+ else
+ input = PrintMysteryGiftMenuMessage(&data->textState, msg);
+ // input var re-used, here it is TRUE if the message is finished
+ if (input)
+ {
+ if (data->msgId == CLI_MSG_NEWS_RECEIVED)
+ {
+ if (data->sourceIsFriend == TRUE)
+ GenerateRandomWonderNews(WONDER_NEWS_RECV_FRIEND);
+ else
+ GenerateRandomWonderNews(WONDER_NEWS_RECV_WIRELESS);
+ }
+ if (!successMsg)
+ {
+ // Did not receive card/news, return to main menu
+ data->state = MG_STATE_TO_MAIN_MENU;
+ PrintMysteryGiftOrEReaderTopMenu(FALSE, FALSE);
+ }
+ else
+ {
+ data->state = MG_STATE_SAVE_LOAD_GIFT;
+ }
+ }
+ break;
+ case MG_STATE_SAVE_LOAD_GIFT:
+ if (SaveOnMysteryGiftMenu(&data->textState))
+ data->state = MG_STATE_LOAD_GIFT;
+ break;
+ case MG_STATE_LOAD_GIFT:
+ if (HandleLoadWonderCardOrNews(&data->textState, data->isWonderNews))
+ data->state = MG_STATE_HANDLE_GIFT_INPUT;
+ break;
+ case MG_STATE_HANDLE_GIFT_INPUT:
+ if (!data->isWonderNews)
+ {
+ // Handle Wonder Card input
+ if (JOY_NEW(A_BUTTON))
+ data->state = MG_STATE_HANDLE_GIFT_SELECT;
+ if (JOY_NEW(B_BUTTON))
+ data->state = MG_STATE_GIFT_INPUT_EXIT;
+ }
+ else
+ {
+ switch (WonderNews_GetInput(gMain.newKeys))
+ {
+ case NEWS_INPUT_A:
+ WonderNews_RemoveScrollIndicatorArrowPair();
+ data->state = MG_STATE_HANDLE_GIFT_SELECT;
+ break;
+ case NEWS_INPUT_B:
+ data->state = MG_STATE_GIFT_INPUT_EXIT;
+ break;
+ }
+ }
+ break;
+ case MG_STATE_HANDLE_GIFT_SELECT:
+ {
+ // A Wonder Card/News has been selected, handle its menu
+ u32 result;
+ if (!data->isWonderNews)
+ {
+ if (IsSendingSavedWonderCardAllowed())
+ result = HandleGiftSelectMenu(&data->textState, &data->var, data->isWonderNews, FALSE);
+ else
+ result = HandleGiftSelectMenu(&data->textState, &data->var, data->isWonderNews, TRUE);
+ }
+ else
+ {
+ if (IsSendingSavedWonderNewsAllowed())
+ result = HandleGiftSelectMenu(&data->textState, &data->var, data->isWonderNews, FALSE);
+ else
+ result = HandleGiftSelectMenu(&data->textState, &data->var, data->isWonderNews, TRUE);
+ }
+ switch (result)
+ {
+ case 0: // Receive
+ data->state = MG_STATE_RECEIVE;
+ break;
+ case 1: // Send
+ data->state = MG_STATE_SEND;
+ break;
+ case 2: // Toss
+ data->state = MG_STATE_ASK_TOSS;
+ break;
+ case LIST_CANCEL:
+ if (data->isWonderNews == TRUE)
+ WonderNews_AddScrollIndicatorArrowPair();
+ data->state = MG_STATE_HANDLE_GIFT_INPUT;
+ break;
+ }
+ break;
+ }
+ case MG_STATE_ASK_TOSS:
+ // Player is attempting to discard a saved Wonder Card/News
+ switch (AskDiscardGift(&data->textState, &data->var, data->isWonderNews))
+ {
+ case 0: // Yes
+ if (!data->isWonderNews && IsSavedWonderCardGiftNotReceived() == TRUE)
+ data->state = MG_STATE_ASK_TOSS_UNRECEIVED;
+ else
+ data->state = MG_STATE_TOSS;
+ break;
+ case 1: // No
+ case MENU_B_PRESSED:
+ data->state = MG_STATE_HANDLE_GIFT_SELECT;
+ break;
+ }
+ break;
+ case MG_STATE_ASK_TOSS_UNRECEIVED:
+ // Player has selected to toss a Wonder Card that they haven't received the gift for.
+ // Ask for confirmation again.
+ switch ((u32)DoMysteryGiftYesNo(&data->textState, &data->var, TRUE, gText_HaventReceivedGiftOkayToDiscard))
+ {
+ case 0: // Yes
+ data->state = MG_STATE_TOSS;
+ break;
+ case 1: // No
+ case MENU_B_PRESSED:
+ data->state = MG_STATE_HANDLE_GIFT_SELECT;
+ break;
+ }
+ break;
+ case MG_STATE_TOSS:
+ if (ExitWonderCardOrNews(data->isWonderNews, TRUE))
+ {
+ ClearSavedNewsOrCard(data->isWonderNews);
+ data->state = MG_STATE_TOSS_SAVE;
+ }
+ break;
+ case MG_STATE_TOSS_SAVE:
+ if (SaveOnMysteryGiftMenu(&data->textState))
+ data->state = MG_STATE_TOSSED;
+ break;
+ case MG_STATE_TOSSED:
+ if (PrintThrownAway(&data->textState, data->isWonderNews))
+ {
+ data->state = MG_STATE_TO_MAIN_MENU;
+ PrintMysteryGiftOrEReaderTopMenu(FALSE, FALSE);
+ }
+ break;
+ case MG_STATE_GIFT_INPUT_EXIT:
+ if (ExitWonderCardOrNews(data->isWonderNews, FALSE))
+ data->state = MG_STATE_TO_MAIN_MENU;
+ break;
+ case MG_STATE_RECEIVE:
+ if (ExitWonderCardOrNews(data->isWonderNews, TRUE))
+ data->state = MG_STATE_SOURCE_PROMPT;
+ break;
+ case MG_STATE_SEND:
+ if (ExitWonderCardOrNews(data->isWonderNews, TRUE))
+ {
+ switch (data->isWonderNews)
+ {
+ case FALSE:
+ CreateTask_SendMysteryGift(ACTIVITY_WONDER_CARD);
+ break;
+ case TRUE:
+ CreateTask_SendMysteryGift(ACTIVITY_WONDER_NEWS);
+ break;
+ }
+ data->sourceIsFriend = TRUE;
+ data->state = MG_STATE_SERVER_LINK_WAIT;
+ }
+ break;
+ case MG_STATE_SERVER_LINK_WAIT:
+ if (gReceivedRemoteLinkPlayers != 0)
+ {
+ ClearScreenInBg0(TRUE);
+ data->state = MG_STATE_SERVER_LINK_START;
+ }
+ else if (gSpecialVar_Result == LINKUP_FAILED)
+ {
+ ClearScreenInBg0(TRUE);
+ data->state = MG_STATE_LOAD_GIFT;
+ }
+ break;
+ case MG_STATE_SERVER_LINK_START:
+ *gStringVar1 = EOS;
+ *gStringVar2 = EOS;
+ *gStringVar3 = EOS;
+
+ if (!data->isWonderNews)
+ {
+ AddTextPrinterToWindow1(gText_SendingWonderCard);
+ MysterGiftServer_CreateForCard();
+ }
+ else
+ {
+ AddTextPrinterToWindow1(gText_SendingWonderNews);
+ MysterGiftServer_CreateForNews();
+ }
+ data->state = MG_STATE_SERVER_LINK;
+ break;
+ case MG_STATE_SERVER_LINK:
+ if (MysterGiftServer_Run(&data->var) == SVR_RET_END)
+ {
+ data->msgId = data->var;
+ data->state = MG_STATE_SERVER_LINK_END;
+ }
+ break;
+ case MG_STATE_SERVER_LINK_END:
+ Rfu_SetCloseLinkCallback();
+ StringCopy(gStringVar1, gLinkPlayers[1].name);
+ data->state = MG_STATE_SERVER_LINK_END_WAIT;
+ break;
+ case MG_STATE_SERVER_LINK_END_WAIT:
+ if (gReceivedRemoteLinkPlayers == 0)
+ {
+ DestroyWirelessStatusIndicatorSprite();
+ data->state = MG_STATE_SERVER_RESULT_MSG;
+ }
+ break;
+ case MG_STATE_SERVER_RESULT_MSG:
+ if (PrintServerResultMessage(&data->textState, &data->var, data->sourceIsFriend, data->msgId))
+ {
+ if (data->sourceIsFriend == TRUE && data->msgId == SVR_MSG_NEWS_SENT)
+ {
+ GenerateRandomWonderNews(WONDER_NEWS_SENT);
+ data->state = MG_STATE_SAVE_LOAD_GIFT;
+ }
+ else
+ {
+ data->state = MG_STATE_TO_MAIN_MENU;
+ PrintMysteryGiftOrEReaderTopMenu(FALSE, FALSE);
+ }
+ }
+ break;
+ case MG_STATE_CLIENT_ERROR:
+ case MG_STATE_SERVER_ERROR:
+ if (PrintMysteryGiftMenuMessage(&data->textState, gText_CommunicationError))
+ {
+ data->state = MG_STATE_TO_MAIN_MENU;
+ PrintMysteryGiftOrEReaderTopMenu(FALSE, FALSE);
+ }
+ break;
+ case MG_STATE_EXIT:
+ CloseLink();
+ Free(data->clientMsg);
+ DestroyTask(taskId);
+ SetMainCallback2(MainCB_FreeAllBuffersAndReturnToInitTitleScreen);
+ break;
+ }
+}
+
+u16 GetMysteryGiftBaseBlock(void)
+{
+ return 0x1A9;
+}
+
+static void LoadMysteryGiftTextboxBorder(u8 bgId)
+{
+ DecompressAndLoadBgGfxUsingHeap(bgId, sTextboxBorder_Gfx, 0x100, 0, 0);
+}
diff --git a/src/mystery_gift_scripts.c b/src/mystery_gift_scripts.c
new file mode 100644
index 000000000..fcd7f568d
--- /dev/null
+++ b/src/mystery_gift_scripts.c
@@ -0,0 +1,217 @@
+#include "global.h"
+#include "mystery_gift_client.h"
+#include "mystery_gift_server.h"
+#include "mystery_gift.h"
+
+static const u8 sText_CanceledReadingCard[] = _("Canceled reading\nthe Card.");
+
+
+//==================
+// 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_DynamicError[] = {
+ {CLI_RECV, MG_LINKID_DYNAMIC_MSG},
+ {CLI_COPY_MSG},
+ {CLI_SEND_READY_END},
+ {CLI_RETURN, CLI_MSG_BUFFER_FAILURE}
+};
+
+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
+//==================
+
+// Create arguments for SVR_LOAD_CLIENT_SCRIPT or SVR_LOAD_MSG
+// (a script/text size and pointer to send to the client)
+#define PTR_ARG(pointer) .parameter = sizeof(pointer), .ptr = pointer
+
+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_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}
+};
+
+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 = sServerScript_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_NEWS},
+ {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_CARD},
+ {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
+};
diff --git a/src/mystery_gift_server.c b/src/mystery_gift_server.c
new file mode 100644
index 000000000..0e0acb642
--- /dev/null
+++ b/src/mystery_gift_server.c
@@ -0,0 +1,291 @@
+#include "global.h"
+#include "malloc.h"
+#include "script.h"
+#include "mystery_gift.h"
+#include "mystery_gift_server.h"
+#include "mystery_gift_link.h"
+
+enum {
+ FUNC_INIT,
+ FUNC_DONE,
+ FUNC_RECV,
+ FUNC_SEND,
+ FUNC_RUN,
+};
+
+EWRAM_DATA static 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(sServer);
+ sServer = NULL;
+ }
+ 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->link, 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)
+{
+ AGB_ASSERT(size <= MG_LINK_BUFFER_SIZE);
+ MysteryGiftLink_InitSend(&svr->link, 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->link))
+ svr->funcId = FUNC_RUN;
+ return SVR_RET_ACTIVE;
+}
+
+static u32 Server_Send(struct MysteryGiftServer * svr)
+{
+ if (MysteryGiftLink_Send(&svr->link))
+ 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:
+ AGB_ASSERT(cmd->ptr == NULL);
+ svr->funcId = FUNC_DONE;
+ svr->param = cmd->parameter; // Set for endVal in MysteryGiftServer_Run
+ break;
+ case SVR_SEND:
+ svr->funcId = FUNC_SEND;
+ break;
+ case SVR_RECV:
+ AGB_ASSERT(cmd->ptr == NULL);
+ MysteryGiftLink_InitRecv(&svr->link, cmd->parameter, svr->recvBuffer);
+ svr->funcId = FUNC_RECV;
+ break;
+ case SVR_GOTO:
+ AGB_ASSERT(cmd->parameter == 0);
+ svr->cmdidx = 0;
+ svr->script = cmd->ptr;
+ break;
+ case SVR_COPY_GAME_DATA:
+ AGB_ASSERT(cmd->parameter == 0);
+ AGB_ASSERT(cmd->ptr == NULL);
+ memcpy(svr->linkGameData, svr->recvBuffer, sizeof(*svr->linkGameData));
+ break;
+ case SVR_CHECK_GAME_DATA_CARD:
+ AGB_ASSERT(cmd->parameter == 0);
+ AGB_ASSERT(cmd->ptr == NULL);
+ svr->param = MysteryGift_ValidateLinkGameData(svr->linkGameData, FALSE);
+ break;
+ case SVR_CHECK_GAME_DATA_NEWS:
+ AGB_ASSERT(cmd->parameter == 0);
+ AGB_ASSERT(cmd->ptr == NULL);
+ svr->param = MysteryGift_ValidateLinkGameData(svr->linkGameData, TRUE);
+ break;
+ case SVR_GOTO_IF_EQ:
+ if (svr->param == cmd->parameter)
+ {
+ svr->cmdidx = 0;
+ svr->script = cmd->ptr;
+ }
+ break;
+ case SVR_CHECK_EXISTING_CARD:
+ AGB_ASSERT(cmd->parameter == 0);
+ ptr = MysteryGiftServer_GetSendData(cmd->ptr, svr->card);
+ svr->param = MysteryGift_CompareCardFlags(ptr, svr->linkGameData, ptr);
+ break;
+ case SVR_READ_RESPONSE:
+ AGB_ASSERT(cmd->parameter == 0);
+ AGB_ASSERT(cmd->ptr == NULL);
+ svr->param = *(u32 *)svr->recvBuffer;
+ break;
+ case SVR_CHECK_EXISTING_STAMPS:
+ AGB_ASSERT(cmd->parameter == 0);
+ ptr = MysteryGiftServer_GetSendData(cmd->ptr, &svr->stamp);
+ svr->param = MysteryGift_CheckStamps(ptr, svr->linkGameData, ptr);
+ break;
+ case SVR_GET_CARD_STAT:
+ AGB_ASSERT(cmd->ptr == NULL);
+ svr->param = MysteryGift_GetCardStatFromLinkData(svr->linkGameData, cmd->parameter);
+ break;
+ case SVR_CHECK_QUESTIONNAIRE:
+ AGB_ASSERT(cmd->parameter == 0);
+ svr->param = MysteryGift_DoesQuestionnaireMatch(svr->linkGameData, cmd->ptr);
+ break;
+ case SVR_COMPARE:
+ AGB_ASSERT(cmd->parameter == 0);
+ svr->param = MysteryGiftServer_Compare(cmd->ptr, *(void **)svr->recvBuffer);
+ break;
+ case SVR_LOAD_NEWS:
+ AGB_ASSERT(cmd->parameter == 0);
+ MysteryGiftServer_InitSend(svr, MG_LINKID_NEWS, MysteryGiftServer_GetSendData(cmd->ptr, svr->news), sizeof(*svr->news));
+ break;
+ case SVR_LOAD_CARD:
+ AGB_ASSERT(cmd->parameter == 0);
+ MysteryGiftServer_InitSend(svr, MG_LINKID_CARD, MysteryGiftServer_GetSendData(cmd->ptr, svr->card), sizeof(*svr->card));
+ break;
+ case SVR_LOAD_STAMP:
+ AGB_ASSERT(cmd->parameter == 0);
+ 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->parameter);
+ 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->parameter);
+ break;
+ case SVR_LOAD_EREADER_TRAINER:
+ AGB_ASSERT(cmd->parameter == 0);
+ 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->parameter);
+ break;
+ case SVR_LOAD_UNK_2:
+ MysteryGiftServer_InitSend(svr, MG_LINKID_UNK_2, cmd->ptr, cmd->parameter);
+ break;
+ case SVR_COPY_CARD:
+ AGB_ASSERT(cmd->parameter == 0);
+ memcpy(svr->card, cmd->ptr, sizeof(*svr->card));
+ break;
+ case SVR_COPY_NEWS:
+ AGB_ASSERT(cmd->parameter == 0);
+ memcpy(svr->news, cmd->ptr, sizeof(*svr->news));
+ break;
+ case SVR_COPY_STAMP:
+ AGB_ASSERT(cmd->parameter == 0);
+ svr->stamp = *(u32 *)cmd->ptr;
+ break;
+ case SVR_SET_RAM_SCRIPT:
+ svr->ramScript = cmd->ptr;
+ svr->ramScriptSize = cmd->parameter;
+ break;
+ case SVR_SET_CLIENT_SCRIPT:
+ svr->clientScript = cmd->ptr;
+ svr->clientScriptSize = cmd->parameter;
+ break;
+ case SVR_COPY_SAVED_CARD:
+ AGB_ASSERT(cmd->parameter == 0 && cmd->ptr == NULL);
+ memcpy(svr->card, GetSavedWonderCard(), sizeof(*svr->card));
+ DisableWonderCardSending(svr->card);
+ break;
+ case SVR_COPY_SAVED_NEWS:
+ AGB_ASSERT(cmd->parameter == 0 && cmd->ptr == NULL);
+ memcpy(svr->news, GetSavedWonderNews(), sizeof(*svr->news));
+ break;
+ case SVR_COPY_SAVED_RAM_SCRIPT:
+ AGB_ASSERT(cmd->parameter == 0 && cmd->ptr == NULL);
+ svr->ramScript = GetSavedRamScriptIfValid();
+ break;
+ case SVR_LOAD_UNK_1:
+ MysteryGiftServer_InitSend(svr, MG_LINKID_UNK_1, cmd->ptr, cmd->parameter);
+ 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;
+ AGB_ASSERT(svr->funcId < ARRAY_COUNT(sFuncTable));
+ response = sFuncTable[svr->funcId](svr);
+ AGB_ASSERT(svr->funcId < ARRAY_COUNT(sFuncTable));
+ return response;
+}
diff --git a/src/mystery_gift_view.c b/src/mystery_gift_view.c
new file mode 100644
index 000000000..0e1c11520
--- /dev/null
+++ b/src/mystery_gift_view.c
@@ -0,0 +1,936 @@
+#include "global.h"
+#include "bg.h"
+#include "gpu_regs.h"
+#include "palette.h"
+#include "decompress.h"
+#include "malloc.h"
+#include "menu.h"
+#include "pokemon_icon.h"
+#include "union_room.h"
+#include "list_menu.h"
+#include "text_window.h"
+#include "string_util.h"
+#include "link_rfu.h"
+#include "mystery_gift.h"
+#include "mystery_gift_menu.h"
+#include "mystery_gift_view.h"
+#include "constants/rgb.h"
+#include "constants/mystery_gift.h"
+
+struct WonderGraphics
+{
+ u8 titleTextPal:4;
+ u8 bodyTextPal:4;
+ u8 footerTextPal:4; // Card only
+ u8 stampShadowPal:4; // Card only
+ const u32 * tiles;
+ const u32 * map;
+ const u16 * pal;
+};
+
+//======================
+// Wonder Cards
+//======================
+
+enum {
+ CARD_WIN_HEADER,
+ CARD_WIN_BODY,
+ CARD_WIN_FOOTER,
+ CARD_WIN_COUNT
+};
+
+#define TAG_STAMP_SHADOW 0x8000
+
+struct CardStatTextData
+{
+ u8 width;
+ u8 statText[WONDER_CARD_TEXT_LENGTH + 1];
+ u8 statNumberText[4];
+};
+
+struct WonderCardData
+{
+ /*0000*/ struct WonderCard card;
+ /*014c*/ struct WonderCardMetadata cardMetadata;
+ /*0170*/ const struct WonderGraphics * gfx;
+ /*0174*/ u8 enterExitState;
+ /*0175*/ u8 statFooterWidth;
+ /*0176*/ u16 windowIds[CARD_WIN_COUNT];
+ /*017C*/ u8 monIconSpriteId;
+ /*017D*/ u8 stampSpriteIds[MAX_STAMP_CARD_STAMPS][2]; // 2 sprites each, 1 for the shadow and 1 for the Pokémon
+ /*018B*/ u8 titleText[WONDER_CARD_TEXT_LENGTH + 1];
+ /*01B4*/ u8 subtitleText[WONDER_CARD_TEXT_LENGTH + 1];
+ /*01DD*/ u8 idNumberText[7];
+ /*01E4*/ u8 bodyText[WONDER_CARD_BODY_TEXT_LINES][WONDER_CARD_TEXT_LENGTH + 1];
+ /*0288*/ u8 footerLine1Text[WONDER_CARD_TEXT_LENGTH + 1];
+ /*02B1*/ u8 giftText[WONDER_CARD_TEXT_LENGTH + 1];
+ /*02DC*/ struct CardStatTextData statTextData[8];
+ /*045C*/ u8 bgTilemapBuffer[0x1000];
+};
+
+EWRAM_DATA static struct WonderCardData * sWonderCardData = NULL;
+
+static void BufferCardText(void);
+static void DrawCardWindow(u8 whichWindow);
+static void CreateCardSprites(void);
+static void DestroyCardSprites(void);
+
+extern const struct OamData gOamData_AffineOff_ObjNormal_32x16;
+
+static const u8 sCard_TextColorTable[][3] = {
+ {TEXT_COLOR_TRANSPARENT, TEXT_COLOR_DARK_GRAY, TEXT_COLOR_LIGHT_GRAY},
+ {TEXT_COLOR_TRANSPARENT, TEXT_COLOR_WHITE, TEXT_COLOR_DARK_GRAY}
+};
+
+static const u8 ALIGNED(4) sCard_FooterTextOffsets[CARD_TYPE_COUNT] =
+{
+ [CARD_TYPE_GIFT] = 7,
+ [CARD_TYPE_STAMP] = 4,
+ [CARD_TYPE_LINK_STAT] = 7
+};
+
+static const struct WindowTemplate sCard_WindowTemplates[] = {
+ [CARD_WIN_HEADER] = {
+ .bg = 1,
+ .tilemapLeft = 1,
+ .tilemapTop = 1,
+ .width = 25,
+ .height = 4,
+ .paletteNum = 2,
+ .baseBlock = 0x029c
+ },
+ [CARD_WIN_BODY] = {
+ .bg = 1,
+ .tilemapLeft = 1,
+ .tilemapTop = 6,
+ .width = 28,
+ .height = 8,
+ .paletteNum = 2,
+ .baseBlock = 0x01bc
+ },
+ [CARD_WIN_FOOTER] = {
+ .bg = 1,
+ .tilemapLeft = 1,
+ .tilemapTop = 14,
+ .width = 28,
+ .height = 5,
+ .paletteNum = 2,
+ .baseBlock = 0x0130
+ }
+};
+
+static const u16 sWonderCardBgPal1[] = INCBIN_U16("graphics/wonder_card/bg1.gbapal");
+static const u16 sWonderCardBgPal2[] = INCBIN_U16("graphics/wonder_card/bg2.gbapal");
+static const u16 sWonderCardBgPal3[] = INCBIN_U16("graphics/wonder_card/bg3.gbapal");
+static const u16 sWonderCardBgPal4[] = INCBIN_U16("graphics/wonder_card/bg4.gbapal");
+static const u16 sWonderCardBgPal5[] = INCBIN_U16("graphics/wonder_card/bg5.gbapal");
+static const u16 sWonderCardBgPal6[] = INCBIN_U16("graphics/wonder_card/bg6.gbapal");
+static const u16 sWonderCardBgPal7[] = INCBIN_U16("graphics/wonder_card/bg7.gbapal");
+static const u16 sWonderCardBgPal8[] = INCBIN_U16("graphics/wonder_card/bg8.gbapal");
+static const u32 sWonderCardBgGfx1[] = INCBIN_U32("graphics/wonder_card/bg1.4bpp.lz");
+static const u32 sWonderCardBgTilemap1[] = INCBIN_U32("graphics/wonder_card/bg1.bin.lz");
+static const u32 sWonderCardBgGfx2[] = INCBIN_U32("graphics/wonder_card/bg2.4bpp.lz");
+static const u32 sWonderCardBgTilemap2[] = INCBIN_U32("graphics/wonder_card/bg2.bin.lz");
+static const u32 sWonderCardBgGfx3[] = INCBIN_U32("graphics/wonder_card/bg3.4bpp.lz");
+static const u32 sWonderCardBgTilemap3[] = INCBIN_U32("graphics/wonder_card/bg3.bin.lz");
+static const u32 sWonderCardBgGfx7[] = INCBIN_U32("graphics/wonder_card/bg7.4bpp.lz");
+static const u32 sWonderCardBgTilemap7[] = INCBIN_U32("graphics/wonder_card/bg7.bin.lz");
+static const u32 sWonderCardBgGfx8[] = INCBIN_U32("graphics/wonder_card/bg8.4bpp.lz");
+static const u32 sWonderCardBgTilemap8[] = INCBIN_U32("graphics/wonder_card/bg8.bin.lz");
+static const u16 sStampShadowPal1[] = INCBIN_U16("graphics/wonder_card/stamp_shadow_1.gbapal");
+static const u16 sStampShadowPal2[] = INCBIN_U16("graphics/wonder_card/stamp_shadow_2.gbapal");
+static const u16 sStampShadowPal3[] = INCBIN_U16("graphics/wonder_card/stamp_shadow_3.gbapal");
+static const u16 sStampShadowPal4[] = INCBIN_U16("graphics/wonder_card/stamp_shadow_4.gbapal");
+static const u16 sStampShadowPal5[] = INCBIN_U16("graphics/wonder_card/stamp_shadow_5.gbapal");
+static const u16 sStampShadowPal6[] = INCBIN_U16("graphics/wonder_card/stamp_shadow_6.gbapal");
+static const u16 sStampShadowPal7[] = INCBIN_U16("graphics/wonder_card/stamp_shadow_7.gbapal");
+static const u16 sStampShadowPal8[] = INCBIN_U16("graphics/wonder_card/stamp_shadow_8.gbapal");
+static const u32 sStampShadowGfx[] = INCBIN_U32("graphics/wonder_card/stamp_shadow.4bpp.lz");
+
+static const struct CompressedSpriteSheet sSpriteSheet_StampShadow = {
+ sStampShadowGfx, 0x100, TAG_STAMP_SHADOW
+};
+
+static const struct SpritePalette sSpritePalettes_StampShadow[] = {
+ {sStampShadowPal1, TAG_STAMP_SHADOW},
+ {sStampShadowPal2, TAG_STAMP_SHADOW},
+ {sStampShadowPal3, TAG_STAMP_SHADOW},
+ {sStampShadowPal4, TAG_STAMP_SHADOW},
+ {sStampShadowPal5, TAG_STAMP_SHADOW},
+ {sStampShadowPal6, TAG_STAMP_SHADOW},
+ {sStampShadowPal7, TAG_STAMP_SHADOW},
+ {sStampShadowPal8, TAG_STAMP_SHADOW}
+};
+
+static const struct SpriteTemplate sSpriteTemplate_StampShadow = {
+ .tileTag = TAG_STAMP_SHADOW,
+ .paletteTag = TAG_STAMP_SHADOW,
+ .oam = &gOamData_AffineOff_ObjNormal_32x16,
+ .anims = gDummySpriteAnimTable,
+ .images = NULL,
+ .affineAnims = gDummySpriteAffineAnimTable,
+ .callback = SpriteCallbackDummy
+};
+
+static const struct WonderGraphics sCardGraphics[NUM_WONDER_BGS] = {
+ {.titleTextPal = 1, .bodyTextPal = 0, .footerTextPal = 0, .stampShadowPal = 0, .tiles = sWonderCardBgGfx1, .map = sWonderCardBgTilemap1, .pal = sWonderCardBgPal1},
+ {.titleTextPal = 1, .bodyTextPal = 0, .footerTextPal = 0, .stampShadowPal = 1, .tiles = sWonderCardBgGfx2, .map = sWonderCardBgTilemap2, .pal = sWonderCardBgPal2},
+ {.titleTextPal = 1, .bodyTextPal = 0, .footerTextPal = 0, .stampShadowPal = 2, .tiles = sWonderCardBgGfx3, .map = sWonderCardBgTilemap3, .pal = sWonderCardBgPal3},
+ {.titleTextPal = 1, .bodyTextPal = 0, .footerTextPal = 0, .stampShadowPal = 3, .tiles = sWonderCardBgGfx3, .map = sWonderCardBgTilemap3, .pal = sWonderCardBgPal4},
+ {.titleTextPal = 1, .bodyTextPal = 0, .footerTextPal = 0, .stampShadowPal = 4, .tiles = sWonderCardBgGfx3, .map = sWonderCardBgTilemap3, .pal = sWonderCardBgPal5},
+ {.titleTextPal = 1, .bodyTextPal = 0, .footerTextPal = 0, .stampShadowPal = 5, .tiles = sWonderCardBgGfx3, .map = sWonderCardBgTilemap3, .pal = sWonderCardBgPal6},
+ {.titleTextPal = 1, .bodyTextPal = 0, .footerTextPal = 0, .stampShadowPal = 6, .tiles = sWonderCardBgGfx7, .map = sWonderCardBgTilemap7, .pal = sWonderCardBgPal7},
+ {.titleTextPal = 1, .bodyTextPal = 0, .footerTextPal = 0, .stampShadowPal = 7, .tiles = sWonderCardBgGfx8, .map = sWonderCardBgTilemap8, .pal = sWonderCardBgPal8}
+};
+
+bool32 WonderCard_Init(struct WonderCard * card, struct WonderCardMetadata * metadata)
+{
+ if (card == NULL || metadata == NULL)
+ return FALSE;
+ sWonderCardData = AllocZeroed(sizeof(*sWonderCardData));
+ if (sWonderCardData == NULL)
+ return FALSE;
+ sWonderCardData->card = *card;
+ sWonderCardData->cardMetadata = *metadata;
+ if (sWonderCardData->card.bgType >= NUM_WONDER_BGS)
+ sWonderCardData->card.bgType = 0;
+ if (sWonderCardData->card.type >= CARD_TYPE_COUNT)
+ sWonderCardData->card.type = 0;
+ if (sWonderCardData->card.maxStamps > MAX_STAMP_CARD_STAMPS)
+ sWonderCardData->card.maxStamps = 0;
+ sWonderCardData->gfx = &sCardGraphics[sWonderCardData->card.bgType];
+ return TRUE;
+}
+
+void WonderCard_Destroy(void)
+{
+ if (sWonderCardData != NULL)
+ {
+ *sWonderCardData = (struct WonderCardData){};
+ Free(sWonderCardData);
+ sWonderCardData = NULL;
+ }
+}
+
+s32 WonderCard_Enter(void)
+{
+ if (sWonderCardData == NULL)
+ return -1;
+ switch(sWonderCardData->enterExitState)
+ {
+ case 0:
+ BeginNormalPaletteFade(PALETTES_ALL, 0, 0, 16, RGB_BLACK);
+ break;
+ case 1:
+ if (UpdatePaletteFade())
+ return 0;
+ break;
+ case 2:
+ FillBgTilemapBufferRect_Palette0(0, 0x000, 0, 0, 30, 20);
+ FillBgTilemapBufferRect_Palette0(1, 0x000, 0, 0, 30, 20);
+ FillBgTilemapBufferRect_Palette0(2, 0x000, 0, 0, 30, 20);
+ CopyBgTilemapBufferToVram(0);
+ CopyBgTilemapBufferToVram(1);
+ CopyBgTilemapBufferToVram(2);
+ DecompressAndCopyTileDataToVram(2, sWonderCardData->gfx->tiles, 0, 0x008, 0);
+ sWonderCardData->windowIds[CARD_WIN_HEADER] = AddWindow(&sCard_WindowTemplates[CARD_WIN_HEADER]);
+ sWonderCardData->windowIds[CARD_WIN_BODY] = AddWindow(&sCard_WindowTemplates[CARD_WIN_BODY]);
+ sWonderCardData->windowIds[CARD_WIN_FOOTER] = AddWindow(&sCard_WindowTemplates[CARD_WIN_FOOTER]);
+ break;
+ case 3:
+ if (FreeTempTileDataBuffersIfPossible())
+ return 0;
+ LoadPalette(GetTextWindowPalette(1), 0x20, 0x20);
+ gPaletteFade.bufferTransferDisabled = TRUE;
+ LoadPalette(sWonderCardData->gfx->pal, 0x10, 0x20);
+ LZ77UnCompWram(sWonderCardData->gfx->map, sWonderCardData->bgTilemapBuffer);
+ CopyRectToBgTilemapBufferRect(2, sWonderCardData->bgTilemapBuffer, 0, 0, 30, 20, 0, 0, 30, 20, 1, 0x008, 0);
+ CopyBgTilemapBufferToVram(2);
+ break;
+ case 4:
+ BufferCardText();
+ break;
+ case 5:
+ DrawCardWindow(CARD_WIN_HEADER);
+ DrawCardWindow(CARD_WIN_BODY);
+ DrawCardWindow(CARD_WIN_FOOTER);
+ CopyBgTilemapBufferToVram(1);
+ break;
+ case 6:
+ LoadMonIconPalettes();
+ break;
+ case 7:
+ ShowBg(1);
+ ShowBg(2);
+ gPaletteFade.bufferTransferDisabled = FALSE;
+ CreateCardSprites();
+ BeginNormalPaletteFade(PALETTES_ALL, 0, 16, 0, RGB_BLACK);
+ UpdatePaletteFade();
+ break;
+ default:
+ if (UpdatePaletteFade())
+ return 0;
+ sWonderCardData->enterExitState = 0;
+ return 1;
+ }
+ sWonderCardData->enterExitState++;
+ return 0;
+}
+
+s32 WonderCard_Exit(bool32 useCancel)
+{
+ if (sWonderCardData == NULL)
+ return -1;
+ switch (sWonderCardData->enterExitState)
+ {
+ case 0:
+ BeginNormalPaletteFade(PALETTES_ALL, 0, 0, 16, RGB_BLACK);
+ break;
+ case 1:
+ if (UpdatePaletteFade())
+ return 0;
+ break;
+ case 2:
+ FillBgTilemapBufferRect_Palette0(0, 0x000, 0, 0, 30, 20);
+ FillBgTilemapBufferRect_Palette0(1, 0x000, 0, 0, 30, 20);
+ FillBgTilemapBufferRect_Palette0(2, 0x000, 0, 0, 30, 20);
+ CopyBgTilemapBufferToVram(0);
+ CopyBgTilemapBufferToVram(1);
+ CopyBgTilemapBufferToVram(2);
+ break;
+ case 3:
+ HideBg(1);
+ HideBg(2);
+ RemoveWindow(sWonderCardData->windowIds[CARD_WIN_FOOTER]);
+ RemoveWindow(sWonderCardData->windowIds[CARD_WIN_BODY]);
+ RemoveWindow(sWonderCardData->windowIds[CARD_WIN_HEADER]);
+ break;
+ case 4:
+ DestroyCardSprites();
+ FreeMonIconPalettes();
+ break;
+ case 5:
+ PrintMysteryGiftOrEReaderTopMenu(gGiftIsFromEReader, useCancel);
+ CopyBgTilemapBufferToVram(0);
+ BeginNormalPaletteFade(PALETTES_ALL, 0, 16, 0, RGB_BLACK);
+ break;
+ default:
+ if (UpdatePaletteFade())
+ return 0;
+ sWonderCardData->enterExitState = 0;
+ return 1;
+ }
+ sWonderCardData->enterExitState++;
+ return 0;
+}
+
+static void BufferCardText(void)
+{
+ u16 i = 0;
+ u16 charsUntilStat;
+ u16 stats[3] = {0, 0, 0};
+
+ // Copy title/subtitle text
+ memcpy(sWonderCardData->titleText, sWonderCardData->card.titleText, WONDER_CARD_TEXT_LENGTH);
+ sWonderCardData->titleText[WONDER_CARD_TEXT_LENGTH] = EOS;
+ memcpy(sWonderCardData->subtitleText, sWonderCardData->card.subtitleText, WONDER_CARD_TEXT_LENGTH);
+ sWonderCardData->subtitleText[WONDER_CARD_TEXT_LENGTH] = EOS;
+
+ // Copy card id number
+ if (sWonderCardData->card.idNumber > 999999)
+ sWonderCardData->card.idNumber = 999999;
+ ConvertIntToDecimalStringN(sWonderCardData->idNumberText, sWonderCardData->card.idNumber, STR_CONV_MODE_LEFT_ALIGN, 6);
+
+ // Copy body text
+ for (i = 0; i < WONDER_CARD_BODY_TEXT_LINES; i++)
+ {
+ memcpy(sWonderCardData->bodyText[i], sWonderCardData->card.bodyText[i], WONDER_CARD_TEXT_LENGTH);
+ sWonderCardData->bodyText[i][WONDER_CARD_TEXT_LENGTH] = EOS;
+ }
+
+ // Copy footer line 1
+ memcpy(sWonderCardData->footerLine1Text, sWonderCardData->card.footerLine1Text, WONDER_CARD_TEXT_LENGTH);
+ sWonderCardData->footerLine1Text[WONDER_CARD_TEXT_LENGTH] = EOS;
+
+ // Copy footer line 2
+ switch (sWonderCardData->card.type)
+ {
+ case CARD_TYPE_GIFT:
+ memcpy(sWonderCardData->giftText, sWonderCardData->card.footerLine2Text, WONDER_CARD_TEXT_LENGTH);
+ sWonderCardData->giftText[WONDER_CARD_TEXT_LENGTH] = EOS;
+ break;
+ case CARD_TYPE_STAMP:
+ sWonderCardData->giftText[0] = EOS;
+ break;
+ case CARD_TYPE_LINK_STAT:
+ sWonderCardData->giftText[0] = EOS;
+
+ // Load stats
+ stats[0] = sWonderCardData->cardMetadata.battlesWon < MAX_WONDER_CARD_STAT ? sWonderCardData->cardMetadata.battlesWon : MAX_WONDER_CARD_STAT;
+ stats[1] = sWonderCardData->cardMetadata.battlesLost < MAX_WONDER_CARD_STAT ? sWonderCardData->cardMetadata.battlesLost : MAX_WONDER_CARD_STAT;
+ stats[2] = sWonderCardData->cardMetadata.numTrades < MAX_WONDER_CARD_STAT ? sWonderCardData->cardMetadata.numTrades : MAX_WONDER_CARD_STAT;
+
+ // Init stat text arrays
+ for (i = 0; i < ARRAY_COUNT(sWonderCardData->statTextData); i++)
+ {
+ memset(sWonderCardData->statTextData[i].statNumberText, EOS, sizeof(sWonderCardData->statTextData[i].statNumberText));
+ memset(sWonderCardData->statTextData[i].statText, EOS, sizeof(sWonderCardData->statTextData[i].statText));
+ }
+
+ // Copy stat texts
+ for (i = 0, charsUntilStat = 0; i < WONDER_CARD_TEXT_LENGTH; i++)
+ {
+ if (sWonderCardData->card.footerLine2Text[i] != CHAR_DYNAMIC)
+ {
+ // Regular text, just copy as is
+ sWonderCardData->statTextData[sWonderCardData->statFooterWidth].statText[charsUntilStat] = sWonderCardData->card.footerLine2Text[i];
+ charsUntilStat++;
+ }
+ else
+ {
+ // Dynamic char encountered
+ // These are used to give the id of which stat to print
+ u8 id = sWonderCardData->card.footerLine2Text[i + 1];
+ if (id >= ARRAY_COUNT(stats))
+ {
+ // Invalid stat id, skip ahead
+ i += 2;
+ }
+ else
+ {
+ // Copy stat number
+ ConvertIntToDecimalStringN(sWonderCardData->statTextData[sWonderCardData->statFooterWidth].statNumberText, stats[id], STR_CONV_MODE_LEADING_ZEROS, 3);
+ sWonderCardData->statTextData[sWonderCardData->statFooterWidth].width = sWonderCardData->card.footerLine2Text[i + 2];
+ sWonderCardData->statFooterWidth++;
+ if (sWonderCardData->statFooterWidth >= ARRAY_COUNT(sWonderCardData->statTextData))
+ break;
+ charsUntilStat = 0;
+ i += 2;
+ }
+ }
+ }
+ }
+}
+
+static void DrawCardWindow(u8 whichWindow)
+{
+ s8 i = 0;
+ s32 windowId = sWonderCardData->windowIds[whichWindow];
+ PutWindowTilemap(windowId);
+ FillWindowPixelBuffer(windowId, 0);
+ switch (whichWindow)
+ {
+ case CARD_WIN_HEADER:
+ {
+ // Print card title/subtitle
+ s32 x;
+ AddTextPrinterParameterized3(windowId, 3, 0, 1, sCard_TextColorTable[sWonderCardData->gfx->titleTextPal], 0, sWonderCardData->titleText);
+ x = 160 - GetStringWidth(3, sWonderCardData->subtitleText, GetFontAttribute(3, FONTATTR_LETTER_SPACING));
+ if (x < 0)
+ x = 0;
+ AddTextPrinterParameterized3(windowId, 3, x, 17, sCard_TextColorTable[sWonderCardData->gfx->titleTextPal], 0, sWonderCardData->subtitleText);
+
+ // Print id number
+ if (sWonderCardData->card.idNumber != 0)
+ AddTextPrinterParameterized3(windowId, 1, 166, 17, sCard_TextColorTable[sWonderCardData->gfx->titleTextPal], 0, sWonderCardData->idNumberText);
+ break;
+ }
+ case CARD_WIN_BODY:
+ // Print body text
+ for (; i < WONDER_CARD_BODY_TEXT_LINES; i++)
+ AddTextPrinterParameterized3(windowId, 3, 0, 16 * i + 2, sCard_TextColorTable[sWonderCardData->gfx->bodyTextPal], 0, sWonderCardData->bodyText[i]);
+ break;
+ case CARD_WIN_FOOTER:
+ // Print footer line 1
+ AddTextPrinterParameterized3(windowId, 3, 0,
+ sCard_FooterTextOffsets[sWonderCardData->card.type],
+ sCard_TextColorTable[sWonderCardData->gfx->footerTextPal],
+ 0, sWonderCardData->footerLine1Text);
+
+ // Print footer line 2
+ if (sWonderCardData->card.type != CARD_TYPE_LINK_STAT)
+ {
+ // Print gift text
+ // Odd that CARD_TYPE_STAMP is not ignored, it has empty text for this
+ AddTextPrinterParameterized3(windowId, 3, 0,
+ 16 + sCard_FooterTextOffsets[sWonderCardData->card.type],
+ sCard_TextColorTable[sWonderCardData->gfx->footerTextPal],
+ 0, sWonderCardData->giftText);
+ }
+ else
+ {
+ s32 x = 0;
+ s32 y = sCard_FooterTextOffsets[sWonderCardData->card.type] + 16;
+ s32 spacing = GetFontAttribute(3, FONTATTR_LETTER_SPACING);
+ for (; i < sWonderCardData->statFooterWidth; i++)
+ {
+ // Print stat text
+ AddTextPrinterParameterized3(windowId, 3, x, y, sCard_TextColorTable[sWonderCardData->gfx->footerTextPal], 0, sWonderCardData->statTextData[i].statText);
+ if (sWonderCardData->statTextData[i].statNumberText[0] != EOS)
+ {
+ // Print stat number
+ x += GetStringWidth(3, sWonderCardData->statTextData[i].statText, spacing);
+ AddTextPrinterParameterized3(windowId, 3, x, y,
+ sCard_TextColorTable[sWonderCardData->gfx->footerTextPal],
+ 0, sWonderCardData->statTextData[i].statNumberText);
+ x += GetStringWidth(3, sWonderCardData->statTextData[i].statNumberText, spacing) + sWonderCardData->statTextData[i].width;
+ }
+ }
+ }
+ break;
+ }
+ CopyWindowToVram(windowId, 3);
+}
+
+static void CreateCardSprites(void)
+{
+ u8 i = 0;
+ sWonderCardData->monIconSpriteId = SPRITE_NONE;
+
+ // Create icon sprite
+ if (sWonderCardData->cardMetadata.iconSpecies != SPECIES_NONE)
+ {
+ sWonderCardData->monIconSpriteId = CreateMonIconNoPersonality(GetIconSpeciesNoPersonality(sWonderCardData->cardMetadata.iconSpecies), SpriteCallbackDummy, 220, 20, 0, FALSE);
+ gSprites[sWonderCardData->monIconSpriteId].oam.priority = 2;
+ }
+
+ // Create stamp sprites
+ if (sWonderCardData->card.maxStamps != 0 && sWonderCardData->card.type == CARD_TYPE_STAMP)
+ {
+ LoadCompressedSpriteSheetUsingHeap(&sSpriteSheet_StampShadow);
+ LoadSpritePalette(&sSpritePalettes_StampShadow[sWonderCardData->gfx->stampShadowPal]);
+ for (; i < sWonderCardData->card.maxStamps; i++)
+ {
+ sWonderCardData->stampSpriteIds[i][0] = SPRITE_NONE;
+ sWonderCardData->stampSpriteIds[i][1] = SPRITE_NONE;
+ sWonderCardData->stampSpriteIds[i][0] = CreateSprite(&sSpriteTemplate_StampShadow, 216 - 32 * i, 144, 8);
+ if (sWonderCardData->cardMetadata.stampData[STAMP_SPECIES][i] != SPECIES_NONE)
+ sWonderCardData->stampSpriteIds[i][1] = CreateMonIconNoPersonality(GetIconSpeciesNoPersonality(sWonderCardData->cardMetadata.stampData[STAMP_SPECIES][i]),
+ SpriteCallbackDummy,
+ 216 - 32 * i,
+ 136, 0, 0);
+ }
+ }
+}
+
+static void DestroyCardSprites(void)
+{
+ u8 i = 0;
+
+ // Destroy icon sprite
+ if (sWonderCardData->monIconSpriteId != SPRITE_NONE)
+ FreeAndDestroyMonIconSprite(&gSprites[sWonderCardData->monIconSpriteId]);
+
+ // Destroy stamp sprites
+ if (sWonderCardData->card.maxStamps != 0 && sWonderCardData->card.type == CARD_TYPE_STAMP)
+ {
+ for (; i < sWonderCardData->card.maxStamps; i++)
+ {
+ if (sWonderCardData->stampSpriteIds[i][0] != SPRITE_NONE)
+ DestroySprite(&gSprites[sWonderCardData->stampSpriteIds[i][0]]);
+ if (sWonderCardData->stampSpriteIds[i][1] != SPRITE_NONE)
+ FreeAndDestroyMonIconSprite(&gSprites[sWonderCardData->stampSpriteIds[i][1]]);
+ }
+ FreeSpriteTilesByTag(TAG_STAMP_SHADOW);
+ FreeSpritePaletteByTag(TAG_STAMP_SHADOW);
+ }
+}
+
+//======================
+// Wonder News
+//======================
+
+enum {
+ NEWS_WIN_TITLE,
+ NEWS_WIN_BODY,
+ NEWS_WIN_COUNT
+};
+
+#define TAG_ARROWS 0x1000
+
+struct WonderNewsData
+{
+ /*0000*/ struct WonderNews news;
+ /*01bc*/ const struct WonderGraphics * gfx;
+ /*01c0*/ u8 arrowsRemoved:1;
+ u8 enterExitState:7;
+ /*01c1*/ u8 arrowTaskId;
+ /*01c2*/ bool8 scrolling:1;
+ u8 scrollIncrement:7;
+ /*01c3*/ bool8 scrollingDown:1;
+ u8 scrollTotal:7;
+ /*01c4*/ u16 scrollEnd;
+ /*01c6*/ u16 scrollOffset;
+ /*01c8*/ u16 windowIds[NEWS_WIN_COUNT];
+ /*01cc*/ u8 unused[2];
+ /*01ce*/ u8 titleText[WONDER_NEWS_TEXT_LENGTH + 1];
+ /*01f7*/ u8 bodyText[WONDER_NEWS_BODY_TEXT_LINES][WONDER_NEWS_TEXT_LENGTH + 1];
+ /*0394*/ struct ScrollArrowsTemplate arrowsTemplate;
+ /*03a4*/ u8 bgTilemapBuffer[0x1000];
+};
+
+EWRAM_DATA static struct WonderNewsData * sWonderNewsData = NULL;
+
+static void BufferNewsText(void);
+static void DrawNewsWindows(void);
+static void UpdateNewsScroll(void);
+
+static const u8 sNews_TextColorTable[][3] = {
+ {TEXT_COLOR_TRANSPARENT, TEXT_COLOR_DARK_GRAY, TEXT_COLOR_LIGHT_GRAY},
+ {TEXT_COLOR_TRANSPARENT, TEXT_COLOR_WHITE, TEXT_COLOR_DARK_GRAY}
+};
+
+static const struct WindowTemplate sNews_WindowTemplates[] = {
+ [NEWS_WIN_TITLE] = {
+ .bg = 0,
+ .tilemapLeft = 1,
+ .tilemapTop = 0,
+ .width = 28,
+ .height = 3,
+ .paletteNum = 2,
+ .baseBlock = 0x2AC
+ },
+ [NEWS_WIN_BODY] = {
+ .bg = 2,
+ .tilemapLeft = 1,
+ .tilemapTop = 3,
+ .width = 28,
+ .height = 20,
+ .paletteNum = 2,
+ .baseBlock = 0x07C
+ }
+};
+
+static const struct ScrollArrowsTemplate sNews_ArrowsTemplate = {
+ .firstArrowType = SCROLL_ARROW_UP,
+ .firstX = 232,
+ .firstY = 24,
+ .secondArrowType = SCROLL_ARROW_DOWN,
+ .secondX = 232,
+ .secondY = 152,
+ .fullyUpThreshold = 0,
+ .fullyDownThreshold = 2,
+ .tileTag = TAG_ARROWS,
+ .palTag = TAG_ARROWS,
+ .palNum = 0
+};
+
+static const u16 sWonderNewsPal1[] = INCBIN_U16("graphics/wonder_news/bg1.gbapal");
+static const u16 sWonderNewsPal7[] = INCBIN_U16("graphics/wonder_news/bg7.gbapal");
+static const u16 sWonderNewsPal8[] = INCBIN_U16("graphics/wonder_news/bg8.gbapal");
+static const u32 sWonderNewsGfx1[] = INCBIN_U32("graphics/wonder_news/bg1.4bpp.lz");
+static const u32 sWonderNewsTilemap1[] = INCBIN_U32("graphics/wonder_news/bg1.bin.lz");
+static const u32 sWonderNewsGfx2[] = INCBIN_U32("graphics/wonder_news/bg2.4bpp.lz");
+static const u32 sWonderNewsTilemap2[] = INCBIN_U32("graphics/wonder_news/bg2.bin.lz");
+static const u32 sWonderNewsGfx3[] = INCBIN_U32("graphics/wonder_news/bg3.4bpp.lz");
+static const u32 sWonderNewsTilemap3[] = INCBIN_U32("graphics/wonder_news/bg3.bin.lz");
+static const u32 sWonderNewsGfx7[] = INCBIN_U32("graphics/wonder_news/bg7.4bpp.lz");
+static const u32 sWonderNewsTilemap7[] = INCBIN_U32("graphics/wonder_news/bg7.bin.lz");
+static const u32 sWonderNewsGfx8[] = INCBIN_U32("graphics/wonder_news/bg8.4bpp.lz");
+static const u32 sWonderNewsTilemap8[] = INCBIN_U32("graphics/wonder_news/bg8.bin.lz");
+
+static const struct WonderGraphics sNewsGraphics[NUM_WONDER_BGS] = {
+ {.titleTextPal = 1, .bodyTextPal = 0, .tiles = sWonderNewsGfx1, .map = sWonderNewsTilemap1, .pal = sWonderNewsPal1},
+ {.titleTextPal = 1, .bodyTextPal = 0, .tiles = sWonderNewsGfx2, .map = sWonderNewsTilemap2, .pal = sWonderCardBgPal2},
+ {.titleTextPal = 1, .bodyTextPal = 0, .tiles = sWonderNewsGfx3, .map = sWonderNewsTilemap3, .pal = sWonderCardBgPal3},
+ {.titleTextPal = 1, .bodyTextPal = 0, .tiles = sWonderNewsGfx3, .map = sWonderNewsTilemap3, .pal = sWonderCardBgPal4},
+ {.titleTextPal = 1, .bodyTextPal = 0, .tiles = sWonderNewsGfx3, .map = sWonderNewsTilemap3, .pal = sWonderCardBgPal5},
+ {.titleTextPal = 1, .bodyTextPal = 0, .tiles = sWonderNewsGfx3, .map = sWonderNewsTilemap3, .pal = sWonderCardBgPal6},
+ {.titleTextPal = 1, .bodyTextPal = 0, .tiles = sWonderNewsGfx7, .map = sWonderNewsTilemap7, .pal = sWonderNewsPal7},
+ {.titleTextPal = 1, .bodyTextPal = 0, .tiles = sWonderNewsGfx8, .map = sWonderNewsTilemap8, .pal = sWonderNewsPal8}
+};
+
+bool32 WonderNews_Init(const struct WonderNews * news)
+{
+ if (news == NULL)
+ return FALSE;
+ sWonderNewsData = AllocZeroed(sizeof(*sWonderNewsData));
+ if (sWonderNewsData == NULL)
+ return FALSE;
+ sWonderNewsData->news = *news;
+ if (sWonderNewsData->news.bgType >= NUM_WONDER_BGS)
+ sWonderNewsData->news.bgType = 0;
+ sWonderNewsData->gfx = &sNewsGraphics[sWonderNewsData->news.bgType];
+ sWonderNewsData->arrowTaskId = TASK_NONE;
+ return TRUE;
+}
+
+void WonderNews_Destroy(void)
+{
+ if (sWonderNewsData != NULL)
+ {
+ *sWonderNewsData = (struct WonderNewsData){};
+ Free(sWonderNewsData);
+ sWonderNewsData = NULL;
+ }
+}
+
+s32 WonderNews_Enter(void)
+{
+ if (sWonderNewsData == NULL)
+ return -1;
+
+ switch (sWonderNewsData->enterExitState)
+ {
+ case 0:
+ BeginNormalPaletteFade(PALETTES_ALL, 0, 0, 16, RGB_BLACK);
+ break;
+ case 1:
+ if (UpdatePaletteFade())
+ return 0;
+ ChangeBgY(0, 0, 0);
+ ChangeBgY(1, 0, 0);
+ ChangeBgY(2, 0, 0);
+ ChangeBgY(3, 0, 0);
+ SetGpuReg(REG_OFFSET_WIN0H, WIN_RANGE(0, DISPLAY_WIDTH));
+ SetGpuReg(REG_OFFSET_WIN0V, WIN_RANGE(26, 152));
+ SetGpuReg(REG_OFFSET_WININ, WININ_WIN0_BG_ALL | WININ_WIN0_OBJ);
+ SetGpuReg(REG_OFFSET_WINOUT, WINOUT_WIN01_BG0 | WINOUT_WIN01_BG1 | WINOUT_WIN01_BG3 | WINOUT_WIN01_OBJ);
+ SetGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_WIN0_ON);
+ break;
+ case 2:
+ FillBgTilemapBufferRect_Palette0(0, 0x000, 0, 0, 30, 20);
+ FillBgTilemapBufferRect_Palette0(1, 0x000, 0, 0, 30, 20);
+ FillBgTilemapBufferRect_Palette0(2, 0x000, 0, 0, 30, 20);
+ FillBgTilemapBufferRect_Palette0(3, 0x000, 0, 0, 30, 20);
+ CopyBgTilemapBufferToVram(0);
+ CopyBgTilemapBufferToVram(1);
+ CopyBgTilemapBufferToVram(2);
+ CopyBgTilemapBufferToVram(3);
+ DecompressAndCopyTileDataToVram(3, sWonderNewsData->gfx->tiles, 0, 8, 0);
+ sWonderNewsData->windowIds[NEWS_WIN_TITLE] = AddWindow(&sNews_WindowTemplates[NEWS_WIN_TITLE]);
+ sWonderNewsData->windowIds[NEWS_WIN_BODY] = AddWindow(&sNews_WindowTemplates[NEWS_WIN_BODY]);
+ break;
+ case 3:
+ if (FreeTempTileDataBuffersIfPossible())
+ return 0;
+ LoadPalette(GetTextWindowPalette(1), 0x20, 0x20);
+ gPaletteFade.bufferTransferDisabled = TRUE;
+ LoadPalette(sWonderNewsData->gfx->pal, 0x10, 0x20);
+ LZ77UnCompWram(sWonderNewsData->gfx->map, sWonderNewsData->bgTilemapBuffer);
+ CopyRectToBgTilemapBufferRect(1, sWonderNewsData->bgTilemapBuffer, 0, 0, 30, 3, 0, 0, 30, 3, 1, 8, 0);
+ CopyRectToBgTilemapBufferRect(3, sWonderNewsData->bgTilemapBuffer, 0, 3, 30, 23, 0, 3, 30, 23, 1, 8, 0);
+ CopyBgTilemapBufferToVram(1);
+ CopyBgTilemapBufferToVram(3);
+ break;
+ case 4:
+ BufferNewsText();
+ break;
+ case 5:
+ DrawNewsWindows();
+ CopyBgTilemapBufferToVram(0);
+ CopyBgTilemapBufferToVram(2);
+ break;
+ case 6:
+ ShowBg(1);
+ ShowBg(2);
+ ShowBg(3);
+ gPaletteFade.bufferTransferDisabled = FALSE;
+ sWonderNewsData->arrowTaskId = AddScrollIndicatorArrowPair(&sWonderNewsData->arrowsTemplate, &sWonderNewsData->scrollOffset);
+ BeginNormalPaletteFade(PALETTES_ALL, 0, 16, 0, RGB_BLACK);
+ UpdatePaletteFade();
+ break;
+ default:
+ if (UpdatePaletteFade())
+ return 0;
+ sWonderNewsData->enterExitState = 0;
+ return 1;
+ }
+
+ sWonderNewsData->enterExitState++;
+ return 0;
+}
+
+s32 WonderNews_Exit(bool32 useCancel)
+{
+ if (sWonderNewsData == NULL)
+ return -1;
+ switch (sWonderNewsData->enterExitState)
+ {
+ case 0:
+ BeginNormalPaletteFade(PALETTES_ALL, 0, 0, 16, RGB_BLACK);
+ break;
+ case 1:
+ if (UpdatePaletteFade())
+ return 0;
+ ChangeBgY(2, 0, 0);
+ SetGpuReg(REG_OFFSET_WIN0H, 0);
+ SetGpuReg(REG_OFFSET_WIN0V, 0);
+ SetGpuReg(REG_OFFSET_WININ, 0);
+ SetGpuReg(REG_OFFSET_WINOUT, 0);
+ ClearGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_WIN0_ON);
+ break;
+ case 2:
+ FillBgTilemapBufferRect_Palette0(0, 0x000, 0, 0, 30, 20);
+ FillBgTilemapBufferRect_Palette0(1, 0x000, 0, 0, 30, 20);
+ FillBgTilemapBufferRect_Palette0(2, 0x000, 0, 0, 30, 24);
+ FillBgTilemapBufferRect_Palette0(3, 0x000, 0, 0, 30, 24);
+ CopyBgTilemapBufferToVram(0);
+ CopyBgTilemapBufferToVram(1);
+ CopyBgTilemapBufferToVram(2);
+ CopyBgTilemapBufferToVram(3);
+ break;
+ case 3:
+ HideBg(1);
+ HideBg(2);
+ RemoveWindow(sWonderNewsData->windowIds[NEWS_WIN_BODY]);
+ RemoveWindow(sWonderNewsData->windowIds[NEWS_WIN_TITLE]);
+ break;
+ case 4:
+ ChangeBgY(2, 0, 0);
+ ChangeBgY(3, 0, 0);
+ if (sWonderNewsData->arrowTaskId != TASK_NONE)
+ {
+ RemoveScrollIndicatorArrowPair(sWonderNewsData->arrowTaskId);
+ sWonderNewsData->arrowTaskId = TASK_NONE;
+ }
+ break;
+ case 5:
+ PrintMysteryGiftOrEReaderTopMenu(gGiftIsFromEReader, useCancel);
+ MG_DrawCheckerboardPattern(3);
+ CopyBgTilemapBufferToVram(0);
+ CopyBgTilemapBufferToVram(3);
+ BeginNormalPaletteFade(PALETTES_ALL, 0, 16, 0, RGB_BLACK);
+ break;
+ default:
+ if (UpdatePaletteFade())
+ return 0;
+ sWonderNewsData->enterExitState = 0;
+ return 1;
+ }
+ sWonderNewsData->enterExitState++;
+ return 0;
+}
+
+void WonderNews_RemoveScrollIndicatorArrowPair(void)
+{
+ if (!sWonderNewsData->arrowsRemoved && sWonderNewsData->arrowTaskId != TASK_NONE)
+ {
+ RemoveScrollIndicatorArrowPair(sWonderNewsData->arrowTaskId);
+ sWonderNewsData->arrowTaskId = TASK_NONE;
+ sWonderNewsData->arrowsRemoved = TRUE;
+ }
+}
+
+
+void WonderNews_AddScrollIndicatorArrowPair(void)
+{
+ if (sWonderNewsData->arrowsRemoved)
+ {
+ sWonderNewsData->arrowTaskId = AddScrollIndicatorArrowPair(&sWonderNewsData->arrowsTemplate, &sWonderNewsData->scrollOffset);
+ sWonderNewsData->arrowsRemoved = FALSE;
+ }
+}
+
+u32 WonderNews_GetInput(u16 input)
+{
+ if (sWonderNewsData->scrolling)
+ {
+ UpdateNewsScroll();
+ return NEWS_INPUT_NONE;
+ }
+ switch (input)
+ {
+ case A_BUTTON:
+ return NEWS_INPUT_A;
+ case B_BUTTON:
+ return NEWS_INPUT_B;
+ case DPAD_UP:
+ if (sWonderNewsData->scrollOffset == 0)
+ return NEWS_INPUT_NONE;
+ if (sWonderNewsData->arrowsRemoved)
+ return NEWS_INPUT_NONE;
+ sWonderNewsData->scrollingDown = FALSE;
+ break;
+ case DPAD_DOWN:
+ if (sWonderNewsData->scrollOffset == sWonderNewsData->scrollEnd)
+ return NEWS_INPUT_NONE;
+ if (sWonderNewsData->arrowsRemoved)
+ return NEWS_INPUT_NONE;
+ sWonderNewsData->scrollingDown = TRUE;
+ break;
+ default:
+ return NEWS_INPUT_NONE;
+ }
+
+ // Init scroll
+ sWonderNewsData->scrolling = TRUE;
+ sWonderNewsData->scrollIncrement = 2;
+ sWonderNewsData->scrollTotal = 0;
+ if (!sWonderNewsData->scrollingDown)
+ return NEWS_INPUT_SCROLL_UP;
+ else
+ return NEWS_INPUT_SCROLL_DOWN;
+}
+
+static void BufferNewsText(void)
+{
+ u8 i = 0;
+
+ // Copy title text
+ memcpy(sWonderNewsData->titleText, sWonderNewsData->news.titleText, WONDER_NEWS_TEXT_LENGTH);
+ sWonderNewsData->titleText[WONDER_NEWS_TEXT_LENGTH] = EOS;
+
+ // Copy body text
+ for (; i < WONDER_NEWS_BODY_TEXT_LINES; i++)
+ {
+ memcpy(sWonderNewsData->bodyText[i], sWonderNewsData->news.bodyText[i], WONDER_NEWS_TEXT_LENGTH);
+ sWonderNewsData->bodyText[i][WONDER_NEWS_TEXT_LENGTH] = EOS;
+ if (i > 7 && sWonderNewsData->bodyText[i][0] != EOS)
+ sWonderNewsData->scrollEnd++;
+ }
+ sWonderNewsData->arrowsTemplate = sNews_ArrowsTemplate;
+ sWonderNewsData->arrowsTemplate.fullyDownThreshold = sWonderNewsData->scrollEnd;
+}
+
+static void DrawNewsWindows(void)
+{
+ u8 i = 0;
+ s32 x;
+ PutWindowTilemap(sWonderNewsData->windowIds[NEWS_WIN_TITLE]);
+ PutWindowTilemap(sWonderNewsData->windowIds[NEWS_WIN_BODY]);
+ FillWindowPixelBuffer(sWonderNewsData->windowIds[NEWS_WIN_TITLE], 0);
+ FillWindowPixelBuffer(sWonderNewsData->windowIds[NEWS_WIN_BODY], 0);
+
+ // Print title text
+ x = (224 - GetStringWidth(3, sWonderNewsData->titleText, GetFontAttribute(3, FONTATTR_LETTER_SPACING))) / 2;
+ if (x < 0)
+ x = 0;
+ AddTextPrinterParameterized3(sWonderNewsData->windowIds[NEWS_WIN_TITLE], 3, x, 6, sNews_TextColorTable[sWonderNewsData->gfx->titleTextPal], 0, sWonderNewsData->titleText);
+
+ // Print body text
+ for (; i < WONDER_NEWS_BODY_TEXT_LINES; i++)
+ AddTextPrinterParameterized3(sWonderNewsData->windowIds[NEWS_WIN_BODY], 3, 0,
+ 16 * i + 2,
+ sNews_TextColorTable[sWonderNewsData->gfx->bodyTextPal],
+ 0, sWonderNewsData->bodyText[i]);
+
+ CopyWindowToVram(sWonderNewsData->windowIds[NEWS_WIN_TITLE], 3);
+ CopyWindowToVram(sWonderNewsData->windowIds[NEWS_WIN_BODY], 3);
+}
+
+static void UpdateNewsScroll(void)
+{
+ u16 bgMove = sWonderNewsData->scrollIncrement;
+ bgMove *= 256;
+ if (sWonderNewsData->scrollingDown)
+ {
+ ChangeBgY(2, bgMove, BG_COORD_ADD);
+ ChangeBgY(3, bgMove, BG_COORD_ADD);
+ }
+ else
+ {
+ ChangeBgY(2, bgMove, BG_COORD_SUB);
+ ChangeBgY(3, bgMove, BG_COORD_SUB);
+ }
+ sWonderNewsData->scrollTotal += sWonderNewsData->scrollIncrement;
+ if (sWonderNewsData->scrollTotal > 15)
+ {
+ if (sWonderNewsData->scrollingDown)
+ sWonderNewsData->scrollOffset++;
+ else
+ sWonderNewsData->scrollOffset--;
+ sWonderNewsData->scrolling = FALSE;
+ sWonderNewsData->scrollTotal = 0;
+ }
+}
diff --git a/src/new_game.c b/src/new_game.c
index 2a950efbc..1362c492d 100644
--- a/src/new_game.c
+++ b/src/new_game.c
@@ -43,7 +43,7 @@
#include "player_pc.h"
#include "field_specials.h"
#include "berry_powder.h"
-#include "mevent.h"
+#include "mystery_gift.h"
#include "union_room_chat.h"
extern const u8 EventScript_ResetAllMapFlags[];
@@ -200,7 +200,7 @@ void NewGameInitData(void)
ResetAllApprenticeData();
ClearRankingHallRecords();
InitMatchCallCounters();
- sub_801AFD8();
+ ClearMysteryGift();
WipeTrainerNameRecords();
ResetTrainerHillResults();
ResetContestLinkResults();
diff --git a/src/scrcmd.c b/src/scrcmd.c
index de0ec7c26..3e3beee59 100644
--- a/src/scrcmd.c
+++ b/src/scrcmd.c
@@ -2230,7 +2230,7 @@ bool8 ScrCmd_checkmoneventlegal(struct ScriptContext *ctx)
}
// TODO: Should be renamed. Name implies general usage, but its specifically for Wonder Card
-// See GetSavedRamScriptIfValid, which is NULL if ValidateReceivedWonderCard returns FALSE
+// See GetSavedRamScriptIfValid, which is NULL if ValidateSavedWonderCard returns FALSE
bool8 ScrCmd_gotoram(struct ScriptContext *ctx)
{
const u8* script = GetSavedRamScriptIfValid();
diff --git a/src/script.c b/src/script.c
index 726c06543..b10e0db49 100644
--- a/src/script.c
+++ b/src/script.c
@@ -1,8 +1,9 @@
#include "global.h"
#include "script.h"
#include "event_data.h"
-#include "mevent.h"
+#include "mystery_gift.h"
#include "util.h"
+#include "constants/maps.h"
#include "constants/map_scripts.h"
#define RAM_SCRIPT_MAGIC 51
@@ -403,9 +404,9 @@ bool32 ValidateSavedRamScript(void)
struct RamScriptData *scriptData = &gSaveBlock1Ptr->ramScript.data;
if (scriptData->magic != RAM_SCRIPT_MAGIC)
return FALSE;
- if (scriptData->mapGroup != 0xFF)
+ if (scriptData->mapGroup != MAP_GROUP(UNDEFINED))
return FALSE;
- if (scriptData->mapNum != 0xFF)
+ if (scriptData->mapNum != MAP_NUM(UNDEFINED))
return FALSE;
if (scriptData->objectId != 0xFF)
return FALSE;
@@ -417,13 +418,13 @@ bool32 ValidateSavedRamScript(void)
u8 *GetSavedRamScriptIfValid(void)
{
struct RamScriptData *scriptData = &gSaveBlock1Ptr->ramScript.data;
- if (!ValidateReceivedWonderCard())
+ if (!ValidateSavedWonderCard())
return NULL;
if (scriptData->magic != RAM_SCRIPT_MAGIC)
return NULL;
- if (scriptData->mapGroup != 0xFF)
+ if (scriptData->mapGroup != MAP_GROUP(UNDEFINED))
return NULL;
- if (scriptData->mapNum != 0xFF)
+ if (scriptData->mapNum != MAP_NUM(UNDEFINED))
return NULL;
if (scriptData->objectId != 0xFF)
return NULL;
@@ -442,5 +443,5 @@ void InitRamScript_NoObjectEvent(u8 *script, u16 scriptSize)
{
if (scriptSize > sizeof(gSaveBlock1Ptr->ramScript.data.script))
scriptSize = sizeof(gSaveBlock1Ptr->ramScript.data.script);
- InitRamScript(script, scriptSize, 0xFF, 0xFF, 0xFF);
+ InitRamScript(script, scriptSize, MAP_GROUP(UNDEFINED), MAP_NUM(UNDEFINED), 0xFF);
}
diff --git a/src/trade.c b/src/trade.c
index d1fc14efe..9c6bb78d0 100644
--- a/src/trade.c
+++ b/src/trade.c
@@ -19,8 +19,8 @@
#include "load_save.h"
#include "mail.h"
#include "main.h"
-#include "mevent2.h"
#include "mystery_gift.h"
+#include "mystery_gift_menu.h"
#include "overworld.h"
#include "palette.h"
#include "party_menu.h"
@@ -4655,9 +4655,8 @@ static void CB2_SaveAndEndTrade(void)
if (!InUnionRoom())
IncrementGameStat(GAME_STAT_POKEMON_TRADES);
if (gWirelessCommType)
- {
- RecordIdOfWonderCardSenderByEventType(2, gLinkPlayers[GetMultiplayerId() ^ 1].trainerId);
- }
+ MysteryGift_TryIncrementStat(CARD_STAT_NUM_TRADES, gLinkPlayers[GetMultiplayerId() ^ 1].trainerId);
+
SetContinueGameWarpStatusToDynamicWarp();
sub_8153380();
gMain.state++;
diff --git a/src/trainer_card.c b/src/trainer_card.c
index c11ee83c0..bad015644 100755
--- a/src/trainer_card.c
+++ b/src/trainer_card.c
@@ -110,7 +110,7 @@ static bool8 HasAllFrontierSymbols(void);
static u8 GetRubyTrainerStars(struct TrainerCard*);
static u16 GetCaughtMonsCount(void);
static void SetPlayerCardData(struct TrainerCard*, u8);
-static void TrainerCard_GenerateCardForLinkPlayer(struct TrainerCard*);
+static void TrainerCard_GenerateCardForPlayer(struct TrainerCard*);
static u8 VersionToCardType(u8);
static void SetDataFromTrainerCard(void);
static void InitGpuRegs(void);
@@ -750,14 +750,14 @@ static void SetPlayerCardData(struct TrainerCard *trainerCard, u8 cardType)
}
}
-static void TrainerCard_GenerateCardForLinkPlayer(struct TrainerCard *trainerCard)
+static void TrainerCard_GenerateCardForPlayer(struct TrainerCard *trainerCard)
{
memset(trainerCard, 0, sizeof(struct TrainerCard));
trainerCard->version = GAME_VERSION;
SetPlayerCardData(trainerCard, CARD_TYPE_EMERALD);
- trainerCard->hasAllSymbols = HasAllFrontierSymbols();
+ trainerCard->hasAllFrontierSymbols = HasAllFrontierSymbols();
trainerCard->frontierBP = gSaveBlock2Ptr->frontier.cardBattlePoints;
- if (trainerCard->hasAllSymbols)
+ if (trainerCard->hasAllFrontierSymbols)
trainerCard->stars++;
if (trainerCard->gender == FEMALE)
@@ -766,14 +766,14 @@ static void TrainerCard_GenerateCardForLinkPlayer(struct TrainerCard *trainerCar
trainerCard->facilityClass = gLinkPlayerFacilityClasses[trainerCard->trainerId % NUM_MALE_LINK_FACILITY_CLASSES];
}
-void TrainerCard_GenerateCardForPlayer(struct TrainerCard *trainerCard)
+void TrainerCard_GenerateCardForLinkPlayer(struct TrainerCard *trainerCard)
{
memset(trainerCard, 0, 0x60);
trainerCard->version = GAME_VERSION;
SetPlayerCardData(trainerCard, CARD_TYPE_EMERALD);
- trainerCard->hasAllFrontierSymbols = HasAllFrontierSymbols();
- *((u16*)&trainerCard->berryCrushPoints) = gSaveBlock2Ptr->frontier.cardBattlePoints;
- if (trainerCard->hasAllFrontierSymbols)
+ trainerCard->linkHasAllFrontierSymbols = HasAllFrontierSymbols();
+ *((u16*)&trainerCard->linkPoints.frontier) = gSaveBlock2Ptr->frontier.cardBattlePoints;
+ if (trainerCard->linkHasAllFrontierSymbols)
trainerCard->stars++;
if (trainerCard->gender == FEMALE)
@@ -782,7 +782,7 @@ void TrainerCard_GenerateCardForPlayer(struct TrainerCard *trainerCard)
trainerCard->facilityClass = gLinkPlayerFacilityClasses[trainerCard->trainerId % NUM_MALE_LINK_FACILITY_CLASSES];
}
-void CopyTrainerCardData(struct TrainerCard *dst, u16 *src, u8 gameVersion)
+void CopyTrainerCardData(struct TrainerCard *dst, struct TrainerCard *src, u8 gameVersion)
{
memset(dst, 0, sizeof(struct TrainerCard));
dst->version = gameVersion;
@@ -797,9 +797,9 @@ void CopyTrainerCardData(struct TrainerCard *dst, u16 *src, u8 gameVersion)
break;
case CARD_TYPE_EMERALD:
memcpy(dst, src, 0x60);
- dst->berryCrushPoints = 0;
- dst->hasAllSymbols = src[29];
- dst->frontierBP = src[30];
+ dst->linkPoints.frontier = 0;
+ dst->hasAllFrontierSymbols = src->linkHasAllFrontierSymbols;
+ dst->frontierBP = *((u16*)&src->linkPoints.frontier);
break;
}
}
@@ -1243,13 +1243,13 @@ static void PrintTradesStringOnCard(void)
static void BufferBerryCrushPoints(void)
{
- if (sData->cardType == CARD_TYPE_FRLG && sData->trainerCard.berryCrushPoints)
- ConvertIntToDecimalStringN(sData->textBerryCrushPts, sData->trainerCard.berryCrushPoints, STR_CONV_MODE_RIGHT_ALIGN, 5);
+ if (sData->cardType == CARD_TYPE_FRLG && sData->trainerCard.linkPoints.berryCrush)
+ ConvertIntToDecimalStringN(sData->textBerryCrushPts, sData->trainerCard.linkPoints.berryCrush, STR_CONV_MODE_RIGHT_ALIGN, 5);
}
static void PrintBerryCrushStringOnCard(void)
{
- if (sData->cardType == CARD_TYPE_FRLG && sData->trainerCard.berryCrushPoints)
+ if (sData->cardType == CARD_TYPE_FRLG && sData->trainerCard.linkPoints.berryCrush)
PrintStatOnBackOfCard(4, gText_BerryCrush, sData->textBerryCrushPts, sTrainerCardStatColors);
}
@@ -1524,7 +1524,7 @@ static void DrawCardBackStats(void)
FillBgTilemapBufferRect(3, 141, 27, 9, 1, 1, 1);
FillBgTilemapBufferRect(3, 157, 27, 10, 1, 1, 1);
}
- if (sData->trainerCard.berryCrushPoints)
+ if (sData->trainerCard.linkPoints.berryCrush)
{
FillBgTilemapBufferRect(3, 141, 21, 13, 1, 1, 1);
FillBgTilemapBufferRect(3, 157, 21, 14, 1, 1, 1);
@@ -1803,7 +1803,7 @@ void ShowPlayerTrainerCard(void (*callback)(void))
sData->isLink = FALSE;
sData->language = GAME_LANGUAGE;
- TrainerCard_GenerateCardForLinkPlayer(&sData->trainerCard);
+ TrainerCard_GenerateCardForPlayer(&sData->trainerCard);
SetMainCallback2(CB2_InitTrainerCard);
}
diff --git a/src/union_room.c b/src/union_room.c
index db2d0247b..6cc54d07c 100644
--- a/src/union_room.c
+++ b/src/union_room.c
@@ -24,8 +24,8 @@
#include "load_save.h"
#include "menu.h"
#include "menu_helpers.h"
-#include "mevent.h"
#include "mystery_gift.h"
+#include "mystery_gift_menu.h"
#include "overworld.h"
#include "palette.h"
#include "party_menu.h"
@@ -219,7 +219,7 @@ static u16 ReadAsU16(const u8 *);
static void Task_TryBecomeLinkLeader(u8);
static void Task_TryJoinLinkGroup(u8);
static void Task_ListenToWireless(u8);
-static void Task_MEvent_Leader(u8);
+static void Task_SendMysteryGift(u8);
static void Task_CardOrNewsWithFriend(u8);
static void Task_CardOrNewsOverWireless(u8);
static void Task_RunUnionRoom(u8);
@@ -1533,17 +1533,21 @@ static void Task_ExchangeCards(u8 taskId)
for (i = 0; i < GetLinkPlayerCount(); i++)
{
recvBuff = gBlockRecvBuffer[i];
- CopyTrainerCardData(&gTrainerCards[i], recvBuff, gLinkPlayers[i].version);
+ CopyTrainerCardData(&gTrainerCards[i], (struct TrainerCard *)recvBuff, gLinkPlayers[i].version);
}
if (GetLinkPlayerCount() == 2)
{
+ // Note: hasAllFrontierSymbols is a re-used field.
+ // Here it is set by CreateTrainerCardInBuffer.
+ // If the player has a saved Wonder Card and it is the same Wonder Card
+ // as their partner then mystery gift stats are enabled.
recvBuff = gBlockRecvBuffer[GetMultiplayerId() ^ 1];
- MEventHandleReceivedWonderCard(recvBuff[48]);
+ MysteryGift_TryEnableStatsByFlagId(((struct TrainerCard *)recvBuff)->hasAllFrontierSymbols);
}
else
{
- ResetReceivedWonderCardFlag();
+ MysteryGift_DisableStats();
}
ResetBlockReceivedFlags();
@@ -1627,18 +1631,19 @@ static void CB2_TransitionToCableClub(void)
static void CreateTrainerCardInBuffer(void *dest, bool32 setWonderCard)
{
- u16 *argAsU16Ptr = dest;
+ struct TrainerCard * card = (struct TrainerCard *)dest;
+ TrainerCard_GenerateCardForLinkPlayer(card);
- TrainerCard_GenerateCardForPlayer((struct TrainerCard *)argAsU16Ptr);
+ // Below field is re-used, to be read by Task_ExchangeCards
if (setWonderCard)
- argAsU16Ptr[48] = GetWonderCardFlagID();
+ card->hasAllFrontierSymbols = GetWonderCardFlagID();
else
- argAsU16Ptr[48] = 0;
+ card->hasAllFrontierSymbols = 0;
}
static void Task_StartActivity(u8 taskId)
{
- ResetReceivedWonderCardFlag();
+ MysteryGift_DisableStats();
switch (gPlayerCurrActivity)
{
case ACTIVITY_BATTLE_SINGLE:
@@ -1858,12 +1863,13 @@ static void CreateTask_StartActivity(void)
gTasks[taskId].data[0] = 0;
}
-void MEvent_CreateTask_Leader(u32 activity)
+// Sending Wonder Card/News
+void CreateTask_SendMysteryGift(u32 activity)
{
u8 taskId;
struct WirelessLink_Leader *data;
- taskId = CreateTask(Task_MEvent_Leader, 0);
+ taskId = CreateTask(Task_SendMysteryGift, 0);
sWirelessLinkMain.leader = data = (void*)(gTasks[taskId].data);
data->state = 0;
@@ -1872,7 +1878,7 @@ void MEvent_CreateTask_Leader(u32 activity)
gSpecialVar_Result = LINKUP_ONGOING;
}
-static void Task_MEvent_Leader(u8 taskId)
+static void Task_SendMysteryGift(u8 taskId)
{
struct WirelessLink_Leader *data = sWirelessLinkMain.leader;
struct WindowTemplate winTemplate;
@@ -1934,7 +1940,7 @@ static void Task_MEvent_Leader(u8 taskId)
}
break;
case 6:
- if (MG_PrintTextOnWindow1AndWaitButton(&data->textState, sText_LinkWithFriendDropped))
+ if (PrintMysteryGiftMenuMessage(&data->textState, sText_LinkWithFriendDropped))
{
data->playerCount = LeaderPrunePlayerList(data->playerList);
RedrawListMenu(data->listTaskId);
@@ -1945,7 +1951,7 @@ static void Task_MEvent_Leader(u8 taskId)
data->state = 7;
break;
case 7:
- switch (mevent_message_print_and_prompt_yes_no(&data->textState, &data->yesNoWindowId, 0, gStringVar4))
+ switch (DoMysteryGiftYesNo(&data->textState, &data->yesNoWindowId, 0, gStringVar4))
{
case 0:
LoadWirelessStatusIndicatorSpriteGfx();
@@ -2031,7 +2037,7 @@ static void Task_MEvent_Leader(u8 taskId)
data->state++;
break;
case 14:
- if (MG_PrintTextOnWindow1AndWaitButton(&data->textState, sText_PleaseStartOver))
+ if (PrintMysteryGiftMenuMessage(&data->textState, sText_PleaseStartOver))
{
DestroyTask(taskId);
gSpecialVar_Result = LINKUP_FAILED;
@@ -2066,7 +2072,7 @@ static void Task_MEvent_Leader(u8 taskId)
}
}
-void MEvent_CreateTask_CardOrNewsWithFriend(u32 activity)
+void CreateTask_LinkMysteryGiftWithFriend(u32 activity)
{
u8 taskId;
struct WirelessLink_Group *data;
@@ -2209,7 +2215,7 @@ static void Task_CardOrNewsWithFriend(u8 taskId)
data->state++;
break;
case 9:
- if (MG_PrintTextOnWindow1AndWaitButton(&data->textState, sLinkDroppedTexts[RfuGetStatus()]))
+ if (PrintMysteryGiftMenuMessage(&data->textState, sLinkDroppedTexts[RfuGetStatus()]))
{
DestroyWirelessStatusIndicatorSprite();
DestroyTask(taskId);
@@ -2235,7 +2241,7 @@ static void Task_CardOrNewsWithFriend(u8 taskId)
}
}
-void MEvent_CreateTask_CardOrNewsOverWireless(u32 activity)
+void CreateTask_LinkMysteryGiftOverWireless(u32 activity)
{
u8 taskId;
struct WirelessLink_Group *data;
@@ -2377,7 +2383,7 @@ static void Task_CardOrNewsOverWireless(u8 taskId)
data->state++;
break;
case 9:
- if (MG_PrintTextOnWindow1AndWaitButton(&data->textState, sText_WirelessLinkDropped))
+ if (PrintMysteryGiftMenuMessage(&data->textState, sText_WirelessLinkDropped))
{
DestroyWirelessStatusIndicatorSprite();
DestroyTask(taskId);
@@ -2386,7 +2392,7 @@ static void Task_CardOrNewsOverWireless(u8 taskId)
}
break;
case 7:
- if (MG_PrintTextOnWindow1AndWaitButton(&data->textState, sText_WirelessSearchCanceled))
+ if (PrintMysteryGiftMenuMessage(&data->textState, sText_WirelessSearchCanceled))
{
DestroyWirelessStatusIndicatorSprite();
DestroyTask(taskId);
@@ -2395,7 +2401,7 @@ static void Task_CardOrNewsOverWireless(u8 taskId)
}
break;
case 11:
- if (MG_PrintTextOnWindow1AndWaitButton(&data->textState, sNoWonderSharedTexts[data->isWonderNews]))
+ if (PrintMysteryGiftMenuMessage(&data->textState, sNoWonderSharedTexts[data->isWonderNews]))
{
DestroyWirelessStatusIndicatorSprite();
DestroyTask(taskId);
diff --git a/src/wonder_news.c b/src/wonder_news.c
new file mode 100644
index 000000000..ec93d293e
--- /dev/null
+++ b/src/wonder_news.c
@@ -0,0 +1,160 @@
+#include "global.h"
+#include "mystery_gift.h"
+#include "random.h"
+#include "event_data.h"
+#include "wonder_news.h"
+
+/*
+ Wonder News related functions.
+ Because this feature is largely unused, the names in here are
+ mostly nebulous and without a real indication of purpose.
+*/
+
+enum {
+ NEWS_VAL_INVALID,
+ NEWS_VAL_RECV_FRIEND,
+ NEWS_VAL_RECV_WIRELESS,
+ NEWS_VAL_NONE,
+ NEWS_VAL_SENT,
+ NEWS_VAL_SENT_MAX,
+ NEWS_VAL_GET_MAX,
+};
+
+static u32 GetNewsId(struct WonderNewsMetadata *);
+static void IncrementGetNewsCounter(struct WonderNewsMetadata *);
+static u32 GetNewsValByNewsType(struct WonderNewsMetadata *);
+static void IncrementSentNewsCounter(struct WonderNewsMetadata *);
+static void ResetSentNewsCounter(struct WonderNewsMetadata *);
+
+void GenerateRandomWonderNews(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:
+ data->rand = (Random() % 15) + 16;
+ break;
+ case WONDER_NEWS_SENT:
+ data->rand = (Random() % 15) + 1;
+ break;
+ }
+}
+
+void InitSavedWonderNews(void)
+{
+ struct WonderNewsMetadata *data = GetSavedWonderNewsMetadata();
+
+ data->newsType = WONDER_NEWS_NONE;
+ data->sentCounter = 0;
+ data->getCounter = 0;
+ data->rand = 0;
+ VarSet(VAR_WONDER_NEWS_COUNTER, 0);
+}
+
+// Unused
+static void TryIncrementWonderNewsVar(void)
+{
+ u16 *var = GetVarPointer(VAR_WONDER_NEWS_COUNTER);
+ struct WonderNewsMetadata *data = GetSavedWonderNewsMetadata();
+
+ if (data->getCounter > 4 && ++(*var) >= 500)
+ {
+ data->getCounter = 0;
+ *var = 0;
+ }
+}
+
+// Unused
+u16 RetrieveWonderNewsVal(void)
+{
+ u16 *result = &gSpecialVar_Result;
+ struct WonderNewsMetadata *data = GetSavedWonderNewsMetadata();
+ u16 newsVal;
+
+ // Checks if Mystery Event is enabled, not Mystery Gift?
+ if (!IsMysteryEventEnabled() || !ValidateSavedWonderNews())
+ return 0;
+
+ newsVal = GetNewsValByNewsType(data);
+
+ switch (newsVal)
+ {
+ case NEWS_VAL_RECV_FRIEND:
+ *result = GetNewsId(data);
+ break;
+ case NEWS_VAL_RECV_WIRELESS:
+ *result = GetNewsId(data);
+ break;
+ case NEWS_VAL_SENT:
+ *result = GetNewsId(data);
+ IncrementSentNewsCounter(data);
+ break;
+ case NEWS_VAL_SENT_MAX:
+ *result = GetNewsId(data);
+ ResetSentNewsCounter(data);
+ break;
+ case NEWS_VAL_INVALID:
+ case NEWS_VAL_NONE:
+ case NEWS_VAL_GET_MAX:
+ break;
+ }
+
+ return newsVal;
+}
+
+static u32 GetNewsId(struct WonderNewsMetadata *data)
+{
+ u32 id;
+ data->newsType = WONDER_NEWS_NONE;
+ id = data->rand + 132;
+ data->rand = 0;
+ IncrementGetNewsCounter(data);
+ return id;
+}
+
+static void ResetSentNewsCounter(struct WonderNewsMetadata *data)
+{
+ data->sentCounter = 0;
+}
+
+static void IncrementSentNewsCounter(struct WonderNewsMetadata *data)
+{
+ data->sentCounter++;
+ if (data->sentCounter > 4)
+ data->sentCounter = 4;
+}
+
+static void IncrementGetNewsCounter(struct WonderNewsMetadata *data)
+{
+ data->getCounter++;
+ if (data->getCounter > 5)
+ data->getCounter = 5;
+}
+
+static u32 GetNewsValByNewsType(struct WonderNewsMetadata *data)
+{
+ if (data->getCounter == 5)
+ return NEWS_VAL_GET_MAX;
+
+ switch (data->newsType)
+ {
+ case WONDER_NEWS_NONE:
+ return NEWS_VAL_NONE;
+ case WONDER_NEWS_RECV_FRIEND:
+ return NEWS_VAL_RECV_FRIEND;
+ case WONDER_NEWS_RECV_WIRELESS:
+ return NEWS_VAL_RECV_WIRELESS;
+ case WONDER_NEWS_SENT:
+ if (data->sentCounter < 3)
+ return NEWS_VAL_SENT;
+ return NEWS_VAL_SENT_MAX;
+ default:
+ AGB_ASSERT(0);
+ return NEWS_VAL_INVALID;
+ }
+}