summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorjiangzhengwenjz <jiangzhengwenjzw@qq.com>2019-11-14 12:57:49 +0800
committerjiangzhengwenjz <jiangzhengwenjzw@qq.com>2019-11-19 10:26:40 +0800
commit1d3ae2fe78823a6a0d4d9d93a988aa5ca1092801 (patch)
treeacb385b82e1b361e36e6075b13329563fe93f415 /src
parent17b55f50dbcdf9797d0aecfba356bc8681dea8f5 (diff)
parentf6dfeba742c415d964b415bfefb859c3a3764930 (diff)
Merge branch 'master' into battle
Diffstat (limited to 'src')
-rw-r--r--src/battle_tower.c1303
-rw-r--r--src/field_door.c537
-rw-r--r--src/item_use.c63
-rw-r--r--src/learn_move.c842
-rw-r--r--src/map_name_popup.c216
-rw-r--r--src/metatile_behavior.c37
-rw-r--r--src/mevent.c2
-rw-r--r--src/mevent_client.c4
-rw-r--r--src/mevent_scripts.c192
-rw-r--r--src/pokemon_size_record.c17
-rw-r--r--src/quest_log.c2
-rw-r--r--src/save_menu_util.c58
-rw-r--r--src/slot_machine.c604
-rw-r--r--src/trainer_tower.c149
14 files changed, 3269 insertions, 757 deletions
diff --git a/src/battle_tower.c b/src/battle_tower.c
index feab13d69..dfbef8fe5 100644
--- a/src/battle_tower.c
+++ b/src/battle_tower.c
@@ -1,13 +1,59 @@
#include "global.h"
#include "battle_tower.h"
+#include "random.h"
+#include "text.h"
+#include "event_data.h"
+#include "string_util.h"
+#include "battle_message.h"
+#include "data.h"
+#include "pokedex.h"
+#include "overworld.h"
+#include "battle_transition.h"
+#include "easy_chat.h"
+#include "battle_setup.h"
+#include "battle_main.h"
+#include "task.h"
+#include "battle.h"
+#include "party_menu.h"
+#include "new_game.h"
+#include "save.h"
+#include "item.h"
+#include "script_pokemon_util_80A0058.h"
#include "constants/species.h"
#include "constants/items.h"
#include "constants/moves.h"
#include "constants/pokemon.h"
+#include "constants/vars.h"
+#include "constants/map_objects.h"
+
+static EWRAM_DATA u16 sSpecialVar_0x8004_Copy = 0;
+
+#define TakeBravoTrainerBattleTowerOffTheAir()
+#define ewram160FB (*((u8 *)&gBattleStruct->field_DA))
+
+static void ResetBattleTowerStreak(u8 levelType);
+static void SetBattleTowerTrainerGfxId(u8 trainerClass);
+static void CheckMonBattleTowerBanlist(u16 species, u16 heldItem, u16 hp, u8 battleTowerLevelType, u8 monLevel, u16 *validPartySpecies, u16 *validPartyHeldItems, u8 *numValid);
+static void SaveCurrentWinStreak(void);
+static void ValidateBattleTowerRecordChecksums(void);
+static void SetBattleTowerRecordChecksum(struct BattleTowerRecord * record);
+static void ClearBattleTowerRecord(struct BattleTowerRecord * record);
+static void PopulateBravoTrainerBattleTowerLostData(void);
+static u16 GetCurrentBattleTowerWinStreak(u8 levelType);
+static void SetEReaderTrainerChecksum(struct BattleTowerEReaderTrainer * eReaderTrainer);
+static void PrintEReaderTrainerFarewellMessage(void);
+
+const u8 unref_83FFAAC[] = {
+ 0x05, 0x04, 0x01, 0x10, 0x04, 0x02, 0x05, 0x06,
+ 0x03, 0x10, 0x06, 0x04, 0x00, 0x01, 0x02, 0x03,
+ 0x00, 0x02, 0x03
+};
+
+const u8 unref_83FFABF[] = _("100");
#include "data/battle_tower/trainers.h"
-const u16 sBattleTowerHeldItems[] = {
+static const u16 sBattleTowerHeldItems[] = {
ITEM_NONE,
ITEM_KINGS_ROCK,
ITEM_SITRUS_BERRY,
@@ -76,22 +122,22 @@ const u16 sBattleTowerHeldItems[] = {
#include "data/battle_tower/level_50_mons.h"
#include "data/battle_tower/level_100_mons.h"
-const u8 sMaleTrainerClasses[] =
+static const u8 sMaleTrainerClasses[] =
{
};
-const u8 sFemaleTrainerClasses[] =
+static const u8 sFemaleTrainerClasses[] =
{
};
-const u8 sMaleTrainerGfx[] =
+static const u8 sMaleTrainerGfx[] =
{
};
-const u8 sFemaleTrainerGfx[] =
+static const u8 sFemaleTrainerGfx[] =
{
};
@@ -110,7 +156,7 @@ const u16 gBattleTowerBannedSpecies[] = {
0xFFFF
};
-const u16 sShortStreakPrizes[] = {
+static const u16 sShortStreakPrizes[] = {
ITEM_HP_UP,
ITEM_PROTEIN,
ITEM_IRON,
@@ -119,7 +165,7 @@ const u16 sShortStreakPrizes[] = {
ITEM_ZINC
};
-const u16 sLongStreakPrizes[] = {
+static const u16 sLongStreakPrizes[] = {
ITEM_BRIGHT_POWDER,
ITEM_WHITE_HERB,
ITEM_QUICK_CLAW,
@@ -131,3 +177,1246 @@ const u16 sLongStreakPrizes[] = {
ITEM_CHOICE_BAND
};
+void ScrSpecial_BattleTowerMapScript2(void)
+{
+ u8 count = 0;
+ s32 levelType;
+
+ for (levelType = 0; levelType < 2; levelType++)
+ {
+ switch (gSaveBlock2Ptr->battleTower.var_4AE[levelType])
+ {
+ default:
+ case 0:
+ ResetBattleTowerStreak(levelType);
+ if (count == 0)
+ VarSet(VAR_0x4000, 5);
+ break;
+ case 1:
+ ResetBattleTowerStreak(levelType);
+ VarSet(VAR_0x4000, BTSPECIAL_RESULT_SAVE_SCUM);
+ count++;
+ break;
+ case 3:
+ break;
+ case 4:
+ VarSet(VAR_0x4000, BTSPECIAL_RESULT_WON7);
+ count++;
+ break;
+ case 5:
+ VarSet(VAR_0x4000, BTSPECIAL_RESULT_LOST);
+ count++;
+ break;
+ case 6:
+ break;
+ case 2:
+ VarSet(VAR_0x4000, BTSPECIAL_RESULT_QUICKSAVE);
+ count++;
+ break;
+ }
+ }
+ if (gSaveBlock2Ptr->battleTower.var_4AE[0] == 3 && gSaveBlock2Ptr->battleTower.var_4AE[1] == 3)
+ VarSet(VAR_0x4000, BTSPECIAL_RESULT_INACTIVE);
+ ValidateBattleTowerRecordChecksums();
+}
+
+static void ResetBattleTowerStreak(u8 levelType)
+{
+ gSaveBlock2Ptr->battleTower.var_4AE[levelType] = 0;
+ gSaveBlock2Ptr->battleTower.curChallengeBattleNum[levelType] = 1;
+ gSaveBlock2Ptr->battleTower.curStreakChallengesNum[levelType] = 1;
+}
+
+static bool8 ShouldBattleEReaderTrainer(u8 levelType, u16 winStreak)
+{
+ u8 trainerTeamLevel;
+ u8 monLevel;
+ s32 i;
+ u16 validPartySpecies[6];
+ u16 validPartyHeldItems[6];
+ u8 numValid;
+
+ numValid = 0;
+
+ ValidateEReaderTrainer();
+
+ if (gSpecialVar_Result != 0 || gSaveBlock2Ptr->battleTower.ereaderTrainer.winStreak != winStreak)
+ return FALSE;
+
+ if (levelType != 0)
+ trainerTeamLevel = 100;
+ else
+ trainerTeamLevel = 50;
+
+ for (i = 0; i < 3; i++)
+ {
+ monLevel = gSaveBlock2Ptr->battleTower.ereaderTrainer.party[i].level;
+ if (gSaveBlock2Ptr->battleTower.ereaderTrainer.party[i].level != trainerTeamLevel)
+ return FALSE;
+
+ CheckMonBattleTowerBanlist(
+ gSaveBlock2Ptr->battleTower.ereaderTrainer.party[i].species,
+ gSaveBlock2Ptr->battleTower.ereaderTrainer.party[i].heldItem,
+ 1,
+ levelType,
+ monLevel,
+ validPartySpecies,
+ validPartyHeldItems,
+ &numValid);
+ }
+
+ return (numValid == 3);
+}
+
+static bool8 ChooseSpecialBattleTowerTrainer(void)
+{
+ s32 recordIndex, i;
+ u8 battleTowerLevelType;
+ u16 winStreak;
+ bool8 retVal;
+ s32 numCandidates;
+ u32 trainerIds[5];
+
+ numCandidates = 0;
+ battleTowerLevelType = gSaveBlock2Ptr->battleTower.battleTowerLevelType;
+
+ winStreak = GetCurrentBattleTowerWinStreak(battleTowerLevelType);
+ if (ShouldBattleEReaderTrainer(battleTowerLevelType, winStreak))
+ {
+ gSaveBlock2Ptr->battleTower.battleTowerTrainerId = BATTLE_TOWER_EREADER_TRAINER_ID;
+ retVal = TRUE;
+ }
+ else
+ {
+ // Check if one of the battle tower trainers from record mixing should be the next trainer.
+ for (recordIndex = 0; recordIndex < 5; recordIndex++)
+ {
+ struct BattleTowerRecord *record = &gSaveBlock2Ptr->battleTower.records[recordIndex];
+ u32 recordHasData = 0;
+ u32 checksum = 0;
+
+ for (i = 0; i < sizeof(struct BattleTowerRecord) / sizeof(u32) - 1; i++)
+ {
+ recordHasData |= ((u32 *) record)[i];
+ checksum += ((u32 *) record)[i];
+ }
+
+ if (gSaveBlock2Ptr->battleTower.records[recordIndex].winStreak == winStreak
+ && gSaveBlock2Ptr->battleTower.records[recordIndex].battleTowerLevelType == battleTowerLevelType
+ && recordHasData
+ && gSaveBlock2Ptr->battleTower.records[recordIndex].checksum == checksum)
+ {
+ trainerIds[numCandidates] = recordIndex;
+ numCandidates++;
+ }
+ }
+
+ if (numCandidates == 0)
+ {
+ retVal = FALSE;
+ }
+ else
+ {
+ gSaveBlock2Ptr->battleTower.battleTowerTrainerId =
+ trainerIds[Random() % numCandidates] + BATTLE_TOWER_RECORD_MIXING_TRAINER_BASE_ID;
+ retVal = TRUE;
+ }
+ }
+ return retVal;
+}
+
+void ChooseNextBattleTowerTrainer(void)
+{
+ int i;
+ u16 trainerId;
+ bool8 levelType;
+
+ levelType = gSaveBlock2Ptr->battleTower.battleTowerLevelType;
+ if (ChooseSpecialBattleTowerTrainer())
+ {
+ SetBattleTowerTrainerGfxId(gSaveBlock2Ptr->battleTower.battleTowerTrainerId);
+ gSaveBlock2Ptr->battleTower.battledTrainerIds[gSaveBlock2Ptr->battleTower.curChallengeBattleNum[levelType] - 1] = gSaveBlock2Ptr->battleTower.battleTowerTrainerId;
+ return;
+ }
+
+ if (gSaveBlock2Ptr->battleTower.curStreakChallengesNum[levelType] <= 7)
+ {
+ if (gSaveBlock2Ptr->battleTower.curChallengeBattleNum[levelType] == 7)
+ {
+ do
+ {
+ trainerId = ((Random() & 0xFF) * 5) >> 7;
+ trainerId += (gSaveBlock2Ptr->battleTower.curStreakChallengesNum[levelType] - 1) * 10 + 20;
+
+ // Ensure trainer wasn't previously fought in this challenge.
+ for (i = 0; i < gSaveBlock2Ptr->battleTower.curChallengeBattleNum[levelType] - 1 && gSaveBlock2Ptr->battleTower.battledTrainerIds[i] != trainerId; i++);
+ }
+ while (i != gSaveBlock2Ptr->battleTower.curChallengeBattleNum[levelType] - 1);
+ gSaveBlock2Ptr->battleTower.battleTowerTrainerId = trainerId;
+ }
+ else
+ {
+ do
+ {
+ trainerId = (((Random() & 0xFF) * 5) >> 6);
+ trainerId += (gSaveBlock2Ptr->battleTower.curStreakChallengesNum[levelType] - 1) * 10;
+
+ // Ensure trainer wasn't previously fought in this challenge.
+ for (i = 0; i < gSaveBlock2Ptr->battleTower.curChallengeBattleNum[levelType] - 1 && gSaveBlock2Ptr->battleTower.battledTrainerIds[i] != trainerId; i++);
+ }
+ while (i != gSaveBlock2Ptr->battleTower.curChallengeBattleNum[levelType] - 1);
+ gSaveBlock2Ptr->battleTower.battleTowerTrainerId = trainerId;
+ }
+ }
+ else
+ {
+ do
+ {
+ trainerId = (((Random() & 0xFF) * 30) >> 8) + 70;
+
+ // Ensure trainer wasn't previously fought in this challenge.
+ for (i = 0; i < gSaveBlock2Ptr->battleTower.curChallengeBattleNum[levelType] - 1 && gSaveBlock2Ptr->battleTower.battledTrainerIds[i] != trainerId; i++);
+ }
+ while (i != gSaveBlock2Ptr->battleTower.curChallengeBattleNum[levelType] - 1);
+ gSaveBlock2Ptr->battleTower.battleTowerTrainerId = trainerId;
+ }
+
+ SetBattleTowerTrainerGfxId(gSaveBlock2Ptr->battleTower.battleTowerTrainerId);
+ // Don't bother saving this trainer, since it's the last one in the challenge.
+ if (gSaveBlock2Ptr->battleTower.curChallengeBattleNum[levelType] < 7)
+ gSaveBlock2Ptr->battleTower.battledTrainerIds[gSaveBlock2Ptr->battleTower.curChallengeBattleNum[levelType] - 1] = gSaveBlock2Ptr->battleTower.battleTowerTrainerId;
+}
+
+static void SetBattleTowerTrainerGfxId(u8 trainerClass)
+{
+ VarSet(VAR_OBJ_GFX_ID_0, MAP_OBJ_GFX_YOUNGSTER);
+}
+
+void SetEReaderTrainerGfxId(void)
+{
+ SetBattleTowerTrainerGfxId(BATTLE_TOWER_EREADER_TRAINER_ID);
+}
+
+// Unreferenced; formerly used by Record Mixing in R/S
+static void UpdateOrInsertReceivedBattleTowerRecord(struct BattleTowerRecord * record0)
+{
+ s32 i;
+ s32 j;
+ s32 k;
+ s32 l = 0;
+ struct BattleTowerRecord * record = record0;
+
+ u16 winStreaks[6];
+ u16 indices[6];
+
+ for (i = 0; i < 5; i++)
+ {
+ k = 0;
+ for (j = 0; j < 4; j++)
+ {
+ if (gSaveBlock2Ptr->battleTower.records[i].trainerId[j] != record->trainerId[j])
+ break;
+ }
+ if (j == 4)
+ {
+ for (k = 0; k < 7; k++)
+ {
+ if (gSaveBlock2Ptr->battleTower.records[i].name[j] != record->name[j])
+ break;
+ if (record->name[j] == EOS)
+ {
+ k = 7;
+ break;
+ }
+ }
+ }
+ if (k == 7)
+ break;
+ }
+
+ if (i < 5)
+ {
+ gSaveBlock2Ptr->battleTower.records[i] = *record;
+ return;
+ }
+
+ for (i = 0; i < 5; i++)
+ {
+ if (gSaveBlock2Ptr->battleTower.records[i].winStreak == 0)
+ break;
+ }
+
+ if (i < 5)
+ {
+ gSaveBlock2Ptr->battleTower.records[i] = *record;
+ return;
+ }
+
+ winStreaks[0] = gSaveBlock2Ptr->battleTower.records[0].winStreak;
+ indices[0] = 0;
+ l++;
+
+ for (i = 1; i < 5; i++)
+ {
+ for (j = 0; j < l; j++)
+ {
+ if (gSaveBlock2Ptr->battleTower.records[i].winStreak < winStreaks[j])
+ {
+ j = 0;
+ l = 1;
+ winStreaks[0] = gSaveBlock2Ptr->battleTower.records[i].winStreak;
+ indices[0] = i;
+ break;
+ }
+ if (gSaveBlock2Ptr->battleTower.records[i].winStreak > winStreaks[j])
+ break;
+ }
+ if (j == l)
+ {
+ winStreaks[l] = gSaveBlock2Ptr->battleTower.records[i].winStreak;
+ indices[l] = i;
+ l++;
+ }
+ }
+ i = Random() % l;
+ gSaveBlock2Ptr->battleTower.records[indices[i]] = *record;
+}
+
+u8 GetBattleTowerTrainerFrontSpriteId(void)
+{
+ if (gSaveBlock2Ptr->battleTower.battleTowerTrainerId == BATTLE_TOWER_EREADER_TRAINER_ID)
+ {
+ return gFacilityClassToPicIndex[gSaveBlock2Ptr->battleTower.ereaderTrainer.trainerClass];
+ }
+ else if (gSaveBlock2Ptr->battleTower.battleTowerTrainerId < BATTLE_TOWER_RECORD_MIXING_TRAINER_BASE_ID)
+ {
+ return gFacilityClassToPicIndex[gBattleTowerTrainers[gSaveBlock2Ptr->battleTower.battleTowerTrainerId].trainerClass];
+ }
+ else
+ {
+ return gFacilityClassToPicIndex[gSaveBlock2Ptr->battleTower.records[gSaveBlock2Ptr->battleTower.battleTowerTrainerId - BATTLE_TOWER_RECORD_MIXING_TRAINER_BASE_ID].trainerClass];
+ }
+}
+
+u8 GetBattleTowerTrainerClassNameId(void)
+{
+ if (gSaveBlock2Ptr->battleTower.battleTowerTrainerId == BATTLE_TOWER_EREADER_TRAINER_ID)
+ {
+ return gFacilityClassToTrainerClass[gSaveBlock2Ptr->battleTower.ereaderTrainer.trainerClass];
+ }
+ else if (gSaveBlock2Ptr->battleTower.battleTowerTrainerId >= BATTLE_TOWER_RECORD_MIXING_TRAINER_BASE_ID)
+ {
+ return gFacilityClassToTrainerClass[gSaveBlock2Ptr->battleTower.records[gSaveBlock2Ptr->battleTower.battleTowerTrainerId - BATTLE_TOWER_RECORD_MIXING_TRAINER_BASE_ID].trainerClass];
+ }
+ else
+ {
+ return gFacilityClassToTrainerClass[gBattleTowerTrainers[gSaveBlock2Ptr->battleTower.battleTowerTrainerId].trainerClass];
+ }
+}
+
+void GetBattleTowerTrainerName(u8 *dest)
+{
+ s32 i;
+ if (gSaveBlock2Ptr->battleTower.battleTowerTrainerId == BATTLE_TOWER_EREADER_TRAINER_ID)
+ {
+ for (i = 0; i < 7; i++)
+ dest[i] = gSaveBlock2Ptr->battleTower.ereaderTrainer.name[i];
+ }
+ else if (gSaveBlock2Ptr->battleTower.battleTowerTrainerId < BATTLE_TOWER_RECORD_MIXING_TRAINER_BASE_ID)
+ {
+ for (i = 0; i < 3; i++)
+ dest[i] = gBattleTowerTrainers[gSaveBlock2Ptr->battleTower.battleTowerTrainerId].name[i];
+ }
+ else
+ {
+ for (i = 0; i < 7; i++)
+ dest[i] = gSaveBlock2Ptr->battleTower.records[gSaveBlock2Ptr->battleTower.battleTowerTrainerId - BATTLE_TOWER_RECORD_MIXING_TRAINER_BASE_ID].name[i];
+ }
+ dest[i] = EOS;
+}
+
+static void FillBattleTowerTrainerParty(void)
+{
+ s32 partyIndex;
+ s32 i;
+ u16 chosenMonIndices[3];
+ u8 friendship;
+ u8 level;
+ u8 fixedIV;
+ u8 battleMonsOffset;
+ u8 monPoolSize;
+ u8 teamFlags;
+ const struct BattleTowerPokemonTemplate *battleTowerMons;
+
+ battleMonsOffset = 0;
+ monPoolSize = 60;
+ friendship = 255;
+
+ ZeroEnemyPartyMons();
+
+ // Different trainers have access to different sets of pokemon to use in battle.
+ // The pokemon later in gBattleTowerLevel100Mons or gBattleTowerLevel50Mons are
+ // stronger. Additionally, the later trainers' pokemon are granted higher IVs.
+ if (gSaveBlock2Ptr->battleTower.battleTowerTrainerId < 20)
+ {
+ fixedIV = 6;
+ }
+ else if (gSaveBlock2Ptr->battleTower.battleTowerTrainerId < 30)
+ {
+ fixedIV = 9;
+ battleMonsOffset = 30;
+ }
+ else if (gSaveBlock2Ptr->battleTower.battleTowerTrainerId < 40)
+ {
+ fixedIV = 12;
+ battleMonsOffset = 60;
+ }
+ else if (gSaveBlock2Ptr->battleTower.battleTowerTrainerId < 50)
+ {
+ fixedIV = 15;
+ battleMonsOffset = 90;
+ }
+ else if (gSaveBlock2Ptr->battleTower.battleTowerTrainerId < 60)
+ {
+ fixedIV = 18;
+ battleMonsOffset = 120;
+ }
+ else if (gSaveBlock2Ptr->battleTower.battleTowerTrainerId < 70)
+ {
+ fixedIV = 21;
+ battleMonsOffset = 150;
+ }
+ else if (gSaveBlock2Ptr->battleTower.battleTowerTrainerId < 80)
+ {
+ fixedIV = 31;
+ battleMonsOffset = 180;
+ }
+ else if (gSaveBlock2Ptr->battleTower.battleTowerTrainerId < BATTLE_TOWER_RECORD_MIXING_TRAINER_BASE_ID)
+ {
+ fixedIV = 31;
+ battleMonsOffset = 200;
+ monPoolSize = 100;
+ }
+ else if (gSaveBlock2Ptr->battleTower.battleTowerTrainerId == BATTLE_TOWER_EREADER_TRAINER_ID)
+ {
+ // Load E-Reader trainer's party.
+ do
+ {
+ for (partyIndex = 0; partyIndex < 3; partyIndex++)
+ CreateBattleTowerMon(&gEnemyParty[partyIndex], &gSaveBlock2Ptr->battleTower.ereaderTrainer.party[partyIndex]);
+ return;
+ } while (0);
+ }
+ else
+ {
+ // Load a battle tower record's party. (From record mixing)
+ for (partyIndex = 0; partyIndex < 3; partyIndex++)
+ {
+ CreateBattleTowerMon(
+ &gEnemyParty[partyIndex],
+ &gSaveBlock2Ptr->battleTower.records[gSaveBlock2Ptr->battleTower.battleTowerTrainerId - BATTLE_TOWER_RECORD_MIXING_TRAINER_BASE_ID].party[partyIndex]);
+ }
+ return;
+ }
+
+ // Use the appropriate list of pokemon and level depending on the
+ // current challenge type. (level 50 or level 100 challenge)
+ if (gSaveBlock2Ptr->battleTower.battleTowerLevelType != 0)
+ {
+ battleTowerMons = gBattleTowerLevel100Mons;
+ level = 100;
+ }
+ else
+ {
+ battleTowerMons = gBattleTowerLevel50Mons;
+ level = 50;
+ }
+
+ teamFlags = gBattleTowerTrainers[gSaveBlock2Ptr->battleTower.battleTowerTrainerId].teamFlags;
+
+ // Attempt to fill the trainer's party with random Pokemon until 3 have been
+ // successfully chosen. The trainer's party may not have duplicate pokemon species
+ // or duplicate held items. Each pokemon must have all of the trainer's team flags
+ // set, as well. If any of those conditions are not met, then the loop starts over
+ // and another pokemon is chosen at random.
+ partyIndex = 0;
+ while (partyIndex != 3)
+ {
+ // Pick a random pokemon index based on the number of pokemon available to choose from
+ // and the starting offset in the battle tower pokemon array.
+ s32 battleMonIndex = ((Random() & 0xFF) * monPoolSize) / 256 + battleMonsOffset;
+
+ // Ensure the chosen pokemon has compatible team flags with the trainer.
+ if (teamFlags == 0 || (battleTowerMons[battleMonIndex].teamFlags & teamFlags) == teamFlags)
+ {
+ // Ensure this pokemon species isn't a duplicate.
+ for (i = 0; i < partyIndex; i++)
+ {
+ if (GetMonData(&gEnemyParty[i], MON_DATA_SPECIES, NULL) == battleTowerMons[battleMonIndex].species)
+ break;
+ }
+
+ if (i != partyIndex)
+ continue;
+
+ // Ensure this pokemon's held item isn't a duplicate.
+ for (i = 0; i < partyIndex; i++)
+ {
+ if (GetMonData(&gEnemyParty[i], MON_DATA_HELD_ITEM, NULL) != ITEM_NONE
+ && GetMonData(&gEnemyParty[i], MON_DATA_HELD_ITEM, NULL) == sBattleTowerHeldItems[battleTowerMons[battleMonIndex].heldItem])
+ break;
+ }
+
+ if (i != partyIndex)
+ continue;
+
+ // Ensure this exact pokemon index isn't a duplicate. This check doesn't seem necessary
+ // because the species and held items were already checked directly above. Perhaps this
+ // is leftover code before the logic for duplicate species and held items was added.
+ //for (i = 0; i < partyIndex && chosenMonIndices[i] != battleMonIndex; i++);
+ for (i = 0; i < partyIndex; i++)
+ {
+ if (chosenMonIndices[i] == battleMonIndex)
+ break;
+ }
+
+ if (i != partyIndex)
+ continue;
+
+ chosenMonIndices[partyIndex] = battleMonIndex;
+
+ // Place the chosen pokemon into the trainer's party.
+ CreateMonWithEVSpread(
+ &gEnemyParty[partyIndex],
+ battleTowerMons[battleMonIndex].species,
+ level,
+ fixedIV,
+ battleTowerMons[battleMonIndex].evSpread);
+
+ // Give the chosen pokemon its specified moves.
+ for (i = 0; i < 4; i++)
+ {
+ SetMonMoveSlot(&gEnemyParty[partyIndex], battleTowerMons[battleMonIndex].moves[i], i);
+ if (battleTowerMons[battleMonIndex].moves[i] == MOVE_FRUSTRATION)
+ friendship = 0; // MOVE_FRUSTRATION is more powerful the lower the pokemon's friendship is.
+ }
+
+ SetMonData(&gEnemyParty[partyIndex], MON_DATA_FRIENDSHIP, &friendship);
+ SetMonData(&gEnemyParty[partyIndex], MON_DATA_HELD_ITEM, &sBattleTowerHeldItems[battleTowerMons[battleMonIndex].heldItem]);
+
+ // The pokemon was successfully added to the trainer's party, so it's safe to move on to
+ // the next party slot.
+ partyIndex++;
+ }
+ }
+}
+
+static u8 AppendBattleTowerBannedSpeciesName(u16 species, u8 count)
+{
+ if (GetSetPokedexFlag(SpeciesToNationalPokedexNum(species), FLAG_GET_CAUGHT))
+ {
+ if (count == 0)
+ StringAppend(gStringVar1, gUnknown_83FE859);
+ count++;
+ StringAppend(gStringVar1, gSpeciesNames[species]);
+ switch (count)
+ {
+ case 2:
+ StringAppend(gStringVar1, gUnknown_83FE85E);
+ break;
+ case 5:
+ case 8:
+ case 11:
+ StringAppend(gStringVar1, gUnknown_83FE85C);
+ break;
+ default:
+ StringAppend(gStringVar1, gUnknown_83FE859);
+ break;
+ }
+ }
+ return count;
+}
+
+static void CheckMonBattleTowerBanlist(u16 species, u16 heldItem, u16 hp, u8 battleTowerLevelType, u8 monLevel, u16 *validPartySpecies, u16 *validPartyHeldItems, u8 *numValid)
+{
+ s32 i;
+ u32 counter = 0;
+
+ if (species == SPECIES_EGG || species == SPECIES_NONE)
+ return;
+
+ while (1)
+ {
+ if (gBattleTowerBannedSpecies[counter] == 0xFFFF)
+ break;
+
+ if (gBattleTowerBannedSpecies[counter] == species)
+ break;
+
+ counter++;
+ }
+
+ if (gBattleTowerBannedSpecies[counter] != 0xFFFF)
+ return;
+
+ if (battleTowerLevelType == 0 && monLevel > 50)
+ return;
+
+ for (i = 0; i < *numValid && validPartySpecies[i] != species ; i++);
+ if (i != *numValid)
+ return;
+
+ if (heldItem != ITEM_NONE)
+ {
+ for (i = 0; i < *numValid && validPartyHeldItems[i] != heldItem ; i++);
+ if (i != *numValid)
+ return;
+ }
+
+ validPartySpecies[*numValid] = species;
+ validPartyHeldItems[*numValid] = heldItem;
+ *numValid = *numValid + 1;
+}
+
+void CheckPartyBattleTowerBanlist(void)
+{
+ s32 i;
+ u16 species2;
+ u16 heldItem;
+ u8 level;
+ u16 hp;
+ u32 numBanlistCaught;
+ u16 validPartySpecies[6];
+ u16 validPartyHeldItems[6];
+ u8 counter;
+
+ counter = 0;
+
+ for (i = 0; i < PARTY_SIZE; i++)
+ {
+ species2 = GetMonData(&gPlayerParty[i], MON_DATA_SPECIES2);
+ heldItem = GetMonData(&gPlayerParty[i], MON_DATA_HELD_ITEM);
+ level = GetMonData(&gPlayerParty[i], MON_DATA_LEVEL);
+ hp = GetMonData(&gPlayerParty[i], MON_DATA_HP);
+
+ CheckMonBattleTowerBanlist(species2, heldItem, hp, gSpecialVar_Result, level, validPartySpecies, validPartyHeldItems, &counter);
+ }
+
+ if (counter < 3)
+ {
+ gStringVar1[0] = EOS;
+ gSpecialVar_0x8004 = 1;
+ counter = 0;
+
+ for (i = 0; gBattleTowerBannedSpecies[i] != 0xFFFF; i++)
+ counter = AppendBattleTowerBannedSpeciesName(gBattleTowerBannedSpecies[i], counter);
+
+ i = StringLength(gStringVar1);
+ gStringVar1[i - 1] = EOS;
+ if (counter < 3)
+ StringAppend(gStringVar1, gUnknown_83FE860);
+ else
+ StringAppend(gStringVar1, gUnknown_83FE864);
+ }
+ else
+ {
+ gSpecialVar_0x8004 = 0;
+ gSaveBlock2Ptr->battleTower.battleTowerLevelType = gSpecialVar_Result;
+ }
+}
+
+static void PrintBattleTowerTrainerMessage(const u16 *greeting)
+{
+ s32 i;
+ if (EC_DoesEasyChatStringFitOnLine(greeting, 3, 2, 18))
+ {
+ ConvertEasyChatWordsToString(gStringVar4, greeting, 2, 3);
+ i = 0;
+ while (gStringVar4[i++] != CHAR_NEWLINE)
+ ;
+ while (gStringVar4[i] != CHAR_NEWLINE)
+ i++;
+ gStringVar4[i] = CHAR_PROMPT_SCROLL;
+ }
+ else
+ {
+ ConvertEasyChatWordsToString(gStringVar4, greeting, 3, 2);
+ }
+}
+
+void PrintBattleTowerTrainerGreeting(void)
+{
+ if (gSaveBlock2Ptr->battleTower.battleTowerTrainerId == BATTLE_TOWER_EREADER_TRAINER_ID)
+ PrintBattleTowerTrainerMessage(gSaveBlock2Ptr->battleTower.ereaderTrainer.greeting);
+ else if (gSaveBlock2Ptr->battleTower.battleTowerTrainerId < BATTLE_TOWER_RECORD_MIXING_TRAINER_BASE_ID)
+ PrintBattleTowerTrainerMessage(gBattleTowerTrainers[gSaveBlock2Ptr->battleTower.battleTowerTrainerId].greeting);
+ else
+ PrintBattleTowerTrainerMessage(gSaveBlock2Ptr->battleTower.records[gSaveBlock2Ptr->battleTower.battleTowerTrainerId - BATTLE_TOWER_RECORD_MIXING_TRAINER_BASE_ID].greeting);
+}
+
+static void CB2_FinishEReaderBattle(void)
+{
+ s32 i;
+ u16 heldItem;
+
+ switch (sSpecialVar_0x8004_Copy)
+ {
+ case 0:
+ break;
+ case 1:
+ for (i = 0; i < PARTY_SIZE; i++)
+ {
+ heldItem = GetMonData(&gSaveBlock1Ptr->playerParty[i], MON_DATA_HELD_ITEM);
+ SetMonData(&gPlayerParty[i], MON_DATA_HELD_ITEM, &heldItem);
+ }
+ break;
+ case 2:
+ PrintEReaderTrainerFarewellMessage();
+ break;
+ }
+
+ SetMainCallback2(CB2_ReturnToFieldContinueScriptPlayMapMusic);
+}
+
+static void Task_WaitBT(u8 taskId)
+{
+ if (BT_IsDone() == TRUE)
+ {
+ gMain.savedCallback = CB2_FinishEReaderBattle;
+ CleanupOverworldWindowsAndTilemaps();
+ SetMainCallback2(CB2_InitBattle);
+ DestroyTask(taskId);
+ }
+}
+
+
+void StartSpecialBattle(void)
+{
+ s32 i;
+ u16 heldItem;
+ u8 transition;
+
+ sSpecialVar_0x8004_Copy = gSpecialVar_0x8004;
+ switch (sSpecialVar_0x8004_Copy)
+ {
+ case 0: // battle tower battle
+ gBattleTypeFlags = (BATTLE_TYPE_BATTLE_TOWER | BATTLE_TYPE_TRAINER);
+ gTrainerBattleOpponent_A = 0;
+
+ FillBattleTowerTrainerParty();
+
+ CreateTask(Task_WaitBT, 1);
+ PlayMapChosenOrBattleBGM(0);
+ transition = BattleSetup_GetBattleTowerBattleTransition();
+ BT_StartOnField(transition);
+ break;
+ case 1: // secret base battle
+ for (i = 0; i < PARTY_SIZE; i++)
+ {
+ heldItem = GetMonData(&gPlayerParty[i], MON_DATA_HELD_ITEM);
+ SetMonData(&gSaveBlock1Ptr->playerParty[i], MON_DATA_HELD_ITEM, &heldItem);
+ }
+
+ CreateTask(Task_WaitBT, 1);
+ PlayMapChosenOrBattleBGM(0);
+ transition = BattleSetup_GetBattleTowerBattleTransition();
+ BT_StartOnField(transition);
+ break;
+ case 2: // e-reader trainer battle
+ ZeroEnemyPartyMons();
+
+ for (i = 0; i < 3; i++)
+ CreateBattleTowerMon(&gEnemyParty[i], &gSaveBlock2Ptr->battleTower.ereaderTrainer.party[i]);
+
+ gBattleTypeFlags = (BATTLE_TYPE_EREADER_TRAINER | BATTLE_TYPE_TRAINER);
+ gTrainerBattleOpponent_A = 0;
+
+ CreateTask(Task_WaitBT, 1);
+ PlayMapChosenOrBattleBGM(0);
+ transition = BattleSetup_GetBattleTowerBattleTransition();
+ BT_StartOnField(transition);
+ break;
+ }
+}
+
+void SetBattleTowerProperty(void)
+{
+ s32 i;
+ u8 battleTowerLevelType = gSaveBlock2Ptr->battleTower.battleTowerLevelType;
+
+ switch (gSpecialVar_0x8004)
+ {
+ case 0:
+ ewram160FB = gSaveBlock2Ptr->battleTower.var_4AE[battleTowerLevelType];
+ gSaveBlock2Ptr->battleTower.var_4AE[battleTowerLevelType] = gSpecialVar_0x8005;
+ break;
+ case 1:
+ gSaveBlock2Ptr->battleTower.battleTowerLevelType = gSpecialVar_0x8005;
+ break;
+ case 2:
+ gSaveBlock2Ptr->battleTower.curChallengeBattleNum[battleTowerLevelType] = gSpecialVar_0x8005;
+ break;
+ case 3:
+ gSaveBlock2Ptr->battleTower.curStreakChallengesNum[battleTowerLevelType] = gSpecialVar_0x8005;
+ break;
+ case 4:
+ gSaveBlock2Ptr->battleTower.battleTowerTrainerId = gSpecialVar_0x8005;
+ break;
+ case 5:
+ for (i = 0; i < 3; i++)
+ gSaveBlock2Ptr->battleTower.selectedPartyMons[i] = gSelectedOrderFromParty[i];
+ break;
+ case 6:
+ if (gSaveBlock2Ptr->battleTower.battleTowerTrainerId == BATTLE_TOWER_EREADER_TRAINER_ID)
+ ClearEReaderTrainer(&gSaveBlock2Ptr->battleTower.ereaderTrainer);
+ if (gSaveBlock2Ptr->battleTower.totalBattleTowerWins < 9999)
+ gSaveBlock2Ptr->battleTower.totalBattleTowerWins++;
+ gSaveBlock2Ptr->battleTower.curChallengeBattleNum[battleTowerLevelType]++;
+ SaveCurrentWinStreak();
+ gSpecialVar_Result = gSaveBlock2Ptr->battleTower.curChallengeBattleNum[battleTowerLevelType];
+ gStringVar1[0] = gSaveBlock2Ptr->battleTower.curChallengeBattleNum[battleTowerLevelType] + 0xA1;
+ gStringVar1[1] = 0xFF;
+ break;
+ case 7:
+ if (gSaveBlock2Ptr->battleTower.curStreakChallengesNum[battleTowerLevelType] < 1430)
+ gSaveBlock2Ptr->battleTower.curStreakChallengesNum[battleTowerLevelType]++;
+ SaveCurrentWinStreak();
+ gSpecialVar_Result = gSaveBlock2Ptr->battleTower.curStreakChallengesNum[battleTowerLevelType];
+ break;
+ case 8:
+ gSaveBlock2Ptr->battleTower.unk_554 = gSpecialVar_0x8005;
+ break;
+ case 9:
+ break;
+ case 10:
+ SetGameStat(GAME_STAT_BATTLE_TOWER_BEST_STREAK, gSaveBlock2Ptr->battleTower.bestBattleTowerWinStreak);
+ break;
+ case 11:
+ if (gSaveBlock2Ptr->battleTower.var_4AE[battleTowerLevelType] != 3)
+ ResetBattleTowerStreak(battleTowerLevelType);
+ break;
+ case 12:
+ gSaveBlock2Ptr->battleTower.var_4AE[battleTowerLevelType] = ewram160FB;
+ break;
+ case 13:
+ gSaveBlock2Ptr->battleTower.currentWinStreaks[battleTowerLevelType] = GetCurrentBattleTowerWinStreak(battleTowerLevelType);
+ break;
+ case 14:
+ gSaveBlock2Ptr->battleTower.lastStreakLevelType = gSaveBlock2Ptr->battleTower.battleTowerLevelType;
+ break;
+ }
+}
+
+void BattleTowerUtil(void)
+{
+ u8 battleTowerLevelType = gSaveBlock2Ptr->battleTower.battleTowerLevelType;
+
+ switch (gSpecialVar_0x8004)
+ {
+ case 0:
+ gSpecialVar_Result = gSaveBlock2Ptr->battleTower.var_4AE[battleTowerLevelType];
+ break;
+ case 1:
+ gSpecialVar_Result = gSaveBlock2Ptr->battleTower.battleTowerLevelType;
+ break;
+ case 2:
+ gSpecialVar_Result = gSaveBlock2Ptr->battleTower.curChallengeBattleNum[battleTowerLevelType];
+ break;
+ case 3:
+ gSpecialVar_Result = gSaveBlock2Ptr->battleTower.curStreakChallengesNum[battleTowerLevelType];
+ break;
+ case 4:
+ gSpecialVar_Result = gSaveBlock2Ptr->battleTower.battleTowerTrainerId;
+ break;
+ case 5:
+ case 6:
+ case 7:
+ break;
+ case 8:
+ gSpecialVar_Result = gSaveBlock2Ptr->battleTower.unk_554;
+ break;
+ case 9:
+ gSpecialVar_Result = GetCurrentBattleTowerWinStreak(battleTowerLevelType);
+ break;
+ case 10:
+ SetGameStat(GAME_STAT_BATTLE_TOWER_BEST_STREAK, gSaveBlock2Ptr->battleTower.bestBattleTowerWinStreak);
+ break;
+ case 11:
+ ResetBattleTowerStreak(battleTowerLevelType);
+ break;
+ case 12:
+ gSaveBlock2Ptr->battleTower.var_4AE[battleTowerLevelType] = ewram160FB;
+ break;
+ case 13:
+ gSaveBlock2Ptr->battleTower.currentWinStreaks[battleTowerLevelType] = GetCurrentBattleTowerWinStreak(battleTowerLevelType);
+ break;
+ case 14:
+ gSaveBlock2Ptr->battleTower.lastStreakLevelType = gSaveBlock2Ptr->battleTower.battleTowerLevelType;
+ break;
+ }
+}
+
+void SetBattleTowerParty(void)
+{
+ s32 i;
+
+ for (i = 0; i < 3; i++)
+ gSelectedOrderFromParty[i] = gSaveBlock2Ptr->battleTower.selectedPartyMons[i];
+
+ ReducePlayerPartyToThree();
+}
+
+static void SaveCurrentWinStreak(void)
+{
+ u8 levelType = gSaveBlock2Ptr->battleTower.battleTowerLevelType;
+ u16 streak = GetCurrentBattleTowerWinStreak(levelType);
+
+ if (gSaveBlock2Ptr->battleTower.recordWinStreaks[levelType] < streak)
+ gSaveBlock2Ptr->battleTower.recordWinStreaks[levelType] = streak;
+
+ if (gSaveBlock2Ptr->battleTower.recordWinStreaks[0] > gSaveBlock2Ptr->battleTower.recordWinStreaks[1])
+ {
+ streak = gSaveBlock2Ptr->battleTower.recordWinStreaks[0];
+ SetGameStat(GAME_STAT_BATTLE_TOWER_BEST_STREAK, streak);
+
+ if (streak > 9999)
+ gSaveBlock2Ptr->battleTower.bestBattleTowerWinStreak = 9999;
+ else
+ gSaveBlock2Ptr->battleTower.bestBattleTowerWinStreak = streak;
+ }
+ else
+ {
+ streak = gSaveBlock2Ptr->battleTower.recordWinStreaks[1];
+ SetGameStat(GAME_STAT_BATTLE_TOWER_BEST_STREAK, streak);
+
+ if (streak > 9999)
+ gSaveBlock2Ptr->battleTower.bestBattleTowerWinStreak = 9999;
+ else
+ gSaveBlock2Ptr->battleTower.bestBattleTowerWinStreak = streak;
+ }
+}
+
+static void SetPlayerBattleTowerRecord(void)
+{
+ s32 i;
+ u8 trainerClass;
+ struct BattleTowerRecord *playerRecord = &gSaveBlock2Ptr->battleTower.playerRecord;
+ u8 battleTowerLevelType = gSaveBlock2Ptr->battleTower.battleTowerLevelType;
+
+ if (gSaveBlock2Ptr->playerGender != MALE)
+ {
+ trainerClass = sFemaleTrainerClasses[(gSaveBlock2Ptr->playerTrainerId[0] + gSaveBlock2Ptr->playerTrainerId[1]
+ + gSaveBlock2Ptr->playerTrainerId[2] + gSaveBlock2Ptr->playerTrainerId[3]) % NELEMS(sFemaleTrainerClasses)];
+ }
+ else
+ {
+ trainerClass = sMaleTrainerClasses[(gSaveBlock2Ptr->playerTrainerId[0] + gSaveBlock2Ptr->playerTrainerId[1]
+ + gSaveBlock2Ptr->playerTrainerId[2] + gSaveBlock2Ptr->playerTrainerId[3]) % NELEMS(sMaleTrainerClasses)];
+ }
+
+ playerRecord->battleTowerLevelType = battleTowerLevelType;
+ playerRecord->trainerClass = trainerClass;
+
+ CopyTrainerId(playerRecord->trainerId, gSaveBlock2Ptr->playerTrainerId);
+ StringCopy7(playerRecord->name, gSaveBlock2Ptr->playerName);
+
+ playerRecord->winStreak = GetCurrentBattleTowerWinStreak(battleTowerLevelType);
+
+ for (i = 0; i < 6; i++)
+ playerRecord->greeting[i] = gSaveBlock1Ptr->easyChatBattleStart[i];
+
+ for (i = 0; i < 3; i++)
+ sub_803E23C(&gPlayerParty[gSaveBlock2Ptr->battleTower.selectedPartyMons[i] - 1], &playerRecord->party[i]);
+
+ SetBattleTowerRecordChecksum(&gSaveBlock2Ptr->battleTower.playerRecord);
+ SaveCurrentWinStreak();
+}
+
+void SaveBattleTowerProgress(void)
+{
+ u8 battleTowerLevelType = gSaveBlock2Ptr->battleTower.battleTowerLevelType;
+
+ if (gSpecialVar_0x8004 == 3 || gSpecialVar_0x8004 == 0)
+ {
+ if (gSaveBlock2Ptr->battleTower.curStreakChallengesNum[battleTowerLevelType] > 1
+ || gSaveBlock2Ptr->battleTower.curChallengeBattleNum[battleTowerLevelType] > 1)
+ SetPlayerBattleTowerRecord();
+ }
+
+ PopulateBravoTrainerBattleTowerLostData();
+
+ gSaveBlock2Ptr->battleTower.battleOutcome = gBattleOutcome;
+
+ if (gSpecialVar_0x8004 != 3)
+ gSaveBlock2Ptr->battleTower.var_4AE[battleTowerLevelType] = gSpecialVar_0x8004;
+
+ VarSet(VAR_0x4000, BTSPECIAL_TEST);
+ gSaveBlock2Ptr->battleTower.unk_554 = 1;
+ TrySavingData(SAVE_EREADER);
+}
+
+void BattleTower_SoftReset(void)
+{
+ DoSoftReset();
+}
+
+static void ValidateBattleTowerRecordChecksums(void)
+{
+ u32 i;
+ s32 recordIndex;
+ struct BattleTowerRecord *record;
+ u32 checksum;
+
+ record = &gSaveBlock2Ptr->battleTower.playerRecord;
+ checksum = 0;
+ for (i = 0; i < (sizeof(struct BattleTowerRecord) / sizeof(u32)) - 1; i++)
+ checksum += ((u32 *)record)[i];
+
+ if (gSaveBlock2Ptr->battleTower.playerRecord.checksum != checksum)
+ ClearBattleTowerRecord(&gSaveBlock2Ptr->battleTower.playerRecord);
+
+ for (recordIndex = 0; recordIndex < 5; recordIndex++)
+ {
+ record = &gSaveBlock2Ptr->battleTower.records[recordIndex];
+ checksum = 0;
+ for (i = 0; i < (sizeof(struct BattleTowerRecord) / sizeof(u32)) - 1; i++)
+ checksum += ((u32 *)record)[i];
+
+ if (gSaveBlock2Ptr->battleTower.records[recordIndex].checksum != checksum)
+ ClearBattleTowerRecord(&gSaveBlock2Ptr->battleTower.records[recordIndex]);
+ }
+}
+
+static void SetBattleTowerRecordChecksum(struct BattleTowerRecord *record)
+{
+ u32 i;
+
+ record->checksum = 0;
+ for (i = 0; i < (sizeof(struct BattleTowerRecord) / sizeof(u32)) - 1; i++)
+ record->checksum += ((u32 *)record)[i];
+}
+
+static void ClearBattleTowerRecord(struct BattleTowerRecord *record)
+{
+ u32 i;
+
+ for (i = 0; i < sizeof(struct BattleTowerRecord) / sizeof(u32); i++)
+ ((u32 *)record)[i] = 0;
+}
+
+static void PopulateBravoTrainerBattleTowerLostData(void)
+{
+ s32 i;
+
+ GetBattleTowerTrainerName(gSaveBlock2Ptr->battleTower.defeatedByTrainerName);
+ gSaveBlock2Ptr->battleTower.defeatedBySpecies = gBattleMons[1].species;
+ gSaveBlock2Ptr->battleTower.firstMonSpecies = gBattleMons[0].species;
+
+ for (i = 0; i < POKEMON_NAME_LENGTH; i++)
+ gSaveBlock2Ptr->battleTower.firstMonNickname[i] = gBattleMons[0].nickname[i];
+}
+
+static u16 GetCurrentBattleTowerWinStreak(u8 battleTowerLevelType)
+{
+ u16 winStreak = ((gSaveBlock2Ptr->battleTower.curStreakChallengesNum[battleTowerLevelType] - 1) * 7 - 1)
+ + gSaveBlock2Ptr->battleTower.curChallengeBattleNum[battleTowerLevelType];
+
+ if (winStreak > 9999)
+ return 9999;
+ else
+ return winStreak;
+}
+
+void DetermineBattleTowerPrize(void)
+{
+ u8 levelType = gSaveBlock2Ptr->battleTower.battleTowerLevelType;
+
+ if (gSaveBlock2Ptr->battleTower.curStreakChallengesNum[levelType] - 1 > 5)
+ gSaveBlock2Ptr->battleTower.prizeItem = sLongStreakPrizes[Random() % NELEMS(sLongStreakPrizes)];
+ else
+ gSaveBlock2Ptr->battleTower.prizeItem = sShortStreakPrizes[Random() % NELEMS(sShortStreakPrizes)];
+}
+
+void GiveBattleTowerPrize(void)
+{
+ u8 battleTowerLevelType = gSaveBlock2Ptr->battleTower.battleTowerLevelType;
+
+ if (AddBagItem(gSaveBlock2Ptr->battleTower.prizeItem, 1) == TRUE)
+ {
+ CopyItemName(gSaveBlock2Ptr->battleTower.prizeItem, gStringVar1);
+ gSpecialVar_Result = 1;
+ }
+ else
+ {
+ gSpecialVar_Result = 0;
+ gSaveBlock2Ptr->battleTower.var_4AE[battleTowerLevelType] = 6;
+ }
+}
+
+void AwardBattleTowerRibbons(void)
+{
+ s32 i;
+ u32 partyIndex;
+ struct Pokemon *pokemon;
+ u8 ribbonType;
+ u8 battleTowerLevelType = gSaveBlock2Ptr->battleTower.battleTowerLevelType;
+
+ if (battleTowerLevelType != 0)
+ ribbonType = MON_DATA_VICTORY_RIBBON;
+ else
+ ribbonType = MON_DATA_WINNING_RIBBON;
+
+ gSpecialVar_Result = 0;
+
+ if (GetCurrentBattleTowerWinStreak(battleTowerLevelType) > 55)
+ {
+ for (i = 0; i < 3; i++)
+ {
+ partyIndex = gSaveBlock2Ptr->battleTower.selectedPartyMons[i] - 1;
+ pokemon = &gPlayerParty[partyIndex];
+ if (!GetMonData(pokemon, ribbonType))
+ {
+ gSpecialVar_Result = 1;
+ SetMonData(pokemon, ribbonType, &gSpecialVar_Result);
+ }
+ }
+ }
+
+ if (gSpecialVar_Result != 0)
+ IncrementGameStat(GAME_STAT_RECEIVED_RIBBONS);
+}
+
+// This is a leftover debugging function that is used to populate the E-Reader
+// trainer with the player's current data.
+static void Debug_FillEReaderTrainerWithPlayerData(void)
+{
+ struct BattleTowerEReaderTrainer *ereaderTrainer;
+ s32 i;
+ s32 j;
+
+ ereaderTrainer = &gSaveBlock2Ptr->battleTower.ereaderTrainer;
+
+ if (gSaveBlock2Ptr->playerGender != MALE)
+ {
+ ereaderTrainer->trainerClass = sFemaleTrainerClasses[(gSaveBlock2Ptr->playerTrainerId[0] + gSaveBlock2Ptr->playerTrainerId[1]
+ + gSaveBlock2Ptr->playerTrainerId[2] + gSaveBlock2Ptr->playerTrainerId[3]) % NELEMS(sFemaleTrainerClasses)];
+ }
+ else
+ {
+ ereaderTrainer->trainerClass = sMaleTrainerClasses[(gSaveBlock2Ptr->playerTrainerId[0] + gSaveBlock2Ptr->playerTrainerId[1]
+ + gSaveBlock2Ptr->playerTrainerId[2] + gSaveBlock2Ptr->playerTrainerId[3]) % NELEMS(sMaleTrainerClasses)];
+ }
+
+ CopyTrainerId(ereaderTrainer->trainerId, gSaveBlock2Ptr->playerTrainerId);
+ StringCopy7(ereaderTrainer->name, gSaveBlock2Ptr->playerName);
+
+ ereaderTrainer->winStreak = 1;
+
+ j = 7;
+ for (i = 0; i < 6; i++)
+ {
+ ereaderTrainer->greeting[i] = gSaveBlock1Ptr->easyChatBattleStart[i];
+ ereaderTrainer->farewellPlayerLost[i] = j;
+ ereaderTrainer->farewellPlayerWon[i] = j + 6;
+ j++;
+ }
+
+ for (i = 0; i < 3; i++)
+ sub_803E23C(&gPlayerParty[i], &ereaderTrainer->party[i]);
+
+ SetEReaderTrainerChecksum(ereaderTrainer);
+}
+
+u8 GetEreaderTrainerFrontSpriteId(void)
+{
+ return gFacilityClassToPicIndex[gSaveBlock2Ptr->battleTower.ereaderTrainer.trainerClass];
+}
+
+u8 GetEreaderTrainerClassId(void)
+{
+ return gFacilityClassToTrainerClass[gSaveBlock2Ptr->battleTower.ereaderTrainer.trainerClass];
+}
+
+void CopyEReaderTrainerName5(u8 *trainerName)
+{
+ s32 i;
+
+ for (i = 0; i < 5; i++)
+ trainerName[i] = gSaveBlock2Ptr->battleTower.ereaderTrainer.name[i];
+
+ trainerName[i] = EOS;
+}
+
+// Checks if the saved E-Reader trainer is valid.
+void ValidateEReaderTrainer(void)
+{
+ u32 i;
+ u32 checksum;
+ struct BattleTowerEReaderTrainer *ereaderTrainer;
+
+ gSpecialVar_Result = 0;
+ ereaderTrainer = &gSaveBlock2Ptr->battleTower.ereaderTrainer;
+
+ checksum = 0;
+ for (i = 0; i < sizeof(struct BattleTowerEReaderTrainer) / sizeof(u32) - 1; i++)
+ checksum |= ((u32 *)ereaderTrainer)[i];
+
+ if (checksum == 0)
+ {
+ gSpecialVar_Result = 1;
+ return;
+ }
+
+ checksum = 0;
+ for (i = 0; i < sizeof(struct BattleTowerEReaderTrainer) / sizeof(u32) - 1; i++)
+ checksum += ((u32 *)ereaderTrainer)[i];
+
+ if (gSaveBlock2Ptr->battleTower.ereaderTrainer.checksum != checksum)
+ {
+ ClearEReaderTrainer(&gSaveBlock2Ptr->battleTower.ereaderTrainer);
+ gSpecialVar_Result = 1;
+ }
+}
+
+static void SetEReaderTrainerChecksum(struct BattleTowerEReaderTrainer *ereaderTrainer)
+{
+ s32 i;
+
+ ereaderTrainer->checksum = 0;
+ for (i = 0; i < sizeof(struct BattleTowerEReaderTrainer) / sizeof(u32) - 1; i++)
+ ereaderTrainer->checksum += ((u32 *)ereaderTrainer)[i];
+}
+
+void ClearEReaderTrainer(struct BattleTowerEReaderTrainer *ereaderTrainer)
+{
+ u32 i;
+
+ for (i = 0; i < sizeof(struct BattleTowerEReaderTrainer) / sizeof(u32); i++)
+ ((u32 *)ereaderTrainer)[i] = 0;
+}
+
+void PrintEReaderTrainerGreeting(void)
+{
+ PrintBattleTowerTrainerMessage(gSaveBlock2Ptr->battleTower.ereaderTrainer.greeting);
+}
+
+static void PrintEReaderTrainerFarewellMessage(void)
+{
+ if (gBattleOutcome == B_OUTCOME_DREW)
+ gStringVar4[0] = EOS;
+ else if (gBattleOutcome == B_OUTCOME_WON)
+ PrintBattleTowerTrainerMessage(gSaveBlock2Ptr->battleTower.ereaderTrainer.farewellPlayerWon);
+ else
+ PrintBattleTowerTrainerMessage(gSaveBlock2Ptr->battleTower.ereaderTrainer.farewellPlayerLost);
+}
+
+void Dummy_TryEnableBravoTrainerBattleTower(void)
+{
+ s32 i;
+
+ for (i = 0; i < 2; i++)
+ {
+ if (gSaveBlock2Ptr->battleTower.var_4AE[i] == 1)
+ TakeBravoTrainerBattleTowerOffTheAir();
+ }
+}
diff --git a/src/field_door.c b/src/field_door.c
new file mode 100644
index 000000000..cbf7a79ea
--- /dev/null
+++ b/src/field_door.c
@@ -0,0 +1,537 @@
+#include "global.h"
+#include "field_camera.h"
+#include "task.h"
+#include "fieldmap.h"
+#include "metatile_behavior.h"
+#include "constants/songs.h"
+
+struct DoorAnimFrame
+{
+ u8 duration;
+ u16 tile;
+};
+
+struct DoorGraphics
+{
+ u16 metatileId;
+ s8 sliding;
+ u8 size;
+ const u8 * tiles;
+ const u8 * palettes;
+};
+
+static void DrawDoorDefaultImage(const struct DoorGraphics * gfx, int x, int y);
+static void LoadDoorFrameTiles(const u8 *a0);
+static void SetDoorFramePalettes(const struct DoorGraphics * gfx, int x, int y, const u8 *a3);
+static void BufferDoorFrameTilesWithPalettes(u16 *a0, u16 a1, const u8 *a2);
+static bool32 PlayDoorAnimationFrame(const struct DoorGraphics * gfx, const struct DoorAnimFrame * frames, s16 *data);
+static const struct DoorAnimFrame * SeekToEndOfDoorAnim(const struct DoorAnimFrame * frames);
+static s8 GetDoorOpenType(const struct DoorGraphics * gfx, int x, int y);
+
+static const u8 gUnknown_8353088[] = INCBIN_U8("graphics/door_anims/frame_8353088_1.4bpp", "graphics/door_anims/frame_8353088_2.4bpp", "graphics/door_anims/frame_8353088_3.4bpp");
+static const u8 gUnknown_8353208[32] = {};
+static const u8 gUnknown_8353228[] = INCBIN_U8("graphics/door_anims/frame_8353228_1.4bpp", "graphics/door_anims/frame_8353228_2.4bpp", "graphics/door_anims/frame_8353228_3.4bpp");
+static const u8 gUnknown_83533A8[32] = {};
+static const u8 gUnknown_83533C8[] = INCBIN_U8("graphics/door_anims/frame_83533C8_1.4bpp", "graphics/door_anims/frame_83533C8_2.4bpp", "graphics/door_anims/frame_83533C8_3.4bpp");
+static const u8 gUnknown_8353548[32] = {};
+static const u8 gUnknown_8353568[] = INCBIN_U8("graphics/door_anims/frame_8353568_1.4bpp", "graphics/door_anims/frame_8353568_2.4bpp", "graphics/door_anims/frame_8353568_3.4bpp");
+static const u8 gUnknown_83536E8[32] = {};
+static const u8 gUnknown_8353708[] = INCBIN_U8("graphics/door_anims/frame_8353708_1.4bpp", "graphics/door_anims/frame_8353708_2.4bpp", "graphics/door_anims/frame_8353708_3.4bpp");
+static const u8 gUnknown_8353888[32] = {};
+static const u8 gUnknown_83538A8[] = INCBIN_U8("graphics/door_anims/frame_83538A8_1.4bpp", "graphics/door_anims/frame_83538A8_2.4bpp", "graphics/door_anims/frame_83538A8_3.4bpp");
+static const u8 gUnknown_8353A28[32] = {};
+static const u8 gUnknown_8353A48[] = INCBIN_U8("graphics/door_anims/frame_8353A48_1.4bpp", "graphics/door_anims/frame_8353A48_2.4bpp", "graphics/door_anims/frame_8353A48_3.4bpp");
+static const u8 gUnknown_8353BC8[32] = {};
+static const u8 gUnknown_8353BE8[] = INCBIN_U8("graphics/door_anims/frame_8353BE8_1.4bpp", "graphics/door_anims/frame_8353BE8_2.4bpp", "graphics/door_anims/frame_8353BE8_3.4bpp");
+static const u8 gUnknown_8353D68[32] = {};
+static const u8 gUnknown_8353D88[] = INCBIN_U8("graphics/door_anims/frame_8353D88_1.4bpp", "graphics/door_anims/frame_8353D88_2.4bpp", "graphics/door_anims/frame_8353D88_3.4bpp");
+static const u8 gUnknown_8353F08[32] = {};
+static const u8 gUnknown_8353F28[] = INCBIN_U8("graphics/door_anims/frame_8353F28_1.4bpp", "graphics/door_anims/frame_8353F28_2.4bpp", "graphics/door_anims/frame_8353F28_3.4bpp");
+static const u8 gUnknown_83540A8[32] = {};
+static const u8 gUnknown_83540C8[] = INCBIN_U8("graphics/door_anims/frame_83540C8_1.4bpp", "graphics/door_anims/frame_83540C8_2.4bpp", "graphics/door_anims/frame_83540C8_3.4bpp");
+static const u8 gUnknown_8354248[32] = {};
+static const u8 gUnknown_8354268[] = INCBIN_U8("graphics/door_anims/frame_8354268_1.4bpp", "graphics/door_anims/frame_8354268_2.4bpp", "graphics/door_anims/frame_8354268_3.4bpp");
+static const u8 gUnknown_83543E8[32] = {};
+static const u8 gUnknown_8354408[] = INCBIN_U8("graphics/door_anims/frame_8354408_1.4bpp", "graphics/door_anims/frame_8354408_2.4bpp", "graphics/door_anims/frame_8354408_3.4bpp");
+static const u8 gUnknown_8354588[32] = {};
+static const u8 gUnknown_83545A8[] = INCBIN_U8("graphics/door_anims/frame_83545A8_1.4bpp", "graphics/door_anims/frame_83545A8_2.4bpp", "graphics/door_anims/frame_83545A8_3.4bpp");
+static const u8 gUnknown_8354728[32] = {};
+static const u8 gUnknown_8354748[] = INCBIN_U8("graphics/door_anims/frame_8354748_1.4bpp", "graphics/door_anims/frame_8354748_2.4bpp", "graphics/door_anims/frame_8354748_3.4bpp");
+static const u8 gUnknown_83548C8[32] = {};
+static const u8 gUnknown_83548E8[] = INCBIN_U8("graphics/door_anims/frame_83548E8_1.4bpp", "graphics/door_anims/frame_83548E8_2.4bpp", "graphics/door_anims/frame_83548E8_3.4bpp");
+static const u8 gUnknown_8354A68[32] = {};
+static const u8 gUnknown_8354A88[] = INCBIN_U8("graphics/door_anims/frame_8354A88_1.4bpp", "graphics/door_anims/frame_8354A88_2.4bpp", "graphics/door_anims/frame_8354A88_3.4bpp");
+static const u8 gUnknown_8354C08[32] = {};
+static const u8 gUnknown_8354C28[] = INCBIN_U8("graphics/door_anims/frame_8354C28_1.4bpp", "graphics/door_anims/frame_8354C28_2.4bpp", "graphics/door_anims/frame_8354C28_3.4bpp");
+static const u8 gUnknown_8354F28[32] = {};
+static const u8 gUnknown_8354F48[] = INCBIN_U8("graphics/door_anims/frame_8354F48_1.4bpp", "graphics/door_anims/frame_8354F48_2.4bpp", "graphics/door_anims/frame_8354F48_3.4bpp");
+static const u8 gUnknown_8355248[32] = {};
+static const u8 gUnknown_8355268[] = INCBIN_U8("graphics/door_anims/frame_8355268_1.4bpp", "graphics/door_anims/frame_8355268_2.4bpp", "graphics/door_anims/frame_8355268_3.4bpp");
+static const u8 gUnknown_8355568[32] = {};
+static const u8 gUnknown_8355588[] = INCBIN_U8("graphics/door_anims/frame_8355588_1.4bpp", "graphics/door_anims/frame_8355588_2.4bpp", "graphics/door_anims/frame_8355588_3.4bpp");
+static const u8 gUnknown_8355888[32] = {};
+static const u8 gUnknown_83558A8[256] = {};
+static const u8 gUnknown_83559A8[256] = {};
+static const u8 gUnknown_8355AA8[256] = {};
+static const u8 gUnknown_8355BA8[32] = {};
+static const u8 gUnknown_8355BC8[256] = {};
+static const u8 gUnknown_8355CC8[256] = {};
+static const u8 gUnknown_8355DC8[256] = {};
+static const u8 gUnknown_8355EC8[32] = {};
+static const u8 gUnknown_8355EE8[256] = {};
+static const u8 gUnknown_8355FE8[256] = {};
+static const u8 gUnknown_83560E8[256] = {};
+static const u8 gUnknown_83561E8[32] = {};
+static const u8 gUnknown_8356208[256] = {};
+static const u8 gUnknown_8356308[256] = {};
+static const u8 gUnknown_8356408[256] = {};
+static const u8 gUnknown_8356508[32] = {};
+static const u8 gUnknown_8356528[256] = {};
+static const u8 gUnknown_8356628[256] = {};
+static const u8 gUnknown_8356728[256] = {};
+static const u8 gUnknown_8356828[32] = {};
+static const u8 gUnknown_8356848[256] = {};
+static const u8 gUnknown_8356948[256] = {};
+static const u8 gUnknown_8356A48[256] = {};
+static const u8 gUnknown_8356B48[32] = {};
+static const u8 gUnknown_8356B68[256] = {};
+static const u8 gUnknown_8356C68[256] = {};
+static const u8 gUnknown_8356D68[256] = {};
+static const u8 gUnknown_8356E68[32] = {};
+static const u8 gUnknown_8356E88[128] = {};
+static const u8 gUnknown_8356F08[128] = {};
+static const u8 gUnknown_8356F88[128] = {};
+static const u8 gUnknown_8357008[32] = {};
+static const u8 gUnknown_8357028[128] = {};
+static const u8 gUnknown_83570A8[128] = {};
+static const u8 gUnknown_8357128[128] = {};
+static const u8 gUnknown_83571A8[32] = {};
+static const u8 gUnknown_83571C8[128] = {};
+static const u8 gUnknown_8357248[128] = {};
+static const u8 gUnknown_83572C8[128] = {};
+static const u8 gUnknown_8357348[32] = {};
+static const u8 gUnknown_8357368[128] = {};
+static const u8 gUnknown_83573E8[128] = {};
+static const u8 gUnknown_8357468[128] = {};
+static const u8 gUnknown_83574E8[32] = {};
+static const u8 gUnknown_8357508[128] = {};
+static const u8 gUnknown_8357588[128] = {};
+static const u8 gUnknown_8357608[128] = {};
+static const u8 gUnknown_8357688[32] = {};
+static const u8 gUnknown_83576A8[128] = {};
+static const u8 gUnknown_8357728[128] = {};
+static const u8 gUnknown_83577A8[128] = {};
+static const u8 gUnknown_8357828[32] = {};
+static const u8 gUnknown_8357848[128] = {};
+static const u8 gUnknown_83578C8[128] = {};
+static const u8 gUnknown_8357948[128] = {};
+static const u8 gUnknown_83579C8[32] = {};
+static const u8 gUnknown_83579E8[128] = {};
+static const u8 gUnknown_8357A68[128] = {};
+static const u8 gUnknown_8357AE8[128] = {};
+static const u8 gUnknown_8357B68[32] = {};
+static const u8 gUnknown_8357B88[128] = {};
+static const u8 gUnknown_8357C08[128] = {};
+static const u8 gUnknown_8357C88[128] = {};
+static const u8 gUnknown_8357D08[32] = {};
+static const u8 gUnknown_8357D28[128] = {};
+static const u8 gUnknown_8357DA8[128] = {};
+static const u8 gUnknown_8357E28[128] = {};
+static const u8 gUnknown_8357EA8[32] = {};
+static const u8 gUnknown_8357EC8[128] = {};
+static const u8 gUnknown_8357F48[128] = {};
+static const u8 gUnknown_8357FC8[128] = {};
+static const u8 gUnknown_8358048[32] = {};
+static const u8 gUnknown_8358068[128] = {};
+static const u8 gUnknown_83580E8[128] = {};
+static const u8 gUnknown_8358168[128] = {};
+static const u8 gUnknown_83581E8[32] = {};
+static const u8 gUnknown_8358208[128] = {};
+static const u8 gUnknown_8358288[128] = {};
+static const u8 gUnknown_8358308[128] = {};
+static const u8 gUnknown_8358388[32] = {};
+static const u8 gUnknown_83583A8[128] = {};
+static const u8 gUnknown_8358428[128] = {};
+static const u8 gUnknown_83584A8[128] = {};
+static const u8 gUnknown_8358528[32] = {};
+static const u8 gUnknown_8358548[128] = {};
+static const u8 gUnknown_83585C8[128] = {};
+static const u8 gUnknown_8358648[128] = {};
+static const u8 gUnknown_83586C8[32] = {};
+static const u8 gUnknown_83586E8[128] = {};
+static const u8 gUnknown_8358768[128] = {};
+static const u8 gUnknown_83587E8[128] = {};
+static const u8 gUnknown_8358868[32] = {};
+static const u8 gUnknown_8358888[128] = {};
+static const u8 gUnknown_8358908[128] = {};
+static const u8 gUnknown_8358988[128] = {};
+static const u8 gUnknown_8358A08[32] = {};
+static const u8 gUnknown_8358A28[128] = {};
+static const u8 gUnknown_8358AA8[128] = {};
+static const u8 gUnknown_8358B28[128] = {};
+static const u8 gUnknown_8358BA8[32] = {};
+static const u8 gUnknown_8358BC8[128] = {};
+static const u8 gUnknown_8358C48[128] = {};
+static const u8 gUnknown_8358CC8[128] = {};
+static const u8 gUnknown_8358D48[32] = {};
+static const u8 gUnknown_8358D68[128] = {};
+static const u8 gUnknown_8358DE8[128] = {};
+static const u8 gUnknown_8358E68[128] = {};
+static const u8 gUnknown_8358EE8[32] = {};
+static const u8 gUnknown_8358F08[128] = {};
+static const u8 gUnknown_8358F88[128] = {};
+static const u8 gUnknown_8359008[128] = {};
+static const u8 gUnknown_8359088[32] = {};
+static const u8 gUnknown_83590A8[128] = {};
+static const u8 gUnknown_8359128[128] = {};
+static const u8 gUnknown_83591A8[128] = {};
+static const u8 gUnknown_8359228[32] = {};
+static const u8 gUnknown_8359248[128] = {};
+static const u8 gUnknown_83592C8[128] = {};
+static const u8 gUnknown_8359348[128] = {};
+static const u8 gUnknown_83593C8[32] = {};
+static const u8 gUnknown_83593E8[128] = {};
+static const u8 gUnknown_8359468[128] = {};
+static const u8 gUnknown_83594E8[128] = {};
+static const u8 gUnknown_8359568[32] = {};
+static const u8 gUnknown_8359588[] = INCBIN_U8("graphics/door_anims/frame_8359588_1.4bpp", "graphics/door_anims/frame_8359588_2.4bpp");
+static const u8 gUnknown_8359688[256] = {};
+static const u8 gUnknown_8359788[] = INCBIN_U8("graphics/door_anims/frame_8359788_1.4bpp", "graphics/door_anims/frame_8359788_2.4bpp", "graphics/door_anims/frame_8359788_3.4bpp", "graphics/door_anims/frame_8359788_4.4bpp");
+static const u8 gUnknown_8359888[256] = {};
+static const u8 gUnknown_8359988[] = INCBIN_U8("graphics/door_anims/frame_8359988_1.4bpp", "graphics/door_anims/frame_8359988_2.4bpp", "graphics/door_anims/frame_8359988_3.4bpp", "graphics/door_anims/frame_8359988_4.4bpp");
+static const u8 gUnknown_8359A88[256] = {};
+static const u8 gUnknown_8359B88[] = INCBIN_U8("graphics/door_anims/frame_8359B88_1.4bpp", "graphics/door_anims/frame_8359B88_2.4bpp", "graphics/door_anims/frame_8359B88_3.4bpp", "graphics/door_anims/frame_8359B88_4.4bpp");
+static const u8 gUnknown_8359C88[32] = {};
+static const u8 gUnknown_8359CA8[] = INCBIN_U8("graphics/door_anims/frame_8359CA8_1.4bpp", "graphics/door_anims/frame_8359CA8_2.4bpp", "graphics/door_anims/frame_8359CA8_3.4bpp");
+static const u8 gUnknown_8359FA8[32] = {};
+static const u8 gUnknown_8359FC8[] = INCBIN_U8("graphics/door_anims/frame_8359FC8_1.4bpp", "graphics/door_anims/frame_8359FC8_2.4bpp", "graphics/door_anims/frame_8359FC8_3.4bpp");
+static const u8 gUnknown_835A148[32] = {};
+static const u8 gUnknown_835A168[] = INCBIN_U8("graphics/door_anims/frame_835A168_1.4bpp", "graphics/door_anims/frame_835A168_2.4bpp", "graphics/door_anims/frame_835A168_3.4bpp");
+static const u8 gUnknown_835A2E8[32] = {};
+static const u8 gUnknown_835A308[] = INCBIN_U8("graphics/door_anims/frame_835A308_1.4bpp", "graphics/door_anims/frame_835A308_2.4bpp", "graphics/door_anims/frame_835A308_3.4bpp");
+static const u8 gUnknown_835A488[32] = {};
+static const u8 gUnknown_835A4A8[] = INCBIN_U8("graphics/door_anims/frame_835A4A8_1.4bpp", "graphics/door_anims/frame_835A4A8_2.4bpp", "graphics/door_anims/frame_835A4A8_3.4bpp");
+static const u8 gUnknown_835A628[32] = {};
+static const u8 gUnknown_835A648[] = INCBIN_U8("graphics/door_anims/frame_835A648_1.4bpp", "graphics/door_anims/frame_835A648_2.4bpp", "graphics/door_anims/frame_835A648_3.4bpp");
+static const u8 gUnknown_835A7C8[32] = {};
+static const u8 gUnknown_835A7E8[] = INCBIN_U8("graphics/door_anims/frame_835A7E8_1.4bpp", "graphics/door_anims/frame_835A7E8_2.4bpp", "graphics/door_anims/frame_835A7E8_3.4bpp");
+static const u8 gUnknown_835A968[32] = {};
+static const u8 gUnknown_835A988[] = INCBIN_U8("graphics/door_anims/frame_835A988_1.4bpp", "graphics/door_anims/frame_835A988_2.4bpp", "graphics/door_anims/frame_835A988_3.4bpp");
+static const u8 gUnknown_835AB08[32] = {};
+static const u8 gUnknown_835AB28[] = INCBIN_U8("graphics/door_anims/frame_835AB28_1.4bpp", "graphics/door_anims/frame_835AB28_2.4bpp", "graphics/door_anims/frame_835AB28_3.4bpp");
+static const u8 gUnknown_835AE28[32] = {};
+static const u8 gUnknown_835AE48[] = INCBIN_U8("graphics/door_anims/frame_835AE48_1.4bpp", "graphics/door_anims/frame_835AE48_2.4bpp", "graphics/door_anims/frame_835AE48_3.4bpp");
+static const u8 gUnknown_835B148[32] = {};
+static const u8 gUnknown_835B168[] = INCBIN_U8("graphics/door_anims/frame_835B168_1.4bpp", "graphics/door_anims/frame_835B168_2.4bpp", "graphics/door_anims/frame_835B168_3.4bpp");
+static const u8 gUnknown_835B468[32] = {};
+
+static const struct DoorAnimFrame sDoorAnimFrames_OpenSmall[] = {
+ {4, 0xFFFF},
+ {4, 0x0000},
+ {4, 0x0080},
+ {4, 0x0100},
+ {}
+};
+
+static const struct DoorAnimFrame sDoorAnimFrames_OpenLarge[] = {
+ {4, 0xFFFF},
+ {4, 0x0000},
+ {4, 0x0100},
+ {4, 0x0200},
+ {}
+};
+
+static const struct DoorAnimFrame sDoorAnimFrames_CloseSmall[] = {
+ {4, 0x0100},
+ {4, 0x0080},
+ {4, 0x0000},
+ {4, 0xFFFF},
+ {}
+};
+
+static const struct DoorAnimFrame sDoorAnimFrames_CloseLarge[] = {
+ {4, 0x0200},
+ {4, 0x0100},
+ {4, 0x0000},
+ {4, 0xFFFF},
+ {}
+};
+
+static const u8 gUnknown_835B4D8[] = {0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2};
+static const u8 gUnknown_835B4E0[] = {0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3};
+static const u8 gUnknown_835B4E8[] = {0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3};
+static const u8 gUnknown_835B4F0[] = {0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8};
+static const u8 gUnknown_835B4F8[] = {0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa};
+static const u8 gUnknown_835B500[] = {0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8};
+static const u8 gUnknown_835B508[] = {0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8};
+static const u8 gUnknown_835B510[] = {0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8};
+static const u8 gUnknown_835B518[] = {0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3};
+static const u8 gUnknown_835B520[] = {0xc, 0xc, 0xc, 0xc, 0xc, 0xc, 0xc, 0xc};
+static const u8 gUnknown_835B528[] = {0x9, 0x9, 0x9, 0x9, 0x9, 0x9, 0x9, 0x9};
+static const u8 gUnknown_835B530[] = {0x9, 0x9, 0x9, 0x9, 0x9, 0x9, 0x9, 0x9};
+static const u8 gUnknown_835B538[] = {0x9, 0x9, 0x9, 0x9, 0x9, 0x9, 0x9, 0x9};
+static const u8 gUnknown_835B540[] = {0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3};
+static const u8 gUnknown_835B548[] = {0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8};
+static const u8 gUnknown_835B550[] = {0x9, 0x9, 0x9, 0x9, 0x9, 0x9, 0x9, 0x9};
+static const u8 gUnknown_835B558[] = {0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3};
+static const u8 gUnknown_835B560[] = {0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8};
+static const u8 gUnknown_835B568[] = {0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8};
+static const u8 gUnknown_835B570[] = {0xc, 0xc, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2};
+static const u8 gUnknown_835B578[] = {0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7};
+static const u8 gUnknown_835B580[] = {0x8, 0x8, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2};
+static const u8 gUnknown_835B588[] = {0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5};
+static const u8 gUnknown_835B590[] = {0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3};
+static const u8 gUnknown_835B598[] = {0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3};
+static const u8 gUnknown_835B5A0[] = {0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5};
+static const u8 gUnknown_835B5A8[] = {0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3};
+static const u8 gUnknown_835B5B0[] = {0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa};
+static const u8 gUnknown_835B5B8[] = {0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5, 0x5};
+static const u8 gUnknown_835B5C0[] = {0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8};
+static const u8 gUnknown_835B5C8[] = {0x8, 0x8, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2};
+static const u8 gUnknown_835B5D0[] = {0xb, 0xb, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2};
+
+static const struct DoorGraphics sDoorGraphics[] = {
+ {0x03d, 0, 0, gUnknown_8353088, gUnknown_835B4D8},
+ {0x062, 1, 0, gUnknown_8353228, gUnknown_835B4E0},
+ {0x15b, 1, 0, gUnknown_83533C8, gUnknown_835B4E8},
+ {0x2a3, 0, 0, gUnknown_8353568, gUnknown_835B4F0},
+ {0x2ac, 0, 0, gUnknown_8353708, gUnknown_835B4F8},
+ {0x299, 0, 0, gUnknown_83538A8, gUnknown_835B500},
+ {0x2ce, 0, 0, gUnknown_8353A48, gUnknown_835B508},
+ {0x284, 0, 0, gUnknown_8353BE8, gUnknown_835B510},
+ {0x2bc, 1, 0, gUnknown_8353D88, gUnknown_835B518},
+ {0x298, 0, 0, gUnknown_8353F28, gUnknown_835B520},
+ {0x2a2, 0, 0, gUnknown_83540C8, gUnknown_835B528},
+ {0x29e, 0, 0, gUnknown_8354268, gUnknown_835B530},
+ {0x2e1, 0, 0, gUnknown_8354408, gUnknown_835B538},
+ {0x294, 1, 0, gUnknown_83545A8, gUnknown_835B540},
+ {0x2bf, 0, 0, gUnknown_8354748, gUnknown_835B548},
+ {0x2d2, 1, 0, gUnknown_83548E8, gUnknown_835B550},
+ {0x2ad, 0, 0, gUnknown_8354A88, gUnknown_835B558},
+ {0x297, 0, 0, gUnknown_8359FC8, gUnknown_835B588},
+ {0x29b, 1, 0, gUnknown_835A168, gUnknown_835B590},
+ {0x2eb, 0, 0, gUnknown_835A308, gUnknown_835B598},
+ {0x29a, 0, 0, gUnknown_835A4A8, gUnknown_835B5A0},
+ {0x2b9, 0, 0, gUnknown_835A648, gUnknown_835B5A8},
+ {0x2af, 0, 0, gUnknown_835A7E8, gUnknown_835B5B0},
+ {0x30c, 0, 0, gUnknown_835A988, gUnknown_835B5B8},
+ {0x28d, 1, 1, gUnknown_8354C28, gUnknown_835B560},
+ {0x2de, 1, 1, gUnknown_8354F48, gUnknown_835B568},
+ {0x2ab, 1, 1, gUnknown_8355268, gUnknown_835B570},
+ {0x281, 0, 1, gUnknown_8355588, gUnknown_835B578},
+ {0x2e2, 1, 1, gUnknown_8359CA8, gUnknown_835B580},
+ {0x296, 1, 1, gUnknown_835AB28, gUnknown_835B5C0},
+ {0x2c3, 1, 1, gUnknown_835AE48, gUnknown_835B5C8},
+ {0x356, 1, 1, gUnknown_835B168, gUnknown_835B5D0},
+ {}
+};
+
+static void UpdateDrawDoorFrame(const struct DoorGraphics * gfx, const struct DoorAnimFrame * frames, int x, int y)
+{
+ if (frames->tile == 0xFFFF)
+ {
+ DrawDoorDefaultImage(gfx, x, y);
+ }
+ else
+ {
+ LoadDoorFrameTiles(&gfx->tiles[frames->tile]);
+ SetDoorFramePalettes(gfx, x, y, gfx->palettes);
+ }
+}
+
+static void DrawDoorDefaultImage(const struct DoorGraphics * gfx, int x, int y)
+{
+ if (gfx->size == 0)
+ {
+ CurrentMapDrawMetatileAt(x, y);
+ }
+ else
+ {
+ CurrentMapDrawMetatileAt(x, y);
+ CurrentMapDrawMetatileAt(x, y - 1);
+ }
+}
+
+static void LoadDoorFrameTiles(const u8 *a0)
+{
+ CpuFastCopy(a0, (void *)(BG_VRAM + 0x7F00), 0x100);
+}
+
+static void SetDoorFramePalettes(const struct DoorGraphics * gfx, int x, int y, const u8 *a3)
+{
+ u16 sp00[8];
+ if (gfx->size == 0)
+ {
+ BufferDoorFrameTilesWithPalettes(sp00, 0x3F8, a3);
+ }
+ else
+ {
+ BufferDoorFrameTilesWithPalettes(sp00, 0x3F8, a3);
+ DrawDoorMetatileAt(x, y - 1, sp00);
+ BufferDoorFrameTilesWithPalettes(sp00, 0x3FC, a3 + 4);
+ }
+ DrawDoorMetatileAt(x, y, sp00);
+}
+
+static void BufferDoorFrameTilesWithPalettes(u16 *a0, u16 a1, const u8 *a2)
+{
+ int i;
+ u16 tile;
+ for (i = 0; i < 4; i++)
+ {
+ tile = *(a2++) << 12;
+ a0[i] = tile | (a1 + i);
+ }
+ for (; i < 8; i++)
+ {
+ tile = *(a2++) << 12;
+ a0[i] = tile;
+ }
+}
+
+static void Task_AnimateDoor(u8 taskId)
+{
+ s16 *data = (void *)gTasks[taskId].data;
+ const struct DoorAnimFrame * frames = (const void *)(((u16)data[0] << 16) | (u16)data[1]);
+ const struct DoorGraphics * gfx = (const void *)(((u16)data[2] << 16) | (u16)data[3]);
+ if (!PlayDoorAnimationFrame(gfx, frames, data))
+ DestroyTask(taskId);
+}
+
+static bool32 PlayDoorAnimationFrame(const struct DoorGraphics * gfx, const struct DoorAnimFrame * frames, s16 *data)
+{
+ if (data[5] == 0)
+ {
+ UpdateDrawDoorFrame(gfx, &frames[data[4]], data[6], data[7]);
+ }
+ if (data[5] == frames[data[4]].duration)
+ {
+ data[5] = 0;
+ data[4]++;
+ if (frames[data[4]].duration == 0)
+ return FALSE;
+ }
+ else
+ {
+ data[5]++;
+ }
+ return TRUE;
+}
+
+static const struct DoorGraphics * door_find(const struct DoorGraphics * gfx, u16 id)
+{
+ while (gfx->tiles != NULL)
+ {
+ if (gfx->metatileId == id)
+ return gfx;
+ gfx++;
+ }
+ return NULL;
+}
+
+static s8 task_overworld_door_add_if_inactive(const struct DoorGraphics * gfx, const struct DoorAnimFrame * frames, int a2, int a3)
+{
+ u8 taskId;
+ s16 *data;
+ if (FuncIsActiveTask(Task_AnimateDoor) == TRUE)
+ return -1;
+ taskId = CreateTask(Task_AnimateDoor, 80);
+ data = gTasks[taskId].data;
+ data[6] = a2;
+ data[7] = a3;
+ data[1] = (uintptr_t)frames;
+ data[0] = (uintptr_t)frames >> 16;
+ data[3] = (uintptr_t)gfx;
+ data[2] = (uintptr_t)gfx >> 16;
+ return taskId;
+}
+
+static void DrawClosedDoor(const struct DoorGraphics * gfx, int a1, int a2)
+{
+ DrawDoorDefaultImage(gfx, a1, a2);
+}
+
+static void DrawOpenedDoor(const struct DoorGraphics * gfx, int x, int y)
+{
+ gfx = door_find(gfx, MapGridGetMetatileIdAt(x, y));
+ if (gfx != NULL)
+ {
+ UpdateDrawDoorFrame(gfx, SeekToEndOfDoorAnim(gfx->size == 0 ? sDoorAnimFrames_OpenSmall : sDoorAnimFrames_OpenLarge), x, y);
+ }
+}
+
+static const struct DoorAnimFrame * SeekToEndOfDoorAnim(const struct DoorAnimFrame * frames)
+{
+ while (frames->duration != 0)
+ frames++;
+ return frames - 1;
+}
+
+static s8 AnimateDoorOpenInternal(const struct DoorGraphics * gfx, int x, int y)
+{
+ gfx = door_find(gfx, MapGridGetMetatileIdAt(x, y));
+ if (gfx == NULL)
+ return -1;
+ else if (gfx->size == 0)
+ return task_overworld_door_add_if_inactive(gfx, sDoorAnimFrames_OpenSmall, x, y);
+ else
+ return task_overworld_door_add_if_inactive(gfx, sDoorAnimFrames_OpenLarge, x, y);
+}
+
+static s8 AnimateDoorCloseInternal(const struct DoorGraphics * gfx, int x, int y)
+{
+ gfx = door_find(gfx, MapGridGetMetatileIdAt(x, y));
+ if (gfx == NULL)
+ return -1;
+ else if (gfx->size == 0)
+ return task_overworld_door_add_if_inactive(gfx, sDoorAnimFrames_CloseSmall, x, y);
+ else
+ return task_overworld_door_add_if_inactive(gfx, sDoorAnimFrames_CloseLarge, x, y);
+}
+
+void FieldSetDoorOpened(int x, int y)
+{
+ if (MetatileBehavior_IsWarpDoor_2(MapGridGetMetatileBehaviorAt((s16)x, (s16)y)))
+ DrawOpenedDoor(sDoorGraphics, x, y);
+}
+
+void FieldSetDoorClosed(int x, int y)
+{
+ if (MetatileBehavior_IsWarpDoor_2(MapGridGetMetatileBehaviorAt((s16)x, (s16)y)))
+ DrawClosedDoor(sDoorGraphics, x, y);
+}
+
+s8 FieldAnimateDoorClose(int x, int y)
+{
+ if (!MetatileBehavior_IsWarpDoor_2(MapGridGetMetatileBehaviorAt((s16)x, (s16)y)))
+ return -1;
+ return AnimateDoorCloseInternal(sDoorGraphics, x, y);
+}
+
+s8 FieldAnimateDoorOpen(int x, int y)
+{
+ if (!MetatileBehavior_IsWarpDoor_2(MapGridGetMetatileBehaviorAt((s16)x, (s16)y)))
+ return -1;
+ return AnimateDoorOpenInternal(sDoorGraphics, x, y);
+}
+
+bool8 FieldIsDoorAnimationRunning(void)
+{
+ return FuncIsActiveTask(Task_AnimateDoor);
+}
+
+u16 GetDoorSoundEffect(x, y)
+{
+ if (!GetDoorOpenType(sDoorGraphics, x, y))
+ return MUS_W_DOOR;
+ else
+ return SE_JIDO_DOA;
+}
+
+static s8 GetDoorOpenType(const struct DoorGraphics * gfx, int x, int y)
+{
+ gfx = door_find(gfx, MapGridGetMetatileIdAt(x, y));
+ if (gfx == NULL)
+ return -1;
+ return gfx->sliding;
+}
diff --git a/src/item_use.c b/src/item_use.c
index 873ce4ab4..db0475370 100644
--- a/src/item_use.c
+++ b/src/item_use.c
@@ -76,7 +76,68 @@ void sub_80A1D68(u8 taskId);
void Task_BattleUse_StatBooster_DelayAndPrint(u8 taskId);
void Task_BattleUse_StatBooster_WaitButton_ReturnToBattle(u8 taskId);
-extern void (*const gUnknown_83E2954[])(void);
+// No clue what this is
+static const u8 sUnref_83E27B4[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x40, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x20, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x04, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x10, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x21, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x10, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x40, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x40, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x40, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x30, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x40, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x10, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x1f, 0x00, 0xe0, 0x03, 0x00, 0x7c,
+ 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+void (*const gUnknown_83E2954[])(void) = {
+ sub_8124C8C,
+ CB2_ReturnToField,
+ NULL,
+ NULL
+};
void sub_80A0FBC(u8 taskId)
{
diff --git a/src/learn_move.c b/src/learn_move.c
new file mode 100644
index 000000000..e22922528
--- /dev/null
+++ b/src/learn_move.c
@@ -0,0 +1,842 @@
+#include "global.h"
+#include "bg.h"
+#include "malloc.h"
+#include "gpu_regs.h"
+#include "palette.h"
+#include "script.h"
+#include "task.h"
+#include "data.h"
+#include "trig.h"
+#include "window.h"
+#include "field_fadetransition.h"
+#include "overworld.h"
+#include "new_menu_helpers.h"
+#include "menu.h"
+#include "list_menu.h"
+#include "event_data.h"
+#include "text_window.h"
+#include "string_util.h"
+#include "pokemon_summary_screen.h"
+#include "graphics.h"
+#include "sound.h"
+#include "strings.h"
+#include "constants/songs.h"
+#include "constants/moves.h"
+
+struct MoveTutorMoveInfoHeaders
+{
+ const u8 *text;
+ u8 left;
+ u8 right;
+ u8 index; // unused
+};
+
+struct LearnMoveGfxResources
+{
+ u8 state;
+ u8 unk_01;
+ u8 unk_02;
+ u8 spriteIds[2];
+ u8 filler_05[0x13];
+ u8 unk_18;
+ u8 scrollPositionMaybe;
+ u8 numLearnableMoves;
+ u8 unk_1B;
+ u8 unk_1C;
+ u8 unk_1D;
+ u8 unk_1E;
+ struct ListMenuItem listMenuItems[25];
+ u16 learnableMoves[25];
+ u8 listMenuStrbufs[25][13];
+ bool8 scheduleMoveInfoUpdate;
+ u8 selectedPartyMember;
+ u8 selectedMoveSlot;
+ u8 unk_262;
+ u8 listMenuTaskId;
+ u8 bg1TilemapBuffer[BG_SCREEN_SIZE]; // 264
+ u8 textColor[3]; // A64
+ u8 selectedIndex;
+ u16 listMenuScrollPos;
+ u16 listMenuScrollRow;
+};
+
+static EWRAM_DATA struct LearnMoveGfxResources * sMoveRelearner = NULL;
+
+static void Task_InitMoveRelearnerMenu(u8 taskId);
+static void CB2_MoveRelearner_Init(void);
+static void CB2_MoveRelearner(void);
+static void MoveRelearnerStateMachine(void);
+static void DrawTextBorderOnWindows6and7(void);
+static void PrintTeachWhichMoveToStrVar1(bool8 onInit);
+static void InitMoveRelearnerStateVariables(void);
+static void SpriteCB_ListMenuScrollIndicators(struct Sprite * sprite);
+static void SpawnListMenuScrollIndicatorSprites(void);
+static void MoveRelearnerInitListMenuBuffersEtc(void);
+static void MoveRelearnerMenuHandleInput(void);
+static void MoveLearnerInitListMenu(void);
+static void LoadMoveInfoUI(void);
+static void PrintMoveInfoHandleCancel_CopyToVram(void);
+static void MoveRelearnerMenu_MoveCursorFunc(s32 itemIndex, bool8 onInit, struct ListMenu *list);
+static s8 YesNoMenuProcessInput(void);
+static void PrintTextOnWindow(u8 windowId, const u8 *str, u8 x, u8 y, s32 speed, s32 colorIdx);
+
+static const u16 sLearnMoveInterfaceSpritesPalette[] = INCBIN_U16("graphics/learn_move/interface_sprites.gbapal");
+static const u16 sLearnMoveInterfaceSpritesTiles[] = INCBIN_U16("graphics/learn_move/interface_sprites.4bpp");
+
+static const u8 sMoveTutorMenuWindowFrameDimensions[][4] =
+{
+ { 0, 0, 19, 13},
+ {20, 0, 29, 13},
+ { 2, 14, 27, 19}
+};
+
+static const u8 sJPText_TatakauWaza[] = _("たたかうわざ");
+static const u8 sJPText_Taipu[] = _("タイプ/");
+static const u8 sJPText_PP[] = _("PP/");
+static const u8 sJPText_Iryoku[] = _("いりょく/");
+static const u8 sJPText_Meichuu[] = _("めいちゅう/");
+
+static const struct MoveTutorMoveInfoHeaders sMoveTutorMoveInfoHeaders[][5] =
+{
+ {
+ {sJPText_TatakauWaza, 7, 1, 0},
+ {sJPText_Taipu, 1, 4, 1},
+ {sJPText_Iryoku, 11, 4, 2},
+ {sJPText_PP, 2, 6, 3},
+ {sJPText_Meichuu, 10, 6, 4},
+ },
+ {
+ {NULL, 0, 0, 0},
+ {NULL, 0, 0, 0},
+ {NULL, 0, 0, 0},
+ {NULL, 0, 0, 0},
+ {NULL, 0, 0, 0},
+ },
+};
+
+static const struct SpriteSheet sSpriteSheet_ListMenuScrollIndicators = {
+ sLearnMoveInterfaceSpritesTiles, 0x180, 5525
+};
+
+static const struct SpritePalette sSpritePalette_ListMenuScrollIndicators = {
+ sLearnMoveInterfaceSpritesPalette, 5526
+};
+
+static const struct OamData sOamdata_MoveRelearnerListMenuScrollIndicators = {
+ .shape = SPRITE_SHAPE(16x8),
+ .size = SPRITE_SIZE(16x8)
+};
+
+static const union AnimCmd sAnimCmd_ScrollIndicatorDown[] = {
+ ANIMCMD_FRAME(4, 5),
+ ANIMCMD_END
+};
+
+static const union AnimCmd sAnimCmd_ScrollIndicatorUp[] = {
+ ANIMCMD_FRAME(6, 5),
+ ANIMCMD_END
+};
+
+static const union AnimCmd *const sSpriteAnimTable_MoveRelearnerListMenuScrollIndicators[] = {
+ sAnimCmd_ScrollIndicatorDown,
+ sAnimCmd_ScrollIndicatorUp
+};
+
+static const struct SpriteTemplate sSpriteTemplate_MoveRelearnerListMenuScrollIndicators = {
+ 5525, 5526, &sOamdata_MoveRelearnerListMenuScrollIndicators, sSpriteAnimTable_MoveRelearnerListMenuScrollIndicators, NULL, gDummySpriteAffineAnimTable, SpriteCB_ListMenuScrollIndicators
+};
+
+static const struct BgTemplate sBgTemplates[2] = {
+ {
+ .bg = 0,
+ .charBaseIndex = 2,
+ .mapBaseIndex = 31,
+ .priority = 0
+ },
+ {
+ .bg = 1,
+ .charBaseIndex = 0,
+ .mapBaseIndex = 8,
+ .priority = 1
+ }
+};
+
+static const struct WindowTemplate sWindowTemplates[9] = {
+ {
+ .bg = 0,
+ .tilemapLeft = 0,
+ .tilemapTop = 0,
+ .width = 6,
+ .height = 7,
+ .paletteNum = 0x0d,
+ .baseBlock = 0x014
+ },
+ {
+ .bg = 0,
+ .tilemapLeft = 10,
+ .tilemapTop = 0,
+ .width = 5,
+ .height = 5,
+ .paletteNum = 0x0d,
+ .baseBlock = 0x03e
+ },
+ {
+ .bg = 0,
+ .tilemapLeft = 5,
+ .tilemapTop = 0,
+ .width = 5,
+ .height = 2,
+ .paletteNum = 0x0d,
+ .baseBlock = 0x057
+ },
+ {
+ .bg = 0,
+ .tilemapLeft = 15,
+ .tilemapTop = 0,
+ .width = 3,
+ .height = 5,
+ .paletteNum = 0x0f,
+ .baseBlock = 0x061
+ },
+ {
+ .bg = 0,
+ .tilemapLeft = 5,
+ .tilemapTop = 2,
+ .width = 3,
+ .height = 3,
+ .paletteNum = 0x0f,
+ .baseBlock = 0x070
+ },
+ {
+ .bg = 0,
+ .tilemapLeft = 2,
+ .tilemapTop = 6,
+ .width = 15,
+ .height = 8,
+ .paletteNum = 0x0f,
+ .baseBlock = 0x079
+ },
+ {
+ .bg = 0,
+ .tilemapLeft = 19,
+ .tilemapTop = 1,
+ .width = 10,
+ .height = 12,
+ .paletteNum = 0x0f,
+ .baseBlock = 0x0f1
+ },
+ {
+ .bg = 0,
+ .tilemapLeft = 2,
+ .tilemapTop = 15,
+ .width = 26,
+ .height = 4,
+ .paletteNum = 0x0f,
+ .baseBlock = 0x169
+ }, DUMMY_WIN_TEMPLATE
+};
+
+static const struct WindowTemplate gUnknown_83FFA8C = {
+ .bg = 0,
+ .tilemapLeft = 21,
+ .tilemapTop = 8,
+ .width = 6,
+ .height = 4,
+ .paletteNum = 0x0f,
+ .baseBlock = 0x1d1
+};
+
+static const struct ListMenuTemplate sMoveRelearnerListMenuTemplate = {
+ .items = NULL,
+ .moveCursorFunc = MoveRelearnerMenu_MoveCursorFunc,
+ .itemPrintFunc = NULL,
+ .totalItems = 0,
+ .maxShowed = 7,
+ .windowId = 6,
+ .header_X = 0,
+ .item_X = 8,
+ .cursor_X = 0,
+ .upText_Y = 0,
+ .cursorPal = 2,
+ .fillValue = 1,
+ .cursorShadowPal = 3,
+ .lettersSpacing = 1,
+ .itemVerticalPadding = 0,
+ .scrollMultiple = 0,
+ .fontId = 2,
+ .cursorKind = 0,
+};
+
+static void VBlankCB_MoveRelearner(void)
+{
+ LoadOam();
+ ProcessSpriteCopyRequests();
+ TransferPlttBuffer();
+}
+
+void DisplayMoveTutorMenu(void)
+{
+ ScriptContext2_Enable();
+ CreateTask(Task_InitMoveRelearnerMenu, 10);
+ BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 16, RGB_BLACK);
+}
+
+static void Task_InitMoveRelearnerMenu(u8 taskId)
+{
+ if (!gPaletteFade.active)
+ {
+ SetMainCallback2(CB2_MoveRelearner_Init);
+ gFieldCallback = FieldCallback_ReturnToEventScript2;
+ DestroyTask(taskId);
+ }
+}
+
+static void MoveRelearnerLoadBgGfx(void)
+{
+ int i;
+ ResetBgsAndClearDma3BusyFlags(FALSE);
+ InitBgsFromTemplates(0, sBgTemplates, NELEMS(sBgTemplates));
+ ResetTempTileDataBuffers();
+ if (InitWindows(sWindowTemplates))
+ {
+ DeactivateAllTextPrinters();
+ for (i = 0; i < NELEMS(sWindowTemplates); i++)
+ {
+ ClearWindowTilemap(i);
+ FillWindowPixelBuffer(i, PIXEL_FILL(0));
+ }
+ FillWindowPixelBuffer(7, PIXEL_FILL(1));
+ FillBgTilemapBufferRect(0, 0x000, 0, 0, 30, 20, 0xF);
+ SetBgTilemapBuffer(1, sMoveRelearner->bg1TilemapBuffer);
+ TextWindow_SetUserSelectedFrame(0, 1, 0xE0);
+ sub_8107D38(0xD0, 1);
+ LoadPalette(gUnknown_8E97DDC, 0x00, 0x20);
+ DecompressAndLoadBgGfxUsingHeap(1, gUnknown_8E97DFC, 0, 0, 0);
+ CopyToBgTilemapBuffer(1, gUnknown_8E97EC4, 0, 0);
+ CopyBgTilemapBufferToVram(1);
+ SetGpuReg(REG_OFFSET_BG0VOFS, 0);
+ SetGpuReg(REG_OFFSET_BG0HOFS, 0);
+ SetGpuReg(REG_OFFSET_BG1VOFS, 0);
+ SetGpuReg(REG_OFFSET_BG1HOFS, 0);
+ }
+}
+
+static void CB2_MoveRelearner_Init(void)
+{
+ SetGpuReg(REG_OFFSET_DISPCNT, 0);
+ ResetSpriteData();
+ FreeAllSpritePalettes();
+ ResetTasks();
+ sMoveRelearner = AllocZeroed(sizeof(struct LearnMoveGfxResources));
+ InitMoveRelearnerStateVariables();
+ sMoveRelearner->selectedPartyMember = gSpecialVar_0x8004;
+ MoveRelearnerInitListMenuBuffersEtc();
+ SetVBlankCallback(VBlankCB_MoveRelearner);
+ MoveRelearnerLoadBgGfx();
+ SpawnListMenuScrollIndicatorSprites();
+ RunTasks();
+ AnimateSprites();
+ BuildOamBuffer();
+ UpdatePaletteFade();
+ SetMainCallback2(CB2_MoveRelearner);
+}
+
+static void CB2_MoveRelearner_Resume(void)
+{
+ SetGpuReg(REG_OFFSET_DISPCNT, 0);
+ ResetSpriteData();
+ FreeAllSpritePalettes();
+ ResetTasks();
+ MoveRelearnerInitListMenuBuffersEtc();
+ sMoveRelearner->selectedMoveSlot = gSpecialVar_0x8005;
+ SetVBlankCallback(VBlankCB_MoveRelearner);
+ MoveRelearnerLoadBgGfx();
+ SpawnListMenuScrollIndicatorSprites();
+ FillPalette(RGB_BLACK, 0, 2);
+
+ RunTasks();
+ AnimateSprites();
+ BuildOamBuffer();
+ UpdatePaletteFade();
+ SetMainCallback2(CB2_MoveRelearner);
+}
+
+static void CB2_MoveRelearner(void)
+{
+ if (!IsTextPrinterActive(7))
+ MoveRelearnerStateMachine();
+ if (sMoveRelearner->scheduleMoveInfoUpdate)
+ {
+ PrintMoveInfoHandleCancel_CopyToVram();
+ sMoveRelearner->scheduleMoveInfoUpdate = FALSE;
+ }
+ RunTasks();
+ RunTextPrinters();
+ AnimateSprites();
+ BuildOamBuffer();
+ UpdatePaletteFade();
+}
+
+static void StringExpandPlaceholdersAndPrintTextOnWindow7Color2(const u8 *str)
+{
+ StringExpandPlaceholders(gStringVar4, str);
+ PrintTextOnWindow(7, gStringVar4, 0, 2, GetTextSpeedSetting(), 2);
+}
+
+static void MoveRelearnerStateMachine(void)
+{
+ u16 move;
+
+ switch (sMoveRelearner->state)
+ {
+ case 0:
+ BeginNormalPaletteFade(0xFFFFFFFF, 0, 16, 0, RGB_BLACK);
+ ShowBg(0);
+ ShowBg(1);
+ LoadMoveInfoUI();
+ sMoveRelearner->state++;
+ DrawTextBorderOnWindows6and7();
+ PrintTeachWhichMoveToStrVar1(FALSE);
+ MoveLearnerInitListMenu();
+ sMoveRelearner->scheduleMoveInfoUpdate = TRUE;
+ break;
+ case 1:
+ if (!gPaletteFade.active)
+ sMoveRelearner->state = 4;
+ break;
+ case 2:
+ sMoveRelearner->state++;
+ break;
+ case 3:
+ PrintTeachWhichMoveToStrVar1(FALSE);
+ sMoveRelearner->scheduleMoveInfoUpdate = TRUE;
+ sMoveRelearner->state++;
+ break;
+ case 4:
+ MoveRelearnerMenuHandleInput();
+ break;
+ case 8:
+ CreateYesNoMenu(&gUnknown_83FFA8C, 3, 0, 2, 0x001, 0xE, 0);
+ sMoveRelearner->state++;
+ break;
+ case 9:
+ switch (YesNoMenuProcessInput())
+ {
+ case 0:
+ if (GiveMoveToMon(&gPlayerParty[sMoveRelearner->selectedPartyMember], sMoveRelearner->learnableMoves[sMoveRelearner->selectedIndex]) != 0xFFFF)
+ {
+ StringExpandPlaceholdersAndPrintTextOnWindow7Color2(gText_MonLearnedMove);
+ gSpecialVar_0x8004 = TRUE;
+ sMoveRelearner->state = 31;
+ }
+ else
+ {
+ sMoveRelearner->state = 16;
+ }
+ break;
+ case 1:
+ case -1:
+ sMoveRelearner->state = 3;
+ break;
+ }
+ break;
+ case 12:
+ CreateYesNoMenu(&gUnknown_83FFA8C, 3, 0, 2, 0x001, 0xE, 0);
+ sMoveRelearner->state++;
+ break;
+ case 13:
+ switch (YesNoMenuProcessInput())
+ {
+ case 0:
+ gSpecialVar_0x8004 = FALSE;
+ sMoveRelearner->state = 14;
+ break;
+ case 1:
+ case -1:
+ sMoveRelearner->state = 3;
+ break;
+ }
+ break;
+ case 16:
+ StringExpandPlaceholdersAndPrintTextOnWindow7Color2(gText_MonIsTryingToLearnMove);
+ sMoveRelearner->state++;
+ break;
+ case 17:
+ CreateYesNoMenu(&gUnknown_83FFA8C, 3, 0, 2, 0x001, 0xE, 0);
+ sMoveRelearner->state = 18;
+ break;
+ case 18:
+ switch (YesNoMenuProcessInput())
+ {
+ case 0:
+ StringExpandPlaceholdersAndPrintTextOnWindow7Color2(gText_WhichMoveShouldBeForgotten);
+ sMoveRelearner->state = 19;
+ break;
+ case 1:
+ case -1:
+ sMoveRelearner->state = 24;
+ break;
+ }
+ break;
+ case 24:
+ StringExpandPlaceholdersAndPrintTextOnWindow7Color2(gText_StopLearningMove);
+ sMoveRelearner->state++;
+ break;
+ case 25:
+ CreateYesNoMenu(&gUnknown_83FFA8C, 3, 0, 2, 0x001, 0xE, 0);
+ sMoveRelearner->state = 26;
+ break;
+ case 26:
+ switch (YesNoMenuProcessInput())
+ {
+ case 0:
+ sMoveRelearner->state = 27;
+ break;
+ case 1:
+ case -1:
+ sMoveRelearner->state = 16;
+ break;
+ }
+ break;
+ case 27:
+ sMoveRelearner->state = 3;
+ break;
+ case 19:
+ sMoveRelearner->state = 20;
+ BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 16, RGB_BLACK);
+ break;
+ case 20:
+ if (!gPaletteFade.active)
+ {
+ ListMenuGetScrollAndRow(sMoveRelearner->listMenuTaskId, &sMoveRelearner->listMenuScrollPos, &sMoveRelearner->listMenuScrollRow);
+ FreeAllWindowBuffers();
+ ShowSelectMovePokemonSummaryScreen(gPlayerParty, sMoveRelearner->selectedPartyMember, gPlayerPartyCount - 1, CB2_MoveRelearner_Resume, sMoveRelearner->learnableMoves[sMoveRelearner->selectedIndex]);
+ sMoveRelearner->state = 28;
+ }
+ break;
+ case 21:
+ sMoveRelearner->state = 14;
+ break;
+ case 22:
+ BeginNormalPaletteFade(0xFFFFFFFF, 0, 16, 0, RGB_BLACK);
+ break;
+ case 14:
+ BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 16, RGB_BLACK);
+ sMoveRelearner->state++;
+ break;
+ case 15:
+ if (!gPaletteFade.active)
+ {
+ FreeAllWindowBuffers();
+ Free(sMoveRelearner);
+ SetMainCallback2(CB2_ReturnToField);
+ }
+ break;
+ case 28:
+ BeginNormalPaletteFade(0xFFFFFFFF, 0, 16, 0, RGB_BLACK);
+ ShowBg(0);
+ ShowBg(1);
+ sMoveRelearner->state++;
+ LoadMoveInfoUI();
+ DrawTextBorderOnWindows6and7();
+ MoveLearnerInitListMenu();
+ PrintTeachWhichMoveToStrVar1(TRUE);
+ PrintMoveInfoHandleCancel_CopyToVram();
+ break;
+ case 29:
+ if (!gPaletteFade.active)
+ {
+ if (sMoveRelearner->selectedMoveSlot == 4)
+ {
+ sMoveRelearner->state = 24;
+ }
+ else
+ {
+ move = GetMonData(&gPlayerParty[sMoveRelearner->selectedPartyMember], MON_DATA_MOVE1 + sMoveRelearner->selectedMoveSlot);
+ StringCopy(gStringVar3, gMoveNames[move]);
+ RemoveMonPPBonus(&gPlayerParty[sMoveRelearner->selectedPartyMember], sMoveRelearner->selectedMoveSlot);
+ SetMonMoveSlot(&gPlayerParty[sMoveRelearner->selectedPartyMember], sMoveRelearner->learnableMoves[sMoveRelearner->selectedIndex], sMoveRelearner->selectedMoveSlot);
+ StringCopy(gStringVar2, gMoveNames[sMoveRelearner->learnableMoves[sMoveRelearner->selectedIndex]]);
+ StringExpandPlaceholdersAndPrintTextOnWindow7Color2(gText_1_2_and_Poof);
+ sMoveRelearner->state = 30;
+ gSpecialVar_0x8004 = TRUE;
+ }
+ }
+ break;
+ case 30:
+ StringExpandPlaceholdersAndPrintTextOnWindow7Color2(gText_MonForgotOldMoveAndMonLearnedNewMove);
+ sMoveRelearner->state = 31;
+ PlayFanfare(MUS_FANFA1);
+ break;
+ case 31:
+ PlayFanfare(MUS_FANFA1);
+ sMoveRelearner->state = 32;
+ break;
+ case 32:
+ if (IsFanfareTaskInactive())
+ sMoveRelearner->state = 33;
+ break;
+ case 33:
+ if (JOY_NEW(A_BUTTON))
+ {
+ PlaySE(SE_SELECT);
+ sMoveRelearner->state = 14;
+ }
+ break;
+ }
+}
+
+static void DrawTextBorderOnWindows6and7(void)
+{
+ int i;
+ for (i = 6; i < 8; i++)
+ DrawTextBorderOuter(i, 0x001, 0xE);
+}
+
+static void PrintTeachWhichMoveToStrVar1(bool8 onInit)
+{
+ if (!onInit)
+ {
+ StringExpandPlaceholders(gStringVar4, gText_TeachWhichMoveToMon);
+ PrintTextOnWindow(7, gStringVar4, 0, 2, 0, 2);
+ PutWindowTilemap(7);
+ CopyWindowToVram(7, 3);
+ }
+}
+
+static void InitMoveRelearnerStateVariables(void)
+{
+ int i;
+ sMoveRelearner->state = 0;
+ sMoveRelearner->unk_02 = 0;
+ sMoveRelearner->scrollPositionMaybe = 0;
+ sMoveRelearner->unk_18 = 0;
+ sMoveRelearner->unk_1C = 0;
+ sMoveRelearner->numLearnableMoves = 0;
+ sMoveRelearner->unk_1B = 0;
+ sMoveRelearner->unk_1D = 0;
+ sMoveRelearner->unk_1E = 0;
+ sMoveRelearner->scheduleMoveInfoUpdate = FALSE;
+ for (i = 0; i < 20; i++)
+ sMoveRelearner->learnableMoves[i] = MOVE_NONE;
+}
+
+static void SpriteCB_ListMenuScrollIndicators(struct Sprite * sprite)
+{
+ s16 abcissa = (sprite->data[1] * 10) & 0xFF;
+ switch (sprite->data[0])
+ {
+ case 0:
+ break;
+ case 1:
+ sprite->pos2.x = Sin(abcissa, 3) * sprite->data[2];
+ break;
+ case 2:
+ sprite->pos2.y = Sin(abcissa, 1) * sprite->data[2];
+ break;
+ }
+ sprite->data[1]++;
+}
+
+static void SpawnListMenuScrollIndicatorSprites(void)
+{
+ int i;
+ LoadSpriteSheet(&sSpriteSheet_ListMenuScrollIndicators);
+ LoadSpritePalette(&sSpritePalette_ListMenuScrollIndicators);
+ sMoveRelearner->spriteIds[0] = CreateSprite(&sSpriteTemplate_MoveRelearnerListMenuScrollIndicators, 200, 4, 0);
+ StartSpriteAnim(&gSprites[sMoveRelearner->spriteIds[0]], 1);
+ gSprites[sMoveRelearner->spriteIds[0]].data[0] = 2;
+ gSprites[sMoveRelearner->spriteIds[0]].data[2] = -1;
+
+ // Bug: This should be using the second element of spriteIds.
+ sMoveRelearner->spriteIds[0] = CreateSprite(&sSpriteTemplate_MoveRelearnerListMenuScrollIndicators, 200, 108, 0);
+ gSprites[sMoveRelearner->spriteIds[0]].data[0] = 2;
+ gSprites[sMoveRelearner->spriteIds[0]].data[2] = 1;
+ for (i = 0; i < 2; i++)
+ gSprites[sMoveRelearner->spriteIds[i]].invisible = TRUE;
+}
+
+static void MoveRelearnerInitListMenuBuffersEtc(void)
+{
+ int i;
+ s32 count;
+ u8 nickname[11];
+
+ sMoveRelearner->numLearnableMoves = GetMoveRelearnerMoves(&gPlayerParty[sMoveRelearner->selectedPartyMember], sMoveRelearner->learnableMoves);
+ count = GetMoveRelearnerMoves(&gPlayerParty[sMoveRelearner->selectedPartyMember], sMoveRelearner->learnableMoves);
+ for (i = 0; i < sMoveRelearner->numLearnableMoves; i++)
+ StringCopy(sMoveRelearner->listMenuStrbufs[i], gMoveNames[sMoveRelearner->learnableMoves[i]]);
+ GetMonData(&gPlayerParty[sMoveRelearner->selectedPartyMember], MON_DATA_NICKNAME, nickname);
+ StringCopy10(gStringVar1, nickname);
+ StringCopy(sMoveRelearner->listMenuStrbufs[sMoveRelearner->numLearnableMoves], gFameCheckerText_Cancel);
+ sMoveRelearner->numLearnableMoves++;
+ for (i = 0; i < count; i++)
+ {
+ sMoveRelearner->listMenuItems[i].label = sMoveRelearner->listMenuStrbufs[i];
+ sMoveRelearner->listMenuItems[i].index = i;
+ }
+ sMoveRelearner->listMenuItems[i].label = gFameCheckerText_Cancel;
+ sMoveRelearner->listMenuItems[i].index = 0xFE;
+ gMultiuseListMenuTemplate = sMoveRelearnerListMenuTemplate;
+ gMultiuseListMenuTemplate.items = sMoveRelearner->listMenuItems;
+ gMultiuseListMenuTemplate.totalItems = count + 1;
+}
+
+static void MoveRelearnerMenuHandleInput(void)
+{
+ ListMenu_ProcessInput(sMoveRelearner->listMenuTaskId);
+ if (JOY_NEW(A_BUTTON))
+ {
+ PlaySE(SE_SELECT);
+ if (sMoveRelearner->selectedIndex != 0xFE)
+ {
+ sMoveRelearner->state = 8;
+ StringCopy(gStringVar2, sMoveRelearner->listMenuStrbufs[sMoveRelearner->selectedIndex]);
+ StringExpandPlaceholdersAndPrintTextOnWindow7Color2(gText_TeachMoveQues);
+ }
+ else
+ {
+ StringExpandPlaceholdersAndPrintTextOnWindow7Color2(gText_GiveUpTryingToTeachNewMove);
+ sMoveRelearner->state = 12;
+ }
+ }
+ else if (JOY_NEW(B_BUTTON))
+ {
+ PlaySE(SE_SELECT);
+ sMoveRelearner->state = 12;
+ StringExpandPlaceholdersAndPrintTextOnWindow7Color2(gText_GiveUpTryingToTeachNewMove);
+ }
+ if (sMoveRelearner->numLearnableMoves > 6)
+ {
+ gSprites[0].invisible = FALSE;
+ gSprites[1].invisible = FALSE;
+ if (sMoveRelearner->scrollPositionMaybe == 0)
+ gSprites[0].invisible = TRUE;
+ else if (sMoveRelearner->scrollPositionMaybe == sMoveRelearner->numLearnableMoves - 6)
+ gSprites[1].invisible = TRUE;
+ }
+}
+
+static void MoveLearnerInitListMenu(void)
+{
+ sMoveRelearner->listMenuTaskId = ListMenuInit(&gMultiuseListMenuTemplate, sMoveRelearner->listMenuScrollPos, sMoveRelearner->listMenuScrollRow);
+ CopyWindowToVram(6, 1);
+}
+
+static void PrintMoveInfo(u16 move)
+{
+ u8 buffer[50];
+ BlitMoveInfoIcon(2, gBattleMoves[move].type + 1, 1, 4);
+
+ if (gBattleMoves[move].power < 2)
+ {
+ PrintTextOnWindow(3, gText_ThreeHyphens, 1, 4, 0, 0);
+ }
+ else
+ {
+ ConvertIntToDecimalStringN(buffer, gBattleMoves[move].power, STR_CONV_MODE_RIGHT_ALIGN, 3);
+ PrintTextOnWindow(3, buffer, 1, 4, 0, 0);
+ }
+
+ if (gBattleMoves[move].accuracy == 0)
+ {
+ PrintTextOnWindow(3, gText_ThreeHyphens, 1, 18, 0, 1);
+ }
+ else
+ {
+ ConvertIntToDecimalStringN(buffer, gBattleMoves[move].accuracy, STR_CONV_MODE_RIGHT_ALIGN, 3);
+ PrintTextOnWindow(3, buffer, 1, 18, 0, 1);
+ }
+ ConvertIntToDecimalStringN(buffer, gBattleMoves[move].pp, STR_CONV_MODE_LEFT_ALIGN, 2);
+ PrintTextOnWindow(4, buffer, 2, 2, 0, 0);
+ PrintTextOnWindow(5, gMoveDescriptionPointers[move - 1], 1, 0, 0, 0);
+}
+
+static void LoadMoveInfoUI(void)
+{
+ BlitMoveInfoIcon(0, 19, 1, 4);
+ BlitMoveInfoIcon(1, 20, 0, 4);
+ BlitMoveInfoIcon(1, 21, 0, 19);
+ BlitMoveInfoIcon(0, 22, 1, 19);
+ BlitMoveInfoIcon(0, 23, 1, 34);
+ PutWindowTilemap(0);
+ PutWindowTilemap(1);
+ PutWindowTilemap(4);
+ PutWindowTilemap(3);
+ PutWindowTilemap(5);
+ PutWindowTilemap(2);
+ PutWindowTilemap(7);
+ CopyWindowToVram(0, 2);
+ CopyWindowToVram(1, 2);
+}
+
+static void PrintMoveInfoHandleCancel_CopyToVram(void)
+{
+ int i;
+ if (sMoveRelearner->selectedIndex != 0xFE)
+ {
+ PrintMoveInfo(sMoveRelearner->learnableMoves[sMoveRelearner->selectedIndex]);
+ }
+ else
+ {
+ for (i = 2; i < 6; i++)
+ {
+ FillWindowPixelBuffer(i, PIXEL_FILL(0));
+ CopyWindowToVram(i, 2);
+ }
+ }
+ CopyWindowToVram(3, 2);
+ CopyWindowToVram(4, 2);
+ CopyWindowToVram(2, 2);
+ CopyWindowToVram(2, 2);
+ CopyWindowToVram(5, 2);
+ CopyWindowToVram(7, 3);
+}
+
+static void MoveRelearnerMenu_MoveCursorFunc(s32 itemIndex, bool8 onInit, struct ListMenu *list)
+{
+ if (!onInit)
+ {
+ PlaySE(SE_SELECT);
+ sMoveRelearner->scheduleMoveInfoUpdate = TRUE;
+ sMoveRelearner->selectedIndex = itemIndex;
+ }
+}
+
+static s8 YesNoMenuProcessInput(void)
+{
+ s8 input = Menu_ProcessInputNoWrapClearOnChoose();
+ if (input != -2)
+ {
+ PutWindowTilemap(6);
+ CopyWindowToVram(6, 1);
+ }
+ return input;
+}
+
+static void PrintTextOnWindow(u8 windowId, const u8 *str, u8 x, u8 y, s32 speed, s32 colorIdx)
+{
+ s32 letterSpacing = 1;
+ s32 lineSpacing = 1;
+ if (colorIdx == 0 || colorIdx == 1)
+ {
+ letterSpacing = 0;
+ lineSpacing = 0;
+ }
+ switch (colorIdx)
+ {
+ case 0:
+ case 1:
+ sMoveRelearner->textColor[0] = 0;
+ sMoveRelearner->textColor[1] = 2;
+ sMoveRelearner->textColor[2] = 3;
+ break;
+ case 2:
+ sMoveRelearner->textColor[0] = 1;
+ sMoveRelearner->textColor[1] = 2;
+ sMoveRelearner->textColor[2] = 3;
+ }
+ if (colorIdx != 1)
+ FillWindowPixelBuffer(windowId, PIXEL_FILL(sMoveRelearner->textColor[0]));
+ AddTextPrinterParameterized4(windowId, 3, x, y, letterSpacing, lineSpacing, sMoveRelearner->textColor, speed, str);
+}
diff --git a/src/map_name_popup.c b/src/map_name_popup.c
new file mode 100644
index 000000000..fe15cc129
--- /dev/null
+++ b/src/map_name_popup.c
@@ -0,0 +1,216 @@
+#include "global.h"
+#include "bg.h"
+#include "gpu_regs.h"
+#include "window.h"
+#include "palette.h"
+#include "task.h"
+#include "event_data.h"
+#include "text_window.h"
+#include "quest_log.h"
+#include "region_map.h"
+#include "text.h"
+#include "strings.h"
+#include "string_util.h"
+#include "constants/flags.h"
+
+static void Task_MapNamePopup(u8 taskId);
+static u16 MapNamePopupCreateWindow(bool32 palIntoFadedBuffer);
+static void MapNamePopupPrintMapNameOnWindow(u16 windowId);
+static u8 *MapNamePopupAppendFloorNum(u8 *dest, s8 flags);
+
+void CreateMapNamePopupIfNotAlreadyRunning(bool32 palIntoFadedBuffer)
+{
+ u8 taskId;
+ if (FlagGet(FLAG_SPECIAL_FLAG_0x4000) != TRUE && !(gUnknown_203ADFA == 2 || gUnknown_203ADFA == 3))
+ {
+ taskId = FindTaskIdByFunc(Task_MapNamePopup);
+ if (taskId == 0xFF)
+ {
+ taskId = CreateTask(Task_MapNamePopup, 90);
+ ChangeBgX(0, 0x00000000, 0);
+ ChangeBgY(0, 0xFFFFEF7F, 0);
+ gTasks[taskId].data[0] = 0;
+ gTasks[taskId].data[2] = 0;
+ gTasks[taskId].data[8] = palIntoFadedBuffer;
+ }
+ else
+ {
+ if (gTasks[taskId].data[0] != 4)
+ gTasks[taskId].data[0] = 4;
+ gTasks[taskId].data[3] = 1;
+ }
+ }
+}
+
+static void Task_MapNamePopup(u8 taskId)
+{
+ struct Task * task = &gTasks[taskId];
+ switch (task->data[0])
+ {
+ case 0:
+ task->data[4] = MapNamePopupCreateWindow(task->data[8]);
+ task->data[5] = 1;
+ task->data[0] = 1;
+ break;
+ case 1:
+ if (IsDma3ManagerBusyWithBgCopy())
+ break;
+ // fallthrough
+ case 2:
+ task->data[2] -= 2;
+ if (task->data[2] <= -24)
+ {
+ task->data[0] = 3;
+ task->data[1] = 0;
+ }
+ break;
+ case 3:
+ task->data[1]++;
+ if (task->data[1] > 120)
+ {
+ task->data[1] = 0;
+ task->data[0] = 4;
+ }
+ break;
+ case 4:
+ task->data[2] += 2;
+ if (task->data[2] >= 0)
+ {
+ if (task->data[3])
+ {
+ MapNamePopupPrintMapNameOnWindow(task->data[4]);
+ CopyWindowToVram(task->data[4], 2);
+ task->data[0] = 1;
+ task->data[3] = 0;
+ }
+ else
+ {
+ task->data[0] = 6;
+ return;
+ }
+ }
+ case 5:
+ break;
+ case 6:
+ if (task->data[5] && !task->data[6])
+ {
+ rbox_fill_rectangle(task->data[4]);
+ CopyWindowToVram(task->data[4], 1);
+ task->data[6] = 1;
+ }
+ task->data[0] = 7;
+ return;
+ case 7:
+ if (!IsDma3ManagerBusyWithBgCopy())
+ {
+ if (task->data[5])
+ {
+ RemoveWindow(task->data[4]);
+ task->data[5] = 0;
+ task->data[7] = 1;
+ }
+ task->data[0] = 8;
+ ChangeBgY(0, 0x00000000, 0);
+ }
+ return;
+ case 8:
+ DestroyTask(taskId);
+ return;
+ }
+ SetGpuReg(REG_OFFSET_BG0VOFS, task->data[2]);
+}
+
+void DismissMapNamePopup(void)
+{
+ u8 taskId;
+ s16 *data;
+ taskId = FindTaskIdByFunc(Task_MapNamePopup);
+ if (taskId != 0xFF)
+ {
+ data = gTasks[taskId].data;
+ if (data[0] < 6)
+ data[0] = 6;
+ }
+}
+
+bool32 IsMapNamePopupTaskActive(void)
+{
+ return FindTaskIdByFunc(Task_MapNamePopup) != 0xFF ? TRUE : FALSE;
+}
+
+static u16 MapNamePopupCreateWindow(bool32 palintoFadedBuffer)
+{
+ struct WindowTemplate windowTemplate = {
+ .bg = 0,
+ .tilemapLeft = 1,
+ .tilemapTop = 29,
+ .width = 14,
+ .height = 2,
+ .paletteNum = 0xD,
+ .baseBlock = 0x001
+ };
+ u16 windowId;
+ u16 r6 = 0x01D;
+ if (gMapHeader.flags != 0)
+ {
+ if (gMapHeader.flags != 0x7F)
+ {
+ windowTemplate.width += 5;
+ r6 = 0x027;
+ }
+ else
+ {
+ windowTemplate.width += 8;
+ r6 = 0x02D;
+ }
+ }
+ windowId = AddWindow(&windowTemplate);
+ if (palintoFadedBuffer)
+ {
+ LoadPalette(stdpal_get(3), 0xd0, 0x20);
+ }
+ else
+ {
+ CpuCopy16(stdpal_get(3), &gPlttBufferUnfaded[0xd0], 0x20);
+ }
+ sub_814FF6C(windowId, r6);
+ DrawTextBorderOuter(windowId, r6, 0xD);
+ PutWindowTilemap(windowId);
+ MapNamePopupPrintMapNameOnWindow(windowId);
+ CopyWindowToVram(windowId, 3);
+ return windowId;
+}
+
+static void MapNamePopupPrintMapNameOnWindow(u16 windowId)
+{
+ u8 mapName[25];
+ u32 maxWidth = 112;
+ u32 xpos;
+ u8 *ptr = GetMapName(mapName, gMapHeader.regionMapSectionId, 0);
+ if (gMapHeader.flags != 0)
+ {
+ ptr = MapNamePopupAppendFloorNum(ptr, gMapHeader.flags);
+ maxWidth = gMapHeader.flags != 0x7F ? 152 : 176;
+ }
+ xpos = (maxWidth - GetStringWidth(2, mapName, -1)) / 2;
+ FillWindowPixelBuffer(windowId, PIXEL_FILL(1));
+ AddTextPrinterParameterized(windowId, 2, mapName, xpos, 2, 0xFF, NULL);
+}
+
+static u8 *MapNamePopupAppendFloorNum(u8 *dest, s8 flags)
+{
+ if (flags == 0)
+ return dest;
+ *dest++ = CHAR_SPACE;
+ if (flags == 0x7F)
+ return StringCopy(dest, gUnknown_841D18D);
+ if (flags < 0)
+ {
+ *dest++ = CHAR_B;
+ flags *= -1;
+ }
+ dest = ConvertIntToDecimalStringN(dest, flags, STR_CONV_MODE_LEFT_ALIGN, 2);
+ *dest++ = CHAR_F;
+ *dest = EOS;
+ return dest;
+}
diff --git a/src/metatile_behavior.c b/src/metatile_behavior.c
index bca99d38f..8e07c1c97 100644
--- a/src/metatile_behavior.c
+++ b/src/metatile_behavior.c
@@ -16,6 +16,41 @@ static const bool8 sTileSurfable[METATILE_COUNT] = {
[MB_SOUTHWARD_CURRENT] = TRUE
};
+static const u8 sTileBitAttributes[] = {
+ 0x00,
+ 0x01,
+ 0x02,
+ 0x04,
+ 0x08,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00
+};
+
bool8 MetatileBehavior_UnusedReturnTrue(u8 metatileBehavior)
{
return TRUE;
@@ -736,7 +771,7 @@ bool8 MetatileBehavior_UnusedReturnFalse_13(u8 metatileBehavior) { return FALSE;
bool8 sub_805A2BC(u8 arg1, u8 arg2)
{
- if(gUnknown_8353068[arg1] & arg2)
+ if(sTileBitAttributes[arg1] & arg2)
return TRUE;
else
return FALSE;
diff --git a/src/mevent.c b/src/mevent.c
index 671e30ee0..5ed001d09 100644
--- a/src/mevent.c
+++ b/src/mevent.c
@@ -588,7 +588,7 @@ void DestroyWonderCard(void)
ClearRamScript();
sub_806E2D0();
sub_806E370();
- sub_80E7524(&gSaveBlock2Ptr->battleTower.ereaderTrainer);
+ ClearEReaderTrainer(&gSaveBlock2Ptr->battleTower.ereaderTrainer);
}
bool32 sub_8143F68(const struct MEWonderCardData * data)
diff --git a/src/mevent_client.c b/src/mevent_client.c
index c2a86afdd..4da0b4bc1 100644
--- a/src/mevent_client.c
+++ b/src/mevent_client.c
@@ -14,7 +14,7 @@ static void mevent_client_init(struct mevent_client *, u32, u32);
static u32 mevent_client_exec(struct mevent_client *);
static void mevent_client_free_resources(struct mevent_client *);
-extern const struct mevent_client_cmd gMEventClientScript_InotialListen[];
+extern const struct mevent_client_cmd gMEventClientScript_InitialListen[];
void mevent_client_do_init(void)
{
@@ -89,7 +89,7 @@ static void mevent_client_send_word(struct mevent_client * svr, u32 ident, u32 w
static u32 client_mainseq_0(struct mevent_client * svr)
{
// init
- memcpy(svr->cmdBuffer, gMEventClientScript_InotialListen, ME_SEND_BUF_SIZE);
+ memcpy(svr->cmdBuffer, gMEventClientScript_InitialListen, ME_SEND_BUF_SIZE);
svr->cmdidx = 0;
svr->mainseqno = 4;
svr->flag = 0;
diff --git a/src/mevent_scripts.c b/src/mevent_scripts.c
new file mode 100644
index 000000000..04d44f603
--- /dev/null
+++ b/src/mevent_scripts.c
@@ -0,0 +1,192 @@
+#include "global.h"
+#include "mevent_server.h"
+
+extern const struct mevent_server_cmd gMEventSrvScript_OtherTrainerCanceled[];
+
+// Unreferenced
+const u8 gUnknown_84687A0[] = _("You have collected all STAMPs!\nWant to input a CARD as a prize?");
+
+/* CLIENT SCRIPTS */
+
+const struct mevent_client_cmd gMEventClientScript_InitialListen[] = { // 84687E0
+ CLI_RECEIVE(0x10),
+ CLI_JUMPBUF
+};
+
+const struct mevent_client_cmd gMEventClientScript_Send1442CC[] = {
+ CLI_SNDHEAD,
+ CLI_WAITSND,
+ CLI_RECEIVE(0x10),
+ CLI_JUMPBUF
+};
+
+const struct mevent_client_cmd gMEventClientScript_UnableToRecv[] = { // can't accept card or news
+ CLI_SENDALL,
+ CLI_RETURN(0x0a)
+};
+
+const struct mevent_client_cmd gMEventClientScript_CommError[] = { // comm error
+ CLI_SENDALL,
+ CLI_RETURN(0x0b)
+};
+
+const struct mevent_client_cmd gMEventClientScript_NothingSentOver[] = { // nothing sent
+ CLI_SENDALL,
+ CLI_RETURN(0x00)
+};
+
+const struct mevent_client_cmd gMEventClientScript_ReceiveCardAndReturnSuccess[] = { // card success
+ CLI_RECEIVE(0x16),
+ CLI_RECVSAV,
+ CLI_RECEIVE(0x19),
+ CLI_RECVRAM,
+ CLI_SENDALL,
+ CLI_RETURN(0x02)
+};
+
+const struct mevent_client_cmd gMEventClientScript_ReceiveNewsAndValidate[] = {
+ CLI_RECEIVE(0x17),
+ CLI_VLDNEWS,
+ CLI_WAITSND,
+ CLI_RECEIVE(0x10),
+ CLI_JUMPBUF
+};
+
+const struct mevent_client_cmd gMEventClientScript_AlreadyHadNews[] = { // already had news
+ CLI_SENDALL,
+ CLI_RETURN(0x07)
+};
+
+const struct mevent_client_cmd gMEventClientScript_RecvNewsSuccess[] = { // news success
+ CLI_SENDALL,
+ CLI_RETURN(0x03)
+};
+
+const struct mevent_client_cmd gMEventClientScript_AskWouldLikeToTossCard[] = {
+ CLI_REQWORD,
+ CLI_SNDWORD,
+ CLI_WAITSND,
+ CLI_RECEIVE(0x10),
+ CLI_JUMPBUF
+};
+
+const struct mevent_client_cmd gMEventClientScript_OtherTrainerCanceled[] = { // comm canceled
+ CLI_SENDALL,
+ CLI_RETURN(0x09)
+};
+
+const struct mevent_client_cmd gMEventClientScript_AlreadyHadCard[] = { // already had card
+ CLI_SENDALL,
+ CLI_RETURN(0x05)
+};
+
+const struct mevent_client_cmd gMEventClientScript_SuccessFromBuffer[] = { // success from buffer
+ CLI_RECEIVE(0x15),
+ CLI_RECVBUF,
+ CLI_SENDALL,
+ CLI_RETURN(0x0d)
+};
+
+/* SERVER SCRIPTS */
+
+const struct mevent_server_cmd gMEventSrvScript_UnableToSend[] = {
+ SRV_SEND(0x10, gMEventClientScript_UnableToRecv),
+ SRV_WAITSND,
+ SRV_RECV(0x14),
+ SRV_RETURN(0x0a)
+};
+
+const struct mevent_server_cmd gUnknown_8468950[] = {
+ SRV_SEND(0x10, gMEventClientScript_CommError),
+ SRV_WAITSND,
+ SRV_RECV(0x14),
+ SRV_RETURN(0x0b)
+};
+
+const struct mevent_server_cmd gUnknown_8468980[] = {
+ SRV_SEND(0x10, gMEventClientScript_OtherTrainerCanceled),
+ SRV_WAITSND,
+ SRV_RECV(0x14),
+ SRV_RETURN(0x09)
+};
+
+const struct mevent_server_cmd gMEventSrvScript_OtherTrnHasNews[] = {
+ SRV_SEND(0x10, gMEventClientScript_AlreadyHadNews),
+ SRV_WAITSND,
+ SRV_RECV(0x14),
+ SRV_RETURN(0x07)
+};
+
+const struct mevent_server_cmd gMEventSrvScript_SentNewsSuccess[] = {
+ SRV_SEND(0x28, gMEventClientScript_ReceiveNewsAndValidate),
+ SRV_WAITSND,
+ SRV_SEND_NEWS,
+ SRV_WAITSND,
+ SRV_RECV(0x13),
+ SRV_READWORD,
+ SRV_BRANCHIF(0x01, gMEventSrvScript_OtherTrnHasNews),
+ SRV_SEND(0x10, gMEventClientScript_RecvNewsSuccess),
+ SRV_WAITSND,
+ SRV_RECV(0x14),
+ SRV_RETURN(0x03)
+};
+
+const struct mevent_server_cmd gMEventSrvScript_SendCardSuccess[] = {
+ SRV_SEND(0x30, gMEventClientScript_ReceiveCardAndReturnSuccess),
+ SRV_WAITSND,
+ SRV_SEND_CARD,
+ SRV_WAITSND,
+ SRV_BUFFER_SEND,
+ SRV_WAITSND,
+ SRV_RECV(0x14),
+ SRV_RETURN(0x02)
+};
+
+const struct mevent_server_cmd gMEventSrvScript_AskClientToOverwriteCard[] = {
+ SRV_SEND(0x28, gMEventClientScript_AskWouldLikeToTossCard),
+ SRV_WAITSND,
+ SRV_RECV(0x13),
+ SRV_READWORD,
+ SRV_BRANCHIF(0x00, gMEventSrvScript_SendCardSuccess),
+ SRV_BRANCH(gMEventSrvScript_OtherTrainerCanceled)
+};
+
+const struct mevent_server_cmd gMEventSrvScript_OtherTrnHasCard[] = {
+ SRV_SEND(0x10, gMEventClientScript_AlreadyHadCard),
+ SRV_WAITSND,
+ SRV_RECV(0x14),
+ SRV_RETURN(0x05)
+};
+
+const struct mevent_server_cmd gUnknown_8468B3C[] = {
+ SRV_SEND(0x10, gMEventClientScript_NothingSentOver),
+ SRV_WAITSND,
+ SRV_RECV(0x14),
+ SRV_RETURN(0x00)
+};
+
+const struct mevent_server_cmd gMEventSrvScript_SendNews[] = {
+ SRV_BUFFER_NEWS,
+ SRV_SEND(0x20, gMEventClientScript_Send1442CC),
+ SRV_WAITSND,
+ SRV_RECV(0x11),
+ SRV_READ_1442CC,
+ SRV_VALID_1442CC,
+ SRV_BRANCHIF(0x00, gMEventSrvScript_UnableToSend),
+ SRV_BRANCH(gMEventSrvScript_SentNewsSuccess)
+};
+
+const struct mevent_server_cmd gMEventSrvScript_SendCard[] = {
+ SRV_BUFFER_CARD,
+ SRV_RAM_SCRIPT_IF_VALID,
+ SRV_SEND(0x20, gMEventClientScript_Send1442CC),
+ SRV_WAITSND,
+ SRV_RECV(0x11),
+ SRV_READ_1442CC,
+ SRV_VALID_1442CC,
+ SRV_BRANCHIF(0x00, gMEventSrvScript_UnableToSend),
+ SRV_CHECK_1442CC_14,
+ SRV_BRANCHIF(0x02, gMEventSrvScript_AskClientToOverwriteCard),
+ SRV_BRANCHIF(0x00, gMEventSrvScript_SendCardSuccess),
+ SRV_BRANCH(gMEventSrvScript_OtherTrnHasCard)
+};
diff --git a/src/pokemon_size_record.c b/src/pokemon_size_record.c
index 06e23618d..6eff367c5 100644
--- a/src/pokemon_size_record.c
+++ b/src/pokemon_size_record.c
@@ -6,6 +6,7 @@
#include "pokemon_size_record.h"
#include "string_util.h"
#include "text.h"
+#include "strings.h"
#include "constants/species.h"
#define DEFAULT_MAX_SIZE 0 // was 0x8100 in Ruby/Sapphire, 0x8000 in Emerald
@@ -28,13 +29,13 @@ static const struct UnknownStruct sBigMonSizeTable[] =
{ 800, 100, 7710 },
{ 900, 150, 17710 },
{ 1000, 150, 32710 },
- { 1100, 100, -17826 },
- { 1200, 50, -7826 },
- { 1300, 20, -2826 },
- { 1400, 5, -826 },
- { 1500, 2, -326 },
- { 1600, 1, -126 },
- { 1700, 1, -26 },
+ { 1100, 100, 47710 },
+ { 1200, 50, 57710 },
+ { 1300, 20, 62710 },
+ { 1400, 5, 64710 },
+ { 1500, 2, 65210 },
+ { 1600, 1, 65410 },
+ { 1700, 1, 65510 },
};
static const u8 sGiftRibbonsMonDataIds[] =
@@ -44,8 +45,6 @@ static const u8 sGiftRibbonsMonDataIds[] =
MON_DATA_GIFT_RIBBON_7
};
-extern const u8 gText_DecimalPoint[];
-
#define CM_PER_INCH 2.54
static u32 GetMonSizeHash(struct Pokemon * pkmn)
diff --git a/src/quest_log.c b/src/quest_log.c
index b880a9b06..a8183e7ab 100644
--- a/src/quest_log.c
+++ b/src/quest_log.c
@@ -1425,7 +1425,7 @@ static void sub_81120AC(u8 taskId)
break;
default:
if (gUnknown_203AE94.unk_0_6 == 1)
- sub_8098110(1);
+ CreateMapNamePopupIfNotAlreadyRunning(1);
CpuCopy16(gUnknown_203AE90, gPlttBufferUnfaded, 0x400);
Free(gUnknown_203AE90);
gUnknown_203AE94 = (struct UnkStruct_203AE94){};
diff --git a/src/save_menu_util.c b/src/save_menu_util.c
new file mode 100644
index 000000000..195b29b0c
--- /dev/null
+++ b/src/save_menu_util.c
@@ -0,0 +1,58 @@
+#include "global.h"
+#include "string_util.h"
+#include "text.h"
+#include "event_data.h"
+#include "pokedex.h"
+#include "region_map.h"
+#include "save_menu_util.h"
+#include "constants/flags.h"
+
+void SaveStatToString(u8 gameStatId, u8 *dest0, u8 color)
+{
+ int nBadges;
+ int flagId;
+
+ u8 *dest = dest0;
+ *dest++ = EXT_CTRL_CODE_BEGIN;
+ *dest++ = EXT_CTRL_CODE_COLOR;
+ *dest++ = color;
+ *dest++ = EXT_CTRL_CODE_BEGIN;
+ *dest++ = EXT_CTRL_CODE_SHADOW;
+ *dest++ = color + 1;
+ switch (gameStatId)
+ {
+ case SAVE_STAT_NAME:
+ dest = StringCopy(dest, gSaveBlock2Ptr->playerName);
+ break;
+ case SAVE_STAT_POKEDEX:
+ if (IsNationalPokedexEnabled())
+ dest = ConvertIntToDecimalStringN(dest, GetNationalPokedexCount(1), STR_CONV_MODE_LEFT_ALIGN, 3);
+ else
+ dest = ConvertIntToDecimalStringN(dest, GetKantoPokedexCount(1), STR_CONV_MODE_LEFT_ALIGN, 3);
+ break;
+ case SAVE_STAT_TIME:
+ dest = ConvertIntToDecimalStringN(dest, gSaveBlock2Ptr->playTimeHours, STR_CONV_MODE_LEFT_ALIGN, 3);
+ *dest++ = CHAR_COLON;
+ dest = ConvertIntToDecimalStringN(dest, gSaveBlock2Ptr->playTimeMinutes, STR_CONV_MODE_LEADING_ZEROS, 2);
+ break;
+ case SAVE_STAT_TIME_HR_RT_ALIGN:
+ dest = ConvertIntToDecimalStringN(dest, gSaveBlock2Ptr->playTimeHours, STR_CONV_MODE_RIGHT_ALIGN, 3);
+ *dest++ = CHAR_COLON;
+ dest = ConvertIntToDecimalStringN(dest, gSaveBlock2Ptr->playTimeMinutes, STR_CONV_MODE_LEADING_ZEROS, 2);
+ break;
+ case SAVE_STAT_LOCATION:
+ sub_80C4DF8(dest, gMapHeader.regionMapSectionId);
+ break;
+ case SAVE_STAT_BADGES:
+ for (flagId = FLAG_BADGE01_GET, nBadges = 0; flagId < FLAG_BADGE01_GET + 8; flagId++)
+ {
+ if (FlagGet(flagId))
+ nBadges++;
+ }
+ *dest++ = nBadges + CHAR_0;
+ *dest++ = 10; // 'こ'
+ *dest++ = EOS;
+ break;
+ }
+}
+
diff --git a/src/slot_machine.c b/src/slot_machine.c
index 3bfbbb08b..903f14d45 100644
--- a/src/slot_machine.c
+++ b/src/slot_machine.c
@@ -1343,13 +1343,13 @@ static bool32 sub_814054C(s32 a0, s32 a1, s32 a2, s32 a3, s32 a4)
return FALSE;
}
-#ifdef NONMATCHING
static bool32 sub_81406E8(s32 a0, s32 a1, s32 a2)
{
u8 sp0[9];
s32 r3, r6;
s32 i;
+ r6++; r6--;
r6 = sSlotMachineState->field_20[sSlotMachineState->field_32[0]] + 1;
r3 = sSlotMachineState->field_20[sSlotMachineState->field_32[1]] + 1;
a1++;
@@ -1364,15 +1364,12 @@ static bool32 sub_81406E8(s32 a0, s32 a1, s32 a2)
sp0[sSlotMachineState->field_32[0] * 3 + i] = gUnknown_8464926[sSlotMachineState->field_32[0]][r6];
sp0[sSlotMachineState->field_32[1] * 3 + i] = gUnknown_8464926[sSlotMachineState->field_32[1]][r3];
sp0[a0 * 3 + i] = gUnknown_8464926[a0][a1];
- r6++;
- if (r6 >= 21)
+ if (++r6 >= 21)
r6 = 0;
- r3++;
- if (r3 >= 21)
+ if (++r3 >= 21)
r3 = 0;
- a1++;
- if (a1 >= 21)
- a1++;
+ if (++a1 >= 21)
+ a1 = 0;
}
switch (a2)
{
@@ -1415,292 +1412,6 @@ static bool32 sub_81406E8(s32 a0, s32 a1, s32 a2)
}
return FALSE;
}
-#else
-NAKED
-static bool32 sub_81406E8(s32 a0, s32 a1, s32 a2)
-{
- asm_unified("\tpush {r4-r7,lr}\n"
- "\tmov r7, r10\n"
- "\tmov r6, r9\n"
- "\tmov r5, r8\n"
- "\tpush {r5-r7}\n"
- "\tsub sp, 0x10\n"
- "\tadds r7, r0, 0\n"
- "\tadds r5, r1, 0\n"
- "\tmov r8, r2\n"
- "\tldr r0, _081407C8 @ =sSlotMachineState\n"
- "\tldr r2, [r0]\n"
- "\tmovs r1, 0x32\n"
- "\tldrsh r0, [r2, r1]\n"
- "\tlsls r0, 1\n"
- "\tadds r1, r2, 0\n"
- "\tadds r1, 0x20\n"
- "\tadds r0, r1, r0\n"
- "\tmovs r3, 0\n"
- "\tldrsh r0, [r0, r3]\n"
- "\tadds r6, r0, 0x1\n"
- "\tmovs r3, 0x34\n"
- "\tldrsh r0, [r2, r3]\n"
- "\tlsls r0, 1\n"
- "\tadds r1, r0\n"
- "\tmovs r3, 0\n"
- "\tldrsh r0, [r1, r3]\n"
- "\tadds r3, r0, 0x1\n"
- "\tadds r5, 0x1\n"
- "\tcmp r6, 0x14\n"
- "\tble _08140726\n"
- "\tmovs r6, 0\n"
- "_08140726:\n"
- "\tcmp r3, 0x14\n"
- "\tble _0814072C\n"
- "\tmovs r3, 0\n"
- "_0814072C:\n"
- "\tcmp r5, 0x14\n"
- "\tble _08140732\n"
- "\tmovs r5, 0\n"
- "_08140732:\n"
- "\tmovs r4, 0\n"
- "\tlsls r1, r7, 1\n"
- "\tlsls r0, r7, 2\n"
- "\tmov r9, r2\n"
- "\tldr r2, _081407CC @ =gUnknown_8464926\n"
- "\tmov r10, r2\n"
- "\tadds r1, r7\n"
- "\tadd r1, sp\n"
- "\tmov r12, r1\n"
- "\tadds r0, r7\n"
- "\tlsls r0, 2\n"
- "\tadds r0, r7\n"
- "\tstr r0, [sp, 0xC]\n"
- "_0814074C:\n"
- "\tmov r7, r9\n"
- "\tmovs r0, 0x32\n"
- "\tldrsh r1, [r7, r0]\n"
- "\tlsls r0, r1, 1\n"
- "\tadds r0, r1\n"
- "\tadds r0, r4\n"
- "\tmov r7, sp\n"
- "\tadds r2, r7, r0\n"
- "\tlsls r0, r1, 2\n"
- "\tadds r0, r1\n"
- "\tlsls r0, 2\n"
- "\tadds r0, r1\n"
- "\tadds r0, r6, r0\n"
- "\tadd r0, r10\n"
- "\tldrb r0, [r0]\n"
- "\tstrb r0, [r2]\n"
- "\tmov r0, r9\n"
- "\tmovs r2, 0x34\n"
- "\tldrsh r1, [r0, r2]\n"
- "\tlsls r0, r1, 1\n"
- "\tadds r0, r1\n"
- "\tadds r0, r4\n"
- "\tadds r2, r7, r0\n"
- "\tlsls r0, r1, 2\n"
- "\tadds r0, r1\n"
- "\tlsls r0, 2\n"
- "\tadds r0, r1\n"
- "\tadds r0, r3, r0\n"
- "\tadd r0, r10\n"
- "\tldrb r0, [r0]\n"
- "\tstrb r0, [r2]\n"
- "\tldr r7, [sp, 0xC]\n"
- "\tadds r0, r5, r7\n"
- "\tadd r0, r10\n"
- "\tldrb r0, [r0]\n"
- "\tmov r1, r12\n"
- "\tstrb r0, [r1]\n"
- "\tadds r6, 0x1\n"
- "\tcmp r6, 0x14\n"
- "\tble _0814079E\n"
- "\tmovs r6, 0\n"
- "_0814079E:\n"
- "\tadds r3, 0x1\n"
- "\tcmp r3, 0x14\n"
- "\tble _081407A6\n"
- "\tmovs r3, 0\n"
- "_081407A6:\n"
- "\tadds r5, 0x1\n"
- "\tcmp r5, 0x14\n"
- "\tble _081407AE\n"
- "\tmovs r5, 0\n"
- "_081407AE:\n"
- "\tmovs r2, 0x1\n"
- "\tadd r12, r2\n"
- "\tadds r4, 0x1\n"
- "\tcmp r4, 0x2\n"
- "\tble _0814074C\n"
- "\tmov r3, r8\n"
- "\tcmp r3, 0x1\n"
- "\tbeq _08140828\n"
- "\tcmp r3, 0x1\n"
- "\tbgt _081407D0\n"
- "\tcmp r3, 0\n"
- "\tbeq _081407D8\n"
- "\tb _081408A0\n"
- "\t.align 2, 0\n"
- "_081407C8: .4byte sSlotMachineState\n"
- "_081407CC: .4byte gUnknown_8464926\n"
- "_081407D0:\n"
- "\tmov r6, r8\n"
- "\tcmp r6, 0x2\n"
- "\tbeq _08140870\n"
- "\tb _081408A0\n"
- "_081407D8:\n"
- "\tmovs r4, 0\n"
- "_081407DA:\n"
- "\tmov r7, sp\n"
- "\tadds r0, r7, r4\n"
- "\tldrb r1, [r0]\n"
- "\tmovs r0, 0x1\n"
- "\tbl sub_81408F4\n"
- "\tcmp r0, 0\n"
- "\tbne _081408DC_return_false\n"
- "\tadds r4, 0x1\n"
- "\tcmp r4, 0x2\n"
- "\tble _081407DA\n"
- "\tmovs r4, 0\n"
- "\tldr r2, _08140824 @ =gUnknown_84648AE\n"
- "\tmovs r3, 0\n"
- "\tadds r5, r2, 0x2\n"
- "_081407F8:\n"
- "\tldrb r0, [r2]\n"
- "\tmov r6, sp\n"
- "\tadds r1, r6, r0\n"
- "\tldrb r0, [r2, 0x1]\n"
- "\tadd r0, sp\n"
- "\tldrb r1, [r1]\n"
- "\tldrb r0, [r0]\n"
- "\tcmp r1, r0\n"
- "\tbne _08140816\n"
- "\tadds r0, r3, r5\n"
- "\tldrb r0, [r0]\n"
- "\tadd r0, sp\n"
- "\tldrb r0, [r0]\n"
- "\tcmp r1, r0\n"
- "\tbeq _081408DC_return_false\n"
- "_08140816:\n"
- "\tadds r2, 0x3\n"
- "\tadds r3, 0x3\n"
- "\tadds r4, 0x1\n"
- "\tcmp r4, 0x4\n"
- "\tble _081407F8\n"
- "_08140820_return_true:\n"
- "\tmovs r0, 0x1\n"
- "\tb _081408DE\n"
- "\t.align 2, 0\n"
- "_08140824: .4byte gUnknown_84648AE\n"
- "_08140828:\n"
- "\tmovs r4, 0\n"
- "\tldr r5, _0814086C @ =gUnknown_84648AE\n"
- "_0814082C:\n"
- "\tldrb r0, [r5]\n"
- "\tmov r7, sp\n"
- "\tadds r2, r7, r0\n"
- "\tldrb r0, [r5, 0x1]\n"
- "\tadds r1, r7, r0\n"
- "\tldrb r0, [r2]\n"
- "\tldrb r1, [r1]\n"
- "\tcmp r0, r1\n"
- "\tbne _0814084A\n"
- "\tadds r1, r0, 0\n"
- "\tmov r0, r8\n"
- "\tbl sub_81408F4\n"
- "\tcmp r0, 0\n"
- "\tbne _081408DC_return_false\n"
- "_0814084A:\n"
- "\tadds r5, 0x3\n"
- "\tadds r4, 0x1\n"
- "\tcmp r4, 0x4\n"
- "\tble _0814082C\n"
- "\tmovs r4, 0\n"
- "_08140854:\n"
- "\tmov r1, sp\n"
- "\tadds r0, r1, r4\n"
- "\tldrb r1, [r0]\n"
- "\tmov r0, r8\n"
- "\tbl sub_81408F4\n"
- "\tcmp r0, 0\n"
- "\tbne _08140820_return_true\n"
- "\tadds r4, 0x1\n"
- "\tcmp r4, 0x2\n"
- "\tble _08140854\n"
- "\tb _081408DC_return_false\n"
- "\t.align 2, 0\n"
- "_0814086C: .4byte gUnknown_84648AE\n"
- "_08140870:\n"
- "\tmovs r4, 0\n"
- "\tldr r5, _0814089C @ =gUnknown_84648AE\n"
- "_08140874:\n"
- "\tldrb r0, [r5]\n"
- "\tmov r3, sp\n"
- "\tadds r2, r3, r0\n"
- "\tldrb r0, [r5, 0x1]\n"
- "\tadds r1, r3, r0\n"
- "\tldrb r0, [r2]\n"
- "\tldrb r1, [r1]\n"
- "\tcmp r0, r1\n"
- "\tbne _08140892\n"
- "\tadds r1, r0, 0\n"
- "\tmov r0, r8\n"
- "\tbl sub_81408F4\n"
- "\tcmp r0, 0\n"
- "\tbne _08140820_return_true\n"
- "_08140892:\n"
- "\tadds r5, 0x3\n"
- "\tadds r4, 0x1\n"
- "\tcmp r4, 0x4\n"
- "\tble _08140874\n"
- "\tb _081408DC_return_false\n"
- "\t.align 2, 0\n"
- "_0814089C: .4byte gUnknown_84648AE\n"
- "_081408A0:\n"
- "\tmovs r4, 0\n"
- "\tldr r5, _081408F0 @ =gUnknown_84648AE\n"
- "\tadds r7, r5, 0\n"
- "\tmovs r6, 0\n"
- "_081408A8:\n"
- "\tldrb r0, [r5]\n"
- "\tmov r1, sp\n"
- "\tadds r2, r1, r0\n"
- "\tadds r0, r7, 0x1\n"
- "\tadds r0, r6, r0\n"
- "\tldrb r0, [r0]\n"
- "\tadd r0, sp\n"
- "\tldrb r1, [r2]\n"
- "\tldrb r0, [r0]\n"
- "\tcmp r1, r0\n"
- "\tbne _081408D2\n"
- "\tldrb r0, [r5, 0x2]\n"
- "\tadd r0, sp\n"
- "\tldrb r0, [r0]\n"
- "\tcmp r1, r0\n"
- "\tbne _081408D2\n"
- "\tmov r0, r8\n"
- "\tbl sub_81408F4\n"
- "\tcmp r0, 0\n"
- "\tbne _08140820_return_true\n"
- "_081408D2:\n"
- "\tadds r5, 0x3\n"
- "\tadds r6, 0x3\n"
- "\tadds r4, 0x1\n"
- "\tcmp r4, 0x4\n"
- "\tble _081408A8\n"
- "_081408DC_return_false:\n"
- "\tmovs r0, 0\n"
- "_081408DE:\n"
- "\tadd sp, 0x10\n"
- "\tpop {r3-r5}\n"
- "\tmov r8, r3\n"
- "\tmov r9, r4\n"
- "\tmov r10, r5\n"
- "\tpop {r4-r7}\n"
- "\tpop {r1}\n"
- "\tbx r1\n"
- "\t.align 2, 0\n"
- "_081408F0: .4byte gUnknown_84648AE");
-}
-#endif //NONMATCHING
static bool32 sub_81408F4(s32 a0, s32 a1)
{
@@ -2070,10 +1781,15 @@ static bool32 sub_8141180(u8 a0)
return sub_814112C()->field_0000[a0].unk3;
}
-#ifdef NONMATCHING
+static inline void LoadColor(u16 color, u16 *pal)
+{
+ *pal = color;
+ LoadPalette(pal, 0x00, 0x02);
+}
+
static bool8 sub_8141198(u8 * state, struct SlotMachineSetupTaskData * ptr)
{
- u16 pal;
+ u16 pal[2];
u8 textColor[3];
u32 x;
@@ -2109,8 +1825,7 @@ static bool8 sub_8141198(u8 * state, struct SlotMachineSetupTaskData * ptr)
LoadPalette(gUnknown_8465930, 0x00, 0xA0);
LoadPalette(gUnknown_84664BC, 0x50, 0x20);
LoadPalette(gUnknown_84665C0, 0x70, 0x60);
- pal = RGB(30, 30, 31);
- LoadPalette(&pal, 0x00, 0x02);
+ LoadColor(RGB(30, 30, 31), pal);
LoadUserWindowBorderGfx(0, 0x00A, 0xD0);
sub_814FDA0(0, 0x001, 0xF0);
@@ -2165,299 +1880,6 @@ static bool8 sub_8141198(u8 * state, struct SlotMachineSetupTaskData * ptr)
}
return TRUE;
}
-#else
-NAKED
-static bool8 sub_8141198(u8 * state, struct SlotMachineSetupTaskData * ptr)
-{
- asm_unified("\tpush {r4-r7,lr}\n"
- "\tmov r7, r8\n"
- "\tpush {r7}\n"
- "\tsub sp, 0x14\n"
- "\tadds r7, r0, 0\n"
- "\tmov r8, r1\n"
- "\tldrb r6, [r7]\n"
- "\tcmp r6, 0x1\n"
- "\tbeq _081411D0\n"
- "\tcmp r6, 0x1\n"
- "\tbgt _081411B4\n"
- "\tcmp r6, 0\n"
- "\tbeq _081411C2\n"
- "\tb _08141450\n"
- "_081411B4:\n"
- "\tcmp r6, 0x2\n"
- "\tbne _081411BA\n"
- "\tb _081413E4\n"
- "_081411BA:\n"
- "\tcmp r6, 0x3\n"
- "\tbne _081411C0\n"
- "\tb _08141436\n"
- "_081411C0:\n"
- "\tb _08141450\n"
- "_081411C2:\n"
- "\tmovs r0, 0x1\n"
- "\tnegs r0, r0\n"
- "\tmovs r1, 0x10\n"
- "\tmovs r2, 0\n"
- "\tbl BlendPalettes\n"
- "\tb _0814142E\n"
- "_081411D0:\n"
- "\tmovs r0, 0\n"
- "\tbl SetVBlankCallback\n"
- "\tbl ResetSpriteData\n"
- "\tbl FreeAllSpritePalettes\n"
- "\tmovs r1, 0xE0\n"
- "\tlsls r1, 19\n"
- "\tmovs r2, 0x80\n"
- "\tlsls r2, 3\n"
- "\tmovs r0, 0\n"
- "\tmovs r3, 0x1\n"
- "\tbl RequestDma3Fill\n"
- "\tmovs r1, 0xC0\n"
- "\tlsls r1, 19\n"
- "\tmovs r0, 0\n"
- "\tmovs r2, 0x20\n"
- "\tmovs r3, 0x1\n"
- "\tbl RequestDma3Fill\n"
- "\tldr r1, _0814139C @ =0x0600c000\n"
- "\tmovs r0, 0\n"
- "\tmovs r2, 0x20\n"
- "\tmovs r3, 0x1\n"
- "\tbl RequestDma3Fill\n"
- "\tmovs r0, 0\n"
- "\tmovs r1, 0\n"
- "\tbl SetGpuReg\n"
- "\tbl ResetBgPositions\n"
- "\tmovs r0, 0\n"
- "\tbl ResetBgsAndClearDma3BusyFlags\n"
- "\tldr r1, _081413A0 @ =gUnknown_8466B10\n"
- "\tmovs r0, 0\n"
- "\tmovs r2, 0x4\n"
- "\tbl InitBgsFromTemplates\n"
- "\tldr r0, _081413A4 @ =gUnknown_8466B20\n"
- "\tbl InitWindows\n"
- "\tldr r1, _081413A8 @ =0x0000205c\n"
- "\tadd r1, r8\n"
- "\tmovs r0, 0x3\n"
- "\tbl SetBgTilemapBuffer\n"
- "\tmovs r4, 0x20\n"
- "\tstr r4, [sp]\n"
- "\tstr r4, [sp, 0x4]\n"
- "\tmovs r0, 0x3\n"
- "\tmovs r1, 0\n"
- "\tmovs r2, 0\n"
- "\tmovs r3, 0\n"
- "\tbl FillBgTilemapBufferRect_Palette0\n"
- "\tmovs r0, 0x3\n"
- "\tbl CopyBgTilemapBufferToVram\n"
- "\tbl ResetTempTileDataBuffers\n"
- "\tldr r1, _081413AC @ =gUnknown_84659D0\n"
- "\tmovs r5, 0\n"
- "\tstr r5, [sp]\n"
- "\tmovs r0, 0x2\n"
- "\tmovs r2, 0\n"
- "\tmovs r3, 0\n"
- "\tbl DecompressAndCopyTileDataToVram\n"
- "\tldr r1, _081413B0 @ =gUnknown_846653C\n"
- "\tstr r5, [sp]\n"
- "\tmovs r0, 0x2\n"
- "\tmovs r2, 0\n"
- "\tmovs r3, 0xC0\n"
- "\tbl DecompressAndCopyTileDataToVram\n"
- "\tldr r1, _081413B4 @ =0x0000185c\n"
- "\tadd r1, r8\n"
- "\tmovs r0, 0x2\n"
- "\tbl SetBgTilemapBuffer\n"
- "\tldr r1, _081413B8 @ =gUnknown_84661D4\n"
- "\tmovs r0, 0x2\n"
- "\tmovs r2, 0\n"
- "\tmovs r3, 0\n"
- "\tbl CopyToBgTilemapBuffer\n"
- "\tmovs r0, 0x2\n"
- "\tbl CopyBgTilemapBufferToVram\n"
- "\tldr r0, _081413BC @ =gUnknown_8465930\n"
- "\tmovs r1, 0\n"
- "\tmovs r2, 0xA0\n"
- "\tbl LoadPalette\n"
- "\tldr r0, _081413C0 @ =gUnknown_84664BC\n"
- "\tmovs r1, 0x50\n"
- "\tmovs r2, 0x20\n"
- "\tbl LoadPalette\n"
- "\tldr r0, _081413C4 @ =gUnknown_84665C0\n"
- "\tmovs r1, 0x70\n"
- "\tmovs r2, 0x60\n"
- "\tbl LoadPalette\n"
- "\tldr r1, _081413C8 @ =0x00007fde\n"
- "\tadd r0, sp, 0xC\n"
- "\tstrh r1, [r0]\n"
- "\tmovs r1, 0\n"
- "\tmovs r2, 0x2\n"
- "\tbl LoadPalette\n"
- "\tmovs r0, 0\n"
- "\tmovs r1, 0xA\n"
- "\tmovs r2, 0xD0\n"
- "\tbl LoadUserWindowBorderGfx\n"
- "\tmovs r0, 0\n"
- "\tmovs r1, 0x1\n"
- "\tmovs r2, 0xF0\n"
- "\tbl sub_814FDA0\n"
- "\tldr r1, _081413CC @ =0x0000085c\n"
- "\tadd r1, r8\n"
- "\tmovs r0, 0\n"
- "\tbl SetBgTilemapBuffer\n"
- "\tstr r4, [sp]\n"
- "\tmovs r0, 0x1E\n"
- "\tstr r0, [sp, 0x4]\n"
- "\tmovs r0, 0\n"
- "\tmovs r1, 0\n"
- "\tmovs r2, 0\n"
- "\tmovs r3, 0x2\n"
- "\tbl FillBgTilemapBufferRect_Palette0\n"
- "\tldr r1, _081413D0 @ =gUnknown_8466620\n"
- "\tstr r5, [sp]\n"
- "\tmovs r0, 0x1\n"
- "\tmovs r2, 0\n"
- "\tmovs r3, 0\n"
- "\tbl DecompressAndCopyTileDataToVram\n"
- "\tldr r1, _081413D4 @ =gUnknown_8466998\n"
- "\tstr r6, [sp]\n"
- "\tmovs r0, 0x1\n"
- "\tmovs r2, 0\n"
- "\tmovs r3, 0\n"
- "\tbl DecompressAndCopyTileDataToVram\n"
- "\tmovs r0, 0x1\n"
- "\tbl CopyBgTilemapBufferToVram\n"
- "\tmovs r0, 0x2\n"
- "\tbl stdpal_get\n"
- "\tmovs r1, 0xE0\n"
- "\tmovs r2, 0x20\n"
- "\tbl LoadPalette\n"
- "\tmovs r0, 0x1\n"
- "\tmovs r1, 0xFF\n"
- "\tbl FillWindowPixelBuffer\n"
- "\tmovs r0, 0x1\n"
- "\tbl PutWindowTilemap\n"
- "\tldr r4, _081413D8 @ =gString_SlotMachineControls\n"
- "\tmovs r0, 0\n"
- "\tadds r1, r4, 0\n"
- "\tmovs r2, 0\n"
- "\tbl GetStringWidth\n"
- "\tmovs r2, 0xEC\n"
- "\tsubs r2, r0\n"
- "\tadd r1, sp, 0x10\n"
- "\tmovs r0, 0xF\n"
- "\tstrb r0, [r1]\n"
- "\tstrb r6, [r1, 0x1]\n"
- "\tmovs r0, 0x2\n"
- "\tstrb r0, [r1, 0x2]\n"
- "\tlsls r2, 24\n"
- "\tlsrs r2, 24\n"
- "\tstr r1, [sp]\n"
- "\tstr r5, [sp, 0x4]\n"
- "\tstr r4, [sp, 0x8]\n"
- "\tmovs r0, 0x1\n"
- "\tmovs r1, 0\n"
- "\tmovs r3, 0\n"
- "\tbl AddTextPrinterParameterized3\n"
- "\tmovs r0, 0\n"
- "\tbl CopyBgTilemapBufferToVram\n"
- "\tmovs r1, 0x83\n"
- "\tlsls r1, 5\n"
- "\tmovs r0, 0\n"
- "\tbl SetGpuRegBits\n"
- "\tmovs r0, 0x50\n"
- "\tmovs r1, 0xF8\n"
- "\tbl SetGpuReg\n"
- "\tbl sub_8140C0C\n"
- "\tbl sub_8140CA0\n"
- "\tbl sub_8140E9C\n"
- "\tbl sub_8140FC4\n"
- "\tbl sub_8140F2C\n"
- "\tmovs r0, 0x1\n"
- "\tnegs r0, r0\n"
- "\tmovs r1, 0x10\n"
- "\tmovs r2, 0\n"
- "\tbl BlendPalettes\n"
- "\tldr r0, _081413DC @ =sub_8141118\n"
- "\tbl SetVBlankCallback\n"
- "\tldr r0, _081413E0 @ =sub_8140E40\n"
- "\tbl SetHBlankCallback\n"
- "\tb _0814142E\n"
- "\t.align 2, 0\n"
- "_0814139C: .4byte 0x0600c000\n"
- "_081413A0: .4byte gUnknown_8466B10\n"
- "_081413A4: .4byte gUnknown_8466B20\n"
- "_081413A8: .4byte 0x0000205c\n"
- "_081413AC: .4byte gUnknown_84659D0\n"
- "_081413B0: .4byte gUnknown_846653C\n"
- "_081413B4: .4byte 0x0000185c\n"
- "_081413B8: .4byte gUnknown_84661D4\n"
- "_081413BC: .4byte gUnknown_8465930\n"
- "_081413C0: .4byte gUnknown_84664BC\n"
- "_081413C4: .4byte gUnknown_84665C0\n"
- "_081413C8: .4byte 0x00007fde\n"
- "_081413CC: .4byte 0x0000085c\n"
- "_081413D0: .4byte gUnknown_8466620\n"
- "_081413D4: .4byte gUnknown_8466998\n"
- "_081413D8: .4byte gString_SlotMachineControls\n"
- "_081413DC: .4byte sub_8141118\n"
- "_081413E0: .4byte sub_8140E40\n"
- "_081413E4:\n"
- "\tbl FreeTempTileDataBuffersIfPossible\n"
- "\tlsls r0, 24\n"
- "\tlsrs r5, r0, 24\n"
- "\tcmp r5, 0\n"
- "\tbne _08141450\n"
- "\tmovs r0, 0\n"
- "\tbl ShowBg\n"
- "\tmovs r0, 0x3\n"
- "\tbl ShowBg\n"
- "\tmovs r0, 0x2\n"
- "\tbl ShowBg\n"
- "\tmovs r0, 0x1\n"
- "\tbl HideBg\n"
- "\tbl sub_8141B34\n"
- "\tmovs r4, 0x1\n"
- "\tnegs r4, r4\n"
- "\tadds r0, r4, 0\n"
- "\tmovs r1, 0x10\n"
- "\tmovs r2, 0\n"
- "\tbl BlendPalettes\n"
- "\tstr r5, [sp]\n"
- "\tadds r0, r4, 0\n"
- "\tadds r1, r4, 0\n"
- "\tmovs r2, 0x10\n"
- "\tmovs r3, 0\n"
- "\tbl BeginNormalPaletteFade\n"
- "\tmovs r0, 0x3\n"
- "\tbl EnableInterrupts\n"
- "_0814142E:\n"
- "\tldrb r0, [r7]\n"
- "\tadds r0, 0x1\n"
- "\tstrb r0, [r7]\n"
- "\tb _08141450\n"
- "_08141436:\n"
- "\tbl UpdatePaletteFade\n"
- "\tldr r0, _0814144C @ =gPaletteFade\n"
- "\tldrb r1, [r0, 0x7]\n"
- "\tmovs r0, 0x80\n"
- "\tands r0, r1\n"
- "\tcmp r0, 0\n"
- "\tbne _08141450\n"
- "\tmovs r0, 0\n"
- "\tb _08141452\n"
- "\t.align 2, 0\n"
- "_0814144C: .4byte gPaletteFade\n"
- "_08141450:\n"
- "\tmovs r0, 0x1\n"
- "_08141452:\n"
- "\tadd sp, 0x14\n"
- "\tpop {r3}\n"
- "\tmov r8, r3\n"
- "\tpop {r4-r7}\n"
- "\tpop {r1}\n"
- "\tbx r1");
-}
-#endif //NONMATCHING
static bool8 sub_8141460(u8 * state, struct SlotMachineSetupTaskData * ptr)
{
diff --git a/src/trainer_tower.c b/src/trainer_tower.c
index a4b511725..19d44d7cc 100644
--- a/src/trainer_tower.c
+++ b/src/trainer_tower.c
@@ -725,14 +725,16 @@ static void TT_ConvertEasyChatMessageToString(u16 *ecWords, u8 *dest)
}
}
-#ifdef NONMATCHING
static void sub_815DF54(void)
{
u16 r4 = gSpecialVar_0x8006;
u8 r1;
u8 r5 = sTrainerTowerState->unk_0004.floors[sTrainerTowerState->floorIdx].challengeType;
- // HOW DO I MATCH THIS CONTROL FLOW?!?!
- r1 = sTrainerTowerState->unk_0004.floors[sTrainerTowerState->floorIdx].trainers[r5 == 1 ? 0 : r4].facilityClass;
+
+ if (r5 != 1)
+ r1 = sTrainerTowerState->unk_0004.floors[sTrainerTowerState->floorIdx].trainers[r4].facilityClass;
+ else
+ r1 = sTrainerTowerState->unk_0004.floors[sTrainerTowerState->floorIdx].trainers[0].facilityClass;
switch (gSpecialVar_0x8005)
{
case 2:
@@ -752,147 +754,6 @@ static void sub_815DF54(void)
break;
}
}
-#else
-NAKED
-static void sub_815DF54(void)
-{
- asm_unified("\tpush {r4,r5,lr}\n"
- "\tldr r0, _0815DF90 @ =gSpecialVar_0x8006\n"
- "\tldrh r4, [r0]\n"
- "\tldr r2, _0815DF94 @ =sTrainerTowerState\n"
- "\tldr r3, [r2]\n"
- "\tldrb r1, [r3]\n"
- "\tlsls r0, r1, 5\n"
- "\tsubs r0, r1\n"
- "\tlsls r1, r0, 5\n"
- "\tadds r0, r3, r1\n"
- "\tldrb r5, [r0, 0xE]\n"
- "\tcmp r5, 0x1\n"
- "\tbeq _0815DF7C\n"
- "\tlsls r0, r4, 2\n"
- "\tadds r0, r4\n"
- "\tlsls r0, 3\n"
- "\tadds r0, r4\n"
- "\tlsls r0, 3\n"
- "\tadds r0, r1\n"
- "\tadds r0, r3, r0\n"
- "_0815DF7C:\n"
- "\tldrb r1, [r0, 0x1B]\n"
- "\tldr r0, _0815DF98 @ =gSpecialVar_0x8005\n"
- "\tldrh r0, [r0]\n"
- "\tcmp r0, 0x3\n"
- "\tbeq _0815DFD4\n"
- "\tcmp r0, 0x3\n"
- "\tbgt _0815DF9C\n"
- "\tcmp r0, 0x2\n"
- "\tbeq _0815DFA6\n"
- "\tb _0815E05C\n"
- "\t.align 2, 0\n"
- "_0815DF90: .4byte gSpecialVar_0x8006\n"
- "_0815DF94: .4byte sTrainerTowerState\n"
- "_0815DF98: .4byte gSpecialVar_0x8005\n"
- "_0815DF9C:\n"
- "\tcmp r0, 0x4\n"
- "\tbeq _0815E000\n"
- "\tcmp r0, 0x5\n"
- "\tbeq _0815E038\n"
- "\tb _0815E05C\n"
- "_0815DFA6:\n"
- "\tadds r0, r5, 0\n"
- "\tbl TrainerTowerGetOpponentTextColor\n"
- "\tldr r0, _0815DFD0 @ =sTrainerTowerState\n"
- "\tldr r0, [r0]\n"
- "\tldrb r2, [r0]\n"
- "\tlsls r1, r2, 5\n"
- "\tsubs r1, r2\n"
- "\tlsls r1, 5\n"
- "\tadds r1, 0xC\n"
- "\tadds r0, r1\n"
- "\tlsls r1, r4, 2\n"
- "\tadds r1, r4\n"
- "\tlsls r1, 3\n"
- "\tadds r1, r4\n"
- "\tlsls r1, 3\n"
- "\tadds r1, 0x4\n"
- "\tadds r0, r1\n"
- "\tadds r0, 0xE\n"
- "\tb _0815E026\n"
- "\t.align 2, 0\n"
- "_0815DFD0: .4byte sTrainerTowerState\n"
- "_0815DFD4:\n"
- "\tadds r0, r5, 0\n"
- "\tbl TrainerTowerGetOpponentTextColor\n"
- "\tldr r0, _0815DFFC @ =sTrainerTowerState\n"
- "\tldr r0, [r0]\n"
- "\tldrb r2, [r0]\n"
- "\tlsls r1, r2, 5\n"
- "\tsubs r1, r2\n"
- "\tlsls r1, 5\n"
- "\tadds r1, 0xC\n"
- "\tadds r0, r1\n"
- "\tlsls r1, r4, 2\n"
- "\tadds r1, r4\n"
- "\tlsls r1, 3\n"
- "\tadds r1, r4\n"
- "\tlsls r1, 3\n"
- "\tadds r1, 0x4\n"
- "\tadds r0, r1\n"
- "\tadds r0, 0x1A\n"
- "\tb _0815E026\n"
- "\t.align 2, 0\n"
- "_0815DFFC: .4byte sTrainerTowerState\n"
- "_0815E000:\n"
- "\tadds r0, r5, 0\n"
- "\tbl TrainerTowerGetOpponentTextColor\n"
- "\tldr r0, _0815E030 @ =sTrainerTowerState\n"
- "\tldr r0, [r0]\n"
- "\tldrb r2, [r0]\n"
- "\tlsls r1, r2, 5\n"
- "\tsubs r1, r2\n"
- "\tlsls r1, 5\n"
- "\tadds r1, 0xC\n"
- "\tadds r0, r1\n"
- "\tlsls r1, r4, 2\n"
- "\tadds r1, r4\n"
- "\tlsls r1, 3\n"
- "\tadds r1, r4\n"
- "\tlsls r1, 3\n"
- "\tadds r1, 0x4\n"
- "\tadds r0, r1\n"
- "\tadds r0, 0x26\n"
- "_0815E026:\n"
- "\tldr r1, _0815E034 @ =gStringVar4\n"
- "\tbl TT_ConvertEasyChatMessageToString\n"
- "\tb _0815E05C\n"
- "\t.align 2, 0\n"
- "_0815E030: .4byte sTrainerTowerState\n"
- "_0815E034: .4byte gStringVar4\n"
- "_0815E038:\n"
- "\tldr r0, [r2]\n"
- "\tldrb r2, [r0]\n"
- "\tlsls r1, r2, 5\n"
- "\tsubs r1, r2\n"
- "\tlsls r1, 5\n"
- "\tadds r1, 0xC\n"
- "\tadds r0, r1\n"
- "\tlsls r1, r4, 2\n"
- "\tadds r1, r4\n"
- "\tlsls r1, 3\n"
- "\tadds r1, r4\n"
- "\tlsls r1, 3\n"
- "\tadds r1, 0x4\n"
- "\tadds r0, r1\n"
- "\tadds r0, 0x32\n"
- "\tldr r1, _0815E064 @ =gStringVar4\n"
- "\tbl TT_ConvertEasyChatMessageToString\n"
- "_0815E05C:\n"
- "\tpop {r4,r5}\n"
- "\tpop {r0}\n"
- "\tbx r0\n"
- "\t.align 2, 0\n"
- "_0815E064: .4byte gStringVar4");
-}
-#endif // NONMATCHING
static void TrainerTowerGetOpponentTextColor(u8 battleType, u8 facilityClass)
{