Merge pull request #1519 from GriffinRichards/doc-mgift

Document Mystery Gift
This commit is contained in:
GriffinR
2021-10-24 15:50:39 -04:00
committed by GitHub
110 changed files with 5190 additions and 4866 deletions

View File

@@ -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;
}
}

View File

@@ -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)

View File

@@ -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"

View File

@@ -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:

View File

@@ -114,36 +114,36 @@ bool32 IsMysteryGiftEnabled(void)
return FlagGet(FLAG_SYS_MYSTERY_GIFT_ENABLE);
}
void ClearMysteryEventFlags(void)
void ClearMysteryGiftFlags(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);
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 ClearMysteryEventVars(void)
void ClearMysteryGiftVars(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);
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)

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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:

View File

@@ -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);
}

View File

@@ -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;
}
}

View File

@@ -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);
}

View File

@@ -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;
}
}

View File

@@ -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}
};

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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.");

View File

@@ -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;
}

2218
src/mystery_gift.c Normal file → Executable file

File diff suppressed because it is too large Load Diff

303
src/mystery_gift_client.c Normal file
View File

@@ -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);
}

222
src/mystery_gift_link.c Normal file
View File

@@ -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;
}

1618
src/mystery_gift_menu.c Normal file

File diff suppressed because it is too large Load Diff

217
src/mystery_gift_scripts.c Normal file
View File

@@ -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
};

291
src/mystery_gift_server.c Normal file
View File

@@ -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;
}

936
src/mystery_gift_view.c Normal file
View File

@@ -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;
}
}

View File

@@ -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();

View File

@@ -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();

View File

@@ -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);
}

View File

@@ -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++;

View File

@@ -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,29 +750,13 @@ 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->frontierBP = gSaveBlock2Ptr->frontier.cardBattlePoints;
if (trainerCard->hasAllSymbols)
trainerCard->stars++;
if (trainerCard->gender == FEMALE)
trainerCard->facilityClass = gLinkPlayerFacilityClasses[(trainerCard->trainerId % NUM_FEMALE_LINK_FACILITY_CLASSES) + NUM_MALE_LINK_FACILITY_CLASSES];
else
trainerCard->facilityClass = gLinkPlayerFacilityClasses[trainerCard->trainerId % NUM_MALE_LINK_FACILITY_CLASSES];
}
void TrainerCard_GenerateCardForPlayer(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;
trainerCard->frontierBP = gSaveBlock2Ptr->frontier.cardBattlePoints;
if (trainerCard->hasAllFrontierSymbols)
trainerCard->stars++;
@@ -782,7 +766,23 @@ 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 TrainerCard_GenerateCardForLinkPlayer(struct TrainerCard *trainerCard)
{
memset(trainerCard, 0, 0x60);
trainerCard->version = GAME_VERSION;
SetPlayerCardData(trainerCard, CARD_TYPE_EMERALD);
trainerCard->linkHasAllFrontierSymbols = HasAllFrontierSymbols();
*((u16*)&trainerCard->linkPoints.frontier) = gSaveBlock2Ptr->frontier.cardBattlePoints;
if (trainerCard->linkHasAllFrontierSymbols)
trainerCard->stars++;
if (trainerCard->gender == FEMALE)
trainerCard->facilityClass = gLinkPlayerFacilityClasses[(trainerCard->trainerId % NUM_FEMALE_LINK_FACILITY_CLASSES) + NUM_MALE_LINK_FACILITY_CLASSES];
else
trainerCard->facilityClass = gLinkPlayerFacilityClasses[trainerCard->trainerId % NUM_MALE_LINK_FACILITY_CLASSES];
}
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);
}

View File

@@ -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);

160
src/wonder_news.c Normal file
View File

@@ -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;
}
}