summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDizzyEggg <jajkodizzy@wp.pl>2017-12-18 16:58:14 +0100
committerDizzyEggg <jajkodizzy@wp.pl>2017-12-18 16:58:14 +0100
commitcb229f56e8951e3f9efc35516447a54e18e8fef0 (patch)
tree656599caae716c6cc8e81121f2b1cd061927b99e /src
parentc3abe2863feb8ebb21921c40d3c685a27a4135c4 (diff)
parent6a674e1e83db097d7a31a3786d12e42987f09f70 (diff)
fix pokeblock conflicts
Diffstat (limited to 'src')
-rw-r--r--src/battle_2.c40
-rw-r--r--src/battle_message.c7
-rw-r--r--src/battle_script_commands.c9
-rw-r--r--src/battle_setup.c1884
-rw-r--r--src/berry_blender.c2
-rwxr-xr-xsrc/clear_save_data_screen.c2
-rw-r--r--src/clock.c93
-rw-r--r--src/egg_hatch.c4
-rw-r--r--src/evolution_scene.c2
-rw-r--r--src/load_save.c6
-rw-r--r--src/mail.c302
-rw-r--r--src/mail_data.c203
-rw-r--r--src/pokemon_2.c2
-rw-r--r--src/pokemon_3.c87
-rw-r--r--src/recorded_battle.c2
-rw-r--r--src/safari_zone.c2
-rw-r--r--src/scrcmd.c32
-rw-r--r--src/secret_base.c2
-rw-r--r--src/starter_choose.c2
-rw-r--r--src/trainer_see.c68
-rw-r--r--src/tv.c2
-rw-r--r--src/wallclock.c1057
22 files changed, 3560 insertions, 250 deletions
diff --git a/src/battle_2.c b/src/battle_2.c
index 52530f6b3..7bde3d174 100644
--- a/src/battle_2.c
+++ b/src/battle_2.c
@@ -17,6 +17,7 @@
#include "item.h"
#include "constants/items.h"
#include "constants/hold_effects.h"
+#include "constants/trainers.h"
#include "link.h"
#include "bg.h"
#include "dma3.h"
@@ -38,7 +39,6 @@
#include "pokedex.h"
#include "constants/abilities.h"
#include "constants/moves.h"
-#include "trainer_classes.h"
#include "evolution_scene.h"
#include "roamer.h"
#include "tv.h"
@@ -185,7 +185,7 @@ extern void sub_80356D0(void);
extern void GetFrontierTrainerName(u8* dst, u16 trainerId); // battle tower
extern void sub_8166188(void); // battle tower, sets link battle mons level but why?
extern void sub_8165B88(u8* dst, u16 trainerId); // battle tower, gets language
-extern void sub_81DB4DC(u8* dst, u8 arg2); //
+extern void PadNameString(u8* dst, u8 arg2); //
extern void sub_81B9150(void);
extern void sub_800AC34(void);
extern void sub_80B3AF8(u8 taskId); // cable club
@@ -415,7 +415,7 @@ static void CB2_InitBattleInternal(void)
gBattleTerrain = BattleSetup_GetTerrainId();
if (gBattleTypeFlags & BATTLE_TYPE_RECORDED)
- gBattleTerrain = BATTLE_TERRAIN_INSIDE;
+ gBattleTerrain = BATTLE_TERRAIN_BUILDING;
sub_80356D0();
LoadBattleTextboxAndBackground();
@@ -1140,7 +1140,7 @@ static void sub_80379F8(u8 arrayIdPlus)
gUnknown_02022FF8[i].gender = GetMonGender(&gPlayerParty[arrayIdPlus + i]);
StripExtCtrlCodes(gUnknown_02022FF8[i].nickname);
if (GetMonData(&gPlayerParty[arrayIdPlus + i], MON_DATA_LANGUAGE) != LANGUAGE_JAPANESE)
- sub_81DB4DC(gUnknown_02022FF8[i].nickname, 0);
+ PadNameString(gUnknown_02022FF8[i].nickname, CHAR_SPACE);
}
memcpy(gUnknown_02023058, gUnknown_02022FF8, sizeof(gUnknown_02022FF8));
}
@@ -1718,7 +1718,7 @@ static u8 CreateNPCTrainerParty(struct Pokemon *party, u16 trainerNum, bool8 fir
{
const struct TrainerMonNoItemDefaultMoves *partyData = gTrainers[trainerNum].party.NoItemDefaultMoves;
- for (j = 0; gSpeciesNames[partyData[i].species][j] != 0xFF; j++)
+ for (j = 0; gSpeciesNames[partyData[i].species][j] != EOS; j++)
nameHash += gSpeciesNames[partyData[i].species][j];
personalityValue += nameHash << 8;
@@ -1726,11 +1726,11 @@ static u8 CreateNPCTrainerParty(struct Pokemon *party, u16 trainerNum, bool8 fir
CreateMon(&party[i], partyData[i].species, partyData[i].lvl, fixedIV, TRUE, personalityValue, OT_ID_RANDOM_NO_SHINY, 0);
break;
}
- case PARTY_FLAG_CUSTOM_MOVES:
+ case F_TRAINER_PARTY_CUSTOM_MOVESET:
{
const struct TrainerMonNoItemCustomMoves *partyData = gTrainers[trainerNum].party.NoItemCustomMoves;
- for (j = 0; gSpeciesNames[partyData[i].species][j] != 0xFF; j++)
+ for (j = 0; gSpeciesNames[partyData[i].species][j] != EOS; j++)
nameHash += gSpeciesNames[partyData[i].species][j];
personalityValue += nameHash << 8;
@@ -1744,11 +1744,11 @@ static u8 CreateNPCTrainerParty(struct Pokemon *party, u16 trainerNum, bool8 fir
}
break;
}
- case PARTY_FLAG_HAS_ITEM:
+ case F_TRAINER_PARTY_HELD_ITEM:
{
const struct TrainerMonItemDefaultMoves *partyData = gTrainers[trainerNum].party.ItemDefaultMoves;
- for (j = 0; gSpeciesNames[partyData[i].species][j] != 0xFF; j++)
+ for (j = 0; gSpeciesNames[partyData[i].species][j] != EOS; j++)
nameHash += gSpeciesNames[partyData[i].species][j];
personalityValue += nameHash << 8;
@@ -1758,11 +1758,11 @@ static u8 CreateNPCTrainerParty(struct Pokemon *party, u16 trainerNum, bool8 fir
SetMonData(&party[i], MON_DATA_HELD_ITEM, &partyData[i].heldItem);
break;
}
- case PARTY_FLAG_CUSTOM_MOVES | PARTY_FLAG_HAS_ITEM:
+ case F_TRAINER_PARTY_CUSTOM_MOVESET | F_TRAINER_PARTY_HELD_ITEM:
{
const struct TrainerMonItemCustomMoves *partyData = gTrainers[trainerNum].party.ItemCustomMoves;
- for (j = 0; gSpeciesNames[partyData[i].species][j] != 0xFF; j++)
+ for (j = 0; gSpeciesNames[partyData[i].species][j] != EOS; j++)
nameHash += gSpeciesNames[partyData[i].species][j];
personalityValue += nameHash << 8;
@@ -4749,19 +4749,19 @@ static void HandleEndTurn_BattleWon(void)
switch (gTrainers[gTrainerBattleOpponent_A].trainerClass)
{
- case CLASS_ELITE_FOUR:
- case CLASS_CHAMPION:
+ case TRAINER_CLASS_ELITE_FOUR:
+ case TRAINER_CLASS_CHAMPION:
PlayBGM(BGM_KACHI5);
break;
- case CLASS_TEAM_AQUA:
- case CLASS_TEAM_MAGMA:
- case CLASS_AQUA_ADMIN:
- case CLASS_AQUA_LEADER:
- case CLASS_MAGMA_ADMIN:
- case CLASS_MAGMA_LEADER:
+ case TRAINER_CLASS_TEAM_AQUA:
+ case TRAINER_CLASS_TEAM_MAGMA:
+ case TRAINER_CLASS_AQUA_ADMIN:
+ case TRAINER_CLASS_AQUA_LEADER:
+ case TRAINER_CLASS_MAGMA_ADMIN:
+ case TRAINER_CLASS_MAGMA_LEADER:
PlayBGM(BGM_KACHI4);
break;
- case CLASS_LEADER:
+ case TRAINER_CLASS_LEADER:
PlayBGM(BGM_KACHI3);
break;
default:
diff --git a/src/battle_message.c b/src/battle_message.c
index ec1cfd626..cab4bdf42 100644
--- a/src/battle_message.c
+++ b/src/battle_message.c
@@ -12,6 +12,7 @@
#include "window.h"
#include "palette.h"
#include "battle_controllers.h"
+#include "battle_setup.h"
extern u16 gLastUsedItem;
extern u8 gLastUsedAbility;
@@ -54,8 +55,6 @@ extern void sub_81D5554(u8 *txtPtr, u16 trainerId); // pokenav
extern void GetEreaderTrainerName(u8 *txtPtr);
extern void sub_81A36D0(u8 arg0, u16 trainerId); // battle_frontier_2
extern void sub_81D572C(u8 arg0, u16 trainerId); // pokenav
-extern const u8* GetTrainer1LoseText(void); // battle_setup
-extern const u8* GetTrainer2LoseText(void); // battle_setup
extern void GetFrontierTrainerName(u8 *dst, u16 trainerId);
extern s32 GetStringCenterAlignXOffsetWithLetterSpacing(u8 fontId, const u8 *str, s32 totalWidth, s16 letterSpacing);
extern u8 GetTextSpeedInRecordedBattle(void);
@@ -2068,7 +2067,7 @@ u32 BattleStringExpandPlaceholders(const u8* src, u8* dst)
}
else
{
- toCpy = GetTrainer1LoseText();
+ toCpy = GetTrainerALoseText();
}
break;
case B_TXT_TRAINER1_WIN_TEXT: // trainerA win text
@@ -2165,7 +2164,7 @@ u32 BattleStringExpandPlaceholders(const u8* src, u8* dst)
}
else
{
- toCpy = GetTrainer2LoseText();
+ toCpy = GetTrainerBLoseText();
}
break;
case B_TXT_TRAINER2_WIN_TEXT:
diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c
index 88d583c1f..656f9f43a 100644
--- a/src/battle_script_commands.c
+++ b/src/battle_script_commands.c
@@ -17,6 +17,7 @@
#include "battle_interface.h"
#include "constants/species.h"
#include "constants/songs.h"
+#include "constants/trainers.h"
#include "text.h"
#include "sound.h"
#include "pokedex.h"
@@ -6236,19 +6237,19 @@ static u32 GetTrainerMoneyToGive(u16 trainerId)
lastMonLevel = party[gTrainers[trainerId].partySize - 1].lvl;
}
break;
- case PARTY_FLAG_CUSTOM_MOVES:
+ case F_TRAINER_PARTY_CUSTOM_MOVESET:
{
const struct TrainerMonNoItemCustomMoves *party = gTrainers[trainerId].party.NoItemCustomMoves;
lastMonLevel = party[gTrainers[trainerId].partySize - 1].lvl;
}
break;
- case PARTY_FLAG_HAS_ITEM:
+ case F_TRAINER_PARTY_HELD_ITEM:
{
const struct TrainerMonItemDefaultMoves *party = gTrainers[trainerId].party.ItemDefaultMoves;
lastMonLevel = party[gTrainers[trainerId].partySize - 1].lvl;
}
break;
- case PARTY_FLAG_CUSTOM_MOVES | PARTY_FLAG_HAS_ITEM:
+ case F_TRAINER_PARTY_CUSTOM_MOVESET | F_TRAINER_PARTY_HELD_ITEM:
{
const struct TrainerMonItemCustomMoves *party = gTrainers[trainerId].party.ItemCustomMoves;
lastMonLevel = party[gTrainers[trainerId].partySize - 1].lvl;
@@ -10334,7 +10335,7 @@ static void atkE4_getsecretpowereffect(void)
case BATTLE_TERRAIN_POND:
gBattleCommunication[MOVE_EFFECT_BYTE] = MOVE_EFFECT_SPD_MINUS_1;
break;
- case BATTLE_TERRAIN_ROCK:
+ case BATTLE_TERRAIN_MOUNTAIN:
gBattleCommunication[MOVE_EFFECT_BYTE] = MOVE_EFFECT_CONFUSION;
break;
case BATTLE_TERRAIN_CAVE:
diff --git a/src/battle_setup.c b/src/battle_setup.c
new file mode 100644
index 000000000..3d4f5afcc
--- /dev/null
+++ b/src/battle_setup.c
@@ -0,0 +1,1884 @@
+#include "global.h"
+#include "constants/trainers.h"
+#include "battle.h"
+#include "battle_setup.h"
+#include "battle_transition.h"
+#include "main.h"
+#include "task.h"
+#include "pokemon_3.h"
+#include "safari_zone.h"
+#include "script.h"
+#include "constants/game_stat.h"
+#include "event_data.h"
+#include "constants/species.h"
+#include "songs.h"
+#include "metatile_behavior.h"
+#include "constants/maps.h"
+#include "field_player_avatar.h"
+#include "fieldmap.h"
+#include "random.h"
+#include "starter_choose.h"
+#include "script_pokemon_80F8.h"
+#include "constants/items.h"
+#include "palette.h"
+#include "window.h"
+#include "field_map_obj.h"
+#include "event_scripts.h"
+#include "trainer_see.h"
+#include "field_message_box.h"
+#include "sound.h"
+#include "strings.h"
+#include "secret_base.h"
+#include "string_util.h"
+
+enum
+{
+ TRAINER_PARAM_LOAD_VAL_8BIT,
+ TRAINER_PARAM_LOAD_VAL_16BIT,
+ TRAINER_PARAM_LOAD_VAL_32BIT,
+ TRAINER_PARAM_CLEAR_VAL_8BIT,
+ TRAINER_PARAM_CLEAR_VAL_16BIT,
+ TRAINER_PARAM_CLEAR_VAL_32BIT,
+ TRAINER_PARAM_LOAD_SCRIPT_RET_ADDR,
+};
+
+struct TrainerBattleParameter
+{
+ void *varPtr;
+ u8 ptrType;
+};
+
+extern bool8 InBattlePyramid(void);
+extern bool8 InBattlePike(void);
+extern bool32 InTrainerHill(void);
+extern bool32 FieldPoisonEffectIsRunning(void);
+extern void overworld_free_bg_tilemaps(void);
+extern void prev_quest_postbuffer_cursor_backup_reset(void);
+extern void ResetPoisonStepCounter(void);
+extern void sub_81BE72C(void);
+extern void FreezeMapObjects(void);
+extern void sub_808BCF4(void);
+extern void sub_80EECC8(void);
+extern void c2_exit_to_overworld_1_continue_scripts_restart_music(void);
+extern void c2_exit_to_overworld_2_switch(void);
+extern void Overworld_ClearSavedMusic(void);
+extern void CB2_WhiteOut(void);
+extern void sub_80AF6F0(void);
+extern void PlayBattleBGM(void);
+extern void sub_81DA57C(void);
+extern u8 GetSav1Weather(void);
+extern u8 Overworld_GetFlashLevel(void);
+extern u16 sub_81A9AA8(u8 localId);
+extern u16 sub_81D6180(u8 localId);
+extern bool8 GetBattlePyramidTrainerFlag(u8 mapObjId);
+extern bool8 GetTrainerHillTrainerFlag(u8 mapObjId);
+extern bool8 sub_81D5C18(void);
+extern void sub_816306C(u8 a0);
+extern void sub_8163048(u8 a0);
+extern void sub_81A9B04(void);
+extern void sub_81D639C(void);
+extern void sub_81D6384(void);
+extern void sub_81D61E8(void);
+extern void sub_80982B8(void);
+extern void sub_81A9EDC(u16 a0);
+extern void sub_81D572C(u8 a0, u16 arg1);
+extern void IncrementGameStat(u8 statId);
+extern u32 GetGameStat(u8 statId);
+
+extern u32 gBattleTypeFlags;
+extern u8 gBattleOutcome;
+extern void (*gFieldCallback)(void);
+extern u8 gApproachingTrainerId;
+extern u8 gNoOfApproachingTrainers;
+extern u16 gUnknown_03006080;
+
+// this file's functions
+static void DoBattlePikeWildBattle(void);
+static void DoSafariBattle(void);
+static void DoStandardWildBattle(void);
+static void CB2_EndWildBattle(void);
+static void CB2_EndScriptedWildBattle(void);
+static u8 GetWildBattleTransition(void);
+static u8 GetTrainerBattleTransition(void);
+static void sub_80B1218(void);
+static void sub_80B1234(void);
+static void CB2_GiveStarter(void);
+static void CB2_StartFirstBattle(void);
+static void CB2_EndFirstBattle(void);
+static void CB2_EndTrainerBattle(void);
+static bool32 IsPlayerDefeated(u32 battleOutcome);
+static u16 GetRematchTrainerId(u16 trainerId);
+static void RegisterTrainerInMatchCall(void);
+static void HandleRematchVarsOnBattleEnd(void);
+static const u8 *GetIntroSpeechOfApproachingTrainer(void);
+static const u8 *GetTrainerCantBattleSpeech(void);
+
+// ewram data
+EWRAM_DATA static u16 sTrainerBattleMode = 0;
+EWRAM_DATA u16 gTrainerBattleOpponent_A = 0;
+EWRAM_DATA u16 gTrainerBattleOpponent_B = 0;
+EWRAM_DATA u16 gPartnerTrainerId = 0;
+EWRAM_DATA static u16 sTrainerMapObjectLocalId = 0;
+EWRAM_DATA static u8 *sTrainerAIntroSpeech = NULL;
+EWRAM_DATA static u8 *sTrainerBIntroSpeech = NULL;
+EWRAM_DATA static u8 *sTrainerADefeatSpeech = NULL;
+EWRAM_DATA static u8 *sTrainerBDefeatSpeech = NULL;
+EWRAM_DATA static u8 *sTrainerVictorySpeech = NULL;
+EWRAM_DATA static u8 *sTrainerCannotBattleSpeech = NULL;
+EWRAM_DATA static u8 *sTrainerBattleEndScript = NULL;
+EWRAM_DATA static u8 *sTrainerABattleScriptRetAddr = NULL;
+EWRAM_DATA static u8 *sTrainerBBattleScriptRetAddr = NULL;
+EWRAM_DATA static bool8 sShouldCheckTrainerBScript = FALSE;
+EWRAM_DATA static u8 sNoOfPossibleTrainerRetScripts = 0;
+
+// const rom data
+
+// The first transition is used if the enemy pokemon are lower level than our pokemon.
+// Otherwise, the second transition is used.
+static const u8 sBattleTransitionTable_Wild[][2] =
+{
+ {B_TRANSITION_SLICE, B_TRANSITION_WHITEFADE}, // Normal
+ {B_TRANSITION_CLOCKWISE_BLACKFADE, B_TRANSITION_GRID_SQUARES}, // Cave
+ {B_TRANSITION_BLUR, B_TRANSITION_GRID_SQUARES}, // Cave with flash used
+ {B_TRANSITION_WAVE, B_TRANSITION_RIPPLE}, // Water
+};
+
+static const u8 sBattleTransitionTable_Trainer[][2] =
+{
+ {B_TRANSITION_POKEBALLS_TRAIL, B_TRANSITION_SHARDS}, // Normal
+ {B_TRANSITION_SHUFFLE, B_TRANSITION_BIG_POKEBALL}, // Cave
+ {B_TRANSITION_BLUR, B_TRANSITION_GRID_SQUARES}, // Cave with flash used
+ {B_TRANSITION_SWIRL, B_TRANSITION_RIPPLE}, // Water
+};
+
+static const u8 sUnknown_0854FE98[] =
+{
+ B_TRANSITION_29, B_TRANSITION_30, B_TRANSITION_31, B_TRANSITION_32,
+ B_TRANSITION_34, B_TRANSITION_35, B_TRANSITION_36, B_TRANSITION_37,
+ B_TRANSITION_38, B_TRANSITION_39, B_TRANSITION_40, B_TRANSITION_41
+};
+
+static const u8 sUnknown_0854FEA4[] =
+{
+ B_TRANSITION_31, B_TRANSITION_32, B_TRANSITION_33
+};
+
+static const u8 sUnknown_0854FEA7[] =
+{
+ B_TRANSITION_29, B_TRANSITION_31, B_TRANSITION_32, B_TRANSITION_33
+};
+
+static const struct TrainerBattleParameter sOrdinaryBattleParams[] =
+{
+ {&sTrainerBattleMode, TRAINER_PARAM_LOAD_VAL_8BIT},
+ {&gTrainerBattleOpponent_A, TRAINER_PARAM_LOAD_VAL_16BIT},
+ {&sTrainerMapObjectLocalId, TRAINER_PARAM_LOAD_VAL_16BIT},
+ {&sTrainerAIntroSpeech, TRAINER_PARAM_LOAD_VAL_32BIT},
+ {&sTrainerADefeatSpeech, TRAINER_PARAM_LOAD_VAL_32BIT},
+ {&sTrainerVictorySpeech, TRAINER_PARAM_CLEAR_VAL_32BIT},
+ {&sTrainerCannotBattleSpeech, TRAINER_PARAM_CLEAR_VAL_32BIT},
+ {&sTrainerABattleScriptRetAddr, TRAINER_PARAM_CLEAR_VAL_32BIT},
+ {&sTrainerBattleEndScript, TRAINER_PARAM_LOAD_SCRIPT_RET_ADDR},
+};
+
+static const struct TrainerBattleParameter sContinueScriptBattleParams[] =
+{
+ {&sTrainerBattleMode, TRAINER_PARAM_LOAD_VAL_8BIT},
+ {&gTrainerBattleOpponent_A, TRAINER_PARAM_LOAD_VAL_16BIT},
+ {&sTrainerMapObjectLocalId, TRAINER_PARAM_LOAD_VAL_16BIT},
+ {&sTrainerAIntroSpeech, TRAINER_PARAM_LOAD_VAL_32BIT},
+ {&sTrainerADefeatSpeech, TRAINER_PARAM_LOAD_VAL_32BIT},
+ {&sTrainerVictorySpeech, TRAINER_PARAM_CLEAR_VAL_32BIT},
+ {&sTrainerCannotBattleSpeech, TRAINER_PARAM_CLEAR_VAL_32BIT},
+ {&sTrainerABattleScriptRetAddr, TRAINER_PARAM_LOAD_VAL_32BIT},
+ {&sTrainerBattleEndScript, TRAINER_PARAM_LOAD_SCRIPT_RET_ADDR},
+};
+
+static const struct TrainerBattleParameter sDoubleBattleParams[] =
+{
+ {&sTrainerBattleMode, TRAINER_PARAM_LOAD_VAL_8BIT},
+ {&gTrainerBattleOpponent_A, TRAINER_PARAM_LOAD_VAL_16BIT},
+ {&sTrainerMapObjectLocalId, TRAINER_PARAM_LOAD_VAL_16BIT},
+ {&sTrainerAIntroSpeech, TRAINER_PARAM_LOAD_VAL_32BIT},
+ {&sTrainerADefeatSpeech, TRAINER_PARAM_LOAD_VAL_32BIT},
+ {&sTrainerVictorySpeech, TRAINER_PARAM_CLEAR_VAL_32BIT},
+ {&sTrainerCannotBattleSpeech, TRAINER_PARAM_LOAD_VAL_32BIT},
+ {&sTrainerABattleScriptRetAddr, TRAINER_PARAM_CLEAR_VAL_32BIT},
+ {&sTrainerBattleEndScript, TRAINER_PARAM_LOAD_SCRIPT_RET_ADDR},
+};
+
+static const struct TrainerBattleParameter sOrdinaryNoIntroBattleParams[] =
+{
+ {&sTrainerBattleMode, TRAINER_PARAM_LOAD_VAL_8BIT},
+ {&gTrainerBattleOpponent_A, TRAINER_PARAM_LOAD_VAL_16BIT},
+ {&sTrainerMapObjectLocalId, TRAINER_PARAM_LOAD_VAL_16BIT},
+ {&sTrainerAIntroSpeech, TRAINER_PARAM_CLEAR_VAL_32BIT},
+ {&sTrainerADefeatSpeech, TRAINER_PARAM_LOAD_VAL_32BIT},
+ {&sTrainerVictorySpeech, TRAINER_PARAM_CLEAR_VAL_32BIT},
+ {&sTrainerCannotBattleSpeech, TRAINER_PARAM_CLEAR_VAL_32BIT},
+ {&sTrainerABattleScriptRetAddr, TRAINER_PARAM_CLEAR_VAL_32BIT},
+ {&sTrainerBattleEndScript, TRAINER_PARAM_LOAD_SCRIPT_RET_ADDR},
+};
+
+static const struct TrainerBattleParameter sContinueScriptDoubleBattleParams[] =
+{
+ {&sTrainerBattleMode, TRAINER_PARAM_LOAD_VAL_8BIT},
+ {&gTrainerBattleOpponent_A, TRAINER_PARAM_LOAD_VAL_16BIT},
+ {&sTrainerMapObjectLocalId, TRAINER_PARAM_LOAD_VAL_16BIT},
+ {&sTrainerAIntroSpeech, TRAINER_PARAM_LOAD_VAL_32BIT},
+ {&sTrainerADefeatSpeech, TRAINER_PARAM_LOAD_VAL_32BIT},
+ {&sTrainerVictorySpeech, TRAINER_PARAM_CLEAR_VAL_32BIT},
+ {&sTrainerCannotBattleSpeech, TRAINER_PARAM_LOAD_VAL_32BIT},
+ {&sTrainerABattleScriptRetAddr, TRAINER_PARAM_LOAD_VAL_32BIT},
+ {&sTrainerBattleEndScript, TRAINER_PARAM_LOAD_SCRIPT_RET_ADDR},
+};
+
+static const struct TrainerBattleParameter sTrainerBOrdinaryBattleParams[] =
+{
+ {&sTrainerBattleMode, TRAINER_PARAM_LOAD_VAL_8BIT},
+ {&gTrainerBattleOpponent_B, TRAINER_PARAM_LOAD_VAL_16BIT},
+ {&sTrainerMapObjectLocalId, TRAINER_PARAM_LOAD_VAL_16BIT},
+ {&sTrainerBIntroSpeech, TRAINER_PARAM_LOAD_VAL_32BIT},
+ {&sTrainerBDefeatSpeech, TRAINER_PARAM_LOAD_VAL_32BIT},
+ {&sTrainerVictorySpeech, TRAINER_PARAM_CLEAR_VAL_32BIT},
+ {&sTrainerCannotBattleSpeech, TRAINER_PARAM_CLEAR_VAL_32BIT},
+ {&sTrainerBBattleScriptRetAddr, TRAINER_PARAM_CLEAR_VAL_32BIT},
+ {&sTrainerBattleEndScript, TRAINER_PARAM_LOAD_SCRIPT_RET_ADDR},
+};
+
+static const struct TrainerBattleParameter sTrainerBContinueScriptBattleParams[] =
+{
+ {&sTrainerBattleMode, TRAINER_PARAM_LOAD_VAL_8BIT},
+ {&gTrainerBattleOpponent_B, TRAINER_PARAM_LOAD_VAL_16BIT},
+ {&sTrainerMapObjectLocalId, TRAINER_PARAM_LOAD_VAL_16BIT},
+ {&sTrainerBIntroSpeech, TRAINER_PARAM_LOAD_VAL_32BIT},
+ {&sTrainerBDefeatSpeech, TRAINER_PARAM_LOAD_VAL_32BIT},
+ {&sTrainerVictorySpeech, TRAINER_PARAM_CLEAR_VAL_32BIT},
+ {&sTrainerCannotBattleSpeech, TRAINER_PARAM_CLEAR_VAL_32BIT},
+ {&sTrainerBBattleScriptRetAddr, TRAINER_PARAM_LOAD_VAL_32BIT},
+ {&sTrainerBattleEndScript, TRAINER_PARAM_LOAD_SCRIPT_RET_ADDR},
+};
+
+const struct RematchTrainer gRematchTable[REMATCH_TABLE_ENTRIES] =
+{
+ {{0x0025, 0x0028, 0x0029, 0x002a, 0x002b}, 0x0000, 0x0021},
+ {{0x02e1, 0x032c, 0x032d, 0x032e, 0x032f}, 0x0000, 0x0014},
+ {{0x002c, 0x002f, 0x0030, 0x0031, 0x0032}, 0x0000, 0x001a},
+ {{0x0039, 0x003c, 0x003d, 0x003e, 0x003f}, 0x0000, 0x0018},
+ {{0x0040, 0x0043, 0x0044, 0x0045, 0x0046}, 0x0000, 0x0018},
+ {{0x02af, 0x02b0, 0x02b1, 0x02b2, 0x02b3}, 0x0000, 0x0027},
+ {{0x02ff, 0x033c, 0x033d, 0x033e, 0x033f}, 0x0000, 0x0024},
+ {{0x005e, 0x0065, 0x0066, 0x0067, 0x0068}, 0x0000, 0x001a},
+ {{0x004e, 0x0054, 0x0055, 0x0056, 0x0057}, 0x0000, 0x001a},
+ {{0x006c, 0x006e, 0x006f, 0x0070, 0x0071}, 0x0018, 0x0014},
+ {{0x0072, 0x0078, 0x0079, 0x007a, 0x007b}, 0x0000, 0x0013},
+ {{0x0090, 0x034c, 0x034d, 0x034e, 0x034f}, 0x0018, 0x0038},
+ {{0x007f, 0x0084, 0x0085, 0x0086, 0x0087}, 0x0000, 0x0024},
+ {{0x0088, 0x008b, 0x008c, 0x008d, 0x008e}, 0x0000, 0x0013},
+ {{0x008f, 0x0093, 0x0094, 0x0095, 0x0096}, 0x0000, 0x001d},
+ {{0x009b, 0x00af, 0x00b0, 0x00b1, 0x00b2}, 0x0000, 0x0016},
+ {{0x00b7, 0x00b8, 0x00b9, 0x00ba, 0x00bb}, 0x0000, 0x001e},
+ {{0x02a0, 0x0338, 0x0339, 0x033a, 0x033b}, 0x0000, 0x002a},
+ {{0x00c3, 0x0340, 0x0341, 0x0342, 0x0343}, 0x0000, 0x0026},
+ {{0x00c4, 0x00c5, 0x00c6, 0x00c7, 0x00c8}, 0x0000, 0x0021},
+ {{0x00ce, 0x00cf, 0x00d0, 0x00d1, 0x00d2}, 0x0000, 0x001d},
+ {{0x00d8, 0x00db, 0x00dc, 0x00dd, 0x00de}, 0x0018, 0x000d},
+ {{0x02a9, 0x02aa, 0x02ab, 0x02ac, 0x02ad}, 0x0018, 0x0001},
+ {{0x00e2, 0x00e4, 0x00e5, 0x00e6, 0x00e7}, 0x0000, 0x0023},
+ {{0x00ee, 0x00ef, 0x00f0, 0x00f1, 0x00f2}, 0x0000, 0x0026},
+ {{0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd}, 0x0000, 0x0026},
+ {{0x00fe, 0x0101, 0x0102, 0x0103, 0x0104}, 0x0000, 0x0024},
+ {{0x0118, 0x011a, 0x011b, 0x011c, 0x011d}, 0x0000, 0x001f},
+ {{0x0111, 0x0114, 0x0115, 0x0116, 0x0117}, 0x0000, 0x001f},
+ {{0x011f, 0x0120, 0x0121, 0x0122, 0x0123}, 0x0000, 0x0020},
+ {{0x012e, 0x012f, 0x0130, 0x0131, 0x0132}, 0x0000, 0x0019},
+ {{0x0125, 0x0127, 0x0128, 0x0129, 0x012a}, 0x0000, 0x0012},
+ {{0x0133, 0x0134, 0x0135, 0x0136, 0x0137}, 0x0000, 0x001e},
+ {{0x0139, 0x013a, 0x013b, 0x013c, 0x013d}, 0x0018, 0x000c},
+ {{0x013e, 0x0148, 0x0149, 0x014a, 0x014b}, 0x0000, 0x0011},
+ {{0x0153, 0x015a, 0x015b, 0x015c, 0x015d}, 0x0000, 0x0015},
+ {{0x0178, 0x017b, 0x017c, 0x017d, 0x017e}, 0x0000, 0x002b},
+ {{0x0171, 0x0172, 0x0173, 0x0174, 0x0175}, 0x0000, 0x0020},
+ {{0x0166, 0x0168, 0x0169, 0x016a, 0x016b}, 0x0000, 0x0019},
+ {{0x016c, 0x016d, 0x016e, 0x016f, 0x0170}, 0x0000, 0x0020},
+ {{0x0182, 0x0184, 0x0185, 0x0186, 0x0187}, 0x0000, 0x002b},
+ {{0x0161, 0x0162, 0x0163, 0x0164, 0x0165}, 0x0000, 0x0019},
+ {{0x0179, 0x0334, 0x0335, 0x0336, 0x0337}, 0x0000, 0x0029},
+ {{0x0188, 0x0189, 0x018a, 0x018b, 0x018c}, 0x0018, 0x0001},
+ {{0x0196, 0x0199, 0x019a, 0x019b, 0x019c}, 0x0000, 0x0023},
+ {{0x01a3, 0x01a5, 0x01a6, 0x01a7, 0x01a8}, 0x0000, 0x001c},
+ {{0x01ab, 0x01ae, 0x01af, 0x01b0, 0x01b1}, 0x0000, 0x001e},
+ {{0x01b2, 0x01b5, 0x01b6, 0x01b7, 0x01b8}, 0x0000, 0x001c},
+ {{0x01c1, 0x01d1, 0x01d2, 0x01d3, 0x01d4}, 0x0000, 0x0027},
+ {{0x01da, 0x01dd, 0x01de, 0x01df, 0x01e0}, 0x0018, 0x000d},
+ {{0x01e1, 0x01e2, 0x01e7, 0x01e8, 0x01e9}, 0x0000, 0x0012},
+ {{0x01ec, 0x01f1, 0x01f2, 0x01f3, 0x01f4}, 0x0000, 0x0028},
+ {{0x02e4, 0x0330, 0x0331, 0x0332, 0x0333}, 0x0000, 0x0017},
+ {{0x0200, 0x0203, 0x0204, 0x0205, 0x0206}, 0x0000, 0x0019},
+ {{0x0221, 0x0224, 0x0225, 0x0226, 0x0227}, 0x0000, 0x0020},
+ {{0x021a, 0x021d, 0x021e, 0x021f, 0x0220}, 0x0000, 0x0020},
+ {{0x0009, 0x0348, 0x0349, 0x034a, 0x034b}, 0x0018, 0x0011},
+ {{0x022f, 0x0232, 0x0233, 0x0234, 0x0235}, 0x0000, 0x0022},
+ {{0x0228, 0x022b, 0x022c, 0x022d, 0x022e}, 0x0000, 0x0022},
+ {{0x025c, 0x025f, 0x0260, 0x0261, 0x0262}, 0x0000, 0x0013},
+ {{0x026d, 0x026e, 0x026f, 0x0270, 0x0271}, 0x0018, 0x000b},
+ {{0x0273, 0x027c, 0x027d, 0x027e, 0x027f}, 0x0000, 0x001b},
+ {{0x0001, 0x0344, 0x0345, 0x0346, 0x0347}, 0x0018, 0x000c},
+ {{0x0282, 0x0283, 0x0284, 0x0285, 0x0286}, 0x0018, 0x003e},
+ {{0x0291, 0x0292, 0x0293, 0x0294, 0x0294}, 0x0018, 0x002b},
+ {{0x0109, 0x0302, 0x0303, 0x0304, 0x0305}, 0x0000, 0x0003},
+ {{0x010a, 0x0306, 0x0307, 0x0308, 0x0309}, 0x0000, 0x000b},
+ {{0x010b, 0x030a, 0x030b, 0x030c, 0x030d}, 0x0000, 0x0002},
+ {{0x010c, 0x030e, 0x030f, 0x0310, 0x0311}, 0x0000, 0x000c},
+ {{0x010d, 0x0312, 0x0313, 0x0314, 0x0315}, 0x0000, 0x0000},
+ {{0x010e, 0x0316, 0x0317, 0x0318, 0x0319}, 0x0000, 0x0004},
+ {{0x010f, 0x031a, 0x031b, 0x031c, 0x031d}, 0x0000, 0x0006},
+ {{0x0110, 0x031e, 0x031f, 0x0320, 0x0321}, 0x0000, 0x0007},
+ {{0x0105, 0x0105, 0x0105, 0x0105, 0x0105}, 0x0000, 0x0008},
+ {{0x0106, 0x0106, 0x0106, 0x0106, 0x0106}, 0x0000, 0x0008},
+ {{0x0107, 0x0107, 0x0107, 0x0107, 0x0107}, 0x0000, 0x0008},
+ {{0x0108, 0x0108, 0x0108, 0x0108, 0x0108}, 0x0000, 0x0008},
+ {{0x014f, 0x014f, 0x014f, 0x014f, 0x014f}, 0x0000, 0x0008},
+};
+
+static const u16 sBadgeFlags[8] =
+{
+ FLAG_BADGE01_GET, FLAG_BADGE02_GET, FLAG_BADGE03_GET, FLAG_BADGE04_GET,
+ FLAG_BADGE05_GET, FLAG_BADGE06_GET, FLAG_BADGE07_GET, FLAG_BADGE08_GET,
+};
+
+#define tState data[0]
+#define tTransition data[1]
+
+static void Task_BattleStart(u8 taskId)
+{
+ s16 *data = gTasks[taskId].data;
+
+ switch (tState)
+ {
+ case 0:
+ if (!FieldPoisonEffectIsRunning()) // is poison not active?
+ {
+ BattleTransition_StartOnField(tTransition);
+ sub_81BE72C();
+ tState++; // go to case 1.
+ }
+ break;
+ case 1:
+ if (IsBattleTransitionDone() == TRUE)
+ {
+ overworld_free_bg_tilemaps();
+ SetMainCallback2(CB2_InitBattle);
+ prev_quest_postbuffer_cursor_backup_reset();
+ ResetPoisonStepCounter();
+ DestroyTask(taskId);
+ }
+ break;
+ }
+}
+
+static void CreateBattleStartTask(u8 transition, u16 song)
+{
+ u8 taskId = CreateTask(Task_BattleStart, 1);
+
+ gTasks[taskId].tTransition = transition;
+ PlayMapChosenOrBattleBGM(song);
+}
+
+#undef tState
+#undef tTransition
+
+void BattleSetup_StartWildBattle(void)
+{
+ if (GetSafariZoneFlag())
+ DoSafariBattle();
+ else
+ DoStandardWildBattle();
+}
+
+void BattleSetup_StartBattlePikeWildBattle(void)
+{
+ DoBattlePikeWildBattle();
+}
+
+static void DoStandardWildBattle(void)
+{
+ ScriptContext2_Enable();
+ FreezeMapObjects();
+ sub_808BCF4();
+ gMain.savedCallback = CB2_EndWildBattle;
+ gBattleTypeFlags = 0;
+ if (InBattlePyramid())
+ {
+ VarSet(VAR_0x400E, 0);
+ gBattleTypeFlags |= BATTLE_TYPE_PYRAMID;
+ }
+ CreateBattleStartTask(GetWildBattleTransition(), 0);
+ IncrementGameStat(GAME_STAT_TOTAL_BATTLES);
+ IncrementGameStat(GAME_STAT_WILD_BATTLES);
+ sub_80EECC8();
+ sub_80B1218();
+}
+
+void BattleSetup_StartRoamerBattle(void)
+{
+ ScriptContext2_Enable();
+ FreezeMapObjects();
+ sub_808BCF4();
+ gMain.savedCallback = CB2_EndWildBattle;
+ gBattleTypeFlags = BATTLE_TYPE_ROAMER;
+ CreateBattleStartTask(GetWildBattleTransition(), 0);
+ IncrementGameStat(GAME_STAT_TOTAL_BATTLES);
+ IncrementGameStat(GAME_STAT_WILD_BATTLES);
+ sub_80EECC8();
+ sub_80B1218();
+}
+
+static void DoSafariBattle(void)
+{
+ ScriptContext2_Enable();
+ FreezeMapObjects();
+ sub_808BCF4();
+ gMain.savedCallback = CB2_EndSafariBattle;
+ gBattleTypeFlags = BATTLE_TYPE_SAFARI;
+ CreateBattleStartTask(GetWildBattleTransition(), 0);
+}
+
+static void DoBattlePikeWildBattle(void)
+{
+ ScriptContext2_Enable();
+ FreezeMapObjects();
+ sub_808BCF4();
+ gMain.savedCallback = CB2_EndWildBattle;
+ gBattleTypeFlags = BATTLE_TYPE_PIKE;
+ CreateBattleStartTask(GetWildBattleTransition(), 0);
+ IncrementGameStat(GAME_STAT_TOTAL_BATTLES);
+ IncrementGameStat(GAME_STAT_WILD_BATTLES);
+ sub_80EECC8();
+ sub_80B1218();
+}
+
+static void DoTrainerBattle(void)
+{
+ CreateBattleStartTask(GetTrainerBattleTransition(), 0);
+ IncrementGameStat(GAME_STAT_TOTAL_BATTLES);
+ IncrementGameStat(GAME_STAT_TRAINER_BATTLES);
+ sub_80B1234();
+}
+
+static void sub_80B0828(void)
+{
+ if (InBattlePyramid())
+ CreateBattleStartTask(sub_80B100C(10), 0);
+ else
+ CreateBattleStartTask(sub_80B100C(11), 0);
+
+ IncrementGameStat(GAME_STAT_TOTAL_BATTLES);
+ IncrementGameStat(GAME_STAT_TRAINER_BATTLES);
+ sub_80B1234();
+}
+
+// Initiates battle where Wally catches Ralts
+void StartWallyTutorialBattle(void)
+{
+ CreateMaleMon(&gEnemyParty[0], SPECIES_RALTS, 5);
+ ScriptContext2_Enable();
+ gMain.savedCallback = c2_exit_to_overworld_1_continue_scripts_restart_music;
+ gBattleTypeFlags = BATTLE_TYPE_WALLY_TUTORIAL;
+ CreateBattleStartTask(B_TRANSITION_SLICE, 0);
+}
+
+void BattleSetup_StartScriptedWildBattle(void)
+{
+ ScriptContext2_Enable();
+ gMain.savedCallback = CB2_EndScriptedWildBattle;
+ gBattleTypeFlags = 0;
+ CreateBattleStartTask(GetWildBattleTransition(), 0);
+ IncrementGameStat(GAME_STAT_TOTAL_BATTLES);
+ IncrementGameStat(GAME_STAT_WILD_BATTLES);
+ sub_80EECC8();
+ sub_80B1218();
+}
+
+void BattleSetup_StartLatiBattle(void)
+{
+ ScriptContext2_Enable();
+ gMain.savedCallback = CB2_EndScriptedWildBattle;
+ gBattleTypeFlags = BATTLE_TYPE_LEGENDARY;
+ CreateBattleStartTask(GetWildBattleTransition(), 0);
+ IncrementGameStat(GAME_STAT_TOTAL_BATTLES);
+ IncrementGameStat(GAME_STAT_WILD_BATTLES);
+ sub_80EECC8();
+ sub_80B1218();
+}
+
+void BattleSetup_StartLegendaryBattle(void)
+{
+ ScriptContext2_Enable();
+ gMain.savedCallback = CB2_EndScriptedWildBattle;
+ gBattleTypeFlags = BATTLE_TYPE_LEGENDARY;
+
+ switch (GetMonData(&gEnemyParty[0], MON_DATA_SPECIES, NULL))
+ {
+ default:
+ case SPECIES_GROUDON:
+ gBattleTypeFlags |= BATTLE_TYPE_GROUDON;
+ CreateBattleStartTask(B_TRANSITION_GROUDON, BGM_BATTLE34);
+ break;
+ case SPECIES_KYOGRE:
+ gBattleTypeFlags |= BATTLE_TYPE_KYOGRE;
+ CreateBattleStartTask(B_TRANSITION_KYOGRE, BGM_BATTLE34);
+ break;
+ case SPECIES_RAYQUAZA:
+ gBattleTypeFlags |= BATTLE_TYPE_RAYQUAZA;
+ CreateBattleStartTask(B_TRANSITION_RAYQUAZA, BGM_BATTLE_LEGENDARY);
+ break;
+ case SPECIES_DEOXYS:
+ CreateBattleStartTask(B_TRANSITION_BLUR, BGM_FRLG_BATTLE_DEOXYS);
+ break;
+ case SPECIES_LUGIA:
+ case SPECIES_HO_OH:
+ CreateBattleStartTask(B_TRANSITION_BLUR, BGM_FRLG_BATTLE_LEGENDARY);
+ break;
+ case SPECIES_MEW:
+ CreateBattleStartTask(B_TRANSITION_GRID_SQUARES, BGM_BATTLE_MEW);
+ break;
+ }
+
+ IncrementGameStat(GAME_STAT_TOTAL_BATTLES);
+ IncrementGameStat(GAME_STAT_WILD_BATTLES);
+ sub_80EECC8();
+ sub_80B1218();
+}
+
+void StartGroudonKyogreBattle(void)
+{
+ ScriptContext2_Enable();
+ gMain.savedCallback = CB2_EndScriptedWildBattle;
+ gBattleTypeFlags = BATTLE_TYPE_LEGENDARY | BATTLE_TYPE_KYOGRE_GROUDON;
+
+ if (gGameVersion == VERSION_RUBY)
+ CreateBattleStartTask(B_TRANSITION_SHARDS, BGM_BATTLE34); // GROUDON
+ else
+ CreateBattleStartTask(B_TRANSITION_RIPPLE, BGM_BATTLE34); // KYOGRE
+
+ IncrementGameStat(GAME_STAT_TOTAL_BATTLES);
+ IncrementGameStat(GAME_STAT_WILD_BATTLES);
+ sub_80EECC8();
+ sub_80B1218();
+}
+
+void StartRegiBattle(void)
+{
+ u8 transitionId;
+ u16 species;
+
+ ScriptContext2_Enable();
+ gMain.savedCallback = CB2_EndScriptedWildBattle;
+ gBattleTypeFlags = BATTLE_TYPE_LEGENDARY | BATTLE_TYPE_REGI;
+
+ species = GetMonData(&gEnemyParty[0], MON_DATA_SPECIES);
+ switch (species)
+ {
+ case SPECIES_REGIROCK:
+ transitionId = B_TRANSITION_REGIROCK;
+ break;
+ case SPECIES_REGICE:
+ transitionId = B_TRANSITION_REGICE;
+ break;
+ case SPECIES_REGISTEEL:
+ transitionId = B_TRANSITION_REGISTEEL;
+ break;
+ default:
+ transitionId = B_TRANSITION_GRID_SQUARES;
+ break;
+ }
+ CreateBattleStartTask(transitionId, BGM_BATTLE36);
+
+ IncrementGameStat(GAME_STAT_TOTAL_BATTLES);
+ IncrementGameStat(GAME_STAT_WILD_BATTLES);
+ sub_80EECC8();
+ sub_80B1218();
+}
+
+static void CB2_EndWildBattle(void)
+{
+ CpuFill16(0, (void*)(BG_PLTT), BG_PLTT_SIZE);
+ ResetOamRange(0, 128);
+
+ if (IsPlayerDefeated(gBattleOutcome) == TRUE && !InBattlePyramid() && !InBattlePike())
+ {
+ SetMainCallback2(CB2_WhiteOut);
+ }
+ else
+ {
+ SetMainCallback2(c2_exit_to_overworld_2_switch);
+ gFieldCallback = sub_80AF6F0;
+ }
+}
+
+static void CB2_EndScriptedWildBattle(void)
+{
+ CpuFill16(0, (void*)(BG_PLTT), BG_PLTT_SIZE);
+ ResetOamRange(0, 128);
+
+ if (IsPlayerDefeated(gBattleOutcome) == TRUE)
+ {
+ if (InBattlePyramid())
+ SetMainCallback2(c2_exit_to_overworld_1_continue_scripts_restart_music);
+ else
+ SetMainCallback2(CB2_WhiteOut);
+ }
+ else
+ {
+ SetMainCallback2(c2_exit_to_overworld_1_continue_scripts_restart_music);
+ }
+}
+
+u8 BattleSetup_GetTerrainId(void)
+{
+ u16 tileBehavior;
+ s16 x, y;
+
+ PlayerGetDestCoords(&x, &y);
+ tileBehavior = MapGridGetMetatileBehaviorAt(x, y);
+
+ if (MetatileBehavior_IsTallGrass(tileBehavior))
+ return BATTLE_TERRAIN_GRASS;
+ if (MetatileBehavior_IsLongGrass(tileBehavior))
+ return BATTLE_TERRAIN_LONG_GRASS;
+ if (MetatileBehavior_IsSandOrDeepSand(tileBehavior))
+ return BATTLE_TERRAIN_SAND;
+
+ switch (gMapHeader.mapType)
+ {
+ case MAP_TYPE_TOWN:
+ case MAP_TYPE_CITY:
+ case MAP_TYPE_ROUTE:
+ break;
+ case MAP_TYPE_UNDERGROUND:
+ if (MetatileBehavior_IsMB_0B(tileBehavior))
+ return BATTLE_TERRAIN_BUILDING;
+ if (MetatileBehavior_IsSurfableWaterOrUnderwater(tileBehavior))
+ return BATTLE_TERRAIN_POND;
+ return BATTLE_TERRAIN_CAVE;
+ case MAP_TYPE_INDOOR:
+ case MAP_TYPE_SECRET_BASE:
+ return BATTLE_TERRAIN_BUILDING;
+ case MAP_TYPE_UNDERWATER:
+ return BATTLE_TERRAIN_UNDERWATER;
+ case MAP_TYPE_6:
+ if (MetatileBehavior_IsSurfableWaterOrUnderwater(tileBehavior))
+ return BATTLE_TERRAIN_WATER;
+ return BATTLE_TERRAIN_PLAIN;
+ }
+ if (MetatileBehavior_IsDeepOrOceanWater(tileBehavior))
+ return BATTLE_TERRAIN_WATER;
+ if (MetatileBehavior_IsSurfableWaterOrUnderwater(tileBehavior))
+ return BATTLE_TERRAIN_POND;
+ if (MetatileBehavior_IsMountain(tileBehavior))
+ return BATTLE_TERRAIN_MOUNTAIN;
+ if (TestPlayerAvatarFlags(PLAYER_AVATAR_FLAG_SURFING))
+ {
+ if (MetatileBehavior_GetBridgeSth(tileBehavior))
+ return BATTLE_TERRAIN_POND;
+ if (MetatileBehavior_IsBridge(tileBehavior) == TRUE)
+ return BATTLE_TERRAIN_WATER;
+ }
+ if (gSaveBlock1Ptr->location.mapGroup == MAP_GROUP(ROUTE113) && gSaveBlock1Ptr->location.mapNum == MAP_NUM(ROUTE113))
+ return BATTLE_TERRAIN_SAND;
+ if (GetSav1Weather() == 8)
+ return BATTLE_TERRAIN_SAND;
+
+ return BATTLE_TERRAIN_PLAIN;
+}
+
+static u8 GetBattleTransitionTypeByMap(void)
+{
+ u16 tileBehavior;
+ s16 x, y;
+
+ PlayerGetDestCoords(&x, &y);
+ tileBehavior = MapGridGetMetatileBehaviorAt(x, y);
+ if (Overworld_GetFlashLevel())
+ return B_TRANSITION_SHUFFLE;
+ if (!MetatileBehavior_IsSurfableWaterOrUnderwater(tileBehavior))
+ {
+ switch (gMapHeader.mapType)
+ {
+ case MAP_TYPE_UNDERGROUND:
+ return B_TRANSITION_SWIRL;
+ case MAP_TYPE_UNDERWATER:
+ return B_TRANSITION_BIG_POKEBALL;
+ default:
+ return B_TRANSITION_BLUR;
+ }
+ }
+ return B_TRANSITION_BIG_POKEBALL;
+}
+
+static u16 GetSumOfPlayerPartyLevel(u8 numMons)
+{
+ u8 sum = 0;
+ int i;
+
+ for (i = 0; i < PARTY_SIZE; i++)
+ {
+ u32 species = GetMonData(&gPlayerParty[i], MON_DATA_SPECIES2);
+
+ if (species != SPECIES_EGG && species != SPECIES_NONE && GetMonData(&gPlayerParty[i], MON_DATA_HP) != 0)
+ {
+ sum += GetMonData(&gPlayerParty[i], MON_DATA_LEVEL);
+ if (--numMons == 0)
+ break;
+ }
+ }
+ return sum;
+}
+
+static u8 GetSumOfEnemyPartyLevel(u16 opponentId, u8 numMons)
+{
+ u8 i;
+ u8 sum;
+ u32 count = numMons;
+
+ if (gTrainers[opponentId].partySize < count)
+ count = gTrainers[opponentId].partySize;
+
+ sum = 0;
+
+ switch (gTrainers[opponentId].partyFlags)
+ {
+ case 0:
+ {
+ const struct TrainerMonNoItemDefaultMoves *party;
+ party = gTrainers[opponentId].party.NoItemDefaultMoves;
+ for (i = 0; i < count; i++)
+ sum += party[i].lvl;
+ }
+ break;
+ case F_TRAINER_PARTY_CUSTOM_MOVESET:
+ {
+ const struct TrainerMonNoItemCustomMoves *party;
+ party = gTrainers[opponentId].party.NoItemCustomMoves;
+ for (i = 0; i < count; i++)
+ sum += party[i].lvl;
+ }
+ break;
+ case F_TRAINER_PARTY_HELD_ITEM:
+ {
+ const struct TrainerMonItemDefaultMoves *party;
+ party = gTrainers[opponentId].party.ItemDefaultMoves;
+ for (i = 0; i < count; i++)
+ sum += party[i].lvl;
+ }
+ break;
+ case F_TRAINER_PARTY_CUSTOM_MOVESET | F_TRAINER_PARTY_HELD_ITEM:
+ {
+ const struct TrainerMonItemCustomMoves *party;
+ party = gTrainers[opponentId].party.ItemCustomMoves;
+ for (i = 0; i < count; i++)
+ sum += party[i].lvl;
+ }
+ break;
+ }
+
+ return sum;
+}
+
+static u8 GetWildBattleTransition(void)
+{
+ u8 transitionType = GetBattleTransitionTypeByMap();
+ u8 enemyLevel = GetMonData(&gEnemyParty[0], MON_DATA_LEVEL);
+ u8 playerLevel = GetSumOfPlayerPartyLevel(1);
+
+ if (enemyLevel < playerLevel)
+ {
+ if (InBattlePyramid())
+ return B_TRANSITION_BLUR;
+ else
+ return sBattleTransitionTable_Wild[transitionType][0];
+ }
+ else
+ {
+ if (InBattlePyramid())
+ return B_TRANSITION_GRID_SQUARES;
+ else
+ return sBattleTransitionTable_Wild[transitionType][1];
+ }
+}
+
+static u8 GetTrainerBattleTransition(void)
+{
+ u8 minPartyCount;
+ u8 transitionType;
+ u8 enemyLevel;
+ u8 playerLevel;
+
+ if (gTrainerBattleOpponent_A == SECRET_BASE_OPPONENT)
+ return B_TRANSITION_CHAMPION;
+
+ if (gTrainers[gTrainerBattleOpponent_A].trainerClass == TRAINER_CLASS_ELITE_FOUR)
+ {
+ if (gTrainerBattleOpponent_A == TRAINER_SIDNEY)
+ return B_TRANSITION_SYDNEY;
+ if (gTrainerBattleOpponent_A == TRAINER_PHOEBE)
+ return B_TRANSITION_PHOEBE;
+ if (gTrainerBattleOpponent_A == TRAINER_GLACIA)
+ return B_TRANSITION_GLACIA;
+ if (gTrainerBattleOpponent_A == TRAINER_DRAKE)
+ return B_TRANSITION_DRAKE;
+ return B_TRANSITION_CHAMPION;
+ }
+
+ if (gTrainers[gTrainerBattleOpponent_A].trainerClass == TRAINER_CLASS_CHAMPION)
+ return B_TRANSITION_CHAMPION;
+
+ if (gTrainers[gTrainerBattleOpponent_A].trainerClass == TRAINER_CLASS_TEAM_MAGMA
+ || gTrainers[gTrainerBattleOpponent_A].trainerClass == TRAINER_CLASS_MAGMA_LEADER
+ || gTrainers[gTrainerBattleOpponent_A].trainerClass == TRAINER_CLASS_MAGMA_ADMIN)
+ return B_TRANSITION_MAGMA;
+
+ if (gTrainers[gTrainerBattleOpponent_A].trainerClass == TRAINER_CLASS_TEAM_AQUA
+ || gTrainers[gTrainerBattleOpponent_A].trainerClass == TRAINER_CLASS_AQUA_LEADER
+ || gTrainers[gTrainerBattleOpponent_A].trainerClass == TRAINER_CLASS_AQUA_ADMIN)
+ return B_TRANSITION_AQUA;
+
+ if (gTrainers[gTrainerBattleOpponent_A].doubleBattle == TRUE)
+ minPartyCount = 2; // double battles always at least have 2 pokemon.
+ else
+ minPartyCount = 1;
+
+ transitionType = GetBattleTransitionTypeByMap();
+ enemyLevel = GetSumOfEnemyPartyLevel(gTrainerBattleOpponent_A, minPartyCount);
+ playerLevel = GetSumOfPlayerPartyLevel(minPartyCount);
+
+ if (enemyLevel < playerLevel)
+ return sBattleTransitionTable_Trainer[transitionType][0];
+ else
+ return sBattleTransitionTable_Trainer[transitionType][1];
+}
+
+u8 sub_80B100C(s32 arg0)
+{
+ u16 var;
+ u8 enemyLevel = GetMonData(&gEnemyParty[0], MON_DATA_LEVEL);
+ u8 playerLevel = GetSumOfPlayerPartyLevel(1);
+
+ if (enemyLevel < playerLevel)
+ {
+ switch (arg0)
+ {
+ case 11:
+ case 12:
+ case 13:
+ return B_TRANSITION_POKEBALLS_TRAIL;
+ case 10:
+ return sUnknown_0854FEA4[Random() % ARRAY_COUNT(sUnknown_0854FEA4)];
+ case 3:
+ return sUnknown_0854FEA7[Random() % ARRAY_COUNT(sUnknown_0854FEA7)];
+ }
+
+ if (VarGet(VAR_0x40CE) != 3)
+ return sUnknown_0854FE98[Random() % ARRAY_COUNT(sUnknown_0854FE98)];
+ }
+ else
+ {
+ switch (arg0)
+ {
+ case 11:
+ case 12:
+ case 13:
+ return B_TRANSITION_BIG_POKEBALL;
+ case 10:
+ return sUnknown_0854FEA4[Random() % ARRAY_COUNT(sUnknown_0854FEA4)];
+ case 3:
+ return sUnknown_0854FEA7[Random() % ARRAY_COUNT(sUnknown_0854FEA7)];
+ }
+
+ if (VarGet(VAR_0x40CE) != 3)
+ return sUnknown_0854FE98[Random() % ARRAY_COUNT(sUnknown_0854FE98)];
+ }
+
+ var = gSaveBlock2Ptr->field_CB4[gSaveBlock2Ptr->battlePyramidWildHeaderId * 2 + 0]
+ + gSaveBlock2Ptr->field_CB4[gSaveBlock2Ptr->battlePyramidWildHeaderId * 2 + 1];
+
+ return sUnknown_0854FE98[var % ARRAY_COUNT(sUnknown_0854FE98)];
+}
+
+void ChooseStarter(void)
+{
+ SetMainCallback2(CB2_ChooseStarter);
+ gMain.savedCallback = CB2_GiveStarter;
+}
+
+static void CB2_GiveStarter(void)
+{
+ u16 starterMon;
+
+ *GetVarPointer(VAR_FIRST_POKE) = gSpecialVar_Result;
+ starterMon = GetStarterPokemon(gSpecialVar_Result);
+ ScriptGiveMon(starterMon, 5, 0, 0, 0, 0);
+ ResetTasks();
+ PlayBattleBGM();
+ SetMainCallback2(CB2_StartFirstBattle);
+ BattleTransition_Start(B_TRANSITION_BLUR);
+}
+
+static void CB2_StartFirstBattle(void)
+{
+ UpdatePaletteFade();
+ RunTasks();
+
+ if (IsBattleTransitionDone() == TRUE)
+ {
+ gBattleTypeFlags = BATTLE_TYPE_FIRST_BATTLE;
+ gMain.savedCallback = CB2_EndFirstBattle;
+ FreeAllWindowBuffers();
+ SetMainCallback2(CB2_InitBattle);
+ prev_quest_postbuffer_cursor_backup_reset();
+ ResetPoisonStepCounter();
+ IncrementGameStat(GAME_STAT_TOTAL_BATTLES);
+ IncrementGameStat(GAME_STAT_WILD_BATTLES);
+ sub_80EECC8();
+ sub_80B1218();
+ }
+}
+
+static void CB2_EndFirstBattle(void)
+{
+ Overworld_ClearSavedMusic();
+ SetMainCallback2(c2_exit_to_overworld_1_continue_scripts_restart_music);
+}
+
+static void sub_80B1218(void)
+{
+ if (GetGameStat(GAME_STAT_WILD_BATTLES) % 60 == 0)
+ sub_81DA57C();
+}
+
+static void sub_80B1234(void)
+{
+ if (GetGameStat(GAME_STAT_TRAINER_BATTLES) % 20 == 0)
+ sub_81DA57C();
+}
+
+// why not just use the macros? maybe its because they didnt want to uncast const every time?
+static u32 TrainerBattleLoadArg32(const u8 *ptr)
+{
+ return T1_READ_32(ptr);
+}
+
+static u16 TrainerBattleLoadArg16(const u8 *ptr)
+{
+ return T1_READ_16(ptr);
+}
+
+static u8 TrainerBattleLoadArg8(const u8 *ptr)
+{
+ return T1_READ_8(ptr);
+}
+
+static u16 GetTrainerAFlag(void)
+{
+ return FLAG_TRAINER_FLAG_START + gTrainerBattleOpponent_A;
+}
+
+static u16 GetTrainerBFlag(void)
+{
+ return FLAG_TRAINER_FLAG_START + gTrainerBattleOpponent_B;
+}
+
+static bool32 IsPlayerDefeated(u32 battleOutcome)
+{
+ switch (battleOutcome)
+ {
+ case BATTLE_LOST:
+ case BATTLE_DREW:
+ return TRUE;
+ case BATTLE_WON:
+ case BATTLE_RAN:
+ case BATTLE_PLAYER_TELEPORTED:
+ case BATTLE_POKE_FLED:
+ case BATTLE_CAUGHT:
+ return FALSE;
+ default:
+ return FALSE;
+ }
+}
+
+void ResetTrainerOpponentIds(void)
+{
+ gTrainerBattleOpponent_A = 0;
+ gTrainerBattleOpponent_B = 0;
+}
+
+static void InitTrainerBattleVariables(void)
+{
+ sTrainerBattleMode = 0;
+ if (gApproachingTrainerId == 0)
+ {
+ sTrainerAIntroSpeech = NULL;
+ sTrainerADefeatSpeech = NULL;
+ sTrainerABattleScriptRetAddr = NULL;
+ }
+ else
+ {
+ sTrainerBIntroSpeech = NULL;
+ sTrainerBDefeatSpeech = NULL;
+ sTrainerBBattleScriptRetAddr = NULL;
+ }
+ sTrainerMapObjectLocalId = 0;
+ sTrainerVictorySpeech = NULL;
+ sTrainerCannotBattleSpeech = NULL;
+ sTrainerBattleEndScript = NULL;
+}
+
+static inline void SetU8(void *ptr, u8 value)
+{
+ *(u8*)(ptr) = value;
+}
+
+static inline void SetU16(void *ptr, u16 value)
+{
+ *(u16*)(ptr) = value;
+}
+
+static inline void SetU32(void *ptr, u32 value)
+{
+ *(u32*)(ptr) = value;
+}
+
+static inline void SetPtr(const void *ptr, const void* value)
+{
+ *(const void**)(ptr) = value;
+}
+
+static void TrainerBattleLoadArgs(const struct TrainerBattleParameter *specs, const u8 *data)
+{
+ while (1)
+ {
+ switch (specs->ptrType)
+ {
+ case TRAINER_PARAM_LOAD_VAL_8BIT:
+ SetU8(specs->varPtr, TrainerBattleLoadArg8(data));
+ data += 1;
+ break;
+ case TRAINER_PARAM_LOAD_VAL_16BIT:
+ SetU16(specs->varPtr, TrainerBattleLoadArg16(data));
+ data += 2;
+ break;
+ case TRAINER_PARAM_LOAD_VAL_32BIT:
+ SetU32(specs->varPtr, TrainerBattleLoadArg32(data));
+ data += 4;
+ break;
+ case TRAINER_PARAM_CLEAR_VAL_8BIT:
+ SetU8(specs->varPtr, 0);
+ break;
+ case TRAINER_PARAM_CLEAR_VAL_16BIT:
+ SetU16(specs->varPtr, 0);
+ break;
+ case TRAINER_PARAM_CLEAR_VAL_32BIT:
+ SetU32(specs->varPtr, 0);
+ break;
+ case TRAINER_PARAM_LOAD_SCRIPT_RET_ADDR:
+ SetPtr(specs->varPtr, data);
+ return;
+ }
+ specs++;
+ }
+}
+
+void SetMapVarsToTrainer(void)
+{
+ if (sTrainerMapObjectLocalId != 0)
+ {
+ gSpecialVar_LastTalked = sTrainerMapObjectLocalId;
+ gSelectedMapObject = GetFieldObjectIdByLocalIdAndMap(sTrainerMapObjectLocalId, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup);
+ }
+}
+
+const u8 *BattleSetup_ConfigureTrainerBattle(const u8 *data)
+{
+ InitTrainerBattleVariables();
+ sTrainerBattleMode = TrainerBattleLoadArg8(data);
+
+ switch (sTrainerBattleMode)
+ {
+ case 3:
+ TrainerBattleLoadArgs(sOrdinaryNoIntroBattleParams, data);
+ return EventScript_2713C2;
+ case 4:
+ TrainerBattleLoadArgs(sDoubleBattleParams, data);
+ SetMapVarsToTrainer();
+ return EventScript_TryDoDoubleTrainerBattle;
+ case 2:
+ if (gApproachingTrainerId == 0)
+ {
+ TrainerBattleLoadArgs(sContinueScriptBattleParams, data);
+ SetMapVarsToTrainer();
+ }
+ else
+ {
+ TrainerBattleLoadArgs(sTrainerBContinueScriptBattleParams, data);
+ }
+ return EventScript_271362;
+ case 1:
+ TrainerBattleLoadArgs(sContinueScriptBattleParams, data);
+ SetMapVarsToTrainer();
+ return EventScript_271362;
+ case 6:
+ case 8:
+ TrainerBattleLoadArgs(sContinueScriptDoubleBattleParams, data);
+ SetMapVarsToTrainer();
+ return EventScript_TryDoDoubleTrainerBattle;
+ case 7:
+ TrainerBattleLoadArgs(sDoubleBattleParams, data);
+ SetMapVarsToTrainer();
+ gTrainerBattleOpponent_A = GetRematchTrainerId(gTrainerBattleOpponent_A);
+ return EventScript_TryDoDoubleRematchBattle;
+ case 5:
+ TrainerBattleLoadArgs(sOrdinaryBattleParams, data);
+ SetMapVarsToTrainer();
+ gTrainerBattleOpponent_A = GetRematchTrainerId(gTrainerBattleOpponent_A);
+ return EventScript_2713D1;
+ case 9:
+ if (gApproachingTrainerId == 0)
+ {
+ TrainerBattleLoadArgs(sOrdinaryBattleParams, data);
+ SetMapVarsToTrainer();
+ gTrainerBattleOpponent_A = sub_81A9AA8(gSpecialVar_LastTalked);
+ }
+ else
+ {
+ TrainerBattleLoadArgs(sTrainerBOrdinaryBattleParams, data);
+ gTrainerBattleOpponent_B = sub_81A9AA8(gSpecialVar_LastTalked);
+ }
+ return EventScript_271362;
+ case 10:
+ TrainerBattleLoadArgs(sOrdinaryBattleParams, data);
+ return NULL;
+ case 11:
+ TrainerBattleLoadArgs(sTrainerBOrdinaryBattleParams, data);
+ return NULL;
+ case 12:
+ if (gApproachingTrainerId == 0)
+ {
+ TrainerBattleLoadArgs(sOrdinaryBattleParams, data);
+ SetMapVarsToTrainer();
+ gTrainerBattleOpponent_A = sub_81D6180(gSpecialVar_LastTalked);
+ }
+ else
+ {
+ TrainerBattleLoadArgs(sTrainerBOrdinaryBattleParams, data);
+ gTrainerBattleOpponent_B = sub_81D6180(gSpecialVar_LastTalked);
+ }
+ return EventScript_271362;
+ default:
+ if (gApproachingTrainerId == 0)
+ {
+ TrainerBattleLoadArgs(sOrdinaryBattleParams, data);
+ SetMapVarsToTrainer();
+ }
+ else
+ {
+ TrainerBattleLoadArgs(sTrainerBOrdinaryBattleParams, data);
+ }
+ return EventScript_271362;
+ }
+}
+
+void ConfigureAndSetUpOneTrainerBattle(u8 trainerMapObjId, const u8 *trainerScript)
+{
+ gSelectedMapObject = trainerMapObjId;
+ gSpecialVar_LastTalked = gMapObjects[trainerMapObjId].localId;
+ BattleSetup_ConfigureTrainerBattle(trainerScript + 1);
+ ScriptContext1_SetupScript(EventScript_271354);
+ ScriptContext2_Enable();
+}
+
+void ConfigureTwoTrainersBattle(u8 trainerMapObjId, const u8 *trainerScript)
+{
+ gSelectedMapObject = trainerMapObjId;
+ gSpecialVar_LastTalked = gMapObjects[trainerMapObjId].localId;
+ BattleSetup_ConfigureTrainerBattle(trainerScript + 1);
+}
+
+void SetUpTwoTrainersBattle(void)
+{
+ ScriptContext1_SetupScript(EventScript_271354);
+ ScriptContext2_Enable();
+}
+
+bool32 GetTrainerFlagFromScriptPointer(const u8 *data)
+{
+ u32 flag = TrainerBattleLoadArg16(data + 2);
+ return FlagGet(FLAG_TRAINER_FLAG_START + flag);
+}
+
+void sub_80B16D8(void)
+{
+ struct MapObject *mapObject = &gMapObjects[gSelectedMapObject];
+
+ npc_set_running_behaviour_etc(mapObject, npc_running_behaviour_by_direction(mapObject->mapobj_unk_18));
+}
+
+u8 GetTrainerBattleMode(void)
+{
+ return sTrainerBattleMode;
+}
+
+bool8 GetTrainerFlag(void)
+{
+ if (InBattlePyramid())
+ return GetBattlePyramidTrainerFlag(gSelectedMapObject);
+ else if (InTrainerHill())
+ return GetTrainerHillTrainerFlag(gSelectedMapObject);
+ else
+ return FlagGet(GetTrainerAFlag());
+}
+
+static void SetBattledTrainersFlags(void)
+{
+ if (gTrainerBattleOpponent_B != 0)
+ FlagSet(GetTrainerBFlag());
+ FlagSet(GetTrainerAFlag());
+}
+
+static void SetBattledTrainerFlag(void)
+{
+ FlagSet(GetTrainerAFlag());
+}
+
+bool8 HasTrainerBeenFought(u16 trainerId)
+{
+ return FlagGet(FLAG_TRAINER_FLAG_START + trainerId);
+}
+
+void SetTrainerFlag(u16 trainerId)
+{
+ FlagSet(FLAG_TRAINER_FLAG_START + trainerId);
+}
+
+void ClearTrainerFlag(u16 trainerId)
+{
+ FlagClear(FLAG_TRAINER_FLAG_START + trainerId);
+}
+
+void BattleSetup_StartTrainerBattle(void)
+{
+ if (gNoOfApproachingTrainers == 2)
+ gBattleTypeFlags = (BATTLE_TYPE_DOUBLE | BATTLE_TYPE_TWO_OPPONENTS | BATTLE_TYPE_TRAINER);
+ else
+ gBattleTypeFlags = (BATTLE_TYPE_TRAINER);
+
+ if (InBattlePyramid())
+ {
+ VarSet(VAR_0x400E, 0);
+ gBattleTypeFlags |= BATTLE_TYPE_PYRAMID;
+
+ if (gNoOfApproachingTrainers == 2)
+ {
+ sub_816306C(1);
+ ZeroMonData(&gEnemyParty[1]);
+ ZeroMonData(&gEnemyParty[2]);
+ ZeroMonData(&gEnemyParty[4]);
+ ZeroMonData(&gEnemyParty[5]);
+ }
+ else
+ {
+ sub_8163048(1);
+ ZeroMonData(&gEnemyParty[1]);
+ ZeroMonData(&gEnemyParty[2]);
+ }
+
+ sub_81A9B04();
+ }
+ else if (sub_81D5C18())
+ {
+ gBattleTypeFlags |= BATTLE_TYPE_x4000000;
+
+ if (gNoOfApproachingTrainers == 2)
+ sub_81D639C();
+ else
+ sub_81D6384();
+
+ sub_81D61E8();
+ }
+
+ sNoOfPossibleTrainerRetScripts = gNoOfApproachingTrainers;
+ gNoOfApproachingTrainers = 0;
+ sShouldCheckTrainerBScript = FALSE;
+ gUnknown_03006080 = 0;
+ gMain.savedCallback = CB2_EndTrainerBattle;
+
+ if (InBattlePyramid() || sub_81D5C18())
+ sub_80B0828();
+ else
+ DoTrainerBattle();
+
+ ScriptContext1_Stop();
+}
+
+static void CB2_EndTrainerBattle(void)
+{
+ if (gTrainerBattleOpponent_A == SECRET_BASE_OPPONENT)
+ {
+ SetMainCallback2(c2_exit_to_overworld_1_continue_scripts_restart_music);
+ }
+ else if (IsPlayerDefeated(gBattleOutcome) == TRUE)
+ {
+ if (InBattlePyramid() || sub_81D5C18())
+ SetMainCallback2(c2_exit_to_overworld_1_continue_scripts_restart_music);
+ else
+ SetMainCallback2(CB2_WhiteOut);
+ }
+ else
+ {
+ SetMainCallback2(c2_exit_to_overworld_1_continue_scripts_restart_music);
+ if (!InBattlePyramid() && !sub_81D5C18())
+ {
+ RegisterTrainerInMatchCall();
+ SetBattledTrainersFlags();
+ }
+ }
+}
+
+static void CB2_EndRematchBattle(void)
+{
+ if (gTrainerBattleOpponent_A == SECRET_BASE_OPPONENT)
+ {
+ SetMainCallback2(c2_exit_to_overworld_1_continue_scripts_restart_music);
+ }
+ else if (IsPlayerDefeated(gBattleOutcome) == TRUE)
+ {
+ SetMainCallback2(CB2_WhiteOut);
+ }
+ else
+ {
+ SetMainCallback2(c2_exit_to_overworld_1_continue_scripts_restart_music);
+ RegisterTrainerInMatchCall();
+ SetBattledTrainersFlags();
+ HandleRematchVarsOnBattleEnd();
+ }
+}
+
+void BattleSetup_StartRematchBattle(void)
+{
+ gBattleTypeFlags = BATTLE_TYPE_TRAINER;
+ gMain.savedCallback = CB2_EndRematchBattle;
+ DoTrainerBattle();
+ ScriptContext1_Stop();
+}
+
+void ShowTrainerIntroSpeech(void)
+{
+ if (InBattlePyramid())
+ {
+ if (gNoOfApproachingTrainers == 0 || gNoOfApproachingTrainers == 1)
+ sub_81A9EDC(sub_81A9AA8(gSpecialVar_LastTalked));
+ else
+ sub_81A9EDC(sub_81A9AA8(gMapObjects[gApproachingTrainers[gApproachingTrainerId].mapObjectId].localId));
+
+ sub_80982B8();
+ }
+ else if (sub_81D5C18())
+ {
+ if (gNoOfApproachingTrainers == 0 || gNoOfApproachingTrainers == 1)
+ sub_81D572C(2, sub_81D6180(gSpecialVar_LastTalked));
+ else
+ sub_81D572C(2, sub_81D6180(gMapObjects[gApproachingTrainers[gApproachingTrainerId].mapObjectId].localId));
+
+ sub_80982B8();
+ }
+ else
+ {
+ ShowFieldMessage(GetIntroSpeechOfApproachingTrainer());
+ }
+}
+
+const u8 *BattleSetup_GetScriptAddrAfterBattle(void)
+{
+ if (sTrainerBattleEndScript != NULL)
+ return sTrainerBattleEndScript;
+ else
+ return EventScript_TestSignpostMsg;
+}
+
+const u8 *BattleSetup_GetTrainerPostBattleScript(void)
+{
+ if (sShouldCheckTrainerBScript)
+ {
+ sShouldCheckTrainerBScript = FALSE;
+ if (sTrainerBBattleScriptRetAddr != NULL)
+ {
+ gUnknown_03006080 = 1;
+ return sTrainerBBattleScriptRetAddr;
+ }
+ }
+ else
+ {
+ if (sTrainerABattleScriptRetAddr != NULL)
+ {
+ gUnknown_03006080 = 0;
+ return sTrainerABattleScriptRetAddr;
+ }
+ }
+
+ return EventScript_TryGetTrainerScript;
+}
+
+void ShowTrainerCantBattleSpeech(void)
+{
+ ShowFieldMessage(GetTrainerCantBattleSpeech());
+}
+
+void SetUpTrainerEncounterMusic(void)
+{
+ u16 trainerId;
+ u16 music;
+
+ if (gApproachingTrainerId == 0)
+ trainerId = gTrainerBattleOpponent_A;
+ else
+ trainerId = gTrainerBattleOpponent_B;
+
+ if (sTrainerBattleMode != TRAINER_BATTLE_CONTINUE_SCRIPT_NO_MUSIC
+ && sTrainerBattleMode != TRAINER_BATTLE_CONTINUE_SCRIPT_DOUBLE_NO_MUSIC)
+ {
+ switch (GetTrainerEncounterMusicId(trainerId))
+ {
+ case TRAINER_ENCOUNTER_MUSIC_MALE:
+ music = BGM_BOYEYE;
+ break;
+ case TRAINER_ENCOUNTER_MUSIC_FEMALE:
+ music = BGM_GIRLEYE;
+ break;
+ case TRAINER_ENCOUNTER_MUSIC_GIRL:
+ music = BGM_SYOUJOEYE;
+ break;
+ case TRAINER_ENCOUNTER_MUSIC_INTENSE:
+ music = BGM_HAGESHII;
+ break;
+ case TRAINER_ENCOUNTER_MUSIC_COOL:
+ music = BGM_KAKKOII;
+ break;
+ case TRAINER_ENCOUNTER_MUSIC_AQUA:
+ music = BGM_AQA_0;
+ break;
+ case TRAINER_ENCOUNTER_MUSIC_MAGMA:
+ music = BGM_MGM0;
+ break;
+ case TRAINER_ENCOUNTER_MUSIC_SWIMMER:
+ music = BGM_SWIMEYE;
+ break;
+ case TRAINER_ENCOUNTER_MUSIC_TWINS:
+ music = BGM_HUTAGO;
+ break;
+ case TRAINER_ENCOUNTER_MUSIC_ELITE_FOUR:
+ music = BGM_SITENNOU;
+ break;
+ case TRAINER_ENCOUNTER_MUSIC_HIKER:
+ music = BGM_YAMA_EYE;
+ break;
+ case TRAINER_ENCOUNTER_MUSIC_INTERVIEWER:
+ music = BGM_INTER_V;
+ break;
+ case TRAINER_ENCOUNTER_MUSIC_RICH:
+ music = BGM_TEST;
+ break;
+ default:
+ music = BGM_AYASII;
+ }
+ PlayNewMapMusic(music);
+ }
+}
+
+static const u8 *ReturnEmptyStringIfNull(const u8 *string)
+{
+ if (string == NULL)
+ return gText_EmptyString2;
+ else
+ return string;
+}
+
+static const u8 *GetIntroSpeechOfApproachingTrainer(void)
+{
+ if (gApproachingTrainerId == 0)
+ return ReturnEmptyStringIfNull(sTrainerAIntroSpeech);
+ else
+ return ReturnEmptyStringIfNull(sTrainerBIntroSpeech);
+}
+
+const u8 *GetTrainerALoseText(void)
+{
+ const u8 *string;
+
+ if (gTrainerBattleOpponent_A == SECRET_BASE_OPPONENT)
+ string = GetSecretBaseTrainerLoseText();
+ else
+ string = sTrainerADefeatSpeech;
+
+ StringExpandPlaceholders(gStringVar4, ReturnEmptyStringIfNull(string));
+ return gStringVar4;
+}
+
+const u8 *GetTrainerBLoseText(void)
+{
+ StringExpandPlaceholders(gStringVar4, ReturnEmptyStringIfNull(sTrainerBDefeatSpeech));
+ return gStringVar4;
+}
+
+const u8 *GetTrainerWonSpeech(void)
+{
+ return ReturnEmptyStringIfNull(sTrainerVictorySpeech);
+}
+
+static const u8 *GetTrainerCantBattleSpeech(void)
+{
+ return ReturnEmptyStringIfNull(sTrainerCannotBattleSpeech);
+}
+
+static s32 FirstBattleTrainerIdToRematchTableId(const struct RematchTrainer *table, u16 trainerId)
+{
+ s32 i;
+
+ for (i = 0; i < REMATCH_TABLE_ENTRIES; i++)
+ {
+ if (table[i].trainerIds[0] == trainerId)
+ return i;
+ }
+
+ return -1;
+}
+
+static s32 TrainerIdToRematchTableId(const struct RematchTrainer *table, u16 trainerId)
+{
+ s32 i, j;
+
+ for (i = 0; i < REMATCH_TABLE_ENTRIES; i++)
+ {
+ for (j = 0; j < REMATCHES_COUNT; j++)
+ {
+ if (table[i].trainerIds[j] == 0)
+ break;
+ if (table[i].trainerIds[j] == trainerId)
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+static bool32 sub_80B1D94(s32 rematchTableId)
+{
+ if (rematchTableId >= REMATCH_ELITE_FOUR_ENTRIES)
+ return TRUE;
+ else if (rematchTableId == REMATCH_WALLY_ENTRY)
+ return (FlagGet(FLAG_0x07E) == FALSE);
+ else
+ return FALSE;
+}
+
+static void SetRematchIdForTrainer(const struct RematchTrainer *table, u32 tableId)
+{
+ s32 i;
+
+ for (i = 1; i < REMATCHES_COUNT; i++)
+ {
+ u16 trainerId = table[tableId].trainerIds[i];
+
+ if (trainerId == 0)
+ break;
+ if (!HasTrainerBeenFought(trainerId))
+ break;
+ }
+
+ gSaveBlock1Ptr->trainerRematches[tableId] = i;
+}
+
+static bool32 UpdateRandomTrainerRematches(const struct RematchTrainer *table, u16 mapGroup, u16 mapNum)
+{
+ s32 i;
+ bool32 ret = FALSE;
+
+ for (i = 0; i <= REMATCH_WALLY_ENTRY; i++)
+ {
+ if (table[i].mapGroup == mapGroup && table[i].mapNum == mapNum && !sub_80B1D94(i))
+ {
+ if (gSaveBlock1Ptr->trainerRematches[i] != 0)
+ {
+ // Trainer already wants a rematch. Don't bother updating it
+ ret = TRUE;
+ }
+ else if (FlagGet(FLAG_MATCH_CALL_REGISTERED + i)
+ && (Random() % 100) <= 30) // 31% chance of getting a rematch
+ {
+ SetRematchIdForTrainer(table, i);
+ ret = TRUE;
+ }
+ }
+ }
+
+ return ret;
+}
+
+void UpdateRematchIfDefeated(s32 rematchTableId)
+{
+ if (HasTrainerBeenFought(gRematchTable[rematchTableId].trainerIds[0]) == TRUE)
+ SetRematchIdForTrainer(gRematchTable, rematchTableId);
+}
+
+static bool32 DoesSomeoneWantRematchIn_(const struct RematchTrainer *table, u16 mapGroup, u16 mapNum)
+{
+ s32 i;
+
+ for (i = 0; i < REMATCH_TABLE_ENTRIES; i++)
+ {
+ if (table[i].mapGroup == mapGroup && table[i].mapNum == mapNum && gSaveBlock1Ptr->trainerRematches[i] != 0)
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static bool32 IsRematchTrainerIn_(const struct RematchTrainer *table, u16 mapGroup, u16 mapNum)
+{
+ s32 i;
+
+ for (i = 0; i < REMATCH_TABLE_ENTRIES; i++)
+ {
+ if (table[i].mapGroup == mapGroup && table[i].mapNum == mapNum)
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static bool8 IsFirstTrainerIdReadyForRematch(const struct RematchTrainer *table, u16 firstBattleTrainerId)
+{
+ s32 tableId = FirstBattleTrainerIdToRematchTableId(table, firstBattleTrainerId);
+
+ if (tableId == -1)
+ return FALSE;
+ if (tableId >= 100)
+ return FALSE;
+ if (gSaveBlock1Ptr->trainerRematches[tableId] == 0)
+ return FALSE;
+
+ return TRUE;
+}
+
+static bool8 IsTrainerReadyForRematch_(const struct RematchTrainer *table, u16 trainerId)
+{
+ s32 tableId = TrainerIdToRematchTableId(table, trainerId);
+
+ if (tableId == -1)
+ return FALSE;
+ if (tableId >= 100)
+ return FALSE;
+ if (gSaveBlock1Ptr->trainerRematches[tableId] == 0)
+ return FALSE;
+
+ return TRUE;
+}
+
+static u16 GetRematchTrainerIdFromTable(const struct RematchTrainer *table, u16 firstBattleTrainerId)
+{
+ const struct RematchTrainer *trainerEntry;
+ s32 i;
+ s32 tableId = FirstBattleTrainerIdToRematchTableId(table, firstBattleTrainerId);
+
+ if (tableId == -1)
+ return FALSE;
+
+ trainerEntry = &table[tableId];
+ for (i = 1; i < REMATCHES_COUNT; i++)
+ {
+ if (trainerEntry->trainerIds[i] == 0) // previous entry was this trainer's last one
+ return trainerEntry->trainerIds[i - 1];
+ if (!HasTrainerBeenFought(trainerEntry->trainerIds[i]))
+ return trainerEntry->trainerIds[i];
+ }
+
+ return trainerEntry->trainerIds[REMATCHES_COUNT - 1]; // already beaten at max stage
+}
+
+static u16 GetLastBeatenRematchTrainerIdFromTable(const struct RematchTrainer *table, u16 firstBattleTrainerId)
+{
+ const struct RematchTrainer *trainerEntry;
+ s32 i;
+ s32 tableId = FirstBattleTrainerIdToRematchTableId(table, firstBattleTrainerId);
+
+ if (tableId == -1)
+ return FALSE;
+
+ trainerEntry = &table[tableId];
+ for (i = 1; i < REMATCHES_COUNT; i++)
+ {
+ if (trainerEntry->trainerIds[i] == 0) // previous entry was this trainer's last one
+ return trainerEntry->trainerIds[i - 1];
+ if (!HasTrainerBeenFought(trainerEntry->trainerIds[i]))
+ return trainerEntry->trainerIds[i - 1];
+ }
+
+ return trainerEntry->trainerIds[REMATCHES_COUNT - 1]; // already beaten at max stage
+}
+
+static void ClearTrainerWantRematchState(const struct RematchTrainer *table, u16 firstBattleTrainerId)
+{
+ s32 tableId = TrainerIdToRematchTableId(table, firstBattleTrainerId);
+
+ if (tableId != -1)
+ gSaveBlock1Ptr->trainerRematches[tableId] = 0;
+}
+
+static u32 GetTrainerMatchCallFlag(u32 trainerId)
+{
+ s32 i;
+
+ for (i = 0; i < REMATCH_TABLE_ENTRIES; i++)
+ {
+ if (gRematchTable[i].trainerIds[0] == trainerId)
+ return FLAG_MATCH_CALL_REGISTERED + i;
+ }
+
+ return 0xFFFF;
+}
+
+static void RegisterTrainerInMatchCall(void)
+{
+ if (FlagGet(FLAG_HAS_MATCH_CALL))
+ {
+ u32 matchCallFlagId = GetTrainerMatchCallFlag(gTrainerBattleOpponent_A);
+ if (matchCallFlagId != 0xFFFF)
+ FlagSet(matchCallFlagId);
+ }
+}
+
+static bool8 WasSecondRematchWon(const struct RematchTrainer *table, u16 firstBattleTrainerId)
+{
+ s32 tableId = FirstBattleTrainerIdToRematchTableId(table, firstBattleTrainerId);
+
+ if (tableId == -1)
+ return FALSE;
+ if (!HasTrainerBeenFought(table[tableId].trainerIds[1]))
+ return FALSE;
+
+ return TRUE;
+}
+
+static bool32 HasAtLeastFiveBadges(void)
+{
+ s32 i, count;
+
+ for (count = 0, i = 0; i < ARRAY_COUNT(sBadgeFlags); i++)
+ {
+ if (FlagGet(sBadgeFlags[i]) == TRUE)
+ {
+ if (++count >= 5)
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+#define STEP_COUNTER_MAX 255
+
+void IncrementRematchStepCounter(void)
+{
+ if (HasAtLeastFiveBadges())
+ {
+ if (gSaveBlock1Ptr->trainerRematchStepCounter >= STEP_COUNTER_MAX)
+ gSaveBlock1Ptr->trainerRematchStepCounter = STEP_COUNTER_MAX;
+ else
+ gSaveBlock1Ptr->trainerRematchStepCounter++;
+ }
+}
+
+static bool32 IsRematchStepCounterMaxed(void)
+{
+ if (HasAtLeastFiveBadges() && gSaveBlock1Ptr->trainerRematchStepCounter >= STEP_COUNTER_MAX)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+void TryUpdateRandomTrainerRematches(u16 mapGroup, u16 mapNum)
+{
+ if (IsRematchStepCounterMaxed() && UpdateRandomTrainerRematches(gRematchTable, mapGroup, mapNum) == TRUE)
+ gSaveBlock1Ptr->trainerRematchStepCounter = 0;
+}
+
+bool32 DoesSomeoneWantRematchIn(u16 mapGroup, u16 mapNum)
+{
+ return DoesSomeoneWantRematchIn_(gRematchTable, mapGroup, mapNum);
+}
+
+bool32 IsRematchTrainerIn(u16 mapGroup, u16 mapNum)
+{
+ return IsRematchTrainerIn_(gRematchTable, mapGroup, mapNum);
+}
+
+static u16 GetRematchTrainerId(u16 trainerId)
+{
+ return GetRematchTrainerIdFromTable(gRematchTable, trainerId);
+}
+
+u16 GetLastBeatenRematchTrainerId(u16 trainerId)
+{
+ return GetLastBeatenRematchTrainerIdFromTable(gRematchTable, trainerId);
+}
+
+bool8 ShouldTryRematchBattle(void)
+{
+ if (IsFirstTrainerIdReadyForRematch(gRematchTable, gTrainerBattleOpponent_A))
+ return TRUE;
+
+ return WasSecondRematchWon(gRematchTable, gTrainerBattleOpponent_A);
+}
+
+bool8 IsTrainerReadyForRematch(void)
+{
+ return IsTrainerReadyForRematch_(gRematchTable, gTrainerBattleOpponent_A);
+}
+
+static void HandleRematchVarsOnBattleEnd(void)
+{
+ ClearTrainerWantRematchState(gRematchTable, gTrainerBattleOpponent_A);
+ SetBattledTrainersFlags();
+}
+
+void ShouldTryGetTrainerScript(void)
+{
+ if (sNoOfPossibleTrainerRetScripts > 1)
+ {
+ sNoOfPossibleTrainerRetScripts = 0;
+ sShouldCheckTrainerBScript = TRUE;
+ gSpecialVar_Result = TRUE;
+ }
+ else
+ {
+ sShouldCheckTrainerBScript = FALSE;
+ gSpecialVar_Result = FALSE;
+ }
+}
+
+u16 CountBattledRematchTeams(u16 trainerId)
+{
+ s32 i;
+
+ if (HasTrainerBeenFought(gRematchTable[trainerId].trainerIds[0]) != TRUE)
+ return 0;
+
+ for (i = 1; i < REMATCHES_COUNT; i++)
+ {
+ if (gRematchTable[trainerId].trainerIds[i] == 0)
+ break;
+ if (!HasTrainerBeenFought(gRematchTable[trainerId].trainerIds[i]))
+ break;
+ }
+
+ return i;
+}
diff --git a/src/berry_blender.c b/src/berry_blender.c
index fe646954d..810162746 100644
--- a/src/berry_blender.c
+++ b/src/berry_blender.c
@@ -2442,7 +2442,7 @@ static void CB2_HandleBlenderEndGame(void)
sBerryBlenderData->gameEndState++;
break;
case 10:
- switch (sub_8198C58())
+ switch (ProcessMenuInputNoWrap_())
{
case 1:
case -1:
diff --git a/src/clear_save_data_screen.c b/src/clear_save_data_screen.c
index d00944ac1..6d6a1545b 100755
--- a/src/clear_save_data_screen.c
+++ b/src/clear_save_data_screen.c
@@ -88,7 +88,7 @@ static void Task_DoClearSaveDataScreenYesNo(u8 taskId)
static void Task_ClearSaveDataScreenYesNoChoice(u8 taskId)
{
- switch(sub_8198C58())
+ switch(ProcessMenuInputNoWrap_())
{
case 0:
FillWindowPixelBuffer(0, 17);
diff --git a/src/clock.c b/src/clock.c
new file mode 100644
index 000000000..7cea30166
--- /dev/null
+++ b/src/clock.c
@@ -0,0 +1,93 @@
+#include "global.h"
+#include "rom6.h"
+#include "event_data.h"
+#include "rtc.h"
+#include "lottery_corner.h"
+#include "dewford_trend.h"
+#include "tv.h"
+#include "field_screen.h"
+#include "berry.h"
+#include "main.h"
+#include "overworld.h"
+#include "wallclock.h"
+
+// static types
+
+// static declarations
+
+static void UpdatePerDay(struct Time *localTime);
+static void UpdatePerMinute(struct Time *localTime);
+
+// rodata
+
+// text
+
+static void InitTimeBasedEvents(void)
+{
+ FlagSet(FLAG_SYS_CLOCK_SET);
+ RtcCalcLocalTime();
+ gSaveBlock2Ptr->lastBerryTreeUpdate = gLocalTime;
+ VarSet(VAR_DAYS, gLocalTime.days);
+}
+
+void DoTimeBasedEvents(void)
+{
+ if (FlagGet(FLAG_SYS_CLOCK_SET) && !sub_813B9C0())
+ {
+ RtcCalcLocalTime();
+ UpdatePerDay(&gLocalTime);
+ UpdatePerMinute(&gLocalTime);
+ }
+}
+
+static void UpdatePerDay(struct Time *localTime)
+{
+ u16 *days = GetVarPointer(VAR_DAYS);
+ u16 daysSince;
+
+ if (*days != localTime->days && *days <= localTime->days)
+ {
+ daysSince = localTime->days - *days;
+ ClearUpperFlags();
+ UpdateDewfordTrendPerDay(daysSince);
+ UpdateTVShowsPerDay(daysSince);
+ UpdateWeatherPerDay(daysSince);
+ UpdatePartyPokerusTime(daysSince);
+ UpdateMirageRnd(daysSince);
+ UpdateBirchState(daysSince);
+ UpdateFrontierManiac(daysSince);
+ UpdateFrontierGambler(daysSince);
+ SetShoalItemFlag(daysSince);
+ SetRandomLotteryNumber(daysSince);
+ *days = localTime->days;
+ }
+}
+
+static void UpdatePerMinute(struct Time *localTime)
+{
+ struct Time difference;
+ int minutes;
+
+ CalcTimeDifference(&difference, &gSaveBlock2Ptr->lastBerryTreeUpdate, localTime);
+ minutes = 24 * 60 * difference.days + 60 * difference.hours + difference.minutes;
+ if (minutes != 0)
+ {
+ if (minutes >= 0)
+ {
+ BerryTreeTimeUpdate(minutes);
+ gSaveBlock2Ptr->lastBerryTreeUpdate = *localTime;
+ }
+ }
+}
+
+static void ReturnFromStartWallClock(void)
+{
+ InitTimeBasedEvents();
+ SetMainCallback2(c2_exit_to_overworld_1_continue_scripts_restart_music);
+}
+
+void StartWallClock(void)
+{
+ SetMainCallback2(Cb2_StartWallClock);
+ gMain.savedCallback = ReturnFromStartWallClock;
+}
diff --git a/src/egg_hatch.c b/src/egg_hatch.c
index 032607806..a31eb0520 100644
--- a/src/egg_hatch.c
+++ b/src/egg_hatch.c
@@ -58,7 +58,7 @@ extern const u8 gText_HatchedFromEgg[];
extern const u8 gText_NickHatchPrompt[];
extern u8 sav1_map_get_name(void);
-extern s8 sub_8198C58(void);
+extern s8 ProcessMenuInputNoWrap_(void);
extern void TVShowConvertInternationalString(u8* str1, u8* str2, u8);
extern void sub_806A068(u16, u8);
extern void fade_screen(u8, u8);
@@ -669,7 +669,7 @@ static void CB2_EggHatch_1(void)
}
break;
case 10:
- switch (sub_8198C58())
+ switch (ProcessMenuInputNoWrap_())
{
case 0:
GetMonNick(&gPlayerParty[sEggHatchData->eggPartyID], gStringVar3);
diff --git a/src/evolution_scene.c b/src/evolution_scene.c
index c17921b74..2b88fec3a 100644
--- a/src/evolution_scene.c
+++ b/src/evolution_scene.c
@@ -1168,7 +1168,7 @@ static void Task_TradeEvolutionScene(u8 taskID)
}
break;
case 4:
- switch (sub_8198C58())
+ switch (ProcessMenuInputNoWrap_())
{
case 0:
sEvoCursorPos = 0;
diff --git a/src/load_save.c b/src/load_save.c
index 2b40f2e92..e0106c0a8 100644
--- a/src/load_save.c
+++ b/src/load_save.c
@@ -1,4 +1,4 @@
-#include "global.h"
+#include "global.h"
#include "gba/flash_internal.h"
#include "load_save.h"
#include "main.h"
@@ -28,7 +28,7 @@ struct LoadedSaveData
/*0x00F0*/ struct ItemSlot pokeBalls[16];
/*0x0130*/ struct ItemSlot TMsHMs[64];
/*0x0230*/ struct ItemSlot berries[46];
- /*0x02E8*/ struct MailStruct mail[16];
+ /*0x02E8*/ struct MailStruct mail[MAIL_COUNT];
};
EWRAM_DATA struct SaveBlock2 gSaveblock2 = {0};
@@ -330,7 +330,7 @@ void LoadSerializedGame(void)
void copy_bags_and_unk_data_from_save_blocks(void)
{
int i;
-
+
// load player items.
for (i = 0; i < 30; i++)
gLoadedSaveData.items[i] = gSaveBlock1Ptr->bagPocket_Items[i];
diff --git a/src/mail.c b/src/mail.c
index 877035fb6..ec7ff2ce2 100644
--- a/src/mail.c
+++ b/src/mail.c
@@ -1,4 +1,5 @@
#include "global.h"
+#include "mail.h"
#include "constants/items.h"
#include "main.h"
#include "overworld.h"
@@ -18,8 +19,43 @@
#include "constants/species.h"
#include "malloc.h"
#include "easy_chat.h"
-#include "mail_data.h"
-#include "mail.h"
+
+extern const u16 gUnknown_08DBE818[];
+extern const u16 gUnknown_08DBE838[];
+extern const u16 gUnknown_08DBE858[];
+extern const u16 gUnknown_08DBE878[];
+extern const u16 gUnknown_08DBE898[];
+extern const u16 gUnknown_08DBE8B8[];
+extern const u16 gUnknown_08DBE8D8[];
+extern const u16 gUnknown_08DBE8F8[];
+extern const u16 gUnknown_08DBE918[];
+extern const u16 gUnknown_08DBE938[];
+extern const u16 gUnknown_08DBE958[];
+extern const u16 gUnknown_08DBE978[];
+extern const u8 gUnknown_08DBE998[];
+extern const u8 gUnknown_08DBFBA4[];
+extern const u8 gUnknown_08DBEB38[];
+extern const u8 gUnknown_08DBFC7C[];
+extern const u8 gUnknown_08DBEC74[];
+extern const u8 gUnknown_08DBFD5C[];
+extern const u8 gUnknown_08DBEE84[];
+extern const u8 gUnknown_08DBFE68[];
+extern const u8 gUnknown_08DBEF5C[];
+extern const u8 gUnknown_08DBFF44[];
+extern const u8 gUnknown_08DBF154[];
+extern const u8 gUnknown_08DC0034[];
+extern const u8 gUnknown_08DBF2D4[];
+extern const u8 gUnknown_08DC0114[];
+extern const u8 gUnknown_08DBF37C[];
+extern const u8 gUnknown_08DC01F4[];
+extern const u8 gUnknown_08DBF50C[];
+extern const u8 gUnknown_08DC0300[];
+extern const u8 gUnknown_08DBF64C[];
+extern const u8 gUnknown_08DC03F0[];
+extern const u8 gUnknown_08DBF7B4[];
+extern const u8 gUnknown_08DC04E8[];
+extern const u8 gUnknown_08DBF904[];
+extern const u8 gUnknown_08DC0600[];
// Static type declarations
@@ -51,9 +87,7 @@ struct MailGraphics
u16 color12;
};
-// Static RAM declarations
-
-static EWRAM_DATA struct
+struct MailRead
{
/*0x0000*/ u8 strbuf[8][64];
/*0x0200*/ u8 playerName[12];
@@ -72,22 +106,26 @@ static EWRAM_DATA struct
/*0x0228*/ const struct MailLayout *layout;
/*0x022c*/ u8 bg1TilemapBuffer[0x1000];
/*0x122c*/ u8 bg2TilemapBuffer[0x1000];
-} *gUnknown_0203A134 = NULL;
+};
+
+// Static RAM declarations
+
+static EWRAM_DATA struct MailRead *sMailRead = NULL;
// Static ROM declarations
-void sub_81219F0(void);
-void sub_8121A1C(void);
-void sub_8121B1C(void);
-void sub_8121C50(void);
-void sub_8121C64(void);
-void sub_8121C98(void);
-void sub_8121CC0(void);
-void sub_8121D00(void);
+static void CB2_InitMailRead(void);
+static void sub_8121A1C(void);
+static void sub_8121B1C(void);
+static void VBlankCB_MailRead(void);
+static void CB2_MailRead(void);
+static void CB2_WaitForPaletteExitOnKeyPress(void);
+static void CB2_ExitOnKeyPress(void);
+static void CB2_ExitMailReadFreeVars(void);
// .rodata
-const struct BgTemplate gUnknown_0859F290[] = {
+static const struct BgTemplate sUnknown_0859F290[] = {
{
.bg = 0,
.charBaseIndex = 2,
@@ -106,7 +144,7 @@ const struct BgTemplate gUnknown_0859F290[] = {
}
};
-const struct WindowTemplate gUnknown_0859F29C[] = {
+static const struct WindowTemplate sUnknown_0859F29C[] = {
{
.priority = 0,
.tilemapLeft = 2,
@@ -119,55 +157,18 @@ const struct WindowTemplate gUnknown_0859F29C[] = {
DUMMY_WIN_TEMPLATE
};
-const u8 gUnknown_0859F2AC[] = {
+static const u8 sUnknown_0859F2AC[] = {
0,
10,
11
};
-const u16 gUnknown_0859F2B0[][2] = {
+static const u16 sUnknown_0859F2B0[][2] = {
{ 0x6ACD, 0x51A5 },
{ 0x45FC, 0x38D4 }
};
-extern const u16 gUnknown_08DBE818[];
-extern const u16 gUnknown_08DBE838[];
-extern const u16 gUnknown_08DBE858[];
-extern const u16 gUnknown_08DBE878[];
-extern const u16 gUnknown_08DBE898[];
-extern const u16 gUnknown_08DBE8B8[];
-extern const u16 gUnknown_08DBE8D8[];
-extern const u16 gUnknown_08DBE8F8[];
-extern const u16 gUnknown_08DBE918[];
-extern const u16 gUnknown_08DBE938[];
-extern const u16 gUnknown_08DBE958[];
-extern const u16 gUnknown_08DBE978[];
-extern const u8 gUnknown_08DBE998[];
-extern const u8 gUnknown_08DBFBA4[];
-extern const u8 gUnknown_08DBEB38[];
-extern const u8 gUnknown_08DBFC7C[];
-extern const u8 gUnknown_08DBEC74[];
-extern const u8 gUnknown_08DBFD5C[];
-extern const u8 gUnknown_08DBEE84[];
-extern const u8 gUnknown_08DBFE68[];
-extern const u8 gUnknown_08DBEF5C[];
-extern const u8 gUnknown_08DBFF44[];
-extern const u8 gUnknown_08DBF154[];
-extern const u8 gUnknown_08DC0034[];
-extern const u8 gUnknown_08DBF2D4[];
-extern const u8 gUnknown_08DC0114[];
-extern const u8 gUnknown_08DBF37C[];
-extern const u8 gUnknown_08DC01F4[];
-extern const u8 gUnknown_08DBF50C[];
-extern const u8 gUnknown_08DC0300[];
-extern const u8 gUnknown_08DBF64C[];
-extern const u8 gUnknown_08DC03F0[];
-extern const u8 gUnknown_08DBF7B4[];
-extern const u8 gUnknown_08DC04E8[];
-extern const u8 gUnknown_08DBF904[];
-extern const u8 gUnknown_08DC0600[];
-
-const struct MailGraphics gUnknown_0859F2B8[] = {
+static const struct MailGraphics sUnknown_0859F2B8[] = {
{
gUnknown_08DBE818, gUnknown_08DBE998, gUnknown_08DBFBA4, 0x02c0, 0x0000, 0x294a, 0x6739
}, {
@@ -195,13 +196,13 @@ const struct MailGraphics gUnknown_0859F2B8[] = {
}
};
-const struct UnkMailStruct Unknown_0859F3A8[] = {
+static const struct UnkMailStruct Unknown_0859F3A8[] = {
{ .numEasyChatWords = 3, .lineHeight = 16 },
{ .numEasyChatWords = 3, .lineHeight = 16 },
{ .numEasyChatWords = 3, .lineHeight = 16 }
};
-const struct MailLayout gUnknown_0859F3B4[] = {
+static const struct MailLayout sUnknown_0859F3B4[] = {
{ 0x03, 0x00, 0x00, 0x02, 0x04, Unknown_0859F3A8 },
{ 0x03, 0x00, 0x00, 0x02, 0x04, Unknown_0859F3A8 },
{ 0x03, 0x00, 0x00, 0x02, 0x04, Unknown_0859F3A8 },
@@ -216,7 +217,7 @@ const struct MailLayout gUnknown_0859F3B4[] = {
{ 0x03, 0x00, 0x00, 0x02, 0x00, Unknown_0859F3A8 }
};
-const struct UnkMailStruct Unknown_0859F444[] = {
+static const struct UnkMailStruct Unknown_0859F444[] = {
{ .numEasyChatWords = 2, .lineHeight = 16 },
{ .numEasyChatWords = 2, .lineHeight = 16 },
{ .numEasyChatWords = 2, .lineHeight = 16 },
@@ -224,7 +225,7 @@ const struct UnkMailStruct Unknown_0859F444[] = {
{ .numEasyChatWords = 1, .lineHeight = 16 }
};
-const struct MailLayout gUnknown_0859F458[] = {
+static const struct MailLayout sUnknown_0859F458[] = {
{ 0x05, 0x07, 0x58, 0x0b, 0x1e, Unknown_0859F444 },
{ 0x05, 0x0a, 0x60, 0x09, 0x1e, Unknown_0859F444 },
{ 0x05, 0x0c, 0x68, 0x05, 0x1e, Unknown_0859F444 },
@@ -241,23 +242,23 @@ const struct MailLayout gUnknown_0859F458[] = {
// What the heck are these meant to be? Call them u16 for now.
-const u16 Unknown_0859F4E8[] = {
+static const u16 Unknown_0859F4E8[] = {
0x00, 0x4000, 0x00, 0x00
};
-const u16 Unknown_0859F4F0[] = {
+static const u16 Unknown_0859F4F0[] = {
0x00, 0x00, -1, 0x00
};
-const u16 Unknown_0859F4F8[] = {
+static const u16 Unknown_0859F4F8[] = {
0x04, 0x00, -1, 0x00
};
-const u16 Unknown_0859F500[] = {
+static const u16 Unknown_0859F500[] = {
0x00, 0x40, -1, 0x00
};
-const u16 *const gUnknown_0859F508[] = {
+static const u16 *const sUnknown_0859F508[] = {
Unknown_0859F4F0,
Unknown_0859F4F8,
Unknown_0859F500
@@ -265,60 +266,62 @@ const u16 *const gUnknown_0859F508[] = {
// .text
-void sub_8121478(struct MailStruct *mail, MainCallback callback, bool8 flag) {
+void ReadMail(struct MailStruct *mail, void (*callback)(void), bool8 flag)
+{
u16 buffer[2];
u16 species;
- gUnknown_0203A134 = calloc(1, sizeof(*gUnknown_0203A134));
- gUnknown_0203A134->language = LANGUAGE_ENGLISH;
- gUnknown_0203A134->playerIsSender = TRUE;
- gUnknown_0203A134->parserSingle = CopyEasyChatWord;
- gUnknown_0203A134->parserMultiple = ConvertEasyChatWordsToString;
- if (mail->itemId >= ITEM_ORANGE_MAIL && mail->itemId <= ITEM_RETRO_MAIL) {
- gUnknown_0203A134->mailType = mail->itemId - ITEM_ORANGE_MAIL;
+ sMailRead = calloc(1, sizeof(*sMailRead));
+ sMailRead->language = LANGUAGE_ENGLISH;
+ sMailRead->playerIsSender = TRUE;
+ sMailRead->parserSingle = CopyEasyChatWord;
+ sMailRead->parserMultiple = ConvertEasyChatWordsToString;
+ if (IS_ITEM_MAIL(mail->itemId))
+ {
+ sMailRead->mailType = mail->itemId - ITEM_ORANGE_MAIL;
}
else
{
- gUnknown_0203A134->mailType = 0;
+ sMailRead->mailType = 0;
flag = FALSE;
}
- switch (gUnknown_0203A134->playerIsSender)
+ switch (sMailRead->playerIsSender)
{
case FALSE:
default:
- gUnknown_0203A134->layout = &gUnknown_0859F3B4[gUnknown_0203A134->mailType];
+ sMailRead->layout = &sUnknown_0859F3B4[sMailRead->mailType];
break;
case TRUE:
- gUnknown_0203A134->layout = &gUnknown_0859F458[gUnknown_0203A134->mailType];
+ sMailRead->layout = &sUnknown_0859F458[sMailRead->mailType];
break;
}
- species = sub_80D45E8(mail->species, buffer);
+ species = MailSpeciesToSpecies(mail->species, buffer);
if (species >= SPECIES_BULBASAUR && species < NUM_SPECIES)
{
- switch (gUnknown_0203A134->mailType)
+ switch (sMailRead->mailType)
{
default:
- gUnknown_0203A134->animsActive = 0;
+ sMailRead->animsActive = 0;
break;
case ITEM_BEAD_MAIL - ITEM_ORANGE_MAIL:
- gUnknown_0203A134->animsActive = 1;
+ sMailRead->animsActive = 1;
break;
case ITEM_DREAM_MAIL - ITEM_ORANGE_MAIL:
- gUnknown_0203A134->animsActive = 2;
+ sMailRead->animsActive = 2;
break;
}
}
else
{
- gUnknown_0203A134->animsActive = 0;
+ sMailRead->animsActive = 0;
}
- gUnknown_0203A134->mail = mail;
- gUnknown_0203A134->callback = callback;
- gUnknown_0203A134->flag = flag;
- SetMainCallback2(sub_81219F0);
+ sMailRead->mail = mail;
+ sMailRead->callback = callback;
+ sMailRead->flag = flag;
+ SetMainCallback2(CB2_InitMailRead);
}
-bool8 sub_81215EC(void)
+static bool8 MailReadBuildGraphics(void)
{
u16 icon;
@@ -352,21 +355,21 @@ bool8 sub_81215EC(void)
SetGpuReg(REG_OFFSET_BG2HOFS, 0x0000);
SetGpuReg(REG_OFFSET_BG3HOFS, 0x0000);
SetGpuReg(REG_OFFSET_BG3VOFS, 0x0000);
- SetGpuReg(REG_OFFSET_BLDCNT, 0x0000);
+ SetGpuReg(REG_OFFSET_BLDCNT, 0x0000);
SetGpuReg(REG_OFFSET_BLDALPHA, 0x0000);
break;
case 6:
ResetBgsAndClearDma3BusyFlags(0);
- InitBgsFromTemplates(0, gUnknown_0859F290, 3);
- SetBgTilemapBuffer(1, gUnknown_0203A134->bg1TilemapBuffer);
- SetBgTilemapBuffer(2, gUnknown_0203A134->bg2TilemapBuffer);
+ InitBgsFromTemplates(0, sUnknown_0859F290, 3);
+ SetBgTilemapBuffer(1, sMailRead->bg1TilemapBuffer);
+ SetBgTilemapBuffer(2, sMailRead->bg2TilemapBuffer);
break;
case 7:
- InitWindows(gUnknown_0859F29C);
+ InitWindows(sUnknown_0859F29C);
DeactivateAllTextPrinters();
break;
case 8:
- decompress_and_copy_tile_data_to_vram(1, gUnknown_0859F2B8[gUnknown_0203A134->mailType].tiles, 0, 0, 0);
+ decompress_and_copy_tile_data_to_vram(1, sUnknown_0859F2B8[sMailRead->mailType].tiles, 0, 0, 0);
break;
case 9:
if (free_temp_tile_data_buffers_if_possible())
@@ -377,7 +380,7 @@ bool8 sub_81215EC(void)
case 10:
FillBgTilemapBufferRect_Palette0(0, 0, 0, 0, 30, 20);
FillBgTilemapBufferRect_Palette0(2, 1, 0, 0, 30, 20);
- CopyToBgTilemapBuffer(1, gUnknown_0859F2B8[gUnknown_0203A134->mailType].tileMap, 0, 0);
+ CopyToBgTilemapBuffer(1, sUnknown_0859F2B8[sMailRead->mailType].tileMap, 0, 0);
break;
case 11:
CopyBgTilemapBufferToVram(0);
@@ -386,24 +389,24 @@ bool8 sub_81215EC(void)
break;
case 12:
LoadPalette(GetOverworldTextboxPalettePtr(), 240, 32);
- gPlttBufferUnfaded[250] = gUnknown_0859F2B8[gUnknown_0203A134->mailType].color10;
- gPlttBufferFaded[250] = gUnknown_0859F2B8[gUnknown_0203A134->mailType].color10;
- gPlttBufferUnfaded[251] = gUnknown_0859F2B8[gUnknown_0203A134->mailType].color12;
- gPlttBufferFaded[251] = gUnknown_0859F2B8[gUnknown_0203A134->mailType].color12;
- LoadPalette(gUnknown_0859F2B8[gUnknown_0203A134->mailType].palette, 0, 32);
- gPlttBufferUnfaded[10] = gUnknown_0859F2B0[gSaveBlock2Ptr->playerGender][0];
- gPlttBufferFaded[10] = gUnknown_0859F2B0[gSaveBlock2Ptr->playerGender][0];
- gPlttBufferUnfaded[11] = gUnknown_0859F2B0[gSaveBlock2Ptr->playerGender][1];
- gPlttBufferFaded[11] = gUnknown_0859F2B0[gSaveBlock2Ptr->playerGender][1];
+ gPlttBufferUnfaded[250] = sUnknown_0859F2B8[sMailRead->mailType].color10;
+ gPlttBufferFaded[250] = sUnknown_0859F2B8[sMailRead->mailType].color10;
+ gPlttBufferUnfaded[251] = sUnknown_0859F2B8[sMailRead->mailType].color12;
+ gPlttBufferFaded[251] = sUnknown_0859F2B8[sMailRead->mailType].color12;
+ LoadPalette(sUnknown_0859F2B8[sMailRead->mailType].palette, 0, 32);
+ gPlttBufferUnfaded[10] = sUnknown_0859F2B0[gSaveBlock2Ptr->playerGender][0];
+ gPlttBufferFaded[10] = sUnknown_0859F2B0[gSaveBlock2Ptr->playerGender][0];
+ gPlttBufferUnfaded[11] = sUnknown_0859F2B0[gSaveBlock2Ptr->playerGender][1];
+ gPlttBufferFaded[11] = sUnknown_0859F2B0[gSaveBlock2Ptr->playerGender][1];
break;
case 13:
- if (gUnknown_0203A134->flag)
+ if (sMailRead->flag)
{
sub_8121A1C();
}
break;
case 14:
- if (gUnknown_0203A134->flag)
+ if (sMailRead->flag)
{
sub_8121B1C();
RunTextPrinters();
@@ -416,20 +419,20 @@ bool8 sub_81215EC(void)
}
break;
case 16:
- SetVBlankCallback(sub_8121C50);
+ SetVBlankCallback(VBlankCB_MailRead);
gPaletteFade.bufferTransferDisabled = TRUE;
break;
case 17:
- icon = sub_80D2E84(gUnknown_0203A134->mail->species);
- switch (gUnknown_0203A134->animsActive)
+ icon = sub_80D2E84(sMailRead->mail->species);
+ switch (sMailRead->animsActive)
{
case 1:
sub_80D2F68(icon);
- gUnknown_0203A134->monIconSprite = sub_80D2D78(icon, SpriteCallbackDummy, 0x60, 0x80, 0, 0);
+ sMailRead->monIconSprite = sub_80D2D78(icon, SpriteCallbackDummy, 0x60, 0x80, 0, 0);
break;
case 2:
sub_80D2F68(icon);
- gUnknown_0203A134->monIconSprite = sub_80D2D78(icon, SpriteCallbackDummy, 0x28, 0x80, 0, 0);
+ sMailRead->monIconSprite = sub_80D2D78(icon, SpriteCallbackDummy, 0x28, 0x80, 0, 0);
break;
}
break;
@@ -440,53 +443,53 @@ bool8 sub_81215EC(void)
ShowBg(2);
BeginNormalPaletteFade(-1, 0, 16, 0, 0);
gPaletteFade.bufferTransferDisabled = FALSE;
- gUnknown_0203A134->callback2 = sub_8121C98;
+ sMailRead->callback2 = CB2_WaitForPaletteExitOnKeyPress;
return TRUE;
default:
return FALSE;
}
- gMain.state ++;
+ gMain.state++;
return FALSE;
}
-void sub_81219F0(void)
+static void CB2_InitMailRead(void)
{
do
{
- if (sub_81215EC() == TRUE)
+ if (MailReadBuildGraphics() == TRUE)
{
- SetMainCallback2(sub_8121C64);
+ SetMainCallback2(CB2_MailRead);
break;
}
} while (sub_81221AC() != TRUE);
}
-void sub_8121A1C(void)
+static void sub_8121A1C(void)
{
u16 i;
u8 total;
u8 *ptr;
total = 0;
- for (i = 0; i < gUnknown_0203A134->layout->numSubStructs; i ++)
+ for (i = 0; i < sMailRead->layout->numSubStructs; i ++)
{
- ConvertEasyChatWordsToString(gUnknown_0203A134->strbuf[i], &gUnknown_0203A134->mail->words[total], gUnknown_0203A134->layout->var8[i].numEasyChatWords, 1);
- total += gUnknown_0203A134->layout->var8[i].numEasyChatWords;
+ ConvertEasyChatWordsToString(sMailRead->strbuf[i], &sMailRead->mail->words[total], sMailRead->layout->var8[i].numEasyChatWords, 1);
+ total += sMailRead->layout->var8[i].numEasyChatWords;
}
- ptr = StringCopy(gUnknown_0203A134->playerName, gUnknown_0203A134->mail->playerName);
- if (!gUnknown_0203A134->playerIsSender)
+ ptr = StringCopy(sMailRead->playerName, sMailRead->mail->playerName);
+ if (!sMailRead->playerIsSender)
{
StringCopy(ptr, gText_FromSpace);
- gUnknown_0203A134->signatureWidth = gUnknown_0203A134->layout->signatureWidth - (StringLength(gUnknown_0203A134->playerName) * 8 - 0x60);
+ sMailRead->signatureWidth = sMailRead->layout->signatureWidth - (StringLength(sMailRead->playerName) * 8 - 0x60);
}
else
{
- sub_81DB52C(gUnknown_0203A134->playerName);
- gUnknown_0203A134->signatureWidth = gUnknown_0203A134->layout->signatureWidth;
+ sub_81DB52C(sMailRead->playerName);
+ sMailRead->signatureWidth = sMailRead->layout->signatureWidth;
}
}
-void sub_8121B1C(void)
+static void sub_8121B1C(void)
{
u16 i;
u8 strbuf[0x20];
@@ -500,77 +503,76 @@ void sub_8121B1C(void)
PutWindowTilemap(1);
FillWindowPixelBuffer(0, 0);
FillWindowPixelBuffer(1, 0);
- for (i = 0; i < gUnknown_0203A134->layout->numSubStructs; i ++)
+ for (i = 0; i < sMailRead->layout->numSubStructs; i ++)
{
- if (gUnknown_0203A134->strbuf[i][0] == EOS || gUnknown_0203A134->strbuf[i][0] == CHAR_SPACE)
+ if (sMailRead->strbuf[i][0] == EOS || sMailRead->strbuf[i][0] == CHAR_SPACE)
{
continue;
}
- box_print(0, 1, gUnknown_0203A134->layout->var8[i].xOffset + gUnknown_0203A134->layout->wordsYPos, y + gUnknown_0203A134->layout->wordsXPos, gUnknown_0859F2AC, 0, gUnknown_0203A134->strbuf[i]);
- y += gUnknown_0203A134->layout->var8[i].lineHeight;
+ box_print(0, 1, sMailRead->layout->var8[i].xOffset + sMailRead->layout->wordsYPos, y + sMailRead->layout->wordsXPos, sUnknown_0859F2AC, 0, sMailRead->strbuf[i]);
+ y += sMailRead->layout->var8[i].lineHeight;
}
bufptr = StringCopy(strbuf, gText_FromSpace);
- StringCopy(bufptr, gUnknown_0203A134->playerName);
- box_x = GetStringCenterAlignXOffset(1, strbuf, gUnknown_0203A134->signatureWidth) + 0x68;
- box_y = gUnknown_0203A134->layout->signatureYPos + 0x58;
- box_print(0, 1, box_x, box_y, gUnknown_0859F2AC, 0, strbuf);
+ StringCopy(bufptr, sMailRead->playerName);
+ box_x = GetStringCenterAlignXOffset(1, strbuf, sMailRead->signatureWidth) + 0x68;
+ box_y = sMailRead->layout->signatureYPos + 0x58;
+ box_print(0, 1, box_x, box_y, sUnknown_0859F2AC, 0, strbuf);
CopyWindowToVram(0, 3);
CopyWindowToVram(1, 3);
}
-void sub_8121C50(void)
+static void VBlankCB_MailRead(void)
{
LoadOam();
ProcessSpriteCopyRequests();
TransferPlttBuffer();
}
-void sub_8121C64(void)
+static void CB2_MailRead(void)
{
- if (gUnknown_0203A134->animsActive != 0)
+ if (sMailRead->animsActive != 0)
{
AnimateSprites();
BuildOamBuffer();
}
- gUnknown_0203A134->callback2();
+ sMailRead->callback2();
}
-void sub_8121C98(void)
+static void CB2_WaitForPaletteExitOnKeyPress(void)
{
if (!UpdatePaletteFade())
{
- gUnknown_0203A134->callback2 = sub_8121CC0;
+ sMailRead->callback2 = CB2_ExitOnKeyPress;
}
}
-void sub_8121CC0(void)
+static void CB2_ExitOnKeyPress(void)
{
if (gMain.newKeys & (A_BUTTON | B_BUTTON))
{
BeginNormalPaletteFade(-1, 0, 0, 16, 0);
- gUnknown_0203A134->callback2 = sub_8121D00;
+ sMailRead->callback2 = CB2_ExitMailReadFreeVars;
}
}
-void sub_8121D00(void)
+static void CB2_ExitMailReadFreeVars(void)
{
if (!UpdatePaletteFade())
{
- SetMainCallback2(gUnknown_0203A134->callback);
- switch (gUnknown_0203A134->animsActive)
+ SetMainCallback2(sMailRead->callback);
+ switch (sMailRead->animsActive)
{
case 1:
case 2:
- sub_80D2FF0(sub_80D2E84(gUnknown_0203A134->mail->species));
- sub_80D2EF8(&gSprites[gUnknown_0203A134->monIconSprite]);
+ sub_80D2FF0(sub_80D2E84(sMailRead->mail->species));
+ sub_80D2EF8(&gSprites[sMailRead->monIconSprite]);
}
- memset(gUnknown_0203A134, 0, sizeof(*gUnknown_0203A134));
+ memset(sMailRead, 0, sizeof(*sMailRead));
ResetPaletteFade();
UnsetBgTilemapBuffer(0);
UnsetBgTilemapBuffer(1);
ResetBgsAndClearDma3BusyFlags(0);
FreeAllWindowBuffers();
- free(gUnknown_0203A134);
- gUnknown_0203A134 = NULL;
+ FREE_AND_SET_NULL(sMailRead);
}
}
diff --git a/src/mail_data.c b/src/mail_data.c
new file mode 100644
index 000000000..ebb49febf
--- /dev/null
+++ b/src/mail_data.c
@@ -0,0 +1,203 @@
+#include "global.h"
+#include "mail.h"
+#include "constants/items.h"
+#include "pokemon.h"
+#include "pokemon_icon.h"
+#include "constants/species.h"
+#include "text.h"
+#include "international_string_util.h"
+
+void ClearMailData(void)
+{
+ u8 i;
+
+ for (i = 0; i < MAIL_COUNT; i++)
+ ClearMailStruct(&gSaveBlock1Ptr->mail[i]);
+}
+
+void ClearMailStruct(struct MailStruct *mail)
+{
+ s32 i;
+
+ for (i = 0; i < MAIL_WORDS_COUNT; i++)
+ mail->words[i] = 0xFFFF;
+
+ for (i = 0; i < PLAYER_NAME_LENGTH; i++)
+ mail->playerName[i] = EOS;
+
+ for (i = 0; i < 4; i++)
+ mail->trainerId[i] = 0;
+
+ mail->species = SPECIES_BULBASAUR;
+ mail->itemId = ITEM_NONE;
+}
+
+bool8 MonHasMail(struct Pokemon *mon)
+{
+ u16 heldItem = GetMonData(mon, MON_DATA_HELD_ITEM);
+ if (ItemIsMail(heldItem) && GetMonData(mon, MON_DATA_MAIL) != 0xFF)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+u8 GiveMailToMon(struct Pokemon *mon, u16 itemId)
+{
+ u8 heldItem[2];
+ u8 id, i;
+ u16 species;
+ u32 personality;
+
+ heldItem[0] = itemId;
+ heldItem[1] = itemId >> 8;
+
+ for (id = 0; id < PARTY_SIZE; id++)
+ {
+ if (gSaveBlock1Ptr->mail[id].itemId == 0)
+ {
+ for (i = 0; i < MAIL_WORDS_COUNT; i++)
+ gSaveBlock1Ptr->mail[id].words[i] = 0xFFFF;
+
+ for (i = 0; i < PLAYER_NAME_LENGTH - 1; i++)
+ gSaveBlock1Ptr->mail[id].playerName[i] = gSaveBlock2Ptr->playerName[i];
+ gSaveBlock1Ptr->mail[id].playerName[i] = EOS;
+ PadNameString(gSaveBlock1Ptr->mail[id].playerName, CHAR_SPACE);
+
+ for (i = 0; i < 4; i++)
+ gSaveBlock1Ptr->mail[id].trainerId[i] = gSaveBlock2Ptr->playerTrainerId[i];
+
+ species = GetBoxMonData(&mon->box, MON_DATA_SPECIES);
+ personality = GetBoxMonData(&mon->box, MON_DATA_PERSONALITY);
+ gSaveBlock1Ptr->mail[id].species = SpeciesToMailSpecies(species, personality);
+ gSaveBlock1Ptr->mail[id].itemId = itemId;
+ SetMonData(mon, MON_DATA_MAIL, &id);
+ SetMonData(mon, MON_DATA_HELD_ITEM, heldItem);
+ return id;
+ }
+ }
+
+ return 0xFF;
+}
+
+u16 SpeciesToMailSpecies(u16 species, u32 personality)
+{
+ if (species == SPECIES_UNOWN)
+ {
+ u32 species = GetUnownLetterByPersonality(personality) + 30000;
+ return species;
+ }
+
+ return species;
+}
+
+u16 MailSpeciesToSpecies(u16 mailSpecies, u16 *buffer)
+{
+ u16 result;
+
+ if (mailSpecies >= 30000 && mailSpecies < (30000 + UNOWN_FORM_COUNT))
+ {
+ result = SPECIES_UNOWN;
+ *buffer = mailSpecies - 30000;
+ }
+ else
+ {
+ result = mailSpecies;
+ }
+
+ return result;
+}
+
+u8 GiveMailToMon2(struct Pokemon *mon, struct MailStruct *mail)
+{
+ u8 heldItem[2];
+ u16 itemId = mail->itemId;
+ u8 mailId = GiveMailToMon(mon, itemId);
+
+ if (mailId == 0xFF)
+ return 0xFF;
+
+ gSaveBlock1Ptr->mail[mailId] = *mail;
+
+ SetMonData(mon, MON_DATA_MAIL, &mailId);
+
+ heldItem[0] = itemId;
+ heldItem[1] = itemId >> 8;
+
+ SetMonData(mon, MON_DATA_HELD_ITEM, heldItem);
+
+ return mailId;
+}
+
+static bool32 DummyMailFunc(void)
+{
+ return FALSE;
+}
+
+void TakeMailFromMon(struct Pokemon *mon)
+{
+ u8 heldItem[2];
+ u8 mailId;
+
+ if (MonHasMail(mon))
+ {
+ mailId = GetMonData(mon, MON_DATA_MAIL);
+ gSaveBlock1Ptr->mail[mailId].itemId = ITEM_NONE;
+ mailId = 0xFF;
+ heldItem[0] = ITEM_NONE;
+ heldItem[1] = ITEM_NONE << 8;
+ SetMonData(mon, MON_DATA_MAIL, &mailId);
+ SetMonData(mon, MON_DATA_HELD_ITEM, heldItem);
+ }
+}
+
+void ClearMailItemId(u8 mailId)
+{
+ gSaveBlock1Ptr->mail[mailId].itemId = ITEM_NONE;
+}
+
+u8 TakeMailFromMon2(struct Pokemon *mon)
+{
+ u8 i;
+ u8 newHeldItem[2];
+ u8 newMailId;
+
+ newHeldItem[0] = ITEM_NONE;
+ newHeldItem[1] = ITEM_NONE << 8;
+ newMailId = 0xFF;
+
+ for (i = PARTY_SIZE; i < MAIL_COUNT; i++)
+ {
+ if (gSaveBlock1Ptr->mail[i].itemId == ITEM_NONE)
+ {
+ memcpy(&gSaveBlock1Ptr->mail[i], &gSaveBlock1Ptr->mail[GetMonData(mon, MON_DATA_MAIL)], sizeof(struct MailStruct));
+ gSaveBlock1Ptr->mail[GetMonData(mon, MON_DATA_MAIL)].itemId = ITEM_NONE;
+ SetMonData(mon, MON_DATA_MAIL, &newMailId);
+ SetMonData(mon, MON_DATA_HELD_ITEM, newHeldItem);
+ return i;
+ }
+ }
+
+ return 0xFF;
+}
+
+bool8 ItemIsMail(u16 itemId)
+{
+ switch (itemId)
+ {
+ case ITEM_ORANGE_MAIL:
+ case ITEM_HARBOR_MAIL:
+ case ITEM_GLITTER_MAIL:
+ case ITEM_MECH_MAIL:
+ case ITEM_WOOD_MAIL:
+ case ITEM_WAVE_MAIL:
+ case ITEM_BEAD_MAIL:
+ case ITEM_SHADOW_MAIL:
+ case ITEM_TROPIC_MAIL:
+ case ITEM_DREAM_MAIL:
+ case ITEM_FAB_MAIL:
+ case ITEM_RETRO_MAIL:
+ return TRUE;
+ default:
+ return FALSE;
+ }
+}
diff --git a/src/pokemon_2.c b/src/pokemon_2.c
index a4d00112b..db176e025 100644
--- a/src/pokemon_2.c
+++ b/src/pokemon_2.c
@@ -1155,7 +1155,7 @@ u8 GetMonsStateToDoubles_2(void)
s32 aliveCount = 0;
s32 i;
- for (i = 0; i < 6; i++)
+ for (i = 0; i < PARTY_SIZE; i++)
{
u32 species = GetMonData(&gPlayerParty[i], MON_DATA_SPECIES2, NULL);
if (species != SPECIES_EGG && species != SPECIES_NONE
diff --git a/src/pokemon_3.c b/src/pokemon_3.c
index 8fb642f5f..e3b340698 100644
--- a/src/pokemon_3.c
+++ b/src/pokemon_3.c
@@ -11,8 +11,7 @@
#include "link.h"
#include "constants/hold_effects.h"
#include "random.h"
-#include "trainer_classes.h"
-#include "trainer_ids.h"
+#include "constants/trainers.h"
#include "constants/songs.h"
#include "sound.h"
#include "m4a.h"
@@ -692,9 +691,9 @@ void AdjustFriendship(struct Pokemon *mon, u8 event)
if ((event != 5 || !(Random() & 1))
&& (event != 3
|| ((gBattleTypeFlags & BATTLE_TYPE_TRAINER)
- && (gTrainers[gTrainerBattleOpponent_A].trainerClass == CLASS_ELITE_FOUR
- || gTrainers[gTrainerBattleOpponent_A].trainerClass == CLASS_LEADER
- || gTrainers[gTrainerBattleOpponent_A].trainerClass == CLASS_CHAMPION))))
+ && (gTrainers[gTrainerBattleOpponent_A].trainerClass == TRAINER_CLASS_ELITE_FOUR
+ || gTrainers[gTrainerBattleOpponent_A].trainerClass == TRAINER_CLASS_LEADER
+ || gTrainers[gTrainerBattleOpponent_A].trainerClass == TRAINER_CLASS_CHAMPION))))
{
s8 mod = gUnknown_08329ECE[event][friendshipLevel];
if (mod > 0 && holdEffect == HOLD_EFFECT_HAPPINESS_UP)
@@ -1146,55 +1145,57 @@ void ClearBattleMonForms(void)
u16 GetBattleBGM(void)
{
if (gBattleTypeFlags & BATTLE_TYPE_KYOGRE_GROUDON)
- return 0x1E0;
+ return BGM_BATTLE34;
if (gBattleTypeFlags & BATTLE_TYPE_REGI)
- return 0x1DF;
+ return BGM_BATTLE36;
if (gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_x2000000))
- return 0x1DC;
+ return BGM_BATTLE20;
if (gBattleTypeFlags & BATTLE_TYPE_TRAINER)
{
u8 trainerClass;
+
if (gBattleTypeFlags & BATTLE_TYPE_FRONTIER)
trainerClass = GetFrontierOpponentClass(gTrainerBattleOpponent_A);
else if (gBattleTypeFlags & BATTLE_TYPE_x4000000)
- trainerClass = CLASS_EXPERT;
+ trainerClass = TRAINER_CLASS_EXPERT;
else
trainerClass = gTrainers[gTrainerBattleOpponent_A].trainerClass;
+
switch (trainerClass)
{
- case CLASS_AQUA_LEADER:
- case CLASS_MAGMA_LEADER:
- return 0x1E3;
- case CLASS_TEAM_AQUA:
- case CLASS_TEAM_MAGMA:
- case CLASS_AQUA_ADMIN:
- case CLASS_MAGMA_ADMIN:
- return 0x1DB;
- case CLASS_LEADER:
- return 0x1DD;
- case CLASS_CHAMPION:
- return 0x1DE;
- case CLASS_PKMN_TRAINER_RIVAL:
+ case TRAINER_CLASS_AQUA_LEADER:
+ case TRAINER_CLASS_MAGMA_LEADER:
+ return BGM_BATTLE30;
+ case TRAINER_CLASS_TEAM_AQUA:
+ case TRAINER_CLASS_TEAM_MAGMA:
+ case TRAINER_CLASS_AQUA_ADMIN:
+ case TRAINER_CLASS_MAGMA_ADMIN:
+ return BGM_BATTLE31;
+ case TRAINER_CLASS_LEADER:
+ return BGM_BATTLE32;
+ case TRAINER_CLASS_CHAMPION:
+ return BGM_BATTLE33;
+ case TRAINER_CLASS_PKMN_TRAINER_3:
if (gBattleTypeFlags & BATTLE_TYPE_FRONTIER)
- return 0x1E1;
+ return BGM_BATTLE35;
if (!StringCompare(gTrainers[gTrainerBattleOpponent_A].trainerName, gText_BattleWallyName))
- return 0x1DC;
- return 0x1E1;
- case CLASS_ELITE_FOUR:
- return 0x1E2;
- case CLASS_SALON_MAIDEN:
- case CLASS_DOME_ACE:
- case CLASS_PALACE_MAVEN:
- case CLASS_ARENA_TYCOON:
- case CLASS_FACTORY_HEAD:
- case CLASS_PIKE_QUEEN:
- case CLASS_PYRAMID_KING:
- return 0x1D7;
+ return BGM_BATTLE20;
+ return BGM_BATTLE35;
+ case TRAINER_CLASS_ELITE_FOUR:
+ return BGM_BATTLE38;
+ case TRAINER_CLASS_SALON_MAIDEN:
+ case TRAINER_CLASS_DOME_ACE:
+ case TRAINER_CLASS_PALACE_MAVEN:
+ case TRAINER_CLASS_ARENA_TYCOON:
+ case TRAINER_CLASS_FACTORY_HEAD:
+ case TRAINER_CLASS_PIKE_QUEEN:
+ case TRAINER_CLASS_PYRAMID_KING:
+ return BGM_BATTLE_FRONTIER_BRAIN;
default:
- return 0x1DC;
+ return BGM_BATTLE20;
}
}
- return 0x1DA;
+ return BGM_BATTLE27;
}
void PlayBattleBGM(void)
@@ -1396,7 +1397,7 @@ static s32 GetWildMonTableIdInAlteringCave(u16 species)
void SetWildMonHeldItem(void)
{
- if (!(gBattleTypeFlags & (BATTLE_TYPE_LEGENDARY | BATTLE_TYPE_TRAINER | BATTLE_TYPE_PYRAMID | BATTLE_TYPE_x100000)))
+ if (!(gBattleTypeFlags & (BATTLE_TYPE_LEGENDARY | BATTLE_TYPE_TRAINER | BATTLE_TYPE_PYRAMID | BATTLE_TYPE_PIKE)))
{
u16 rnd = Random() % 100;
u16 species = GetMonData(&gEnemyParty[0], MON_DATA_SPECIES, 0);
@@ -1462,12 +1463,14 @@ bool8 IsShinyOtIdPersonality(u32 otId, u32 personality)
return retVal;
}
-const u8* GetTrainerPartnerName(void)
+const u8 *GetTrainerPartnerName(void)
{
if (gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER)
{
if (gPartnerTrainerId == STEVEN_PARTNER_ID)
- return gTrainers[TRAINER_ID_STEVEN].trainerName;
+ {
+ return gTrainers[TRAINER_STEVEN].trainerName;
+ }
else
{
GetFrontierTrainerName(gStringVar1, gPartnerTrainerId);
@@ -1682,14 +1685,14 @@ void HandleSetPokedexFlag(u16 nationalNum, u8 caseId, u32 personality)
}
}
-const u8* GetTrainerClassNameFromId(u16 trainerId)
+const u8 *GetTrainerClassNameFromId(u16 trainerId)
{
if (trainerId > NO_OF_TRAINERS)
trainerId = 0;
return gTrainerClassNames[gTrainers[trainerId].trainerClass];
}
-const u8* GetTrainerNameFromId(u16 trainerId)
+const u8 *GetTrainerNameFromId(u16 trainerId)
{
if (trainerId > NO_OF_TRAINERS)
trainerId = 0;
diff --git a/src/recorded_battle.c b/src/recorded_battle.c
index 4f3fe4ab9..c88229c61 100644
--- a/src/recorded_battle.c
+++ b/src/recorded_battle.c
@@ -19,7 +19,7 @@
| BATTLE_TYPE_WALLY_TUTORIAL | BATTLE_TYPE_ROAMER | BATTLE_TYPE_EREADER_TRAINER \
| BATTLE_TYPE_KYOGRE_GROUDON | BATTLE_TYPE_LEGENDARY | BATTLE_TYPE_REGI \
| BATTLE_TYPE_RECORDED | BATTLE_TYPE_x4000000 | BATTLE_TYPE_SECRET_BASE \
- | BATTLE_TYPE_GROUDON | BATTLE_TYPE_KYORGE | BATTLE_TYPE_RAYQUAZA))
+ | BATTLE_TYPE_GROUDON | BATTLE_TYPE_KYOGRE | BATTLE_TYPE_RAYQUAZA))
extern u32 gBattleTypeFlags;
extern u16 gTrainerBattleOpponent_A;
diff --git a/src/safari_zone.c b/src/safari_zone.c
index 8bd1fffa7..ce1eb65bc 100644
--- a/src/safari_zone.c
+++ b/src/safari_zone.c
@@ -105,7 +105,7 @@ void SafariZoneRetirePrompt(void)
ScriptContext1_SetupScript(EventScript_2A4B6F);
}
-void sub_80FC190(void)
+void CB2_EndSafariBattle(void)
{
sSafariZoneFleedMons += gBattleResults.field_1F;
if (gBattleOutcome == BATTLE_CAUGHT)
diff --git a/src/scrcmd.c b/src/scrcmd.c
index 504d001ea..1b10501fc 100644
--- a/src/scrcmd.c
+++ b/src/scrcmd.c
@@ -656,7 +656,7 @@ bool8 ScrCmd_fadescreenspeed(struct ScriptContext *ctx)
bool8 ScrCmd_fadescreenswapbuffers(struct ScriptContext *ctx)
{
u8 mode = ScriptReadByte(ctx);
-
+
switch (mode)
{
case 1:
@@ -1445,7 +1445,7 @@ bool8 ScrCmd_drawboxtext(struct ScriptContext *ctx)
u8 top = ScriptReadByte(ctx);
u8 multichoiceId = ScriptReadByte(ctx);
u8 ignoreBPress = ScriptReadByte(ctx);
-
+
/*if (Multichoice(left, top, multichoiceId, ignoreBPress) == TRUE)
{
ScriptContext1_Stop();
@@ -1501,31 +1501,31 @@ bool8 ScrCmd_braillemessage(struct ScriptContext *ctx)
u8 y;
StringExpandPlaceholders(gStringVar4, ptr + 6);
-
+
width = GetStringWidth(6, gStringVar4, -1) / 8;
-
+
if (width > 0x1C)
width = 0x1C;
-
+
for (i = 0, height = 4; gStringVar4[i] != 0xFF;)
{
if (gStringVar4[i++] == 0xFE)
height += 3;
}
-
+
if (height > 0x12)
height = 0x12;
-
+
x = width + 2;
temp1 = (0x1E - x) / 2;
x = temp1 + 1;
temp1 = ((x - temp1 - 1) * 8 + 3);
-
+
y = height + 2;
temp2 = (0x14 - y) / 2;
y = temp2 + 2;
temp2 = ((y - temp2 - 1) * 8);
-
+
sub_8198A50(&template1, 0, x, y, width, height, 0xF, 0x1);
template2 = template1;
gUnknown_03000F30 = AddWindow(&template2);
@@ -1924,7 +1924,7 @@ bool8 ScrCmd_hidemoneybox(struct ScriptContext *ctx)
{
/*u8 x = ScriptReadByte(ctx);
u8 y = ScriptReadByte(ctx);*/
-
+
HideMoneyBox();
return FALSE;
}
@@ -1979,13 +1979,13 @@ bool8 ScrCmd_dotrainerbattle(struct ScriptContext *ctx)
return TRUE;
}
-bool8 ScrCmd_ontrainerbattleend(struct ScriptContext *ctx)
+bool8 ScrCmd_gotopostbattlescript(struct ScriptContext *ctx)
{
ctx->scriptPtr = BattleSetup_GetScriptAddrAfterBattle();
return FALSE;
}
-bool8 ScrCmd_ontrainerbattleendgoto(struct ScriptContext *ctx)
+bool8 ScrCmd_gotobeatenscript(struct ScriptContext *ctx)
{
ctx->scriptPtr = BattleSetup_GetTrainerPostBattleScript();
return FALSE;
@@ -1995,7 +1995,7 @@ bool8 ScrCmd_checktrainerflag(struct ScriptContext *ctx)
{
u16 index = VarGet(ScriptReadHalfword(ctx));
- ctx->comparisonResult = HasTrainerAlreadyBeenFought(index);
+ ctx->comparisonResult = HasTrainerBeenFought(index);
return FALSE;
}
@@ -2003,7 +2003,7 @@ bool8 ScrCmd_settrainerflag(struct ScriptContext *ctx)
{
u16 index = VarGet(ScriptReadHalfword(ctx));
- trainer_flag_set(index);
+ SetTrainerFlag(index);
return FALSE;
}
@@ -2011,7 +2011,7 @@ bool8 ScrCmd_cleartrainerflag(struct ScriptContext *ctx)
{
u16 index = VarGet(ScriptReadHalfword(ctx));
- trainer_flag_clear(index);
+ ClearTrainerFlag(index);
return FALSE;
}
@@ -2374,7 +2374,7 @@ bool8 ScrCmd_checkmonobedience(struct ScriptContext *ctx)
bool8 ScrCmd_cmdCF(struct ScriptContext *ctx)
{
const u8* v1 = sub_8099244();
-
+
if (v1)
{
((u8*)gUnknown_020375C0) = ctx->scriptPtr;
diff --git a/src/secret_base.c b/src/secret_base.c
index 6926bd804..bf6bec1f8 100644
--- a/src/secret_base.c
+++ b/src/secret_base.c
@@ -1283,7 +1283,7 @@ u8 sub_80EA20C(u8 secretBaseRecordId)
return (gSaveBlock1Ptr->secretBases[secretBaseRecordId].trainerId[0] % 5) + (gSaveBlock1Ptr->secretBases[secretBaseRecordId].gender * 5);
}
-const u8 *sub_80EA250(void)
+const u8 *GetSecretBaseTrainerLoseText(void)
{
u8 param;
diff --git a/src/starter_choose.c b/src/starter_choose.c
index 82f8f75f6..2d78af8fb 100644
--- a/src/starter_choose.c
+++ b/src/starter_choose.c
@@ -265,7 +265,7 @@ static void Task_StarterChoose5(u8 taskId)
{
u8 spriteId;
- switch (sub_8198C58())
+ switch (ProcessMenuInputNoWrap_())
{
case 0: // YES
// Return the starter choice and exit.
diff --git a/src/trainer_see.c b/src/trainer_see.c
new file mode 100644
index 000000000..b30f27347
--- /dev/null
+++ b/src/trainer_see.c
@@ -0,0 +1,68 @@
+#include "global.h"
+#include "trainer_see.h"
+#include "battle_setup.h"
+
+extern u8 gApproachingTrainerId;
+extern u8 gNoOfApproachingTrainers;
+extern u8 gUnknown_030060AC;
+extern u16 gUnknown_03006080;
+
+// this file's functions
+u8 CheckIfTrainerWantsBattle(u8 mapObjectId);
+
+bool8 CheckForTrainersWantingBattle(void)
+{
+ u8 i;
+
+ gNoOfApproachingTrainers = 0;
+ gApproachingTrainerId = 0;
+
+ for (i = 0; i < MAP_OBJECTS_COUNT; i++)
+ {
+ u8 retVal;
+
+ if (!gMapObjects[i].active)
+ continue;
+ if (gMapObjects[i].trainerType != 1 && gMapObjects[i].trainerType != 3)
+ continue;
+
+ retVal = CheckIfTrainerWantsBattle(i);
+ if (retVal == 2)
+ break; // two trainers have been found
+
+ if (retVal == 0) // no trainers
+ continue;
+
+ if (gNoOfApproachingTrainers > 1)
+ break;
+ if (GetMonsStateToDoubles_2() != 0) // one trainer found and cant have a double battle
+ break;
+ }
+
+ if (gNoOfApproachingTrainers == 1)
+ {
+ ResetTrainerOpponentIds();
+ ConfigureAndSetUpOneTrainerBattle(gApproachingTrainers[gNoOfApproachingTrainers - 1].mapObjectId,
+ gApproachingTrainers[gNoOfApproachingTrainers - 1].trainerScriptPtr);
+ gUnknown_030060AC = 1;
+ return TRUE;
+ }
+ else if (gNoOfApproachingTrainers == 2)
+ {
+ ResetTrainerOpponentIds();
+ for (i = 0; i < gNoOfApproachingTrainers; i++, gApproachingTrainerId++)
+ {
+ ConfigureTwoTrainersBattle(gApproachingTrainers[i].mapObjectId,
+ gApproachingTrainers[i].trainerScriptPtr);
+ }
+ SetUpTwoTrainersBattle();
+ gApproachingTrainerId = 0;
+ gUnknown_030060AC = 1;
+ return TRUE;
+ }
+ else
+ {
+ gUnknown_030060AC = 0;
+ return FALSE;
+ }
+}
diff --git a/src/tv.c b/src/tv.c
index 1605be29c..205adbf4d 100644
--- a/src/tv.c
+++ b/src/tv.c
@@ -1793,7 +1793,7 @@ void EndMassOutbreak(void)
gSaveBlock1Ptr->outbreakDaysLeft = 0;
}
-void sub_80ED888(u16 days)
+void UpdateTVShowsPerDay(u16 days)
{
sub_80ED8B4(days);
diff --git a/src/wallclock.c b/src/wallclock.c
new file mode 100644
index 000000000..892ef3f05
--- /dev/null
+++ b/src/wallclock.c
@@ -0,0 +1,1057 @@
+#include "global.h"
+#include "main.h"
+#include "palette.h"
+#include "gpu_regs.h"
+#include "bg.h"
+#include "rtc.h"
+#include "clock.h"
+#include "wallclock.h"
+#include "event_data.h"
+#include "graphics.h"
+#include "text.h"
+#include "window.h"
+#include "text_window.h"
+#include "menu.h"
+#include "unknown_task.h"
+#include "task.h"
+#include "strings.h"
+#include "sound.h"
+#include "songs.h"
+#include "trig.h"
+#include "decompress.h"
+
+// static types
+
+#define tMinuteHandAngle data[0]
+#define tHourHandAngle data[1]
+#define tHours data[2]
+#define tMinutes data[3]
+#define tMvmtDir data[4]
+#define tPeriod data[5]
+#define tMvmtSpeed data[6]
+
+#define TAG_GFX_WALL_CLOCK_HAND 0x1000
+#define TAG_PAL_WALL_CLOCK_HAND 0x1000
+
+// static declarations
+
+static void WallClockMainCallback(void);
+static void Task_SetClock1(u8 taskId);
+static void Task_SetClock2(u8 taskId);
+static void Task_SetClock3(u8 taskId);
+static void Task_SetClock4(u8 taskId);
+static void Task_SetClock5(u8 taskId);
+static void Task_SetClock6(u8 taskId);
+static void Task_ViewClock1(u8 taskId);
+static void Task_ViewClock2(u8 taskId);
+static void Task_ViewClock3(u8 taskId);
+static void Task_ViewClock4(u8 taskId);
+static u16 CalcNewMinHandAngle(u16 a0, u8 command, u8 a2);
+static bool32 AdvanceClock(u8 taskId, u8 command);
+static void UpdateClockPeriod(u8 taskId, u8 command);
+static void InitClockWithRtc(u8 taskId);
+static void SpriteCB_MinuteHand(struct Sprite *sprite);
+static void SpriteCB_HourHand(struct Sprite *sprite);
+static void SpriteCB_AMIndicator(struct Sprite *sprite);
+static void SpriteCB_PMIndicator(struct Sprite *sprite);
+
+// rodata
+
+static const u8 gUnknown_085B1F58[] = INCBIN_U8("graphics/wallclock/graphics_85b1f58.4bpp.lz");
+static const u16 gUnknown_085B21D4[] = INCBIN_U16("graphics/wallclock/palette_85b21d4.gbapal");
+static const struct WindowTemplate gUnknown_085B21DC[] = {
+ { 0x00, 0x03, 0x11, 0x18, 0x02, 0x0e, 0x200 },
+ { 0x02, 0x18, 0x10, 0x06, 0x02, 0x0c, 0x230 },
+ DUMMY_WIN_TEMPLATE
+};
+static const struct WindowTemplate gUnknown_085B21F4 = {
+ 0x00, 0x18, 0x09, 0x05, 0x04, 0x0e, 0x23c
+};
+static const struct BgTemplate gUnknown_085B21FC[] = {
+ {
+ .bg = 0,
+ .charBaseIndex = 2,
+ .mapBaseIndex = 31,
+ .priority = 0
+ },
+ {
+ .bg = 2,
+ .charBaseIndex = 1,
+ .mapBaseIndex = 8,
+ .priority = 1
+ },
+ {
+ .bg = 3,
+ .charBaseIndex = 0,
+ .mapBaseIndex = 7,
+ .priority = 2
+ }
+};
+static const struct CompressedSpriteSheet gUnknown_085B2208 = {
+ gUnknown_085B1F58, 0x2000, TAG_GFX_WALL_CLOCK_HAND
+};
+static const u32 filler_85B2210[2] = {};
+static const struct SpritePalette gUnknown_085B2218[] = {
+ { gUnknown_08DCC01C, TAG_PAL_WALL_CLOCK_HAND },
+ { gUnknown_08DCC03C, 0x1001 },
+ {}
+};
+static const struct OamData Unknown_085B2230 = {
+ .y = 0xa0,
+ .size = 3,
+ .priority = 1
+};
+static const union AnimCmd Unknown_085B2238[] = {
+ ANIMCMD_FRAME(0, 30),
+ ANIMCMD_END
+};
+static const union AnimCmd Unknown_085B2240[] = {
+ ANIMCMD_FRAME(64, 30),
+ ANIMCMD_END
+};
+static const union AnimCmd *const gUnknown_085B2248[] = {
+ Unknown_085B2238
+};
+static const union AnimCmd *const gUnknown_085B224C[] = {
+ Unknown_085B2240
+};
+static const struct SpriteTemplate gUnknown_085B2250 = {
+ TAG_GFX_WALL_CLOCK_HAND,
+ TAG_PAL_WALL_CLOCK_HAND,
+ &Unknown_085B2230,
+ gUnknown_085B2248,
+ NULL,
+ gDummySpriteAffineAnimTable,
+ SpriteCB_MinuteHand
+};
+static const struct SpriteTemplate gUnknown_085B2268 = {
+ TAG_GFX_WALL_CLOCK_HAND,
+ TAG_PAL_WALL_CLOCK_HAND,
+ &Unknown_085B2230,
+ gUnknown_085B224C,
+ NULL,
+ gDummySpriteAffineAnimTable,
+ SpriteCB_HourHand
+};
+static const struct OamData Unknown_085B2280 = {
+ .y = 0xa0,
+ .size = 1,
+ .priority = 3
+};
+static const union AnimCmd Unknown_085B2288[] = {
+ ANIMCMD_FRAME(0x84, 30),
+ ANIMCMD_END
+};
+static const union AnimCmd Unknown_085B2290[] = {
+ ANIMCMD_FRAME(0x80, 30),
+ ANIMCMD_END
+};
+static const union AnimCmd *const gUnknown_085B2298[] = {
+ Unknown_085B2288
+};
+static const union AnimCmd *const gUnknown_085B229C[] = {
+ Unknown_085B2290
+};
+static const struct SpriteTemplate gUnknown_085B22A0 = {
+ TAG_GFX_WALL_CLOCK_HAND,
+ TAG_PAL_WALL_CLOCK_HAND,
+ &Unknown_085B2280,
+ gUnknown_085B2298,
+ NULL,
+ gDummySpriteAffineAnimTable,
+ SpriteCB_AMIndicator
+};
+static const struct SpriteTemplate gUnknown_085B22B8 = {
+ TAG_GFX_WALL_CLOCK_HAND,
+ TAG_PAL_WALL_CLOCK_HAND,
+ &Unknown_085B2280,
+ gUnknown_085B229C,
+ NULL,
+ gDummySpriteAffineAnimTable,
+ SpriteCB_PMIndicator
+};
+static const s8 sClockHandCoords[][2] = {
+ { 0x00, -0x18},
+ { 0x01, -0x19},
+ { 0x01, -0x19},
+ { 0x02, -0x19},
+ { 0x02, -0x19},
+ { 0x02, -0x19},
+ { 0x03, -0x18},
+ { 0x03, -0x19},
+ { 0x04, -0x19},
+ { 0x04, -0x19},
+ { 0x04, -0x19},
+ { 0x05, -0x19},
+ { 0x05, -0x19},
+ { 0x06, -0x18},
+ { 0x06, -0x18},
+ { 0x06, -0x18},
+ { 0x07, -0x18},
+ { 0x07, -0x18},
+ { 0x07, -0x18},
+ { 0x08, -0x18},
+ { 0x08, -0x18},
+ { 0x09, -0x18},
+ { 0x09, -0x18},
+ { 0x0a, -0x17},
+ { 0x0a, -0x17},
+ { 0x0b, -0x16},
+ { 0x0b, -0x16},
+ { 0x0b, -0x16},
+ { 0x0c, -0x16},
+ { 0x0c, -0x15},
+ { 0x0d, -0x15},
+ { 0x0d, -0x15},
+ { 0x0d, -0x15},
+ { 0x0e, -0x15},
+ { 0x0e, -0x15},
+ { 0x0e, -0x14},
+ { 0x0e, -0x14},
+ { 0x0f, -0x14},
+ { 0x0f, -0x13},
+ { 0x10, -0x13},
+ { 0x10, -0x13},
+ { 0x10, -0x13},
+ { 0x10, -0x12},
+ { 0x10, -0x12},
+ { 0x11, -0x12},
+ { 0x11, -0x11},
+ { 0x11, -0x11},
+ { 0x12, -0x11},
+ { 0x12, -0x11},
+ { 0x12, -0x10},
+ { 0x12, -0x10},
+ { 0x13, -0x10},
+ { 0x13, -0x0f},
+ { 0x13, -0x0f},
+ { 0x14, -0x0f},
+ { 0x14, -0x0e},
+ { 0x14, -0x0e},
+ { 0x14, -0x0d},
+ { 0x14, -0x0d},
+ { 0x15, -0x0d},
+ { 0x15, -0x0d},
+ { 0x15, -0x0c},
+ { 0x16, -0x0c},
+ { 0x16, -0x0c},
+ { 0x16, -0x0b},
+ { 0x16, -0x0b},
+ { 0x16, -0x0a},
+ { 0x17, -0x0a},
+ { 0x17, -0x09},
+ { 0x17, -0x09},
+ { 0x17, -0x09},
+ { 0x17, -0x09},
+ { 0x17, -0x08},
+ { 0x17, -0x08},
+ { 0x17, -0x07},
+ { 0x17, -0x07},
+ { 0x17, -0x06},
+ { 0x18, -0x06},
+ { 0x18, -0x06},
+ { 0x19, -0x05},
+ { 0x19, -0x05},
+ { 0x18, -0x04},
+ { 0x19, -0x04},
+ { 0x18, -0x03},
+ { 0x19, -0x03},
+ { 0x19, -0x03},
+ { 0x19, -0x02},
+ { 0x19, -0x02},
+ { 0x18, -0x01},
+ { 0x19, -0x01},
+ { 0x18, 0x00},
+ { 0x18, 0x00},
+ { 0x18, 0x00},
+ { 0x18, 0x01},
+ { 0x18, 0x01},
+ { 0x19, 0x02},
+ { 0x18, 0x02},
+ { 0x19, 0x02},
+ { 0x18, 0x03},
+ { 0x18, 0x03},
+ { 0x19, 0x04},
+ { 0x18, 0x04},
+ { 0x18, 0x05},
+ { 0x18, 0x05},
+ { 0x18, 0x05},
+ { 0x18, 0x06},
+ { 0x17, 0x06},
+ { 0x17, 0x06},
+ { 0x17, 0x07},
+ { 0x17, 0x08},
+ { 0x17, 0x08},
+ { 0x17, 0x08},
+ { 0x17, 0x09},
+ { 0x17, 0x09},
+ { 0x17, 0x0a},
+ { 0x16, 0x0a},
+ { 0x16, 0x0a},
+ { 0x16, 0x0b},
+ { 0x16, 0x0b},
+ { 0x16, 0x0b},
+ { 0x16, 0x0c},
+ { 0x15, 0x0c},
+ { 0x15, 0x0c},
+ { 0x15, 0x0d},
+ { 0x14, 0x0d},
+ { 0x14, 0x0d},
+ { 0x13, 0x0d},
+ { 0x13, 0x0d},
+ { 0x13, 0x0e},
+ { 0x13, 0x0e},
+ { 0x13, 0x0f},
+ { 0x13, 0x0f},
+ { 0x12, 0x0f},
+ { 0x12, 0x10},
+ { 0x11, 0x10},
+ { 0x11, 0x10},
+ { 0x11, 0x11},
+ { 0x11, 0x11},
+ { 0x10, 0x11},
+ { 0x10, 0x12},
+ { 0x10, 0x12},
+ { 0x0f, 0x12},
+ { 0x0e, 0x12},
+ { 0x0f, 0x13},
+ { 0x0e, 0x13},
+ { 0x0e, 0x13},
+ { 0x0d, 0x13},
+ { 0x0d, 0x14},
+ { 0x0d, 0x14},
+ { 0x0d, 0x14},
+ { 0x0c, 0x14},
+ { 0x0c, 0x14},
+ { 0x0c, 0x15},
+ { 0x0b, 0x15},
+ { 0x0b, 0x15},
+ { 0x0b, 0x15},
+ { 0x0a, 0x15},
+ { 0x0a, 0x16},
+ { 0x0a, 0x16},
+ { 0x09, 0x16},
+ { 0x09, 0x16},
+ { 0x08, 0x16},
+ { 0x07, 0x16},
+ { 0x07, 0x17},
+ { 0x07, 0x17},
+ { 0x06, 0x17},
+ { 0x06, 0x17},
+ { 0x05, 0x17},
+ { 0x05, 0x17},
+ { 0x05, 0x18},
+ { 0x04, 0x18},
+ { 0x04, 0x18},
+ { 0x04, 0x18},
+ { 0x03, 0x18},
+ { 0x02, 0x18},
+ { 0x02, 0x18},
+ { 0x01, 0x18},
+ { 0x01, 0x18},
+ { 0x00, 0x18},
+ { 0x00, 0x18},
+ {-0x01, 0x17},
+ { 0x00, 0x18},
+ { 0x00, 0x18},
+ {-0x01, 0x18},
+ {-0x01, 0x18},
+ {-0x02, 0x18},
+ {-0x02, 0x18},
+ {-0x03, 0x18},
+ {-0x03, 0x18},
+ {-0x04, 0x18},
+ {-0x04, 0x18},
+ {-0x05, 0x18},
+ {-0x05, 0x17},
+ {-0x05, 0x17},
+ {-0x06, 0x17},
+ {-0x06, 0x17},
+ {-0x07, 0x17},
+ {-0x07, 0x17},
+ {-0x07, 0x17},
+ {-0x08, 0x17},
+ {-0x08, 0x16},
+ {-0x09, 0x16},
+ {-0x09, 0x16},
+ {-0x0a, 0x16},
+ {-0x0a, 0x16},
+ {-0x0a, 0x15},
+ {-0x0b, 0x15},
+ {-0x0b, 0x15},
+ {-0x0b, 0x15},
+ {-0x0b, 0x14},
+ {-0x0c, 0x14},
+ {-0x0c, 0x14},
+ {-0x0d, 0x14},
+ {-0x0d, 0x14},
+ {-0x0d, 0x13},
+ {-0x0e, 0x13},
+ {-0x0e, 0x13},
+ {-0x0e, 0x13},
+ {-0x0e, 0x12},
+ {-0x0f, 0x12},
+ {-0x0f, 0x12},
+ {-0x0f, 0x11},
+ {-0x10, 0x11},
+ {-0x10, 0x11},
+ {-0x11, 0x11},
+ {-0x11, 0x10},
+ {-0x11, 0x10},
+ {-0x12, 0x10},
+ {-0x11, 0x0f},
+ {-0x12, 0x0f},
+ {-0x12, 0x0f},
+ {-0x13, 0x0f},
+ {-0x13, 0x0e},
+ {-0x13, 0x0e},
+ {-0x13, 0x0d},
+ {-0x13, 0x0d},
+ {-0x14, 0x0d},
+ {-0x14, 0x0c},
+ {-0x14, 0x0c},
+ {-0x15, 0x0c},
+ {-0x15, 0x0c},
+ {-0x15, 0x0b},
+ {-0x15, 0x0b},
+ {-0x15, 0x0a},
+ {-0x15, 0x0a},
+ {-0x15, 0x09},
+ {-0x16, 0x09},
+ {-0x16, 0x09},
+ {-0x16, 0x08},
+ {-0x16, 0x08},
+ {-0x16, 0x07},
+ {-0x17, 0x07},
+ {-0x17, 0x07},
+ {-0x17, 0x06},
+ {-0x17, 0x06},
+ {-0x17, 0x05},
+ {-0x18, 0x05},
+ {-0x17, 0x04},
+ {-0x17, 0x04},
+ {-0x18, 0x04},
+ {-0x18, 0x04},
+ {-0x18, 0x03},
+ {-0x18, 0x03},
+ {-0x18, 0x02},
+ {-0x18, 0x02},
+ {-0x18, 0x01},
+ {-0x18, 0x01},
+ {-0x18, 0x01},
+ {-0x18, 0x00},
+ {-0x19, 0x00},
+ {-0x18, -0x01},
+ {-0x19, -0x01},
+ {-0x18, -0x01},
+ {-0x18, -0x02},
+ {-0x18, -0x02},
+ {-0x18, -0x03},
+ {-0x18, -0x03},
+ {-0x18, -0x04},
+ {-0x18, -0x04},
+ {-0x18, -0x04},
+ {-0x18, -0x05},
+ {-0x18, -0x05},
+ {-0x18, -0x06},
+ {-0x18, -0x06},
+ {-0x17, -0x06},
+ {-0x17, -0x07},
+ {-0x17, -0x07},
+ {-0x17, -0x08},
+ {-0x17, -0x08},
+ {-0x17, -0x09},
+ {-0x17, -0x09},
+ {-0x16, -0x09},
+ {-0x16, -0x09},
+ {-0x16, -0x0a},
+ {-0x16, -0x0a},
+ {-0x15, -0x0a},
+ {-0x15, -0x0b},
+ {-0x16, -0x0b},
+ {-0x16, -0x0c},
+ {-0x15, -0x0c},
+ {-0x15, -0x0d},
+ {-0x15, -0x0d},
+ {-0x14, -0x0d},
+ {-0x15, -0x0e},
+ {-0x14, -0x0e},
+ {-0x14, -0x0e},
+ {-0x13, -0x0e},
+ {-0x13, -0x0f},
+ {-0x13, -0x0f},
+ {-0x12, -0x10},
+ {-0x12, -0x10},
+ {-0x12, -0x10},
+ {-0x12, -0x11},
+ {-0x12, -0x11},
+ {-0x11, -0x11},
+ {-0x11, -0x12},
+ {-0x11, -0x12},
+ {-0x10, -0x12},
+ {-0x10, -0x12},
+ {-0x10, -0x13},
+ {-0x10, -0x13},
+ {-0x0f, -0x13},
+ {-0x0f, -0x13},
+ {-0x0f, -0x14},
+ {-0x0e, -0x14},
+ {-0x0e, -0x14},
+ {-0x0e, -0x15},
+ {-0x0d, -0x15},
+ {-0x0d, -0x15},
+ {-0x0d, -0x15},
+ {-0x0c, -0x15},
+ {-0x0c, -0x16},
+ {-0x0b, -0x16},
+ {-0x0b, -0x16},
+ {-0x0b, -0x16},
+ {-0x0a, -0x16},
+ {-0x0a, -0x16},
+ {-0x09, -0x16},
+ {-0x09, -0x17},
+ {-0x09, -0x17},
+ {-0x08, -0x17},
+ {-0x08, -0x17},
+ {-0x07, -0x17},
+ {-0x07, -0x17},
+ {-0x07, -0x18},
+ {-0x06, -0x18},
+ {-0x06, -0x18},
+ {-0x05, -0x18},
+ {-0x05, -0x18},
+ {-0x04, -0x18},
+ {-0x04, -0x18},
+ {-0x04, -0x18},
+ {-0x04, -0x19},
+ {-0x03, -0x19},
+ {-0x02, -0x19},
+ {-0x02, -0x18},
+ {-0x02, -0x18},
+ {-0x01, -0x19},
+ {-0x01, -0x19},
+ { 0x00, -0x19}
+};
+
+// text
+
+static void WallClockVblankCallback(void)
+{
+ LoadOam();
+ ProcessSpriteCopyRequests();
+ TransferPlttBuffer();
+}
+
+static void LoadWallClockGraphics(void)
+{
+ SetVBlankCallback(NULL);
+ SetGpuReg(REG_OFFSET_DISPCNT, 0x0000);
+ SetGpuReg(REG_OFFSET_BG3CNT, 0x0000);
+ SetGpuReg(REG_OFFSET_BG2CNT, 0x0000);
+ SetGpuReg(REG_OFFSET_BG1CNT, 0x0000);
+ SetGpuReg(REG_OFFSET_BG0CNT, 0x0000);
+ ChangeBgX(0, 0, 0);
+ ChangeBgY(0, 0, 0);
+ ChangeBgX(1, 0, 0);
+ ChangeBgY(1, 0, 0);
+ ChangeBgX(2, 0, 0);
+ ChangeBgY(2, 0, 0);
+ ChangeBgX(3, 0, 0);
+ ChangeBgY(3, 0, 0);
+ DmaFillLarge16(3, 0, (void *)VRAM, VRAM_SIZE, 0x1000);
+ DmaClear32(3, (void *)OAM, OAM_SIZE);
+ DmaClear16(3, (void *)PLTT, PLTT_SIZE);
+ LZ77UnCompVram(gUnknown_08DCC05C, (void *)VRAM);
+ if (gSpecialVar_0x8004 == 0)
+ {
+ LoadPalette(gUnknown_08DCC01C, 0x00, 0x20);
+ }
+ else
+ {
+ LoadPalette(gUnknown_08DCC03C, 0x00, 0x20);
+ }
+ LoadPalette(GetOverworldTextboxPalettePtr(), 0xe0, 0x20);
+ LoadPalette(gUnknown_085B21D4, 0xc0, 0x08);
+ ResetBgsAndClearDma3BusyFlags(0);
+ InitBgsFromTemplates(0, gUnknown_085B21FC, 3);
+ InitWindows(gUnknown_085B21DC);
+ DeactivateAllTextPrinters();
+ sub_809882C(0, 0x250, 0xd0);
+ clear_scheduled_bg_copies_to_vram();
+ remove_some_task();
+ ResetTasks();
+ ResetSpriteData();
+ ResetPaletteFade();
+ FreeAllSpritePalettes();
+ LoadCompressedObjectPic(&gUnknown_085B2208);
+ LoadSpritePalettes(gUnknown_085B2218);
+}
+
+static void WallClockInit(void)
+{
+ BeginNormalPaletteFade(-1, 0, 16, 0, 0);
+ EnableInterrupts(INTR_FLAG_VBLANK);
+ SetVBlankCallback(WallClockVblankCallback);
+ SetMainCallback2(WallClockMainCallback);
+ SetGpuReg(REG_OFFSET_BLDCNT, 0x0000);
+ SetGpuReg(REG_OFFSET_BLDALPHA, 0x0000);
+ SetGpuReg(REG_OFFSET_BLDY, 0x0000);
+ SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_OBJ_1D_MAP | DISPCNT_OBJ_ON);
+ ShowBg(0);
+ ShowBg(2);
+ ShowBg(3);
+}
+
+void Cb2_StartWallClock(void)
+{
+ u8 taskId;
+ u8 spriteId;
+
+ LoadWallClockGraphics();
+ LZ77UnCompVram(gUnknown_08DCC648, (u16 *)BG_SCREEN_ADDR(7));
+
+ taskId = CreateTask(Task_SetClock1, 0);
+ gTasks[taskId].tHours = 10;
+ gTasks[taskId].tMinutes = 0;
+ gTasks[taskId].tMvmtDir = 0;
+ gTasks[taskId].tPeriod = 0;
+ gTasks[taskId].tMvmtSpeed = 0;
+ gTasks[taskId].tMinuteHandAngle = 0;
+ gTasks[taskId].tHourHandAngle = 300;
+
+ spriteId = CreateSprite(&gUnknown_085B2250, 0x78, 0x50, 1);
+ gSprites[spriteId].data[0] = taskId;
+ gSprites[spriteId].oam.affineMode = ST_OAM_AFFINE_NORMAL;
+ gSprites[spriteId].oam.matrixNum = 0;
+
+ spriteId = CreateSprite(&gUnknown_085B2268, 0x78, 0x50, 0);
+ gSprites[spriteId].data[0] = taskId;
+ gSprites[spriteId].oam.affineMode = ST_OAM_AFFINE_NORMAL;
+ gSprites[spriteId].oam.matrixNum = 1;
+
+ spriteId = CreateSprite(&gUnknown_085B22A0, 0x78, 0x50, 2);
+ gSprites[spriteId].data[0] = taskId;
+ gSprites[spriteId].data[1] = 45;
+
+ spriteId = CreateSprite(&gUnknown_085B22B8, 0x78, 0x50, 2);
+ gSprites[spriteId].data[0] = taskId;
+ gSprites[spriteId].data[1] = 90;
+
+ WallClockInit();
+
+ PrintTextOnWindow(1, 1, gText_Confirm3, 0, 1, 0, NULL);
+ PutWindowTilemap(1);
+ schedule_bg_copy_tilemap_to_vram(2);
+}
+
+void Cb2_ViewWallClock(void)
+{
+ u8 taskId;
+ u8 spriteId;
+ u8 angle1;
+ u8 angle2;
+
+ LoadWallClockGraphics();
+ LZ77UnCompVram(gUnknown_08DCC908, (u16 *)BG_SCREEN_ADDR(7));
+
+ taskId = CreateTask(Task_ViewClock1, 0);
+ InitClockWithRtc(taskId);
+ if (gTasks[taskId].tPeriod == 0)
+ {
+ angle1 = 45;
+ angle2 = 90;
+ }
+ else
+ {
+ angle1 = 90;
+ angle2 = 135;
+ }
+
+ spriteId = CreateSprite(&gUnknown_085B2250, 0x78, 0x50, 1);
+ gSprites[spriteId].data[0] = taskId;
+ gSprites[spriteId].oam.affineMode = ST_OAM_AFFINE_NORMAL;
+ gSprites[spriteId].oam.matrixNum = 0;
+
+ spriteId = CreateSprite(&gUnknown_085B2268, 0x78, 0x50, 0);
+ gSprites[spriteId].data[0] = taskId;
+ gSprites[spriteId].oam.affineMode = ST_OAM_AFFINE_NORMAL;
+ gSprites[spriteId].oam.matrixNum = 1;
+
+ spriteId = CreateSprite(&gUnknown_085B22A0, 0x78, 0x50, 2);
+ gSprites[spriteId].data[0] = taskId;
+ gSprites[spriteId].data[1] = angle1;
+
+ spriteId = CreateSprite(&gUnknown_085B22B8, 0x78, 0x50, 2);
+ gSprites[spriteId].data[0] = taskId;
+ gSprites[spriteId].data[1] = angle2;
+
+ WallClockInit();
+
+ PrintTextOnWindow(1, 1, gText_Cancel4, 0, 1, 0, NULL);
+ PutWindowTilemap(1);
+ schedule_bg_copy_tilemap_to_vram(2);
+}
+
+static void WallClockMainCallback(void)
+{
+ RunTasks();
+ AnimateSprites();
+ BuildOamBuffer();
+ do_scheduled_bg_tilemap_copies_to_vram();
+ UpdatePaletteFade();
+}
+
+static void Task_SetClock1(u8 taskId)
+{
+ if (!gPaletteFade.active)
+ {
+ gTasks[taskId].func = Task_SetClock2;
+ }
+}
+
+static void Task_SetClock2(u8 taskId)
+{
+ if (gTasks[taskId].tMinuteHandAngle % 6)
+ {
+ gTasks[taskId].tMinuteHandAngle = CalcNewMinHandAngle(gTasks[taskId].tMinuteHandAngle, gTasks[taskId].tMvmtDir, gTasks[taskId].tMvmtSpeed);
+ }
+ else
+ {
+ gTasks[taskId].tMinuteHandAngle = gTasks[taskId].tMinutes * 6;
+ gTasks[taskId].tHourHandAngle = (gTasks[taskId].tHours % 12) * 30 + (gTasks[taskId].tMinutes / 10) * 5;
+ if (gMain.newKeys & A_BUTTON)
+ {
+ gTasks[taskId].func = Task_SetClock3;
+ }
+ else
+ {
+ gTasks[taskId].tMvmtDir = 0;
+ if (gMain.heldKeys & DPAD_LEFT)
+ {
+ gTasks[taskId].tMvmtDir = 1;
+ }
+ if (gMain.heldKeys & DPAD_RIGHT)
+ {
+ gTasks[taskId].tMvmtDir = 2;
+ }
+ if (gTasks[taskId].tMvmtDir != 0)
+ {
+ if (gTasks[taskId].tMvmtSpeed < 0xFF)
+ {
+ gTasks[taskId].tMvmtSpeed++;
+ }
+ gTasks[taskId].tMinuteHandAngle = CalcNewMinHandAngle(gTasks[taskId].tMinuteHandAngle, gTasks[taskId].tMvmtDir, gTasks[taskId].tMvmtSpeed);
+ AdvanceClock(taskId, gTasks[taskId].tMvmtDir);
+ }
+ else
+ {
+ gTasks[taskId].tMvmtSpeed = 0;
+ }
+ }
+ }
+}
+
+static void Task_SetClock3(u8 taskId)
+{
+ SetWindowBorderStyle(0, FALSE, 0x250, 0x0d);
+ PrintTextOnWindow(0, 1, gText_IsThisTheCorrectTime, 0, 1, 0, NULL);
+ PutWindowTilemap(0);
+ schedule_bg_copy_tilemap_to_vram(0);
+ CreateYesNoMenu(&gUnknown_085B21F4, 0x250, 0x0d, 1);
+ gTasks[taskId].func = Task_SetClock4;
+}
+
+static void Task_SetClock4(u8 taskId)
+{
+ switch (ProcessMenuInputNoWrap_())
+ {
+ case 0:
+ PlaySE(SE_SELECT);
+ gTasks[taskId].func = Task_SetClock5;
+ break;
+ case 1:
+ case -1:
+ PlaySE(SE_SELECT);
+ sub_8198070(0, FALSE);
+ ClearWindowTilemap(0);
+ gTasks[taskId].func = Task_SetClock2;
+ break;
+ }
+}
+
+static void Task_SetClock5(u8 taskId)
+{
+ RtcInitLocalTimeOffset(gTasks[taskId].tHours, gTasks[taskId].tMinutes);
+ BeginNormalPaletteFade(-1, 0, 0, 16, 0);
+ gTasks[taskId].func = Task_SetClock6;
+}
+
+static void Task_SetClock6(u8 taskId)
+{
+ if (!gPaletteFade.active)
+ {
+ FreeAllWindowBuffers();
+ SetMainCallback2(gMain.savedCallback);
+ }
+}
+
+static void Task_ViewClock1(u8 taskId)
+{
+ if (!gPaletteFade.active)
+ {
+ gTasks[taskId].func = Task_ViewClock2;
+ }
+}
+
+static void Task_ViewClock2(u8 taskId)
+{
+ InitClockWithRtc(taskId);
+ if (gMain.newKeys & (A_BUTTON | B_BUTTON))
+ {
+ gTasks[taskId].func = Task_ViewClock3;
+ }
+}
+
+static void Task_ViewClock3(u8 taskId)
+{
+ BeginNormalPaletteFade(-1, 0, 0, 16, 0);
+ gTasks[taskId].func = Task_ViewClock4;
+}
+
+static void Task_ViewClock4(u8 taskId)
+{
+ if (!gPaletteFade.active)
+ {
+ SetMainCallback2(gMain.savedCallback);
+ }
+}
+
+static u8 CalcMinHandDelta(u16 a0)
+{
+ if (a0 > 60)
+ {
+ return 6;
+ }
+ if (a0 > 30)
+ {
+ return 3;
+ }
+ if (a0 > 10)
+ {
+ return 2;
+ }
+ return 1;
+}
+
+static u16 CalcNewMinHandAngle(u16 a0, u8 command, u8 a2)
+{
+ u8 r1 = CalcMinHandDelta(a2);
+ switch (command)
+ {
+ case 1:
+ if (a0) a0 -= r1;
+ else a0 = 360 - r1;
+ break;
+ case 2:
+ if (a0 < 360 - r1) a0 += r1;
+ else a0 = 0;
+ break;
+ }
+ return a0;
+}
+
+static bool32 AdvanceClock(u8 taskId, u8 command)
+{
+ switch (command)
+ {
+ case 1:
+ if (gTasks[taskId].tMinutes > 0)
+ {
+ gTasks[taskId].tMinutes--;
+ }
+ else
+ {
+ gTasks[taskId].tMinutes = 59;
+ if (gTasks[taskId].tHours > 0)
+ {
+ gTasks[taskId].tHours--;
+ }
+ else
+ {
+ gTasks[taskId].tHours = 23;
+ }
+ UpdateClockPeriod(taskId, command);
+ }
+ break;
+ case 2:
+ if (gTasks[taskId].tMinutes < 59)
+ {
+ gTasks[taskId].tMinutes++;
+ }
+ else
+ {
+ gTasks[taskId].tMinutes = 0;
+ if (gTasks[taskId].tHours < 23)
+ {
+ gTasks[taskId].tHours++;
+ }
+ else
+ {
+ gTasks[taskId].tHours = 0;
+ }
+ UpdateClockPeriod(taskId, command);
+ }
+ break;
+ }
+ return FALSE;
+}
+
+static void UpdateClockPeriod(u8 taskId, u8 command)
+{
+ u8 hours = gTasks[taskId].tHours;
+ switch (command)
+ {
+ case 1:
+ switch (hours)
+ {
+ case 11:
+ gTasks[taskId].tPeriod = FALSE;
+ break;
+ case 23:
+ gTasks[taskId].tPeriod = TRUE;
+ break;
+ }
+ break;
+ case 2:
+ switch (hours)
+ {
+ case 0:
+ gTasks[taskId].tPeriod = FALSE;
+ break;
+ case 12:
+ gTasks[taskId].tPeriod = TRUE;
+ break;
+ }
+ break;
+ }
+}
+
+static void InitClockWithRtc(u8 taskId)
+{
+ RtcCalcLocalTime();
+ gTasks[taskId].tHours = gLocalTime.hours;
+ gTasks[taskId].tMinutes = gLocalTime.minutes;
+ gTasks[taskId].tMinuteHandAngle = gTasks[taskId].tMinutes * 6;
+ gTasks[taskId].tHourHandAngle = (gTasks[taskId].tHours % 12) * 30 + (gTasks[taskId].tMinutes / 10) * 5;
+ if (gLocalTime.hours < 12)
+ {
+ gTasks[taskId].tPeriod = FALSE;
+ }
+ else
+ {
+ gTasks[taskId].tPeriod = TRUE;
+ }
+}
+
+static void SpriteCB_MinuteHand(struct Sprite *sprite)
+{
+ u16 angle = gTasks[sprite->data[0]].tMinuteHandAngle;
+ s16 sin = Sin2(angle) / 16;
+ s16 cos = Cos2(angle) / 16;
+ u16 xhat;
+ u16 yhat;
+
+ SetOamMatrix(0, cos, sin, -sin, cos);
+ xhat = sClockHandCoords[angle][0];
+ yhat = sClockHandCoords[angle][1];
+
+ if (xhat > 0x80)
+ {
+ xhat |= 0xff00;
+ }
+ if (yhat > 0x80)
+ {
+ yhat |= 0xff00;
+ }
+ sprite->pos2.x = xhat;
+ sprite->pos2.y = yhat;
+}
+
+static void SpriteCB_HourHand(struct Sprite *sprite)
+{
+ u16 angle = gTasks[sprite->data[0]].tHourHandAngle;
+ s16 sin = Sin2(angle) / 16;
+ s16 cos = Cos2(angle) / 16;
+ u16 xhat;
+ u16 yhat;
+
+ SetOamMatrix(1, cos, sin, -sin, cos);
+ xhat = sClockHandCoords[angle][0];
+ yhat = sClockHandCoords[angle][1];
+ if (xhat > 0x80)
+ {
+ xhat |= 0xff00;
+ }
+ if (yhat > 0x80)
+ {
+ yhat |= 0xff00;
+ }
+ sprite->pos2.x = xhat;
+ sprite->pos2.y = yhat;
+}
+
+static void SpriteCB_AMIndicator(struct Sprite *sprite)
+{
+ if (gTasks[sprite->data[0]].tPeriod)
+ {
+ if (sprite->data[1] >= 60 && sprite->data[1] < 90)
+ {
+ sprite->data[1] += 5;
+ }
+ if (sprite->data[1] < 60)
+ {
+ sprite->data[1]++;
+ }
+ }
+ else
+ {
+ if (sprite->data[1] >= 46 && sprite->data[1] < 76)
+ {
+ sprite->data[1] -= 5;
+ }
+ if (sprite->data[1] > 75)
+ {
+ sprite->data[1]--;
+ }
+ }
+ sprite->pos2.x = Cos2(sprite->data[1]) * 30 / 0x1000;
+ sprite->pos2.y = Sin2(sprite->data[1]) * 30 / 0x1000;
+}
+
+static void SpriteCB_PMIndicator(struct Sprite *sprite)
+{
+ if (gTasks[sprite->data[0]].tPeriod)
+ {
+ if (sprite->data[1] >= 105 && sprite->data[1] < 135)
+ {
+ sprite->data[1] += 5;
+ }
+ if (sprite->data[1] < 105)
+ {
+ sprite->data[1]++;
+ }
+ }
+ else
+ {
+ if (sprite->data[1] >= 91 && sprite->data[1] < 121)
+ {
+ sprite->data[1] -= 5;
+ }
+ if (sprite->data[1] > 120)
+ {
+ sprite->data[1]--;
+ }
+ }
+ sprite->pos2.x = Cos2(sprite->data[1]) * 30 / 0x1000;
+ sprite->pos2.y = Sin2(sprite->data[1]) * 30 / 0x1000;
+}