summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/battle_ai.c1595
-rw-r--r--src/battle_setup.c1157
-rw-r--r--src/berry.c607
-rw-r--r--src/coins.c87
-rw-r--r--src/decompress.c116
-rw-r--r--src/dewford_trend.c642
-rw-r--r--src/diploma.c1
-rw-r--r--src/field_camera.c516
-rw-r--r--src/field_door.c233
-rw-r--r--src/field_effect.c218
-rw-r--r--src/field_player_avatar.c1685
-rw-r--r--src/field_poison.c144
-rw-r--r--src/flag.c1
-rw-r--r--src/heal_location.c45
-rw-r--r--src/intro.c2
-rw-r--r--src/item.c530
-rw-r--r--src/landmark.c72
-rw-r--r--src/libc.c242
-rw-r--r--src/link.c10
-rw-r--r--src/lottery_corner.c28
-rw-r--r--src/m4a_2.c5
-rw-r--r--src/m4a_tables.c2
-rw-r--r--src/main_menu.c1
-rw-r--r--src/map_obj_lock.c4
-rw-r--r--src/menu_cursor.c610
-rw-r--r--src/mori_debug_menu.c157
-rw-r--r--src/pokedex.c2312
-rw-r--r--src/pokemon_2.c2
-rw-r--r--src/pokemon_size_record.c195
-rw-r--r--src/record_mixing.c735
-rw-r--r--src/rom4.c68
-rw-r--r--src/safari_zone.c256
-rw-r--r--src/save_menu_util.c40
-rw-r--r--src/scrcmd.c91
-rw-r--r--src/script.c3
-rw-r--r--src/sprite.c2
-rw-r--r--src/start_menu.c21
-rw-r--r--src/starter_choose.c1
-rw-r--r--src/text.c5
-rw-r--r--src/tileset_anim.c596
-rw-r--r--src/title_screen.c496
-rw-r--r--src/trainer_see.c404
-rw-r--r--src/truck_scene.c229
-rw-r--r--src/var.c1
-rw-r--r--src/wallclock.c5
-rw-r--r--src/wild_encounter.c676
46 files changed, 13329 insertions, 1519 deletions
diff --git a/src/battle_ai.c b/src/battle_ai.c
new file mode 100644
index 000000000..945176b64
--- /dev/null
+++ b/src/battle_ai.c
@@ -0,0 +1,1595 @@
+#include "global.h"
+#include "battle.h"
+#include "pokemon.h"
+#include "rng.h"
+
+#define AIScriptRead32(ptr) ((ptr)[0] | (ptr)[1] << 8 | (ptr)[2] << 16 | (ptr)[3] << 24)
+#define AIScriptRead16(ptr) ((ptr)[0] | (ptr)[1] << 8)
+#define AIScriptRead8(ptr) ((ptr)[0])
+
+/*
+this file is a mess. I stopped part way because it starts to involve a huge struct that begins at 0x2000000 and goes
+all the way to at least 0x2016800, in addition to extremely hard functions that I can't seem to get right. I am leaving this file
+as it currently is until someone bothers to document this huge struct.
+*/
+
+extern u8 sub_8015A98(u8, u8, u8);
+extern u8 battle_side_get_owner(u8);
+extern s16 battle_get_per_side_status(u8);
+extern u8 b_first_side(u8, u8, u8);
+
+extern u16 gUnknown_020239F8;
+extern u8 gUnknown_02024A60;
+extern u8 gUnknown_02024C07;
+extern u8 gUnknown_02024C08;
+extern u8 gUnknown_02024C0C;
+extern u16 gUnknown_02024DEC;
+extern u8 gUnknown_02024C68;
+extern u32 gUnknown_02024BEC;
+extern u8 gUnknown_0201601C;
+extern u8 gUnknown_0201601F;
+extern u16 gUnknown_02024BE6;
+extern u8 gCritMultiplier;
+extern u16 gUnknown_02024C34[];
+extern u32 gUnknown_02024ACC[];
+extern u32 gUnknown_02024C98[];
+extern u16 gUnknown_02024C7A[];
+extern struct BattlePokemon gUnknown_02024A8C[];
+extern u8 gUnknown_030042E0[];
+extern u8 *gAIScriptPtr;
+extern u16 gTrainerBattleOpponent;
+extern u32 gBitTable[];
+extern u8 *BattleAIs[];
+extern struct Trainer gTrainers[];
+extern struct BattlePokemon gBattleMons[];
+extern struct BattleMove gBattleMoves[];
+extern struct BaseStats gBaseStats[];
+extern void (*gBattleAICmdTable[])(void);
+
+struct UnknownStruct1
+{
+/* 0x00 */ u16 unk0[2][8];
+/* 0x20 */ u8 unk20[2];
+/* 0x22 */ u8 unk22[2];
+/* 0x24 */ u16 items[4];
+/* 0x2C */ u8 unk8;
+};
+
+struct UnknownStruct2 /* 0x2016800 */
+{
+/* 0x00 */ u8 unk0;
+/* 0x01 */ u8 moveConsidered;
+/* 0x02 */ u16 unk2;
+/* 0x04 */ s8 score[4]; // score?
+/* 0x08 */ u32 unk8;
+/* 0x0C */ u32 aiFlags;
+/* 0x10 */ u8 unk10;
+/* 0x11 */ u8 unk11;
+/* 0x12 */ u8 filler12[6];
+/* 0x18 */ u8 unk18[4];
+};
+
+struct UnknownStruct3
+{
+ u8 filler0[0x20];
+ u8 unk20;
+};
+
+struct SmallBattleStruct1
+{
+ u8 unk1;
+ u8 unk2;
+ u8 unk3;
+ u8 unk4;
+};
+
+// move to battle.h before PR.
+struct BattleStruct /* 0x2000000 */
+{
+ u8 filler0[0x1601C];
+ struct SmallBattleStruct1 unk;
+};
+
+extern struct BattleStruct unk_2000000;
+extern struct UnknownStruct2 unk_2016800;
+extern struct UnknownStruct1 unk_2016A00;
+extern struct UnknownStruct3 unk_2016C00;
+
+void sub_810715C(void);
+void sub_8107374(void);
+void sub_810745C(void);
+
+void sub_81070D4(void)
+{
+ s32 i;
+ u8 *data = (u8 *)&unk_2016A00;
+
+ for(i = 0; (u32)i < 48; i++)
+ data[i] = 0;
+ if((gUnknown_020239F8 & 8) && gTrainerBattleOpponent != 0x400 && !(gUnknown_020239F8 & 0x982))
+ {
+ for(i = 0; i < 4; i++)
+ {
+ if(gTrainers[gTrainerBattleOpponent].items[i] != 0)
+ {
+ unk_2016A00.items[unk_2016A00.unk8] = gTrainers[gTrainerBattleOpponent].items[i];
+ unk_2016A00.unk8++;
+ }
+ }
+ }
+ sub_810715C();
+}
+
+void sub_810715C(void)
+{
+ s32 i;
+ u8 *data = (u8 *)&unk_2016800;
+ u8 r7;
+
+ for(i = 0; (u32)i < 28; i++)
+ data[i] = 0;
+ for(i = 0; i < 4; i++)
+ unk_2016800.score[i] = 100;
+ r7 = sub_8015A98(gUnknown_02024A60, 0, 0xFF);
+ for(i = 0; i < 4; i++)
+ {
+ u16 rand;
+
+ if(gBitTable[i] & r7)
+ unk_2016800.score[i] = 0;
+ rand = Random();
+ unk_2016800.unk18[i] = 100 - (rand & 0xF);
+ }
+ unk_2016C00.unk20 = 0;
+ gUnknown_02024C07 = gUnknown_02024A60;
+
+ if(gUnknown_020239F8 & 1)
+ {
+ gUnknown_02024C08 = Random() & 2;
+
+ if(gUnknown_02024C0C & gBitTable[gUnknown_02024C08])
+ gUnknown_02024C08 ^= 2;
+ }
+ else
+ gUnknown_02024C08 = gUnknown_02024A60 ^ 1;
+
+ if(gUnknown_020239F8 & 0x80)
+ unk_2016800.aiFlags = 0x40000000;
+ else if(gUnknown_020239F8 & 0x400)
+ unk_2016800.aiFlags = 0x20000000;
+ else if(gUnknown_020239F8 & 0x10)
+ unk_2016800.aiFlags = 0x80000000;
+ else
+ unk_2016800.aiFlags = gTrainers[gTrainerBattleOpponent].aiFlags;
+}
+
+u8 sub_81072A8(void)
+{
+ u8 arr1[4];
+ u8 arr2[4];
+ u8 r5;
+ s32 i;
+
+ sub_810745C();
+ while(unk_2016800.aiFlags != 0)
+ {
+ if(unk_2016800.aiFlags & 1)
+ {
+ unk_2016800.unk0 = 0;
+ sub_8107374();
+ }
+ unk_2016800.aiFlags >>= 1;
+ unk_2016800.unk11++;
+ unk_2016800.moveConsidered = 0;
+ }
+ if(unk_2016800.unk10 & 2)
+ return 4;
+ if(unk_2016800.unk10 & 4)
+ return 5;
+ r5 = 1;
+ arr1[0] = unk_2016800.score[0];
+ arr2[0] = 0;
+ for(i = 1; i < 4; i++)
+ {
+ if(arr1[0] < (s8)unk_2016800.score[i])
+ {
+ r5 = 1;
+ arr1[0] = unk_2016800.score[i];
+ arr2[0] = i;
+ }
+ if(arr1[0] == (s8)unk_2016800.score[i])
+ {
+ arr1[r5] = unk_2016800.score[i];
+ arr2[r5++] = i;
+ }
+ }
+ return arr2[Random() % r5];
+}
+
+void sub_8107374(void)
+{
+ while(unk_2016800.unk0 != 2)
+ {
+ switch(unk_2016800.unk0)
+ {
+ case 3: //Needed to match.
+ break;
+ case 0:
+ gAIScriptPtr = BattleAIs[unk_2016800.unk11];
+ if(gBattleMons[gUnknown_02024C07].pp[unk_2016800.moveConsidered] == 0)
+ {
+ unk_2016800.unk2 = 0;
+ }
+ else
+ {
+ unk_2016800.unk2 = gBattleMons[gUnknown_02024C07].moves[unk_2016800.moveConsidered];
+ }
+ unk_2016800.unk0++;
+ break;
+ case 1:
+ if(unk_2016800.unk2 != 0)
+ gBattleAICmdTable[*(u8 *)gAIScriptPtr](); //weird...
+ else
+ {
+ unk_2016800.score[unk_2016800.moveConsidered] = 0;
+ unk_2016800.unk10 |= 1;
+ }
+ if(unk_2016800.unk10 & 1)
+ {
+ unk_2016800.moveConsidered++;
+ if(unk_2016800.moveConsidered < 4 && !(unk_2016800.unk10 & 8))
+ unk_2016800.unk0 = 0;
+ else
+ unk_2016800.unk0++;
+ unk_2016800.unk10 &= 0xFE;
+ }
+ break;
+ }
+ }
+}
+
+#ifdef NONMATCHING
+void sub_810745C(void)
+{
+ s32 i;
+
+ for(i = 0; i < 8; i++)
+ {
+ if(unk_2016A00.unk0[gUnknown_02024C08 / 2][i] == 0)
+ {
+ //gUnknown_02024C34[gUnknown_02024C08] += 0;
+ unk_2016A00.unk0[gUnknown_02024C08 / 2][i] = gUnknown_02024C34[gUnknown_02024C08];
+ return;
+ }
+ }
+}
+#else
+__attribute__((naked))
+void sub_810745C(void)
+{
+ asm(".syntax unified\n\
+ push {r4-r6,lr}\n\
+ movs r2, 0\n\
+ ldr r3, _08107488 @ =gUnknown_02024C08\n\
+ ldr r5, _0810748C @ =0x02016a00\n\
+ ldr r6, _08107490 @ =gUnknown_02024C34\n\
+ adds r4, r3, 0\n\
+_08107468:\n\
+ lsls r0, r2, 1\n\
+ ldrb r1, [r4]\n\
+ lsrs r1, 1\n\
+ lsls r1, 4\n\
+ adds r0, r1\n\
+ adds r1, r0, r5\n\
+ ldrh r0, [r1]\n\
+ cmp r0, 0\n\
+ bne _08107494\n\
+ ldrb r0, [r3]\n\
+ lsls r0, 1\n\
+ adds r0, r6\n\
+ ldrh r0, [r0]\n\
+ strh r0, [r1]\n\
+ b _0810749A\n\
+ .align 2, 0\n\
+_08107488: .4byte gUnknown_02024C08\n\
+_0810748C: .4byte 0x02016a00\n\
+_08107490: .4byte gUnknown_02024C34\n\
+_08107494:\n\
+ adds r2, 0x1\n\
+ cmp r2, 0x7\n\
+ ble _08107468\n\
+_0810749A:\n\
+ pop {r4-r6}\n\
+ pop {r0}\n\
+ bx r0\n\
+ .syntax divided");
+}
+#endif
+
+void unref_sub_81074A0(u8 a)
+{
+ s32 i;
+
+ for(i = 0; i < 8; i++)
+ unk_2016A00.unk0[a / 2][i] = 0;
+}
+
+void sub_81074C4(u8 a, u8 b)
+{
+ if(battle_side_get_owner(a) == 0)
+ unk_2016A00.unk20[battle_get_per_side_status(a) & 1] = b;
+}
+
+void sub_81074F8(u8 a, u8 b)
+{
+ if(battle_side_get_owner(a) == 0)
+ unk_2016A00.unk22[battle_get_per_side_status(a) & 1] = b;
+}
+
+void BattleAICmd_if_random(void)
+{
+ u16 random = Random();
+
+ if (!(random % 256 >= gAIScriptPtr[1])) // roll a random value. is it less than the parameter of the if_random call? (96 on if_random 80 will return true)
+ gAIScriptPtr = AIScriptRead32(gAIScriptPtr + 2);
+ else
+ gAIScriptPtr += 6;
+}
+
+void BattleAICmd_if_not_random(void)
+{
+ u16 random = Random();
+
+ if (!(random % 256 <= gAIScriptPtr[1])) // roll a random value. is it greater than the parameter of the if_random call? (96 on if_random 80 will return true)
+ gAIScriptPtr = AIScriptRead32(gAIScriptPtr + 2);
+ else
+ gAIScriptPtr += 6;
+}
+
+void BattleAICmd_if_random_1(void) // if RNG Value equal to
+{
+ u16 random = Random();
+
+ if (random % 256 == gAIScriptPtr[1]) // roll a random value. is it greater than the parameter of the if_random call? (96 on if_random 80 will return true)
+ gAIScriptPtr = AIScriptRead32(gAIScriptPtr + 2);
+ else
+ gAIScriptPtr += 6;
+}
+
+void BattleAICmd_if_not_random_1(void) // if RNG value not equal to
+{
+ u16 random = Random();
+
+ if (random % 256 != gAIScriptPtr[1]) // roll a random value. is it greater than the parameter of the if_random call? (96 on if_random 80 will return true)
+ gAIScriptPtr = AIScriptRead32(gAIScriptPtr + 2);
+ else
+ gAIScriptPtr += 6;
+}
+
+void BattleAICmd_score(void)
+{
+ unk_2016800.score[unk_2016800.moveConsidered] += gAIScriptPtr[1]; // add the result to the array of the move consider's score.
+
+ if(unk_2016800.score[unk_2016800.moveConsidered] < 0) // if the score is negative, flatten it to 0.
+ unk_2016800.score[unk_2016800.moveConsidered] = 0;
+
+ gAIScriptPtr += 2; // AI return.
+}
+
+void BattleAICmd_if_hp_less_than(void)
+{
+ u16 var;
+
+ if ( gAIScriptPtr[1] == 1 )
+ var = gUnknown_02024C07;
+ else
+ var = gUnknown_02024C08;
+
+ if ((u32)(100 * gBattleMons[var].hp / gBattleMons[var].maxHP) < gAIScriptPtr[2])
+ gAIScriptPtr = AIScriptRead32(gAIScriptPtr + 3);
+ else
+ gAIScriptPtr += 7;
+}
+
+void BattleAICmd_if_hp_more_than(void)
+{
+ u16 var;
+
+ if ( gAIScriptPtr[1] == 1 )
+ var = gUnknown_02024C07;
+ else
+ var = gUnknown_02024C08;
+
+ if ((u32)(100 * gBattleMons[var].hp / gBattleMons[var].maxHP) > gAIScriptPtr[2])
+ gAIScriptPtr = AIScriptRead32(gAIScriptPtr + 3);
+ else
+ gAIScriptPtr += 7;
+}
+
+void BattleAICmd_if_hp_equal(void)
+{
+ u16 var;
+
+ if ( gAIScriptPtr[1] == 1 )
+ var = gUnknown_02024C07;
+ else
+ var = gUnknown_02024C08;
+
+ if ((u32)(100 * gBattleMons[var].hp / gBattleMons[var].maxHP) == gAIScriptPtr[2])
+ gAIScriptPtr = AIScriptRead32(gAIScriptPtr + 3);
+ else
+ gAIScriptPtr += 7;
+}
+
+void BattleAICmd_if_hp_not_equal(void)
+{
+ u16 var;
+
+ if ( gAIScriptPtr[1] == 1 )
+ var = gUnknown_02024C07;
+ else
+ var = gUnknown_02024C08;
+
+ if ((u32)(100 * gBattleMons[var].hp / gBattleMons[var].maxHP) != gAIScriptPtr[2])
+ gAIScriptPtr = AIScriptRead32(gAIScriptPtr + 3);
+ else
+ gAIScriptPtr += 7;
+}
+
+void BattleAICmd_if_status(void)
+{
+ u16 var;
+ u32 temp;
+
+ if ( gAIScriptPtr[1] == 1 )
+ var = gUnknown_02024C07;
+ else
+ var = gUnknown_02024C08;
+
+ temp = AIScriptRead32(gAIScriptPtr + 2);
+
+ if (gBattleMons[var].status1 & temp)
+ gAIScriptPtr = AIScriptRead32(gAIScriptPtr + 6);
+ else
+ gAIScriptPtr += 10;
+}
+
+void BattleAICmd_if_not_status(void)
+{
+ u16 var;
+ u32 temp;
+
+ if ( gAIScriptPtr[1] == 1 )
+ var = gUnknown_02024C07;
+ else
+ var = gUnknown_02024C08;
+
+ temp = AIScriptRead32(gAIScriptPtr + 2);
+
+ if (!(gBattleMons[var].status1 & temp))
+ gAIScriptPtr = AIScriptRead32(gAIScriptPtr + 6);
+ else
+ gAIScriptPtr += 10;
+}
+
+void BattleAICmd_if_status2(void)
+{
+ u8 var;
+ u32 temp;
+
+ if ( gAIScriptPtr[1] == 1 )
+ var = gUnknown_02024C07;
+ else
+ var = gUnknown_02024C08;
+
+ temp = AIScriptRead32(gAIScriptPtr + 2);
+
+ if (gBattleMons[var].status2 & temp)
+ gAIScriptPtr = AIScriptRead32(gAIScriptPtr + 6);
+ else
+ gAIScriptPtr += 10;
+}
+
+void BattleAICmd_if_not_status2(void)
+{
+ u8 var;
+ u32 temp;
+
+ if ( gAIScriptPtr[1] == 1 )
+ var = gUnknown_02024C07;
+ else
+ var = gUnknown_02024C08;
+
+ temp = AIScriptRead32(gAIScriptPtr + 2);
+
+ if (!(gBattleMons[var].status2 & temp))
+ gAIScriptPtr = AIScriptRead32(gAIScriptPtr + 6);
+ else
+ gAIScriptPtr += 10;
+}
+
+void BattleAICmd_if_status3(void)
+{
+ u8 var;
+ u32 temp;
+
+ if ( gAIScriptPtr[1] == 1 )
+ var = gUnknown_02024C07;
+ else
+ var = gUnknown_02024C08;
+
+ temp = AIScriptRead32(gAIScriptPtr + 2);
+
+ if ( gUnknown_02024C98[var] & temp )
+ gAIScriptPtr = AIScriptRead32(gAIScriptPtr + 6);
+ else
+ gAIScriptPtr += 10;
+}
+
+void BattleAICmd_if_not_status3(void)
+{
+ u8 var;
+ u32 temp;
+
+ if ( gAIScriptPtr[1] == 1 )
+ var = gUnknown_02024C07;
+ else
+ var = gUnknown_02024C08;
+
+ temp = AIScriptRead32(gAIScriptPtr + 2);
+
+ if (!(gUnknown_02024C98[var] & temp))
+ gAIScriptPtr = AIScriptRead32(gAIScriptPtr + 6);
+ else
+ gAIScriptPtr += 10;
+}
+
+void BattleAICmd_if_status4(void)
+{
+ u8 var;
+ u32 temp;
+ u32 temp2;
+
+ if ( gAIScriptPtr[1] == 1 )
+ var = gUnknown_02024C07;
+ else
+ var = gUnknown_02024C08;
+
+ temp = battle_get_per_side_status(var) & 1;
+ temp2 = AIScriptRead32(gAIScriptPtr + 2);
+
+ if ( gUnknown_02024C7A[temp] & temp2 )
+ gAIScriptPtr = AIScriptRead32(gAIScriptPtr + 6);
+ else
+ gAIScriptPtr += 10;
+}
+
+void BattleAICmd_if_not_status4(void)
+{
+ u8 var;
+ u32 temp;
+ u32 temp2;
+
+ if (gAIScriptPtr[1] == 1)
+ var = gUnknown_02024C07;
+ else
+ var = gUnknown_02024C08;
+
+ temp = battle_get_per_side_status(var) & 1;
+ temp2 = AIScriptRead32(gAIScriptPtr + 2);
+
+ if (!(gUnknown_02024C7A[temp] & temp2))
+ gAIScriptPtr = AIScriptRead32(gAIScriptPtr + 6);
+ else
+ gAIScriptPtr += 10;
+}
+
+void BattleAICmd_if_less_than(void)
+{
+ if (unk_2016800.unk8 < gAIScriptPtr[1])
+ gAIScriptPtr = AIScriptRead32(gAIScriptPtr + 2);
+ else
+ gAIScriptPtr += 6;
+}
+
+void BattleAICmd_if_more_than(void)
+{
+ if (unk_2016800.unk8 > gAIScriptPtr[1])
+ gAIScriptPtr = AIScriptRead32(gAIScriptPtr + 2);
+ else
+ gAIScriptPtr += 6;
+}
+
+void BattleAICmd_if_equal(void)
+{
+ if (unk_2016800.unk8 == gAIScriptPtr[1])
+ gAIScriptPtr = AIScriptRead32(gAIScriptPtr + 2);
+ else
+ gAIScriptPtr += 6;
+}
+
+void BattleAICmd_if_not_equal(void)
+{
+ if (unk_2016800.unk8 != gAIScriptPtr[1])
+ gAIScriptPtr = AIScriptRead32(gAIScriptPtr + 2);
+ else
+ gAIScriptPtr += 6;
+}
+
+void BattleAICmd_if_less_than_32(void)
+{
+ u8 *temp = AIScriptRead32(gAIScriptPtr + 1);
+
+ if (unk_2016800.unk8 < *temp)
+ gAIScriptPtr = AIScriptRead32(gAIScriptPtr + 5);
+ else
+ gAIScriptPtr += 9;
+}
+
+void BattleAICmd_if_more_than_32(void)
+{
+ u8 *temp = AIScriptRead32(gAIScriptPtr + 1);
+
+ if (unk_2016800.unk8 > *temp)
+ gAIScriptPtr = AIScriptRead32(gAIScriptPtr + 5);
+ else
+ gAIScriptPtr += 9;
+}
+
+void BattleAICmd_if_equal_32(void)
+{
+ u8 *temp = AIScriptRead32(gAIScriptPtr + 1);
+
+ if (unk_2016800.unk8 == *temp)
+ gAIScriptPtr = AIScriptRead32(gAIScriptPtr + 5);
+ else
+ gAIScriptPtr += 9;
+}
+
+void BattleAICmd_if_not_equal_32(void)
+{
+ u8 *temp = AIScriptRead32(gAIScriptPtr + 1);
+
+ if (unk_2016800.unk8 != *temp)
+ gAIScriptPtr = AIScriptRead32(gAIScriptPtr + 5);
+ else
+ gAIScriptPtr += 9;
+}
+
+void BattleAICmd_if_move(void)
+{
+ u16 move = AIScriptRead16(gAIScriptPtr + 1);
+
+ if (unk_2016800.unk2 == move)
+ gAIScriptPtr = AIScriptRead32(gAIScriptPtr + 3);
+ else
+ gAIScriptPtr += 7;
+}
+
+void BattleAICmd_if_not_move(void)
+{
+ u16 move = AIScriptRead16(gAIScriptPtr + 1);
+
+ if (unk_2016800.unk2 != move)
+ gAIScriptPtr = AIScriptRead32(gAIScriptPtr + 3);
+ else
+ gAIScriptPtr += 7;
+}
+
+void BattleAICmd_if_in_bytes(void)
+{
+ u8 *ptr = AIScriptRead32(gAIScriptPtr + 1);
+
+ while(*ptr != 0xFF)
+ {
+ if(unk_2016800.unk8 == *ptr)
+ {
+ gAIScriptPtr = AIScriptRead32(gAIScriptPtr + 5);
+ return;
+ }
+ ptr++;
+ }
+ gAIScriptPtr += 9;
+}
+
+void BattleAICmd_if_not_in_bytes(void)
+{
+ u8 *ptr = AIScriptRead32(gAIScriptPtr + 1);
+
+ while(*ptr != 0xFF)
+ {
+ if(unk_2016800.unk8 == *ptr)
+ {
+ gAIScriptPtr += 9;
+ return;
+ }
+ ptr++;
+ }
+ gAIScriptPtr = AIScriptRead32(gAIScriptPtr + 5);
+}
+
+void BattleAICmd_if_in_words(void)
+{
+ u16 *ptr = AIScriptRead32(gAIScriptPtr + 1);
+
+ while(*ptr != 0xFFFF)
+ {
+ if(unk_2016800.unk8 == *ptr)
+ {
+ gAIScriptPtr = AIScriptRead32(gAIScriptPtr + 5);
+ return;
+ }
+ ptr++;
+ }
+ gAIScriptPtr += 9;
+}
+
+void BattleAICmd_if_not_in_words(void)
+{
+ u16 *ptr = AIScriptRead32(gAIScriptPtr + 1);
+
+ while(*ptr != 0xFFFF)
+ {
+ if(unk_2016800.unk8 == *ptr)
+ {
+ gAIScriptPtr += 9;
+ return;
+ }
+ ptr++;
+ }
+ gAIScriptPtr = AIScriptRead32(gAIScriptPtr + 5);
+}
+
+void BattleAICmd_if_user_can_damage(void)
+{
+ s32 i;
+
+ for(i = 0; i < 4; i++)
+ {
+ if (gBattleMons[gUnknown_02024C07].moves[i] != 0
+ && gBattleMoves[gBattleMons[gUnknown_02024C07].moves[i]].power != 0)
+ break;
+ }
+ if(i == 4)
+ gAIScriptPtr += 5;
+ else
+ gAIScriptPtr = AIScriptRead32(gAIScriptPtr + 1);
+}
+
+void BattleAICmd_if_user_cant_damage(void)
+{
+ s32 i;
+
+ for(i = 0; i < 4; i++)
+ {
+ if (gBattleMons[gUnknown_02024C07].moves[i] != 0
+ && gBattleMoves[gBattleMons[gUnknown_02024C07].moves[i]].power != 0)
+ break;
+ }
+ if(i != 4)
+ gAIScriptPtr += 5;
+ else
+ gAIScriptPtr = AIScriptRead32(gAIScriptPtr + 1);
+}
+
+void BattleAICmd_unk_21(void)
+{
+ unk_2016800.unk8 = gUnknown_030042E0[19];
+ gAIScriptPtr += 1;
+}
+
+void BattleAICmd_get_type(void)
+{
+ u8 typeVar = gAIScriptPtr[1];
+
+ switch(typeVar)
+ {
+ case 1:
+ unk_2016800.unk8 = gBattleMons[gUnknown_02024C07].type1;
+ break;
+ case 0:
+ unk_2016800.unk8 = gBattleMons[gUnknown_02024C08].type1;
+ break;
+ case 3:
+ unk_2016800.unk8 = gBattleMons[gUnknown_02024C07].type2;
+ break;
+ case 2:
+ unk_2016800.unk8 = gBattleMons[gUnknown_02024C08].type2;
+ break;
+ case 4:
+ unk_2016800.unk8 = gBattleMoves[unk_2016800.unk2].type;
+ break;
+ }
+ gAIScriptPtr += 2;
+}
+
+void BattleAICmd_unk_23(void)
+{
+ unk_2016800.unk8 = gBattleMoves[unk_2016800.unk2].power;
+ gAIScriptPtr += 1;
+}
+
+__attribute__((naked))
+void BattleAICmd_unk_24(void)
+{
+ asm(".syntax unified\n\
+ push {r4-r7,lr}\n\
+ mov r7, r10\n\
+ mov r6, r9\n\
+ mov r5, r8\n\
+ push {r5-r7}\n\
+ sub sp, 0x14\n\
+ movs r3, 0\n\
+ ldr r0, _08108328 @ =gUnknown_083F62BC\n\
+ ldrh r1, [r0]\n\
+ ldr r4, _0810832C @ =0x0000ffff\n\
+ ldr r6, _08108330 @ =gBattleMoves\n\
+ ldr r5, _08108334 @ =0x02016800\n\
+ cmp r1, r4\n\
+ beq _0810822E\n\
+ ldrh r1, [r5, 0x2]\n\
+ lsls r0, r1, 1\n\
+ adds r0, r1\n\
+ lsls r0, 2\n\
+ adds r0, r6\n\
+ ldrb r2, [r0]\n\
+ ldr r1, _08108328 @ =gUnknown_083F62BC\n\
+_0810821E:\n\
+ ldrh r0, [r1]\n\
+ cmp r2, r0\n\
+ beq _0810822E\n\
+ adds r1, 0x2\n\
+ adds r3, 0x1\n\
+ ldrh r0, [r1]\n\
+ cmp r0, r4\n\
+ bne _0810821E\n\
+_0810822E:\n\
+ ldrh r0, [r5, 0x2]\n\
+ lsls r1, r0, 1\n\
+ adds r1, r0\n\
+ lsls r1, 2\n\
+ adds r1, r6\n\
+ ldrb r0, [r1, 0x1]\n\
+ cmp r0, 0x1\n\
+ bhi _08108240\n\
+ b _081083B2\n\
+_08108240:\n\
+ lsls r0, r3, 1\n\
+ ldr r1, _08108328 @ =gUnknown_083F62BC\n\
+ adds r0, r1\n\
+ ldrh r3, [r0]\n\
+ ldr r0, _0810832C @ =0x0000ffff\n\
+ cmp r3, r0\n\
+ beq _08108250\n\
+ b _081083B2\n\
+_08108250:\n\
+ ldr r0, _08108338 @ =gUnknown_02024DEC\n\
+ movs r1, 0\n\
+ strh r1, [r0]\n\
+ ldr r2, _0810833C @ =0xfffff81c\n\
+ adds r0, r5, r2\n\
+ strb r1, [r0]\n\
+ adds r2, 0x3\n\
+ adds r0, r5, r2\n\
+ movs r2, 0x1\n\
+ strb r2, [r0]\n\
+ ldr r0, _08108340 @ =gUnknown_02024C68\n\
+ strb r1, [r0]\n\
+ ldr r0, _08108344 @ =gCritMultiplier\n\
+ strb r2, [r0]\n\
+ movs r6, 0\n\
+ mov r9, r3\n\
+ ldr r0, _08108328 @ =gUnknown_083F62BC\n\
+ ldrh r0, [r0]\n\
+ str r0, [sp, 0x10]\n\
+_08108276:\n\
+ movs r3, 0\n\
+ ldr r5, _08108348 @ =gBattleMons\n\
+ lsls r4, r6, 1\n\
+ ldr r7, _0810834C @ =gUnknown_02024C07\n\
+ lsls r1, r6, 2\n\
+ mov r8, r1\n\
+ adds r2, r6, 0x1\n\
+ mov r10, r2\n\
+ ldr r0, [sp, 0x10]\n\
+ cmp r0, r9\n\
+ beq _081082BA\n\
+ ldr r2, _08108330 @ =gBattleMoves\n\
+ ldrb r1, [r7]\n\
+ movs r0, 0x58\n\
+ muls r0, r1\n\
+ adds r0, r4, r0\n\
+ adds r1, r5, 0\n\
+ adds r1, 0xC\n\
+ adds r0, r1\n\
+ ldrh r1, [r0]\n\
+ lsls r0, r1, 1\n\
+ adds r0, r1\n\
+ lsls r0, 2\n\
+ adds r0, r2\n\
+ ldrb r2, [r0]\n\
+ ldr r1, _08108328 @ =gUnknown_083F62BC\n\
+_081082AA:\n\
+ ldrh r0, [r1]\n\
+ cmp r2, r0\n\
+ beq _081082BA\n\
+ adds r1, 0x2\n\
+ adds r3, 0x1\n\
+ ldrh r0, [r1]\n\
+ cmp r0, r9\n\
+ bne _081082AA\n\
+_081082BA:\n\
+ ldrb r1, [r7]\n\
+ movs r0, 0x58\n\
+ muls r0, r1\n\
+ adds r0, r4, r0\n\
+ adds r1, r5, 0\n\
+ adds r1, 0xC\n\
+ adds r1, r0, r1\n\
+ ldrh r0, [r1]\n\
+ cmp r0, 0\n\
+ beq _0810835C\n\
+ lsls r0, r3, 1\n\
+ ldr r2, _08108328 @ =gUnknown_083F62BC\n\
+ adds r0, r2\n\
+ ldrh r0, [r0]\n\
+ cmp r0, r9\n\
+ bne _0810835C\n\
+ ldr r0, _08108330 @ =gBattleMoves\n\
+ ldrh r2, [r1]\n\
+ lsls r1, r2, 1\n\
+ adds r1, r2\n\
+ lsls r1, 2\n\
+ adds r1, r0\n\
+ ldrb r0, [r1, 0x1]\n\
+ cmp r0, 0x1\n\
+ bls _0810835C\n\
+ ldr r5, _08108350 @ =gUnknown_02024BE6\n\
+ strh r2, [r5]\n\
+ ldrb r0, [r7]\n\
+ ldr r4, _08108354 @ =gUnknown_02024C08\n\
+ ldrb r1, [r4]\n\
+ bl sub_801CAF8\n\
+ ldrh r0, [r5]\n\
+ ldrb r1, [r7]\n\
+ ldrb r2, [r4]\n\
+ bl move_effectiveness_something\n\
+ mov r4, sp\n\
+ add r4, r8\n\
+ ldr r2, _08108358 @ =gUnknown_02024BEC\n\
+ ldr r0, _08108334 @ =0x02016800\n\
+ adds r0, 0x18\n\
+ adds r0, r6, r0\n\
+ ldrb r1, [r0]\n\
+ ldr r0, [r2]\n\
+ muls r0, r1\n\
+ movs r1, 0x64\n\
+ bl __divsi3\n\
+ str r0, [r4]\n\
+ cmp r0, 0\n\
+ bne _08108364\n\
+ movs r0, 0x1\n\
+ str r0, [r4]\n\
+ b _08108364\n\
+ .align 2, 0\n\
+_08108328: .4byte gUnknown_083F62BC\n\
+_0810832C: .4byte 0x0000ffff\n\
+_08108330: .4byte gBattleMoves\n\
+_08108334: .4byte 0x02016800\n\
+_08108338: .4byte gUnknown_02024DEC\n\
+_0810833C: .4byte 0xfffff81c\n\
+_08108340: .4byte gUnknown_02024C68\n\
+_08108344: .4byte gCritMultiplier\n\
+_08108348: .4byte gBattleMons\n\
+_0810834C: .4byte gUnknown_02024C07\n\
+_08108350: .4byte gUnknown_02024BE6\n\
+_08108354: .4byte gUnknown_02024C08\n\
+_08108358: .4byte gUnknown_02024BEC\n\
+_0810835C:\n\
+ mov r1, sp\n\
+ add r1, r8\n\
+ movs r0, 0\n\
+ str r0, [r1]\n\
+_08108364:\n\
+ mov r6, r10\n\
+ cmp r6, 0x3\n\
+ ble _08108276\n\
+ movs r6, 0\n\
+ ldr r1, _081083A4 @ =0x02016800\n\
+ ldrb r0, [r1, 0x1]\n\
+ lsls r0, 2\n\
+ add r0, sp\n\
+ ldr r2, [sp]\n\
+ ldr r0, [r0]\n\
+ adds r5, r1, 0\n\
+ ldr r4, _081083A8 @ =gAIScriptPtr\n\
+ cmp r2, r0\n\
+ bgt _0810839A\n\
+ adds r3, r5, 0\n\
+ mov r2, sp\n\
+_08108384:\n\
+ adds r2, 0x4\n\
+ adds r6, 0x1\n\
+ cmp r6, 0x3\n\
+ bgt _0810839A\n\
+ ldrb r0, [r3, 0x1]\n\
+ lsls r0, 2\n\
+ add r0, sp\n\
+ ldr r1, [r2]\n\
+ ldr r0, [r0]\n\
+ cmp r1, r0\n\
+ ble _08108384\n\
+_0810839A:\n\
+ cmp r6, 0x4\n\
+ bne _081083AC\n\
+ movs r0, 0x2\n\
+ str r0, [r5, 0x8]\n\
+ b _081083B8\n\
+ .align 2, 0\n\
+_081083A4: .4byte 0x02016800\n\
+_081083A8: .4byte gAIScriptPtr\n\
+_081083AC:\n\
+ movs r0, 0x1\n\
+ str r0, [r5, 0x8]\n\
+ b _081083B8\n\
+_081083B2:\n\
+ movs r0, 0\n\
+ str r0, [r5, 0x8]\n\
+ ldr r4, _081083D0 @ =gAIScriptPtr\n\
+_081083B8:\n\
+ ldr r0, [r4]\n\
+ adds r0, 0x1\n\
+ str r0, [r4]\n\
+ add sp, 0x14\n\
+ pop {r3-r5}\n\
+ mov r8, r3\n\
+ mov r9, r4\n\
+ mov r10, r5\n\
+ pop {r4-r7}\n\
+ pop {r0}\n\
+ bx r0\n\
+ .align 2, 0\n\
+_081083D0: .4byte gAIScriptPtr\n\
+ .syntax divided\n");
+}
+
+void BattleAICmd_get_move(void)
+{
+ if ( gAIScriptPtr[1] == 1 )
+ unk_2016800.unk8 = gUnknown_02024C34[gUnknown_02024C07];
+ else
+ unk_2016800.unk8 = gUnknown_02024C34[gUnknown_02024C08];
+
+ gAIScriptPtr += 2;
+}
+
+void BattleAICmd_if_type(void)
+{
+ if ( gAIScriptPtr[1] == unk_2016800.unk8 )
+ gAIScriptPtr = AIScriptRead32(gAIScriptPtr + 2);
+ else
+ gAIScriptPtr += 6;
+}
+
+void BattleAICmd_unk_27(void) // if_not_type
+{
+ if ( gAIScriptPtr[1] != unk_2016800.unk8 )
+ gAIScriptPtr = AIScriptRead32(gAIScriptPtr + 2);
+ else
+ gAIScriptPtr += 6;
+}
+
+void BattleAICmd_if_would_go_first(void)
+{
+ if ( b_first_side(gUnknown_02024C07, gUnknown_02024C08, 1) == gAIScriptPtr[1] )
+ gAIScriptPtr = AIScriptRead32(gAIScriptPtr + 2);
+ else
+ gAIScriptPtr += 6;
+}
+
+void BattleAICmd_if_would_not_go_first(void)
+{
+ if ( b_first_side(gUnknown_02024C07, gUnknown_02024C08, 1) != gAIScriptPtr[1] )
+ gAIScriptPtr = AIScriptRead32(gAIScriptPtr + 2);
+ else
+ gAIScriptPtr += 6;
+}
+
+void BattleAICmd_unk_2A(void)
+{}
+
+void BattleAICmd_unk_2B(void)
+{}
+
+__attribute__((naked))
+void BattleAICmd_count_alive_pokemon(void)
+{
+ asm(".syntax unified\n\
+ push {r4-r7,lr}\n\
+ mov r7, r9\n\
+ mov r6, r8\n\
+ push {r6,r7}\n\
+ ldr r1, _08108550 @ =0x02016800\n\
+ movs r0, 0\n\
+ str r0, [r1, 0x8]\n\
+ ldr r0, _08108554 @ =gAIScriptPtr\n\
+ ldr r0, [r0]\n\
+ ldrb r0, [r0, 0x1]\n\
+ cmp r0, 0x1\n\
+ bne _0810855C\n\
+ ldr r0, _08108558 @ =gUnknown_02024C07\n\
+ b _0810855E\n\
+ .align 2, 0\n\
+_08108550: .4byte 0x02016800\n\
+_08108554: .4byte gAIScriptPtr\n\
+_08108558: .4byte gUnknown_02024C07\n\
+_0810855C:\n\
+ ldr r0, _081085A8 @ =gUnknown_02024C08\n\
+_0810855E:\n\
+ ldrb r5, [r0]\n\
+ adds r0, r5, 0\n\
+ bl battle_side_get_owner\n\
+ lsls r0, 24\n\
+ ldr r1, _081085AC @ =gEnemyParty\n\
+ mov r9, r1\n\
+ cmp r0, 0\n\
+ bne _08108574\n\
+ ldr r0, _081085B0 @ =gPlayerParty\n\
+ mov r9, r0\n\
+_08108574:\n\
+ ldr r0, _081085B4 @ =gUnknown_020239F8\n\
+ ldrh r1, [r0]\n\
+ movs r0, 0x1\n\
+ ands r0, r1\n\
+ cmp r0, 0\n\
+ beq _081085BC\n\
+ ldr r4, _081085B8 @ =gUnknown_02024A6A\n\
+ lsls r0, r5, 1\n\
+ adds r0, r4\n\
+ ldrb r0, [r0]\n\
+ mov r8, r0\n\
+ adds r0, r5, 0\n\
+ bl battle_get_per_side_status\n\
+ movs r1, 0x2\n\
+ eors r0, r1\n\
+ lsls r0, 24\n\
+ lsrs r0, 24\n\
+ bl battle_get_side_with_given_state\n\
+ lsls r0, 24\n\
+ lsrs r0, 23\n\
+ adds r0, r4\n\
+ ldrb r6, [r0]\n\
+ b _081085C6\n\
+ .align 2, 0\n\
+_081085A8: .4byte gUnknown_02024C08\n\
+_081085AC: .4byte gEnemyParty\n\
+_081085B0: .4byte gPlayerParty\n\
+_081085B4: .4byte gUnknown_020239F8\n\
+_081085B8: .4byte gUnknown_02024A6A\n\
+_081085BC:\n\
+ ldr r1, _08108624 @ =gUnknown_02024A6A\n\
+ lsls r0, r5, 1\n\
+ adds r0, r1\n\
+ ldrb r6, [r0]\n\
+ mov r8, r6\n\
+_081085C6:\n\
+ movs r5, 0\n\
+ ldr r7, _08108628 @ =0x02016800\n\
+_081085CA:\n\
+ cmp r5, r8\n\
+ beq _08108608\n\
+ cmp r5, r6\n\
+ beq _08108608\n\
+ movs r0, 0x64\n\
+ muls r0, r5\n\
+ mov r1, r9\n\
+ adds r4, r1, r0\n\
+ adds r0, r4, 0\n\
+ movs r1, 0x39\n\
+ bl GetMonData\n\
+ cmp r0, 0\n\
+ beq _08108608\n\
+ adds r0, r4, 0\n\
+ movs r1, 0x41\n\
+ bl GetMonData\n\
+ cmp r0, 0\n\
+ beq _08108608\n\
+ adds r0, r4, 0\n\
+ movs r1, 0x41\n\
+ bl GetMonData\n\
+ movs r1, 0xCE\n\
+ lsls r1, 1\n\
+ cmp r0, r1\n\
+ beq _08108608\n\
+ ldr r0, [r7, 0x8]\n\
+ adds r0, 0x1\n\
+ str r0, [r7, 0x8]\n\
+_08108608:\n\
+ adds r5, 0x1\n\
+ cmp r5, 0x5\n\
+ ble _081085CA\n\
+ ldr r1, _0810862C @ =gAIScriptPtr\n\
+ ldr r0, [r1]\n\
+ adds r0, 0x2\n\
+ str r0, [r1]\n\
+ pop {r3,r4}\n\
+ mov r8, r3\n\
+ mov r9, r4\n\
+ pop {r4-r7}\n\
+ pop {r0}\n\
+ bx r0\n\
+ .align 2, 0\n\
+_08108624: .4byte gUnknown_02024A6A\n\
+_08108628: .4byte 0x02016800\n\
+_0810862C: .4byte gAIScriptPtr\n\
+ .syntax divided");
+}
+
+void BattleAICmd_unk_2D(void)
+{
+ unk_2016800.unk8 = unk_2016800.unk2;
+ gAIScriptPtr += 1;
+}
+
+void BattleAICmd_unk_2E(void)
+{
+ unk_2016800.unk8 = gBattleMoves[unk_2016800.unk2].effect;
+ gAIScriptPtr += 1;
+}
+
+void BattleAICmd_get_ability(void)
+{
+ u8 var;
+
+ if(gAIScriptPtr[1] == 1)
+ var = gUnknown_02024C07;
+ else
+ var = gUnknown_02024C08;
+ if(battle_side_get_owner(var) == 0)
+ {
+ //register u8 unk asm("r1") = battle_get_per_side_status(var) & 1;
+ s32 unk = battle_get_per_side_status(var) & 1;
+
+ if(unk_2016A00.unk20[unk] != 0)
+ {
+ ((struct UnknownStruct2 *)((u8 *)&unk_2016A00 - 512))->unk8 = unk_2016A00.unk20[unk];
+ gAIScriptPtr += 2;
+ return;
+ }
+ //_081086C8
+ if(gBattleMons[var].ability == 0x17 || gBattleMons[var].ability == 0x2A || gBattleMons[var].ability == 0x47)
+ {
+ //_081086E4
+ unk_2016800.unk8 = gBattleMons[var].ability;
+ gAIScriptPtr += 2;
+ return;
+ }
+ //_081086FC
+ if(gBaseStats[gBattleMons[var].species].ability1 != 0)
+ {
+ if(gBaseStats[gBattleMons[var].species].ability2 != 0)
+ {
+ if(Random() & 1)
+ {
+ ((struct UnknownStruct2 *)((u8 *)&unk_2016A00 - 512))->unk8 = gBaseStats[gBattleMons[var].species].ability1;
+ gAIScriptPtr += 2;
+ return;
+ }
+ //_0810873C
+ else
+ {
+ ((struct UnknownStruct2 *)((u8 *)&unk_2016A00 - 512))->unk8 = gBaseStats[gBattleMons[var].species].ability2;
+ gAIScriptPtr += 2;
+ return;
+ }
+ }
+ //_08108754
+ else
+ {
+ ((struct UnknownStruct2 *)((u8 *)&unk_2016A00 - 512))->unk8 = gBaseStats[gBattleMons[var].species].ability1;
+ gAIScriptPtr += 2;
+ return;
+ }
+ }
+ //_08108764
+ else
+ {
+ ((struct UnknownStruct2 *)((u8 *)&unk_2016A00 - 512))->unk8 = gBaseStats[gBattleMons[var].species].ability2;
+ gAIScriptPtr += 2;
+ return;
+ }
+ }
+ //_08108774
+ unk_2016800.unk8 = gBattleMons[var].ability;
+ gAIScriptPtr += 2;
+}
+
+// this should probably be in battle.h after this file is fully decompiled.
+extern struct
+{
+ u8 unknownStuff[0x16000];
+ struct
+ {
+ u8 filler0[0x1C];
+ u8 unk1C;
+ u8 filler1D[2];
+ u8 unk1F;
+ u8 filler16020[0x7E0];
+ } unk_2016000;
+ struct UnknownStruct2 unk_2016800;
+} ewram; //0x02000000
+
+#ifdef NONMATCHING
+void BattleAICmd_unk_30(void)
+{
+ s32 loopCounter;
+
+ gUnknown_02024DEC = 0;
+ ewram.unk_2016000.unk1C = 0;
+ ewram.unk_2016000.unk1F = 1;
+ gUnknown_02024C68 = 0;
+ gCritMultiplier = 1;
+ ewram.unk_2016800.unk8 = 0;
+
+ for(loopCounter = 0; loopCounter <= 3; loopCounter++)
+ {
+ gUnknown_02024BEC = 40;
+ gUnknown_02024BE6 = gBattleMons[gUnknown_02024C07].moves[loopCounter];
+
+ if (gUnknown_02024BE6)
+ {
+ move_effectiveness_something(gUnknown_02024BE6, gUnknown_02024C07, gUnknown_02024C08);
+
+ // reduce by 1/3.
+ if (gUnknown_02024BEC == 120)
+ gUnknown_02024BEC = 80;
+ if(gUnknown_02024BEC == 240)
+ gUnknown_02024BEC = 160;
+ if(gUnknown_02024BEC == 30)
+ gUnknown_02024BEC = 20;
+ if(gUnknown_02024BEC == 15)
+ gUnknown_02024BEC = 10;
+
+ if(gUnknown_02024C68 & 8)
+ gUnknown_02024BEC = 0;
+
+ if (ewram.unk_2016800.unk8 < gUnknown_02024BEC)
+ ewram.unk_2016800.unk8 = gUnknown_02024BEC;
+ }
+ }
+ gAIScriptPtr += 1;
+}
+#else
+__attribute__((naked))
+void BattleAICmd_unk_30(void)
+{
+ asm(".syntax unified\n\
+ push {r4-r7,lr}\n\
+ mov r7, r8\n\
+ push {r7}\n\
+ ldr r0, _0810885C @ =gUnknown_02024DEC\n\
+ movs r2, 0\n\
+ strh r2, [r0]\n\
+ ldr r1, _08108860 @ =0x02000000\n\
+ ldr r3, _08108864 @ =0x0001601c\n\
+ adds r0, r1, r3\n\
+ movs r4, 0\n\
+ strb r2, [r0]\n\
+ adds r3, 0x3\n\
+ adds r0, r1, r3\n\
+ movs r3, 0x1\n\
+ strb r3, [r0]\n\
+ ldr r0, _08108868 @ =gUnknown_02024C68\n\
+ strb r2, [r0]\n\
+ ldr r0, _0810886C @ =gCritMultiplier\n\
+ strb r3, [r0]\n\
+ movs r0, 0xB4\n\
+ lsls r0, 9\n\
+ adds r1, r0\n\
+ str r4, [r1, 0x8]\n\
+ movs r5, 0\n\
+ ldr r4, _08108870 @ =gUnknown_02024BEC\n\
+ ldr r7, _08108874 @ =gUnknown_02024BE6\n\
+ ldr r3, _08108878 @ =gUnknown_02024A8C\n\
+ mov r8, r3\n\
+ ldr r6, _0810887C @ =gUnknown_02024C07\n\
+_081087DA:\n\
+ movs r0, 0x28\n\
+ str r0, [r4]\n\
+ lsls r1, r5, 1\n\
+ ldrb r2, [r6]\n\
+ movs r0, 0x58\n\
+ muls r0, r2\n\
+ adds r1, r0\n\
+ add r1, r8\n\
+ ldrh r0, [r1]\n\
+ strh r0, [r7]\n\
+ lsls r0, 16\n\
+ cmp r0, 0\n\
+ beq _08108844\n\
+ ldrh r0, [r7]\n\
+ ldrb r1, [r6]\n\
+ ldr r2, _08108880 @ =gUnknown_02024C08\n\
+ ldrb r2, [r2]\n\
+ bl move_effectiveness_something\n\
+ ldr r0, [r4]\n\
+ cmp r0, 0x78\n\
+ bne _0810880A\n\
+ movs r0, 0x50\n\
+ str r0, [r4]\n\
+_0810880A:\n\
+ ldr r0, [r4]\n\
+ cmp r0, 0xF0\n\
+ bne _08108814\n\
+ movs r0, 0xA0\n\
+ str r0, [r4]\n\
+_08108814:\n\
+ ldr r0, [r4]\n\
+ cmp r0, 0x1E\n\
+ bne _0810881E\n\
+ movs r0, 0x14\n\
+ str r0, [r4]\n\
+_0810881E:\n\
+ ldr r0, [r4]\n\
+ cmp r0, 0xF\n\
+ bne _08108828\n\
+ movs r0, 0xA\n\
+ str r0, [r4]\n\
+_08108828:\n\
+ ldr r0, _08108868 @ =gUnknown_02024C68\n\
+ ldrb r1, [r0]\n\
+ movs r0, 0x8\n\
+ ands r0, r1\n\
+ cmp r0, 0\n\
+ beq _08108838\n\
+ movs r0, 0\n\
+ str r0, [r4]\n\
+_08108838:\n\
+ ldr r2, _08108884 @ =0x02016800\n\
+ ldr r0, [r2, 0x8]\n\
+ ldr r1, [r4]\n\
+ cmp r0, r1\n\
+ bcs _08108844\n\
+ str r1, [r2, 0x8]\n\
+_08108844:\n\
+ adds r5, 0x1\n\
+ cmp r5, 0x3\n\
+ ble _081087DA\n\
+ ldr r1, _08108888 @ =gAIScriptPtr\n\
+ ldr r0, [r1]\n\
+ adds r0, 0x1\n\
+ str r0, [r1]\n\
+ pop {r3}\n\
+ mov r8, r3\n\
+ pop {r4-r7}\n\
+ pop {r0}\n\
+ bx r0\n\
+ .align 2, 0\n\
+_0810885C: .4byte gUnknown_02024DEC\n\
+_08108860: .4byte 0x02000000\n\
+_08108864: .4byte 0x0001601c\n\
+_08108868: .4byte gUnknown_02024C68\n\
+_0810886C: .4byte gCritMultiplier\n\
+_08108870: .4byte gUnknown_02024BEC\n\
+_08108874: .4byte gUnknown_02024BE6\n\
+_08108878: .4byte gUnknown_02024A8C\n\
+_0810887C: .4byte gUnknown_02024C07\n\
+_08108880: .4byte gUnknown_02024C08\n\
+_08108884: .4byte 0x02016800\n\
+_08108888: .4byte gAIScriptPtr\n\
+ .syntax divided\n");
+}
+#endif
+
+// same function as above but no for loop.
+__attribute__((naked))
+void BattleAICmd_if_damage_bonus(void)
+{
+ asm(".syntax unified\n\
+ push {r4,r5,lr}\n\
+ ldr r0, _08108928 @ =gUnknown_02024DEC\n\
+ movs r1, 0\n\
+ strh r1, [r0]\n\
+ ldr r2, _0810892C @ =0x02000000\n\
+ ldr r3, _08108930 @ =0x0001601c\n\
+ adds r0, r2, r3\n\
+ strb r1, [r0]\n\
+ adds r3, 0x3\n\
+ adds r0, r2, r3\n\
+ movs r3, 0x1\n\
+ strb r3, [r0]\n\
+ ldr r5, _08108934 @ =gUnknown_02024C68\n\
+ strb r1, [r5]\n\
+ ldr r0, _08108938 @ =gCritMultiplier\n\
+ strb r3, [r0]\n\
+ ldr r4, _0810893C @ =gUnknown_02024BEC\n\
+ movs r0, 0x28\n\
+ str r0, [r4]\n\
+ ldr r1, _08108940 @ =gUnknown_02024BE6\n\
+ movs r0, 0xB4\n\
+ lsls r0, 9\n\
+ adds r2, r0\n\
+ ldrh r0, [r2, 0x2]\n\
+ strh r0, [r1]\n\
+ ldrh r0, [r1]\n\
+ ldr r1, _08108944 @ =gUnknown_02024C07\n\
+ ldrb r1, [r1]\n\
+ ldr r2, _08108948 @ =gUnknown_02024C08\n\
+ ldrb r2, [r2]\n\
+ bl move_effectiveness_something\n\
+ ldr r0, [r4]\n\
+ cmp r0, 0x78\n\
+ bne _081088D6\n\
+ movs r0, 0x50\n\
+ str r0, [r4]\n\
+_081088D6:\n\
+ ldr r0, [r4]\n\
+ cmp r0, 0xF0\n\
+ bne _081088E0\n\
+ movs r0, 0xA0\n\
+ str r0, [r4]\n\
+_081088E0:\n\
+ ldr r0, [r4]\n\
+ cmp r0, 0x1E\n\
+ bne _081088EA\n\
+ movs r0, 0x14\n\
+ str r0, [r4]\n\
+_081088EA:\n\
+ ldr r0, [r4]\n\
+ cmp r0, 0xF\n\
+ bne _081088F4\n\
+ movs r0, 0xA\n\
+ str r0, [r4]\n\
+_081088F4:\n\
+ ldrb r1, [r5]\n\
+ movs r0, 0x8\n\
+ ands r0, r1\n\
+ cmp r0, 0\n\
+ beq _08108902\n\
+ movs r0, 0\n\
+ str r0, [r4]\n\
+_08108902:\n\
+ ldrb r0, [r4]\n\
+ ldr r3, _0810894C @ =gAIScriptPtr\n\
+ ldr r2, [r3]\n\
+ ldrb r1, [r2, 0x1]\n\
+ cmp r0, r1\n\
+ bne _08108950\n\
+ ldrb r1, [r2, 0x2]\n\
+ ldrb r0, [r2, 0x3]\n\
+ lsls r0, 8\n\
+ orrs r1, r0\n\
+ ldrb r0, [r2, 0x4]\n\
+ lsls r0, 16\n\
+ orrs r1, r0\n\
+ ldrb r0, [r2, 0x5]\n\
+ lsls r0, 24\n\
+ orrs r1, r0\n\
+ str r1, [r3]\n\
+ b _08108954\n\
+ .align 2, 0\n\
+_08108928: .4byte gUnknown_02024DEC\n\
+_0810892C: .4byte 0x02000000\n\
+_08108930: .4byte 0x0001601c\n\
+_08108934: .4byte gUnknown_02024C68\n\
+_08108938: .4byte gCritMultiplier\n\
+_0810893C: .4byte gUnknown_02024BEC\n\
+_08108940: .4byte gUnknown_02024BE6\n\
+_08108944: .4byte gUnknown_02024C07\n\
+_08108948: .4byte gUnknown_02024C08\n\
+_0810894C: .4byte gAIScriptPtr\n\
+_08108950:\n\
+ adds r0, r2, 0x6\n\
+ str r0, [r3]\n\
+_08108954:\n\
+ pop {r4,r5}\n\
+ pop {r0}\n\
+ bx r0\n\
+ .syntax divided\n");
+}
+
+void BattleAICmd_unk_32(void)
+{}
+
+void BattleAICmd_unk_33(void)
+{}
diff --git a/src/battle_setup.c b/src/battle_setup.c
new file mode 100644
index 000000000..15b09645f
--- /dev/null
+++ b/src/battle_setup.c
@@ -0,0 +1,1157 @@
+#include "global.h"
+#include "battle.h"
+#include "main.h"
+#include "species.h"
+#include "pokemon.h"
+#include "songs.h"
+#include "task.h"
+#include "fieldmap.h"
+#include "string_util.h"
+#include "rng.h"
+#include "flag.h"
+#include "var.h"
+#include "script.h"
+#include "field_message_box.h"
+#include "trainer.h"
+
+#define NUM_TRAINER_EYE_TRAINERS 56
+#define TRAINER_REMATCH_STEPS 255
+
+extern void prev_quest_postbuffer_cursor_backup_reset(void);
+extern void overworld_poison_timer_set(void);
+extern void current_map_music_set__default_for_battle(u16);
+extern void c2_exit_to_overworld_1_continue_scripts_restart_music(void);
+extern void c2_exit_to_overworld_2_switch(void);
+extern void npc_set_running_behaviour_etc(struct MapObject *, u8);
+extern void c2_whiteout(void);
+extern void sub_800E7C4(void);
+extern void sub_8081AA4(void);
+extern void sub_8081A18(void);
+extern void sub_8081C8C(void);
+extern void sub_80C824C(void);
+extern void sub_8081CEC(void);
+extern void sub_8080E44(void);
+extern void sub_80821D8(void);
+extern void sub_8082228(void);
+extern void sub_808260C(void);
+extern void sub_8082CB8(void);
+extern u8 *sub_80BCCE8(void);
+extern void CB2_ChooseStarter(void);
+extern void sub_811AABC(u8);
+extern u8 sub_811AAE8(void);
+extern u8 GetFieldObjectIdByLocalIdAndMap(u8, u8, u8);
+extern u8 *sub_8082880(void);
+extern u8 sub_803FC58(u16);
+extern bool32 FieldPoisonEffectIsRunning(void);
+extern bool32 GetSafariZoneFlag(void);
+extern void player_bitmagic(void);
+
+u8 GetWildBattleTransition(void);
+u8 GetTrainerBattleTransition(void);
+bool32 battle_exit_is_player_defeat(u32 a1);
+u8 *sub_808281C(void);
+u16 sub_8082C4C(u16 a1);
+
+extern u16 gScriptResult;
+
+struct TrainerPartyMember0
+{
+ u16 iv;
+ u8 level;
+ u16 species;
+};
+
+struct TrainerPartyMember1
+{
+ u16 iv;
+ u8 level;
+ u16 species;
+ u16 moves[4];
+};
+
+struct TrainerPartyMember2
+{
+ u16 iv;
+ u8 level;
+ u16 species;
+ u16 heldItem;
+};
+
+struct TrainerPartyMember3
+{
+ u16 iv;
+ u8 level;
+ u16 species;
+ u16 heldItem;
+ u16 moves[4];
+};
+
+struct TrainerBattleSpec
+{
+ void *ptr;
+ u8 ptrType;
+};
+
+struct TrainerEyeTrainer
+{
+ u16 trainerNums[5];
+ u16 mapGroup;
+ u16 mapNum;
+};
+
+extern u16 MapGridGetMetatileBehaviorAt(s16, s16);
+extern bool8 MetatileBehavior_IsTallGrass(char);
+extern bool8 MetatileBehavior_IsLongGrass(char);
+extern bool8 MetatileBehavior_IsSandOrDeepSand(char);
+extern bool8 MetatileBehavior_IsSurfableWaterOrUnderwater(char);
+extern bool8 MetatileBehavior_IsBridge(char);
+extern bool8 sub_80574C4(char);
+extern bool8 sub_80574D8(char);
+extern bool8 sub_8057568(char);
+extern u8 TestPlayerAvatarFlags(u8);
+extern u8 sub_8057450(u8);
+extern u8 GetSav1Weather(void);
+extern void PlayNewMapMusic(u16);
+
+extern u8 ScriptGiveMon(u16, u8, u16, u32, u32, u8);
+
+extern void (*gUnknown_0300485C)(void);
+
+extern struct Pokemon gEnemyParty[];
+extern struct Pokemon gPlayerParty[];
+extern struct Trainer gTrainers[];
+
+EWRAM_DATA u16 gTrainerBattleMode = 0;
+EWRAM_DATA u16 gTrainerBattleOpponent = 0;
+EWRAM_DATA u16 gTrainerMapObjectLocalId = 0;
+EWRAM_DATA u8 *gTrainerIntroSpeech = NULL;
+EWRAM_DATA u8 *gTrainerDefeatSpeech = NULL;
+EWRAM_DATA u8 *gTrainerVictorySpeech = NULL;
+EWRAM_DATA u8 *gTrainerCannotBattleSpeech = NULL;
+EWRAM_DATA u8 *gTrainerBattleScriptReturnAddress = NULL;
+EWRAM_DATA u8 *gTrainerBattleEndScript = NULL;
+
+extern struct TrainerEyeTrainer gTrainerEyeTrainers[];
+
+extern u8 gOtherText_CancelWithTerminator[];
+
+extern u16 gUnknown_020239F8;
+extern u16 gScriptLastTalked;
+extern u8 gUnknown_02024D26;
+extern u16 gBadgeFlags[];
+
+extern struct MapObject gMapObjects[];
+
+extern u8 gUnknown_0819F818[];
+extern u8 gUnknown_0819F840[];
+extern u8 gUnknown_0819F878[];
+extern u8 gUnknown_0819F887[];
+extern u8 gUnknown_0819F8AE[];
+
+extern u8 gUnknown_0819F80B[];
+extern u8 gUnknown_081C6C02[];
+
+extern struct TrainerBattleSpec gTrainerBattleSpecs_0[];
+extern struct TrainerBattleSpec gTrainerBattleSpecs_1[];
+extern struct TrainerBattleSpec gTrainerBattleSpecs_2[];
+extern struct TrainerBattleSpec gTrainerBattleSpecs_3[];
+extern struct TrainerBattleSpec gTrainerBattleSpecs_4[];
+
+extern u8 gStringVar4[];
+
+extern u8 gBattleTransitionTable_Wild[][2];
+extern u8 gBattleTransitionTable_Trainer[][2];
+
+void sub_8082188(void);
+
+void task01_battle_start(u8 taskId)
+{
+ s16 *data = gTasks[taskId].data;
+
+ switch (data[0])
+ {
+ case 0:
+ if (!FieldPoisonEffectIsRunning()) // is poison not active?
+ {
+ sub_811AABC(data[1]);
+ data[0]++; // go to case 1.
+ }
+ break;
+ case 1:
+ if (sub_811AAE8() == TRUE)
+ {
+ SetMainCallback2(sub_800E7C4);
+ prev_quest_postbuffer_cursor_backup_reset();
+ overworld_poison_timer_set();
+ DestroyTask(taskId);
+ }
+ break;
+ }
+}
+
+void task_add_01_battle_start(u8 transition, u16 song)
+{
+ u8 taskId = CreateTask(task01_battle_start, 1);
+
+ gTasks[taskId].data[1] = transition;
+ current_map_music_set__default_for_battle(song);
+}
+
+void CheckForSafariZoneAndProceed(void)
+{
+ if (GetSafariZoneFlag())
+ sub_8081AA4();
+ else
+ sub_8081A18();
+}
+
+void sub_8081A18(void)
+{
+ ScriptContext2_Enable();
+ player_bitmagic();
+ sub_80597F4();
+ gMain.field_8 = sub_8081C8C;
+ gUnknown_020239F8 = 0;
+ task_add_01_battle_start(GetWildBattleTransition(), 0);
+ sav12_xor_increment(7);
+ sav12_xor_increment(8);
+}
+
+void sub_8081A5C(void)
+{
+ ScriptContext2_Enable();
+ player_bitmagic();
+ sub_80597F4();
+ gMain.field_8 = sub_8081C8C;
+ gUnknown_020239F8 = 1024;
+ task_add_01_battle_start(GetWildBattleTransition(), 0);
+ sav12_xor_increment(7);
+ sav12_xor_increment(8);
+}
+
+void sub_8081AA4(void)
+{
+ ScriptContext2_Enable();
+ player_bitmagic();
+ sub_80597F4();
+ gMain.field_8 = sub_80C824C;
+ gUnknown_020239F8 = 128;
+ task_add_01_battle_start(GetWildBattleTransition(), 0);
+}
+
+void task_add_01_battle_start_with_music_and_stats(void)
+{
+ task_add_01_battle_start(GetTrainerBattleTransition(), 0);
+ sav12_xor_increment(7);
+ sav12_xor_increment(9);
+}
+
+//Initiates battle where Wally catches Ralts
+void sub_8081AFC(void)
+{
+ CreateMaleMon(&gEnemyParty[0], SPECIES_RALTS, 5);
+ ScriptContext2_Enable();
+ gMain.field_8 = c2_exit_to_overworld_1_continue_scripts_restart_music;
+ gUnknown_020239F8 = 512;
+ task_add_01_battle_start(8, 0);
+}
+
+void sub_8081B3C(void)
+{
+ ScriptContext2_Enable();
+ gMain.field_8 = sub_8081CEC;
+ gUnknown_020239F8 = 0;
+ task_add_01_battle_start(GetWildBattleTransition(), 0);
+ sav12_xor_increment(7);
+ sav12_xor_increment(8);
+}
+
+void sub_8081B78(void)
+{
+ ScriptContext2_Enable();
+ gMain.field_8 = sub_8081CEC;
+ gUnknown_020239F8 = 0x2000;
+ task_add_01_battle_start(GetWildBattleTransition(), 0);
+ sav12_xor_increment(7);
+ sav12_xor_increment(8);
+}
+
+void sub_8081BB8(void)
+{
+ ScriptContext2_Enable();
+ gMain.field_8 = sub_8081CEC;
+ gUnknown_020239F8 = 0x2000;
+ task_add_01_battle_start(0, BGM_BATTLE34);
+ sav12_xor_increment(7);
+ sav12_xor_increment(8);
+}
+
+void sub_8081BF8(void)
+{
+ ScriptContext2_Enable();
+ gMain.field_8 = sub_8081CEC;
+ gUnknown_020239F8 = 12288;
+ if (gGameVersion == 2)
+ task_add_01_battle_start(0xB, BGM_BATTLE34); // KYOGRE
+ else
+ task_add_01_battle_start(0x6, BGM_BATTLE34); // GROUDON
+ sav12_xor_increment(7);
+ sav12_xor_increment(8);
+}
+
+void sub_8081C50(void)
+{
+ ScriptContext2_Enable();
+ gMain.field_8 = sub_8081CEC;
+ gUnknown_020239F8 = 24576;
+ task_add_01_battle_start(0xA, BGM_BATTLE36);
+ sav12_xor_increment(7);
+ sav12_xor_increment(8);
+}
+
+void sub_8081C8C(void)
+{
+ CpuFill16(0, (void *)BG_PLTT, BG_PLTT_SIZE);
+ ResetOamRange(0, 128);
+
+ if (battle_exit_is_player_defeat(gUnknown_02024D26) == TRUE)
+ {
+ SetMainCallback2(c2_whiteout);
+ }
+ else
+ {
+ SetMainCallback2(c2_exit_to_overworld_2_switch);
+ gUnknown_0300485C = sub_8080E44;
+ }
+}
+
+void sub_8081CEC(void)
+{
+ CpuFill16(0, (void *)BG_PLTT, BG_PLTT_SIZE);
+ ResetOamRange(0, 128);
+
+ if (battle_exit_is_player_defeat(gUnknown_02024D26) == TRUE)
+ SetMainCallback2(c2_whiteout);
+ else
+ SetMainCallback2(c2_exit_to_overworld_1_continue_scripts_restart_music);
+}
+
+s8 sub_8081D3C(void)
+{
+ u16 tileBehavior;
+ s16 x, y;
+
+ PlayerGetDestCoords(&x, &y);
+ tileBehavior = MapGridGetMetatileBehaviorAt(x, y);
+
+ if (MetatileBehavior_IsTallGrass(tileBehavior))
+ return 0;
+ if (MetatileBehavior_IsLongGrass(tileBehavior))
+ return 1;
+ if (MetatileBehavior_IsSandOrDeepSand(tileBehavior))
+ return 2;
+ switch (gMapHeader.light)
+ {
+ case 1:
+ case 2:
+ case 3:
+ break;
+ case 4:
+ if (sub_80574C4(tileBehavior))
+ return 8;
+ if (MetatileBehavior_IsSurfableWaterOrUnderwater(tileBehavior))
+ return 5;
+ return 7;
+ case 8:
+ case 9:
+ return 8;
+ case 5:
+ return 3;
+ case 6:
+ if (MetatileBehavior_IsSurfableWaterOrUnderwater(tileBehavior))
+ return 4;
+ return 9;
+ }
+ if (sub_8057568(tileBehavior))
+ return 4;
+ if (MetatileBehavior_IsSurfableWaterOrUnderwater(tileBehavior))
+ return 5;
+ if (sub_80574D8(tileBehavior))
+ return 6;
+ if (TestPlayerAvatarFlags(8))
+ {
+ if (sub_8057450(tileBehavior))
+ return 5;
+ if (MetatileBehavior_IsBridge(tileBehavior) == TRUE)
+ return 4;
+ }
+ if (gSaveBlock1.location.mapGroup == 0 && gSaveBlock1.location.mapNum == 28)
+ return 2;
+ if (GetSav1Weather() == 8)
+ return 2;
+ return 9;
+}
+
+s8 sub_8081E90(void)
+{
+ u8 flashUsed;
+ u16 tileBehavior;
+ s16 x, y;
+
+ PlayerGetDestCoords(&x, &y);
+ tileBehavior = MapGridGetMetatileBehaviorAt(x, y);
+
+ flashUsed = sav1_get_flash_used_on_map();
+
+ if (flashUsed)
+ return 2;
+
+ if (!MetatileBehavior_IsSurfableWaterOrUnderwater(tileBehavior))
+ {
+ switch (gMapHeader.light)
+ {
+ case 4:
+ return 1;
+ case 5:
+ return 3;
+ default:
+ return 0;
+ }
+ }
+ return 3;
+}
+
+u16 GetSumOfPartyMonLevel(u8 numMons)
+{
+ u8 sum = 0;
+ int i;
+
+ for (i = 0; i < 6; i++)
+ {
+ u32 species = GetMonData(&gPlayerParty[i], MON_DATA_SPECIES2);
+
+ if (species != 412 && species != 0 && GetMonData(&gPlayerParty[i], MON_DATA_HP) != 0)
+ {
+ sum += GetMonData(&gPlayerParty[i], MON_DATA_LEVEL);
+ numMons--;
+ if (numMons == 0)
+ break;
+ }
+ }
+ return sum;
+}
+
+u8 GetSumOfEnemyPartyLevel(u16 trainerNum, u8 numMons)
+{
+ u8 i;
+ u8 sum;
+ u32 count = numMons;
+ void *party;
+
+ if (gTrainers[trainerNum].partySize < count)
+ count = gTrainers[trainerNum].partySize;
+
+ sum = 0;
+
+ switch (gTrainers[trainerNum].partyFlags)
+ {
+ case 0:
+ party = gTrainers[trainerNum].party;
+ for (i = 0; i < count; i++)
+ sum += ((struct TrainerPartyMember0 *)party)[i].level;
+ break;
+ case 1:
+ party = gTrainers[trainerNum].party;
+ for (i = 0; i < count; i++)
+ sum += ((struct TrainerPartyMember1 *)party)[i].level;
+ break;
+ case 2:
+ party = gTrainers[trainerNum].party;
+ for (i = 0; i < count; i++)
+ sum += ((struct TrainerPartyMember2 *)party)[i].level;
+ break;
+ case 3:
+ party = gTrainers[trainerNum].party;
+ for (i = 0; i < count; i++)
+ sum += ((struct TrainerPartyMember3 *)party)[i].level;
+ break;
+ }
+
+ return sum;
+}
+
+u8 GetWildBattleTransition(void)
+{
+ u8 flashVar = sub_8081E90();
+ u8 level = GetMonData(&gEnemyParty[0], MON_DATA_LEVEL);
+
+ if (level < (u8)GetSumOfPartyMonLevel(1)) // is wild mon level than the player's mon level?
+ return gBattleTransitionTable_Wild[flashVar][0];
+ else
+ return gBattleTransitionTable_Wild[flashVar][1]; // use a white fade in instead of normal transition.
+}
+
+u8 GetTrainerBattleTransition(void)
+{
+ struct Trainer *trainer;
+ u8 trainerClass;
+ u8 partyCount;
+ u8 flashVar;
+ u8 level;
+
+ if (gTrainerBattleOpponent == 1024) // link battle?
+ return 16;
+
+ trainer = gTrainers;
+
+ if (trainer[gTrainerBattleOpponent].trainerClass == 24) // league?
+ {
+ if (gTrainerBattleOpponent == 261)
+ return 12;
+ if (gTrainerBattleOpponent == 262)
+ return 13;
+ if (gTrainerBattleOpponent == 263)
+ return 14;
+ if (gTrainerBattleOpponent == 264)
+ return 15;
+ return 16;
+ }
+
+ if (trainer[gTrainerBattleOpponent].trainerClass == 32) // team leader?
+ return 16;
+
+ if (trainer[gTrainerBattleOpponent].doubleBattle == TRUE)
+ partyCount = 2; // double battles always at least have 2 pokemon.
+ else
+ partyCount = 1;
+
+ flashVar = sub_8081E90();
+ level = GetSumOfEnemyPartyLevel(gTrainerBattleOpponent, partyCount);
+
+ if (level < (u8)GetSumOfPartyMonLevel(partyCount)) // is wild mon level than the player's mon level?
+ return gBattleTransitionTable_Trainer[flashVar][0];
+ else
+ return gBattleTransitionTable_Trainer[flashVar][1];
+}
+
+u8 GetBattleTowerBattleTransition(void)
+{
+ u8 monData = GetMonData(&gEnemyParty[0], MON_DATA_LEVEL);
+
+ if (monData < (u8)GetSumOfPartyMonLevel(1))
+ return 4;
+ else
+ return 3;
+}
+
+void sub_8082168(void)
+{
+ SetMainCallback2(CB2_ChooseStarter);
+ gMain.field_8 = sub_8082188;
+}
+
+void sub_8082188(void)
+{
+ u16 starterPoke;
+
+ *GetVarPointer(0x4023) = gScriptResult;
+ starterPoke = GetStarterPokemon(gScriptResult);
+ ScriptGiveMon(starterPoke, 5, 0, 0, 0, 0);
+ ResetTasks();
+ sub_80408BC();
+ SetMainCallback2(sub_80821D8);
+ sub_811AAD8(0);
+}
+
+void sub_80821D8(void)
+{
+ UpdatePaletteFade();
+ RunTasks();
+
+ if (sub_811AAE8() == TRUE)
+ {
+ gUnknown_020239F8 = 16;
+ gMain.field_8 = sub_8082228;
+ SetMainCallback2(sub_800E7C4);
+ prev_quest_postbuffer_cursor_backup_reset();
+ overworld_poison_timer_set();
+ sav12_xor_increment(7);
+ sav12_xor_increment(8);
+ }
+}
+
+void sub_8082228(void)
+{
+ sav1_reset_battle_music_maybe();
+ SetMainCallback2(c2_exit_to_overworld_1_continue_scripts_restart_music);
+}
+
+u32 TrainerBattleLoadArg32(u8 *ptr)
+{
+ return ptr[0] | (ptr[1] << 8) | (ptr[2] << 16) | (ptr[3] << 24);
+}
+
+u16 TrainerBattleLoadArg16(u8 *ptr)
+{
+ return ptr[0] | (ptr[1] << 8);
+}
+
+u8 TrainerBattleLoadArg8(u8 *ptr)
+{
+ return ptr[0];
+}
+
+u16 trainerflag_opponent(void)
+{
+ return TRAINER_FLAG_START + gTrainerBattleOpponent;
+}
+
+bool32 battle_exit_is_player_defeat(u32 a1)
+{
+ switch (a1 - 1)
+ {
+ case 1:
+ case 2:
+ return TRUE;
+ case 0:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ return FALSE;
+ }
+ return FALSE;
+}
+
+void sub_80822BC(void)
+{
+ gTrainerBattleMode = 0;
+ gTrainerBattleOpponent = 0;
+ gTrainerMapObjectLocalId = 0;
+ gTrainerIntroSpeech = 0;
+ gTrainerDefeatSpeech = 0;
+ gTrainerVictorySpeech = 0;
+ gTrainerCannotBattleSpeech = 0;
+ gTrainerBattleScriptReturnAddress = 0;
+ gTrainerBattleEndScript = 0;
+}
+
+void TrainerBattleLoadArgs(struct TrainerBattleSpec *specs, u8 *data)
+{
+ while (1)
+ {
+ switch (specs->ptrType)
+ {
+ case 0:
+ *(u8 *)specs->ptr = TrainerBattleLoadArg8(data);
+ data++;
+ break;
+ case 1:
+ *(u16 *)specs->ptr = TrainerBattleLoadArg16(data);
+ data += 2;
+ break;
+ case 2:
+ *(u32 *)specs->ptr = TrainerBattleLoadArg32(data);
+ data += 4;
+ break;
+ case 3:
+ *(u8 *)specs->ptr = 0;
+ break;
+ case 4:
+ *(u16 *)specs->ptr = 0;
+ break;
+ case 5:
+ *(u32 *)specs->ptr = 0;
+ break;
+ case 6:
+ *(u8 **)specs->ptr = data;
+ return;
+ }
+ specs++;
+ }
+}
+
+void battle_80801F0(void)
+{
+ if (gTrainerMapObjectLocalId)
+ {
+ gScriptLastTalked = gTrainerMapObjectLocalId;
+ gSelectedMapObject = GetFieldObjectIdByLocalIdAndMap(gTrainerMapObjectLocalId, gSaveBlock1.location.mapNum, gSaveBlock1.location.mapGroup);
+ }
+}
+
+u8 *TrainerBattleConfigure(u8 *data)
+{
+ sub_80822BC();
+ gTrainerBattleMode = TrainerBattleLoadArg8(data);
+
+ switch (gTrainerBattleMode)
+ {
+ case 3:
+ TrainerBattleLoadArgs(gTrainerBattleSpecs_3, data);
+ return gUnknown_0819F878;
+ case 4:
+ TrainerBattleLoadArgs(gTrainerBattleSpecs_2, data);
+ battle_80801F0();
+ return gUnknown_0819F840;
+ case 1:
+ case 2:
+ TrainerBattleLoadArgs(gTrainerBattleSpecs_1, data);
+ battle_80801F0();
+ return gUnknown_0819F818;
+ case 6:
+ case 8:
+ TrainerBattleLoadArgs(gTrainerBattleSpecs_4, data);
+ battle_80801F0();
+ return gUnknown_0819F840;
+ case 7:
+ TrainerBattleLoadArgs(gTrainerBattleSpecs_2, data);
+ battle_80801F0();
+ gTrainerBattleOpponent = sub_8082C4C(gTrainerBattleOpponent);
+ return gUnknown_0819F8AE;
+ case 5:
+ TrainerBattleLoadArgs(gTrainerBattleSpecs_0, data);
+ battle_80801F0();
+ gTrainerBattleOpponent = sub_8082C4C(gTrainerBattleOpponent);
+ return gUnknown_0819F887;
+ default:
+ TrainerBattleLoadArgs(gTrainerBattleSpecs_0, data);
+ battle_80801F0();
+ return gUnknown_0819F818;
+ }
+}
+
+void TrainerWantsBattle(u8 trainerMapObjId, u8 *trainerScript)
+{
+ gSelectedMapObject = trainerMapObjId;
+ gScriptLastTalked = gMapObjects[trainerMapObjId].localId;
+ TrainerBattleConfigure(trainerScript + 1);
+ ScriptContext1_SetupScript(gUnknown_0819F80B);
+ ScriptContext2_Enable();
+}
+
+u8 GetTrainerFlagFromScriptPointer(u8 *data)
+{
+ u32 flag = TrainerBattleLoadArg16(data + 2);
+ return FlagGet(TRAINER_FLAG_START + flag);
+}
+
+void sub_8082524(void)
+{
+ struct MapObject *mapObject = &gMapObjects[gSelectedMapObject];
+
+ npc_set_running_behaviour_etc(mapObject, npc_running_behaviour_by_direction(mapObject->mapobj_unk_18));
+}
+
+u8 sub_8082558(void)
+{
+ return gTrainerBattleMode;
+}
+
+u8 sub_8082564(void)
+{
+ return FlagGet(trainerflag_opponent());
+}
+
+void sub_808257C(void)
+{
+ FlagSet(trainerflag_opponent());
+}
+
+void unref_sub_8082590(void)
+{
+ FlagSet(trainerflag_opponent()); // duplicate function
+}
+
+u8 trainer_flag_check(u16 flag)
+{
+ return FlagGet(TRAINER_FLAG_START + flag);
+}
+
+void trainer_flag_set(u16 flag)
+{
+ FlagSet(TRAINER_FLAG_START + flag);
+}
+
+void trainer_flag_clear(u16 flag)
+{
+ FlagReset(TRAINER_FLAG_START + flag);
+}
+
+void sub_80825E4(void)
+{
+ gUnknown_020239F8 = 8;
+ gMain.field_8 = sub_808260C;
+ task_add_01_battle_start_with_music_and_stats();
+ ScriptContext1_Stop();
+}
+
+void sub_808260C(void)
+{
+ if (gTrainerBattleOpponent == 1024)
+ {
+ SetMainCallback2(c2_exit_to_overworld_1_continue_scripts_restart_music); // link battle?
+ }
+ else if (battle_exit_is_player_defeat(gUnknown_02024D26) == TRUE)
+ {
+ SetMainCallback2(c2_whiteout);
+ }
+ else
+ {
+ SetMainCallback2(c2_exit_to_overworld_1_continue_scripts_restart_music);
+ sub_808257C();
+ }
+}
+
+void do_choose_name_or_words_screen(void)
+{
+ if (gTrainerBattleOpponent == 1024)
+ {
+ SetMainCallback2(c2_exit_to_overworld_1_continue_scripts_restart_music); // link battle?
+ }
+ else if (battle_exit_is_player_defeat(gUnknown_02024D26) == TRUE)
+ {
+ SetMainCallback2(c2_whiteout);
+ }
+ else
+ {
+ SetMainCallback2(c2_exit_to_overworld_1_continue_scripts_restart_music);
+ sub_808257C();
+ sub_8082CB8();
+ }
+}
+
+void sub_80826B0(void)
+{
+ gUnknown_020239F8 = 8;
+ gMain.field_8 = do_choose_name_or_words_screen;
+ task_add_01_battle_start_with_music_and_stats();
+ ScriptContext1_Stop();
+}
+
+void sub_80826D8(void)
+{
+ ShowFieldMessage(sub_808281C());
+}
+
+u8 *sub_80826E8(void)
+{
+ if (gTrainerBattleScriptReturnAddress)
+ return gTrainerBattleScriptReturnAddress;
+ else
+ return gUnknown_081C6C02;
+}
+
+u8 *sub_8082700(void)
+{
+ if (gTrainerBattleEndScript)
+ return gTrainerBattleEndScript;
+ else
+ return gUnknown_081C6C02;
+}
+
+void sub_8082718()
+{
+ ShowFieldMessage(sub_8082880());
+}
+
+void PlayTrainerEncounterMusic(void)
+{
+ u16 music;
+
+ if (gTrainerBattleMode != 1 && gTrainerBattleMode != 8)
+ {
+ switch (sub_803FC58(gTrainerBattleOpponent))
+ {
+ 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);
+ }
+}
+
+//Returns an empty string if a null pointer was passed, otherwise returns str
+u8 *SanitizeString(u8 *str)
+{
+ if (str)
+ return str;
+ else
+ return gOtherText_CancelWithTerminator;
+}
+
+u8 *sub_808281C(void)
+{
+ return SanitizeString(gTrainerIntroSpeech);
+}
+
+u8 *sub_8082830(void)
+{
+ u8 *str;
+
+ if (gTrainerBattleOpponent == 1024)
+ str = sub_80BCCE8();
+ else
+ str = gTrainerDefeatSpeech;
+
+ StringExpandPlaceholders(gStringVar4, SanitizeString(str));
+ return gStringVar4;
+}
+
+u8 *unref_sub_808286C(void)
+{
+ return SanitizeString(gTrainerVictorySpeech);
+}
+
+u8 *sub_8082880(void)
+{
+ return SanitizeString(gTrainerCannotBattleSpeech);
+}
+
+s32 sub_8082894(struct TrainerEyeTrainer *trainers, u16 trainerNum)
+{
+ s32 i;
+
+ for (i = 0; i < NUM_TRAINER_EYE_TRAINERS; i++)
+ {
+ if (trainers[i].trainerNums[0] == trainerNum)
+ return i;
+ }
+ return -1;
+}
+
+s32 sub_80828B8(struct TrainerEyeTrainer *trainers, u16 trainerNum)
+{
+ s32 i;
+ s32 j;
+
+ for (i = 0; i < NUM_TRAINER_EYE_TRAINERS; i++)
+ {
+ for (j = 0; j < 5 && trainers[i].trainerNums[j] != 0; j++)
+ {
+ if (trainers[i].trainerNums[j] == trainerNum)
+ return i;
+ }
+ }
+ return -1;
+}
+
+bool32 sub_80828FC(struct TrainerEyeTrainer *trainers, u16 mapGroup, u16 mapNum)
+{
+ int i;
+ bool32 ret = FALSE;
+
+ for (i = 0; i < NUM_TRAINER_EYE_TRAINERS; i++)
+ {
+ if (trainers[i].mapGroup == mapGroup && trainers[i].mapNum == mapNum)
+ {
+ if (gSaveBlock1.trainerRematches[i] != 0)
+ ret = TRUE;
+ else if (trainer_flag_check(trainers[i].trainerNums[0]) == TRUE && (Random() % 100) <= 30)
+ {
+ int j = 1;
+
+ while (j < 5 && trainers[i].trainerNums[j] != 0 && trainer_flag_check(trainers[i].trainerNums[j]))
+ j++;
+ gSaveBlock1.trainerRematches[i] = j;
+ ret = TRUE;
+ }
+ }
+ }
+ return ret;
+}
+
+s32 sub_80829A8(struct TrainerEyeTrainer *trainers, u16 mapGroup, u16 mapNum)
+{
+ s32 i;
+
+ for (i = 0; i < NUM_TRAINER_EYE_TRAINERS; i++)
+ {
+ if (trainers[i].mapGroup == mapGroup && trainers[i].mapNum == mapNum && gSaveBlock1.trainerRematches[i])
+ return 1;
+ }
+ return 0;
+}
+
+s32 sub_80829E8(struct TrainerEyeTrainer *trainers, u16 mapGroup, u16 mapNum)
+{
+ s32 i;
+
+ for (i = 0; i < NUM_TRAINER_EYE_TRAINERS; i++)
+ {
+ if (trainers[i].mapGroup == mapGroup && trainers[i].mapNum == mapNum)
+ return 1;
+ }
+ return 0;
+}
+
+bool8 sub_8082A18(struct TrainerEyeTrainer *trainers, u16 trainerNum)
+{
+ s32 trainerEyeIndex = sub_8082894(trainers, trainerNum);
+
+ if (trainerEyeIndex != -1 && trainerEyeIndex < 100 && gSaveBlock1.trainerRematches[trainerEyeIndex])
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 sub_8082A54(struct TrainerEyeTrainer *trainers, u16 trainerNum)
+{
+ s32 trainerEyeIndex = sub_80828B8(trainers, trainerNum);
+
+ if (trainerEyeIndex != -1 && trainerEyeIndex < 100 && gSaveBlock1.trainerRematches[trainerEyeIndex])
+ return TRUE;
+ else
+ return FALSE;
+}
+
+u16 sub_8082A90(struct TrainerEyeTrainer *trainers, u16 trainerNum)
+{
+ int i;
+ struct TrainerEyeTrainer *trainer;
+ s32 trainerEyeIndex = sub_8082894(trainers, trainerNum);
+
+ if (trainerEyeIndex == -1)
+ return 0;
+ trainer = &trainers[trainerEyeIndex];
+ for (i = 1; i < 5; i++)
+ {
+ if (!trainer->trainerNums[i])
+ return trainer->trainerNums[i - 1];
+ if (!trainer_flag_check(trainer->trainerNums[i]))
+ return trainer->trainerNums[i];
+ }
+ return trainer->trainerNums[4];
+}
+
+void sub_8082AE4(struct TrainerEyeTrainer *trainers, u16 trainerNum)
+{
+ s32 trainerEyeIndex = sub_80828B8(trainers, trainerNum);
+
+ if (trainerEyeIndex != -1)
+ gSaveBlock1.trainerRematches[trainerEyeIndex] = 0;
+}
+
+bool8 sub_8082B10(struct TrainerEyeTrainer *trainers, u16 trainerNum)
+{
+ s32 trainerEyeIndex = sub_8082894(trainers, trainerNum);
+
+ if (trainerEyeIndex != -1 && trainer_flag_check(trainers[trainerEyeIndex].trainerNums[1]))
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool32 sub_8082B44(void)
+{
+ int badgeCount = 0;
+ u32 i;
+
+ for (i = 0; i < 8; i++)
+ {
+ if (FlagGet(gBadgeFlags[i]) == TRUE)
+ {
+ badgeCount++;
+ if (badgeCount >= 5)
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+void sub_8082B78(void)
+{
+ if (sub_8082B44())
+ {
+ if (gSaveBlock1.trainerRematchStepCounter >= TRAINER_REMATCH_STEPS)
+ gSaveBlock1.trainerRematchStepCounter = TRAINER_REMATCH_STEPS;
+ else
+ gSaveBlock1.trainerRematchStepCounter++;
+ }
+}
+
+bool32 sub_8082BA4(void)
+{
+ if (sub_8082B44() && gSaveBlock1.trainerRematchStepCounter >= TRAINER_REMATCH_STEPS)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+void sub_8082BD0(u16 mapGroup, u16 mapNum)
+{
+ if (sub_8082BA4() && sub_80828FC(gTrainerEyeTrainers, mapGroup, mapNum) == TRUE)
+ gSaveBlock1.trainerRematchStepCounter = 0;
+}
+
+s32 sub_8082C0C(u16 mapGroup, u16 mapNum)
+{
+ return sub_80829A8(gTrainerEyeTrainers, mapGroup, mapNum);
+}
+
+s32 unref_sub_8082C2C(u16 mapGroup, u16 mapNum)
+{
+ return sub_80829E8(gTrainerEyeTrainers, mapGroup, mapNum);
+}
+
+u16 sub_8082C4C(u16 trainerNum)
+{
+ return sub_8082A90(gTrainerEyeTrainers, trainerNum);
+}
+
+s32 sub_8082C68(void)
+{
+ if (sub_8082A18(gTrainerEyeTrainers, gTrainerBattleOpponent))
+ return 1;
+ else
+ return sub_8082B10(gTrainerEyeTrainers, gTrainerBattleOpponent);
+}
+
+u8 sub_8082C9C(void)
+{
+ return sub_8082A54(gTrainerEyeTrainers, gTrainerBattleOpponent);
+}
+
+void sub_8082CB8(void)
+{
+ sub_8082AE4(gTrainerEyeTrainers, gTrainerBattleOpponent);
+ sub_808257C();
+}
diff --git a/src/berry.c b/src/berry.c
index 11d261790..e00015477 100644
--- a/src/berry.c
+++ b/src/berry.c
@@ -1,4 +1,5 @@
#include "global.h"
+#include "text.h"
#define FIRST_BERRY 0x85 // ITEM_CHERI_BERRY
#define LAST_BERRY 0xaf // ITEM_ENIGMA_BERRY
@@ -19,453 +20,409 @@ extern u8 *GetFieldObjectScriptPointerForComparison();
extern struct Berry gBerries[];
extern u8 BerryTreeScript;
extern struct BerryTree gUnknown_083CD780;
-extern u16 gUnknown_0202E8DE;
-extern u16 gUnknown_0202E8CC;
-extern u16 gUnknown_0202E8CE;
-extern u16 gUnknown_0202E8D0;
+extern u16 gScriptItemId;
+extern u16 gScriptLastTalked;
+extern u16 gSpecialVar_0x8004;
+extern u16 gSpecialVar_0x8005;
+extern u16 gSpecialVar_0x8006;
u8 CalcBerryYield(struct BerryTree *tree);
void unref_sub_80B4884(void)
{
- CpuFill16(0, &gSaveBlock1.enigmaBerry, sizeof(gSaveBlock1.enigmaBerry));
+ CpuFill16(0, &gSaveBlock1.enigmaBerry, sizeof(gSaveBlock1.enigmaBerry));
}
// setEnigmaBerry
void sub_80B48A8(u8 *src)
{
- u8 *dest;
- struct SaveBlock1 *saveBlock;
- unsigned int i;
- dest = (u8*)&gSaveBlock1.enigmaBerry;
- saveBlock = &gSaveBlock1;
- for (i = 0; i < sizeof(gSaveBlock1.enigmaBerry); i++)
- {
- dest[i] = src[i];
- }
- gSaveBlock1.enigmaBerry.berry.description1 = gSaveBlock1.enigmaBerry.description1;
- gSaveBlock1.enigmaBerry.berry.description2 = gSaveBlock1.enigmaBerry.description2;
+ unsigned int i;
+ u8 *dest = (u8*)&gSaveBlock1.enigmaBerry;
+
+ for (i = 0; i < sizeof(gSaveBlock1.enigmaBerry); i++)
+ dest[i] = src[i];
+ gSaveBlock1.enigmaBerry.berry.description1 = gSaveBlock1.enigmaBerry.description1;
+ gSaveBlock1.enigmaBerry.berry.description2 = gSaveBlock1.enigmaBerry.description2;
}
// checksum
u32 sub_80B48F8(struct EnigmaBerry *enigmaBerry)
{
- u8 *description1;
- u8 *description2;
- unsigned int i;
- u32 checksum;
- u8 *dest;
+ u8 *description1;
+ u8 *description2;
+ unsigned int i;
+ u32 checksum;
+ u8 *dest;
- description1 = gSaveBlock1.enigmaBerry.berry.description1;
- description2 = gSaveBlock1.enigmaBerry.berry.description2;
- gSaveBlock1.enigmaBerry.berry.description1 = 0;
- gSaveBlock1.enigmaBerry.berry.description2 = 0;
+ description1 = gSaveBlock1.enigmaBerry.berry.description1;
+ description2 = gSaveBlock1.enigmaBerry.berry.description2;
+ gSaveBlock1.enigmaBerry.berry.description1 = 0;
+ gSaveBlock1.enigmaBerry.berry.description2 = 0;
- dest = (u8*)enigmaBerry;
- checksum = 0;
- for (i = 0; i < ((int)&gSaveBlock1.enigmaBerry.checksum - (int)&gSaveBlock1.enigmaBerry); i++)
- {
- checksum += dest[i];
- }
+ dest = (u8*)enigmaBerry;
+ checksum = 0;
+ for (i = 0; i < ((int)&gSaveBlock1.enigmaBerry.checksum - (int)&gSaveBlock1.enigmaBerry); i++)
+ {
+ checksum += dest[i];
+ }
- gSaveBlock1.enigmaBerry.berry.description1 = description1;
- gSaveBlock1.enigmaBerry.berry.description2 = description2;
+ gSaveBlock1.enigmaBerry.berry.description1 = description1;
+ gSaveBlock1.enigmaBerry.berry.description2 = description2;
- return checksum;
+ return checksum;
}
-int sub_80B4940(void)
+bool32 sub_80B4940(void)
{
- if (!gSaveBlock1.enigmaBerry.berry.stageDuration)
- return 0;
- if (!gSaveBlock1.enigmaBerry.berry.maxYield)
- return 0;
- if (sub_80B48F8(&gSaveBlock1.enigmaBerry) != gSaveBlock1.enigmaBerry.checksum)
- return 0;
- return 1;
+ if (!gSaveBlock1.enigmaBerry.berry.stageDuration)
+ return FALSE;
+ if (!gSaveBlock1.enigmaBerry.berry.maxYield)
+ return FALSE;
+ if (sub_80B48F8(&gSaveBlock1.enigmaBerry) != gSaveBlock1.enigmaBerry.checksum)
+ return FALSE;
+ return TRUE;
}
struct Berry *GetBerryInfo(u8 berry)
{
- if ((u8)berry == 0x2b)
- {
- if (sub_80B4940())
- return &gSaveBlock1.enigmaBerry.berry;
- }
- if ((u8)(berry - 1) > 0x2a)
- {
- berry = 1;
- }
- return &gBerries[berry - 1];
+ if (berry == 0x2B && sub_80B4940())
+ return &gSaveBlock1.enigmaBerry.berry;
+ else
+ {
+ if (berry == 0 || berry > 0x2B)
+ berry = 1;
+ return &gBerries[berry - 1];
+ }
}
struct BerryTree *GetBerryTreeInfo(u8 id)
{
- return &gSaveBlock1.berryTrees[id];
+ return &gSaveBlock1.berryTrees[id];
}
-int FieldObjectInteractionWaterBerryTree(void)
+bool32 FieldObjectInteractionWaterBerryTree(void)
{
- struct BerryTree *tree = GetBerryTreeInfo(FieldObjectGetBerryTreeId(gSelectedMapObject));
- switch (tree->stage)
- {
- case 1:
- tree->watered1 = 1;
- break;
- case 2:
- tree->watered2 = 1;
- break;
- case 3:
- tree->watered3 = 1;
- break;
- case 4:
- tree->watered4 = 1;
- break;
- default:
- return 0;
- }
- return 1;
+ struct BerryTree *tree = GetBerryTreeInfo(FieldObjectGetBerryTreeId(gSelectedMapObject));
+
+ switch (tree->stage)
+ {
+ case 1:
+ tree->watered1 = TRUE;
+ break;
+ case 2:
+ tree->watered2 = TRUE;
+ break;
+ case 3:
+ tree->watered3 = TRUE;
+ break;
+ case 4:
+ tree->watered4 = TRUE;
+ break;
+ default:
+ return FALSE;
+ }
+ return TRUE;
}
-int IsPlayerFacingPlantedBerryTree(void)
+bool32 IsPlayerFacingPlantedBerryTree(void)
{
- if (GetFieldObjectScriptPointerForComparison() == &BerryTreeScript)
- if (GetStageByBerryTreeId(FieldObjectGetBerryTreeId(gSelectedMapObject)) == 0)
- return 1;
- return 0;
+ if (GetFieldObjectScriptPointerForComparison() == &BerryTreeScript
+ && GetStageByBerryTreeId(FieldObjectGetBerryTreeId(gSelectedMapObject)) == 0)
+ return TRUE;
+ else
+ return FALSE;
}
u8 WaterBerryTree(void)
{
- if (GetFieldObjectScriptPointerForComparison() != &BerryTreeScript)
- return 0;
- return FieldObjectInteractionWaterBerryTree();
+ if (GetFieldObjectScriptPointerForComparison() != &BerryTreeScript)
+ return 0;
+ else
+ return FieldObjectInteractionWaterBerryTree();
}
void sub_80B4A90(void)
{
- int i;
- struct SaveBlock1 *saveBlock1 = &gSaveBlock1;
- struct BerryTree berryTree = gUnknown_083CD780;
- for (i = 127; i >= 0; i--)
- {
- saveBlock1->berryTrees[i] = berryTree;
- }
-}
-
-int BerryTreeGrow(struct BerryTree *tree)
-{
- if (tree->growthSparkle)
- return 0;
- switch (tree->stage)
- {
- case 0:
- return 0;
- case 4:
- tree->berryYield = CalcBerryYield(tree);
- case 1:
- case 2:
- case 3:
- tree->stage++;
- break;
- case 5:
- tree->watered1 = 0;
- tree->watered2 = 0;
- tree->watered3 = 0;
- tree->watered4 = 0;
- tree->berryYield = 0;
- tree->stage = 2;
- if (++tree->regrowthCount == 10)
- *tree = gUnknown_083CD780;
- break;
- }
- return 1;
+ int i;
+ struct SaveBlock1 *saveBlock1 = &gSaveBlock1;
+ struct BerryTree berryTree = gUnknown_083CD780;
+
+ for (i = 0; i < 128; i++)
+ saveBlock1->berryTrees[i] = berryTree;
+}
+
+bool32 BerryTreeGrow(struct BerryTree *tree)
+{
+ if (tree->growthSparkle)
+ return FALSE;
+ switch (tree->stage)
+ {
+ case 0:
+ return FALSE;
+ case 4:
+ tree->berryYield = CalcBerryYield(tree);
+ case 1:
+ case 2:
+ case 3:
+ tree->stage++;
+ break;
+ case 5:
+ tree->watered1 = 0;
+ tree->watered2 = 0;
+ tree->watered3 = 0;
+ tree->watered4 = 0;
+ tree->berryYield = 0;
+ tree->stage = 2;
+ if (++tree->regrowthCount == 10)
+ *tree = gUnknown_083CD780;
+ break;
+ }
+ return TRUE;
}
void BerryTreeTimeUpdate(int time)
{
- int i;
- struct BerryTree *tree;
- int time2;
- for (i = 0; i <= 0x7f; i++)
- {
- tree = &gSaveBlock1.berryTrees[i];
-
- if (tree->berry == 0)
- continue;
- if (tree->stage == 0)
- continue;
- if (tree->growthSparkle)
- continue;
-
- if (time >= GetStageDurationByBerryType(tree->berry) * 71)
- {
- *tree = gUnknown_083CD780;
- continue;
- }
-
- time2 = time;
- if (!time2)
- continue;
-
- if (tree->secondsUntilNextStage > time2)
- {
- tree->secondsUntilNextStage -= time2;
- time2 = tree->secondsUntilNextStage;
- continue;
- }
-
- while (1)
- {
- time2 -= tree->secondsUntilNextStage;
- tree->secondsUntilNextStage = GetStageDurationByBerryType(tree->berry);
- if (BerryTreeGrow(tree))
- {
- if (tree->stage == 5)
- {
- tree->secondsUntilNextStage *= 4;
- }
- if (!time2)
- {
- break;
- }
- }
- else
- {
- break;
- }
- if (tree->secondsUntilNextStage > time2)
- {
- tree->secondsUntilNextStage -= time2;
- time2 = tree->secondsUntilNextStage;
- break;
- }
- }
- }
-}
-
-void PlantBerryTree(u8 id, u8 berry, u8 stage, u8 sparkle)
-{
- struct BerryTree *tree;
- tree = GetBerryTreeInfo(id);
- *tree = gUnknown_083CD780;
- tree->berry = berry;
- tree->secondsUntilNextStage = GetStageDurationByBerryType(berry);
- tree->stage = stage;
- if (stage == 5)
- {
- tree->berryYield = CalcBerryYield(tree);
- tree->secondsUntilNextStage *= 4;
- }
- if (sparkle == 0)
- {
- tree->growthSparkle = 1;
- }
+ int i;
+ struct BerryTree *tree;
+
+ for (i = 0; i < 128; i++)
+ {
+ tree = &gSaveBlock1.berryTrees[i];
+
+ if (tree->berry && tree->stage && !tree->growthSparkle)
+ {
+ if (time >= GetStageDurationByBerryType(tree->berry) * 71)
+ {
+ *tree = gUnknown_083CD780;
+ }
+ else
+ {
+ int time2 = time;
+
+ while (time2 != 0)
+ {
+ if (tree->secondsUntilNextStage > time2)
+ {
+ tree->secondsUntilNextStage -= time2;
+ break;
+ }
+ time2 -= tree->secondsUntilNextStage;
+ tree->secondsUntilNextStage = GetStageDurationByBerryType(tree->berry);
+ if (!BerryTreeGrow(tree))
+ break;
+ if (tree->stage == 5)
+ tree->secondsUntilNextStage *= 4;
+ }
+ }
+ }
+ }
+}
+
+void PlantBerryTree(u8 id, u8 berry, u8 stage, bool8 sparkle)
+{
+ struct BerryTree *tree = GetBerryTreeInfo(id);
+
+ *tree = gUnknown_083CD780;
+ tree->berry = berry;
+ tree->secondsUntilNextStage = GetStageDurationByBerryType(berry);
+ tree->stage = stage;
+ if (stage == 5)
+ {
+ tree->berryYield = CalcBerryYield(tree);
+ tree->secondsUntilNextStage *= 4;
+ }
+ if (!sparkle)
+ {
+ tree->growthSparkle = TRUE;
+ }
}
void RemoveBerryTree(u8 id)
{
- gSaveBlock1.berryTrees[id] = gUnknown_083CD780;
+ gSaveBlock1.berryTrees[id] = gUnknown_083CD780;
}
u8 GetBerryTypeByBerryTreeId(u8 id)
{
- return gSaveBlock1.berryTrees[id].berry;
+ return gSaveBlock1.berryTrees[id].berry;
}
u8 GetStageByBerryTreeId(u8 id)
{
- return gSaveBlock1.berryTrees[id].stage;
+ return gSaveBlock1.berryTrees[id].stage;
}
u8 ItemIdToBerryType(u16 item)
{
- u16 berry = item - FIRST_BERRY;
- if (berry > LAST_BERRY - FIRST_BERRY)
- return 1;
- return item - FIRST_BERRY + 1;
+ u16 berry = item - FIRST_BERRY;
+
+ if (berry > LAST_BERRY - FIRST_BERRY)
+ return 1;
+ else
+ return item - FIRST_BERRY + 1;
}
u16 BerryTypeToItemId(u16 berry)
{
- u16 item = berry;
- item -= 1;
- if (item > LAST_BERRY - FIRST_BERRY)
- return FIRST_BERRY;
- item = berry;
- return item + FIRST_BERRY - 1;
+ u16 item = berry - 1;
+
+ if (item > LAST_BERRY - FIRST_BERRY)
+ return FIRST_BERRY;
+ else
+ return berry + FIRST_BERRY - 1;
}
void GetBerryNameByBerryType(u8 berry, u8 *string)
{
- struct Berry *info;
- info = GetBerryInfo(berry);
- memcpy(string, info->name, 6);
- string[6] = 0xff;
+ memcpy(string, GetBerryInfo(berry)->name, 6);
+ string[6] = EOS;
}
void ResetBerryTreeSparkleFlag(u8 id)
{
- struct BerryTree *tree;
- tree = GetBerryTreeInfo(id);
- tree->growthSparkle = 0;
+ GetBerryTreeInfo(id)->growthSparkle = 0;
}
u8 BerryTreeGetNumStagesWatered(struct BerryTree *tree)
{
- u8 count = 0;
- if (tree->watered1)
- count++;
- if (tree->watered2)
- count++;
- if (tree->watered3)
- count++;
- if (tree->watered4)
- count++;
- return count;
+ u8 count = 0;
+
+ if (tree->watered1)
+ count++;
+ if (tree->watered2)
+ count++;
+ if (tree->watered3)
+ count++;
+ if (tree->watered4)
+ count++;
+ return count;
}
u8 GetNumStagesWateredByBerryTreeId(u8 id)
{
- return BerryTreeGetNumStagesWatered(GetBerryTreeInfo(id));
-}
-
-u8 CalcBerryYieldInternal(u16 a1, u16 a2, u8 a3)
-{
- u32 v6;
- u32 v1;
- u32 v5;
- u32 v4;
- u16 random;
- u32 ret;
- v6 = a2;
- if (a3 == 0)
- return v6;
- v1 = a1 - v6;
- v5 = v1 * (a3 - 1);
- v4 = v1 * a3;
- random = Random();
- v4 -= v5;
- v4 += 1;
- v5 += random % v4;
- if ((v5 & 3) <= 1)
- {
- ret = v5 / 4;
- return ret + v6;
- }
- else
- {
- ret = v5 / 4 + 1;
- return ret + v6;
- }
+ return BerryTreeGetNumStagesWatered(GetBerryTreeInfo(id));
+}
+
+u8 CalcBerryYieldInternal(u16 max, u16 min, u8 water)
+{
+ u32 randMin;
+ u32 randMax;
+ u32 rand;
+ u32 extraYield;
+
+ if (water == 0)
+ return min;
+ else
+ {
+ randMin = (max - min) * (water - 1);
+ randMax = (max - min) * (water);
+ rand = randMin + Random() % (randMax - randMin + 1);
+
+ if ((rand & 3) > 1)
+ extraYield = rand / 4 + 1;
+ else
+ extraYield = rand / 4;
+ return extraYield + min;
+ }
}
u8 CalcBerryYield(struct BerryTree *tree)
{
- struct Berry *berry = GetBerryInfo(tree->berry);
- u8 min = berry->minYield;
- u8 max = berry->maxYield;
- return CalcBerryYieldInternal(max, min, BerryTreeGetNumStagesWatered(tree));
+ struct Berry *berry = GetBerryInfo(tree->berry);
+ u8 min = berry->minYield;
+ u8 max = berry->maxYield;
+
+ return CalcBerryYieldInternal(max, min, BerryTreeGetNumStagesWatered(tree));
}
u8 GetBerryCountByBerryTreeId(u8 id)
{
- return gSaveBlock1.berryTrees[id].berryYield;
+ return gSaveBlock1.berryTrees[id].berryYield;
}
u16 GetStageDurationByBerryType(u8 berry)
{
- return GetBerryInfo(berry)->stageDuration * 60;
+ return GetBerryInfo(berry)->stageDuration * 60;
}
void FieldObjectInteractionGetBerryTreeData(void)
{
- u8 id;
- u8 berry;
- u8 unk;
- u8 group;
- u8 num;
- id = FieldObjectGetBerryTreeId(gSelectedMapObject);
- berry = GetBerryTypeByBerryTreeId(id);
- ResetBerryTreeSparkleFlag(id);
- unk = gUnknown_0202E8DE;
- num = gSaveBlock1.location.mapNum;
- group = gSaveBlock1.location.mapGroup;
-
- if (sub_8060234(unk, num, group))
- gUnknown_0202E8CC = 0xff;
- else
- gUnknown_0202E8CC = (u8)GetStageByBerryTreeId(id);
-
- gUnknown_0202E8CE = (u8)GetNumStagesWateredByBerryTreeId(id);
- gUnknown_0202E8D0 = (u8)GetBerryCountByBerryTreeId(id);
- GetBerryNameByBerryType(berry, gStringVar1);
+ u8 id;
+ u8 berry;
+ u8 unk;
+ u8 group;
+ u8 num;
+
+ id = FieldObjectGetBerryTreeId(gSelectedMapObject);
+ berry = GetBerryTypeByBerryTreeId(id);
+ ResetBerryTreeSparkleFlag(id);
+ unk = gScriptLastTalked;
+ num = gSaveBlock1.location.mapNum;
+ group = gSaveBlock1.location.mapGroup;
+ if (sub_8060234(unk, num, group))
+ gSpecialVar_0x8004 = 0xFF;
+ else
+ gSpecialVar_0x8004 = GetStageByBerryTreeId(id);
+ gSpecialVar_0x8005 = GetNumStagesWateredByBerryTreeId(id);
+ gSpecialVar_0x8006 = GetBerryCountByBerryTreeId(id);
+ GetBerryNameByBerryType(berry, gStringVar1);
}
void sub_80B4EE4(void)
{
- SetMainCallback2(sub_80A68CC);
+ SetMainCallback2(sub_80A68CC);
}
void FieldObjectInteractionPlantBerryTree(void)
{
- extern u16 word_203855E;
- u8 berry = ItemIdToBerryType(word_203855E);
- PlantBerryTree(FieldObjectGetBerryTreeId(gSelectedMapObject), berry, 1, 1);
- FieldObjectInteractionGetBerryTreeData();
+ u8 berry = ItemIdToBerryType(gScriptItemId);
+
+ PlantBerryTree(FieldObjectGetBerryTreeId(gSelectedMapObject), berry, 1, TRUE);
+ FieldObjectInteractionGetBerryTreeData();
}
void FieldObjectInteractionPickBerryTree(void)
{
- u8 id;
- u8 berry;
- id = FieldObjectGetBerryTreeId(gSelectedMapObject);
- berry = GetBerryTypeByBerryTreeId(id);
- gUnknown_0202E8CC = AddBagItem(BerryTypeToItemId(berry), GetBerryCountByBerryTreeId(id));
+ u8 id = FieldObjectGetBerryTreeId(gSelectedMapObject);
+ u8 berry = GetBerryTypeByBerryTreeId(id);
+
+ gSpecialVar_0x8004 = AddBagItem(BerryTypeToItemId(berry), GetBerryCountByBerryTreeId(id));
}
void FieldObjectInteractionRemoveBerryTree(void)
{
- u8 id;
- u8 unk;
- u8 group, num;
- id = FieldObjectGetBerryTreeId(gSelectedMapObject);
- RemoveBerryTree(id);
- unk = gUnknown_0202E8DE;
- num = gSaveBlock1.location.mapNum;
- group = gSaveBlock1.location.mapGroup;
- sub_8060288(unk, num, group);
+ RemoveBerryTree(FieldObjectGetBerryTreeId(gSelectedMapObject));
+ sub_8060288(gScriptLastTalked, gSaveBlock1.location.mapNum, gSaveBlock1.location.mapGroup);
}
u8 PlayerHasBerries(void)
{
- return IsBagPocketNonEmpty(4);
+ return IsBagPocketNonEmpty(4);
}
void ResetBerryTreeSparkleFlags(void)
{
- s16 cam_left;
- s16 cam_top;
- s16 left;
- s16 top;
- s16 right;
- s16 bottom;
- int i;
-
- GetCameraCoords(&cam_left, &cam_top);
- left = cam_left;
- top = cam_top + 3;
- right = cam_left + 14;
- bottom = top + 8;
-
- for (i = 0; i < 16; i++)
- {
- if (gMapObjects[i].active && gMapObjects[i].animPattern == 12)
- {
- cam_left = gMapObjects[i].coords2.x;
- cam_top = gMapObjects[i].coords2.y;
- if (left <= cam_left && cam_left <= right && top <= cam_top && cam_top <= bottom)
- ResetBerryTreeSparkleFlag(gMapObjects[i].trainerRange_berryTreeId);
- }
- }
+ s16 cam_left;
+ s16 cam_top;
+ s16 left;
+ s16 top;
+ s16 right;
+ s16 bottom;
+ int i;
+
+ GetCameraCoords(&cam_left, &cam_top);
+ left = cam_left;
+ top = cam_top + 3;
+ right = cam_left + 14;
+ bottom = top + 8;
+ for (i = 0; i < 16; i++)
+ {
+ if (gMapObjects[i].active && gMapObjects[i].animPattern == 12)
+ {
+ cam_left = gMapObjects[i].coords2.x;
+ cam_top = gMapObjects[i].coords2.y;
+ if (left <= cam_left && cam_left <= right && top <= cam_top && cam_top <= bottom)
+ ResetBerryTreeSparkleFlag(gMapObjects[i].trainerRange_berryTreeId);
+ }
+ }
}
diff --git a/src/coins.c b/src/coins.c
new file mode 100644
index 000000000..acd8c6e10
--- /dev/null
+++ b/src/coins.c
@@ -0,0 +1,87 @@
+#include "global.h"
+#include "menu.h"
+#include "string_util.h"
+
+#define MAX_COINS 9999
+
+extern u8 gOtherText_Coins2[];
+
+void PrintCoins(s32, u8, u8, u8);
+
+void UpdateCoinsWindow(s32 a, u8 b, u8 c)
+{
+ PrintCoins(a, 4, b + 2, c + 1);
+}
+
+void ShowCoinsWindow(u32 a, u8 b, u8 c)
+{
+ MenuDrawTextWindow(b, c, b + 9, c + 3);
+ UpdateCoinsWindow(a, b, c);
+}
+
+void HideCoinsWindow(u8 a, u8 b)
+{
+ MenuZeroFillWindowRect(a, b, a + 9, b + 3);
+}
+
+void PrintCoins(s32 a, u8 b, u8 c, u8 d)
+{
+ u8 string[16];
+ u8 *ptr;
+ u8 r1;
+ u8 r6;
+ u8 foo;
+
+ ConvertIntToDecimalString(string, a);
+ r1 = (b * 6 + 0x21 - 8 * (b + 2));
+ c = c - r1 / 8;
+ foo = r1 % 8;
+ ptr = gStringVar1;
+ if(foo)
+ {
+ ptr[0] = 0xFC;
+ ptr[1] = 0x11;
+ ptr[2] = 8 - (foo);
+ ptr += 3;
+ }
+ ptr[0] = 0xFC;
+ ptr[1] = 0x11;
+ ptr[2] = (b - StringLength(string)) * 6;
+ ptr += 3;
+ StringCopy(ptr, string);
+ MenuPrint(gOtherText_Coins2, c, d);
+}
+
+u16 GetCoins(void)
+{
+ return gSaveBlock1.coins;
+}
+
+bool8 GiveCoins(u16 coins)
+{
+ u32 newCoins;
+
+ if(GetCoins() >= MAX_COINS)
+ return FALSE;
+ newCoins = coins + gSaveBlock1.coins;
+ if(gSaveBlock1.coins > (u16)newCoins)
+ gSaveBlock1.coins = MAX_COINS;
+ else
+ {
+ gSaveBlock1.coins = newCoins;
+ if((u16)newCoins > MAX_COINS)
+ gSaveBlock1.coins = MAX_COINS;
+ }
+ return TRUE;
+}
+
+bool8 TakeCoins(u16 coins)
+{
+ if(GetCoins() >= coins)
+ {
+ gSaveBlock1.coins -= coins;
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
diff --git a/src/decompress.c b/src/decompress.c
new file mode 100644
index 000000000..adc6798b6
--- /dev/null
+++ b/src/decompress.c
@@ -0,0 +1,116 @@
+#include "global.h"
+#include "species.h"
+#include "sprite.h"
+
+#define WRAM 0x02000000
+
+extern struct SpriteSheet gMonFrontPicTable[];
+extern struct SpriteSheet gMonBackPicTable[];
+extern void *gUnknown_081FAF4C[];
+
+extern void DrawSpindaSpots(u16, u32, void *, u8);
+
+void sub_800D378(struct SpriteSheet *a, u32 b, u32 c, u32 d, void *e, s32 f, u32 g, u32 h);
+
+void sub_800D238(const void *src, void *dest)
+{
+ LZ77UnCompWram(src, dest);
+}
+
+void LZDecompressVram(const void *src, void *dest)
+{
+ LZ77UnCompVram(src, dest);
+}
+
+void LoadCompressedObjectPic(struct SpriteSheet *a)
+{
+ struct SpriteSheet spriteSheet;
+
+ LZ77UnCompWram(a->data, (void *)WRAM);
+ spriteSheet.data = (void *)WRAM;
+ spriteSheet.size = a->size;
+ spriteSheet.tag = a->tag;
+ LoadSpriteSheet(&spriteSheet);
+}
+
+void LoadCompressedObjectPicOverrideBuffer(struct SpriteSheet *a, void *buffer)
+{
+ struct SpriteSheet spriteSheet;
+
+ LZ77UnCompWram(a->data, buffer);
+ spriteSheet.data = buffer;
+ spriteSheet.size = a->size;
+ spriteSheet.tag = a->tag;
+ LoadSpriteSheet(&spriteSheet);
+}
+
+void LoadCompressedObjectPalette(struct SpritePalette *a)
+{
+ struct SpritePalette spritePalette;
+
+ LZ77UnCompWram(a->data, (void *)WRAM);
+ spritePalette.data = (void *)WRAM;
+ spritePalette.tag = a->tag;
+ LoadSpritePalette(&spritePalette);
+}
+
+void LoadCompressedObjectPaletteOverrideBuffer(struct SpritePalette *a, void *buffer)
+{
+ struct SpritePalette spritePalette;
+
+ LZ77UnCompWram(a->data, buffer);
+ spritePalette.data = buffer;
+ spritePalette.tag = a->tag;
+ LoadSpritePalette(&spritePalette);
+}
+
+void DecompressPicFromTable_2(const struct SpriteSheet *a, u8 b, u8 c, void *d, void *e, s32 f)
+{
+ if (f > 412)
+ LZ77UnCompWram(gMonFrontPicTable[0].data, e);
+ else
+ LZ77UnCompWram(a->data, e);
+}
+
+void sub_800D334(struct SpriteSheet *a, u32 b, u32 c, u32 d, void *dest, s32 f, u32 g)
+{
+ u32 unk;
+
+ if (dest == gUnknown_081FAF4C[0] || dest == gUnknown_081FAF4C[2])
+ unk = 0;
+ else
+ unk = 1;
+ sub_800D378(a, b, c, d, dest, f, g, unk);
+}
+
+void sub_800D378(struct SpriteSheet *a, u32 b, u32 c, u32 d, void *dest, s32 f, u32 g, u32 h)
+{
+ u8 r7 = h;
+
+ if (f == SPECIES_UNOWN)
+ {
+ u16 r1 = (((g & 0x3000000) >> 18) | ((g & 0x30000) >> 12) | ((g & 0x300) >> 6) | (g & 3)) % 0x1C;
+
+ if (r1 == 0)
+ r1 = SPECIES_UNOWN;
+ else
+ r1 += 412;
+ if (r7 == 0)
+ LZ77UnCompWram(gMonBackPicTable[r1].data, dest);
+ else
+ LZ77UnCompWram(gMonFrontPicTable[r1].data, dest);
+ }
+ else
+ {
+ if (f > 412)
+ LZ77UnCompWram(gMonFrontPicTable[0].data, dest);
+ else
+ LZ77UnCompWram(a->data, dest);
+ }
+ DrawSpindaSpots(f, g, dest, r7);
+}
+
+static void Unused_LZDecompressWramIndirect(const void **src, void *dest)
+{
+ LZ77UnCompWram(*src, dest);
+}
diff --git a/src/dewford_trend.c b/src/dewford_trend.c
new file mode 100644
index 000000000..8d683e072
--- /dev/null
+++ b/src/dewford_trend.c
@@ -0,0 +1,642 @@
+#include "global.h"
+#include "link.h"
+#include "rng.h"
+#include "flag.h"
+
+extern u8 GetLinkPlayerCount(void);
+extern u16 sub_80EB72C(u16);
+extern u8 ConvertEasyChatWordsToString(u8 *dst, u16 *words, u16, u16);
+
+extern struct EasyChatPair unk_2007800[5];
+extern struct EasyChatPair unk_2007900[5];
+extern u16 gScriptResult;
+extern u16 gSpecialVar_0x8004;
+
+void sub_80FA740(struct EasyChatPair *);
+void sub_80FA46C(struct EasyChatPair *, u16, u8);
+bool8 sub_80FA670(struct EasyChatPair *, struct EasyChatPair *, u8);
+bool8 IsEasyChatPairEqual(u16 *, u16 *);
+bool8 SB1ContainsWords(u16 *);
+
+void sub_80FA17C(void)
+{
+ u16 i;
+
+ for(i = 0; i < 5; i++)
+ {
+ gSaveBlock1.easyChatPairs[i].words[0] = sub_80EB72C(10);
+
+ if(Random() & 1)
+ gSaveBlock1.easyChatPairs[i].words[1] = sub_80EB72C(12);
+ else
+ gSaveBlock1.easyChatPairs[i].words[1] = sub_80EB72C(13);
+
+ gSaveBlock1.easyChatPairs[i].unk1_6 = Random() & 1;
+ sub_80FA740(&gSaveBlock1.easyChatPairs[i]);
+ }
+ sub_80FA46C(gSaveBlock1.easyChatPairs, 5, 0);
+}
+
+#ifdef NONMATCHING
+void sub_80FA220(u16 a)
+{
+ u16 i;
+ u32 sp0;
+ u32 sp4;
+
+ if(a != 0)
+ {
+ sp0 = a * 5;
+
+ for(i = 0; i < 5; i++)
+ {
+ //_080FA24A
+ u32 r2 = sp0;
+ u32 r4;
+
+ if(gSaveBlock1.easyChatPairs[i].unk1_6 == 0)
+ {
+ if(gSaveBlock1.easyChatPairs[i].unk0_0 >= r2)
+ {
+ gSaveBlock1.easyChatPairs[i].unk0_0 -= r2;
+ if(gSaveBlock1.easyChatPairs[i].unk0_0 == 0)
+ gSaveBlock1.easyChatPairs[i].unk1_6 = 1;
+ continue;
+ }
+ //_080FA290
+ r2 -= gSaveBlock1.easyChatPairs[i].unk0_0;
+ gSaveBlock1.easyChatPairs[i].unk1_6 = 1;
+ }
+ //_080FA2A0
+ r4 = gSaveBlock1.easyChatPairs[i].unk0_0 + r2;
+ if(r4 > gSaveBlock1.easyChatPairs[i].unk0_7)
+ {
+ sp4 = r4 % gSaveBlock1.easyChatPairs[i].unk0_7;
+ r4 = r4 / gSaveBlock1.easyChatPairs[i].unk0_7;
+
+ if(r4 == 0)
+ gSaveBlock1.easyChatPairs[i].unk1_6 = 1;
+ else
+ gSaveBlock1.easyChatPairs[i].unk1_6 = 0;
+
+
+ if(gSaveBlock1.easyChatPairs[i].unk1_6)
+ {
+ gSaveBlock1.easyChatPairs[i].unk0_0 += sp4;
+ continue;
+ }
+ //_080FA2FA
+ gSaveBlock1.easyChatPairs[i].unk0_7 -= sp4;
+ continue;
+ }
+ //_080FA310
+ gSaveBlock1.easyChatPairs[i].unk0_0 = r4;
+
+ if(gSaveBlock1.easyChatPairs[i].unk0_0 == gSaveBlock1.easyChatPairs[i].unk0_7)
+ gSaveBlock1.easyChatPairs[i].unk1_6 = 0;
+ }
+ sub_80FA46C(gSaveBlock1.easyChatPairs, 5, 0);
+ }
+ //_080FA34E
+}
+
+#else
+__attribute__((naked))
+void sub_80FA220(u16 a)
+{
+ asm(".syntax unified\n\
+ push {r4-r7,lr}\n\
+ mov r7, r10\n\
+ mov r6, r9\n\
+ mov r5, r8\n\
+ push {r5-r7}\n\
+ sub sp, 0x8\n\
+ lsls r0, 16\n\
+ lsrs r1, r0, 16\n\
+ cmp r1, 0\n\
+ bne _080FA236\n\
+ b _080FA34E\n\
+_080FA236:\n\
+ lsls r0, r1, 2\n\
+ adds r0, r1\n\
+ str r0, [sp]\n\
+ movs r0, 0\n\
+ mov r10, r0\n\
+ movs r1, 0x7F\n\
+ mov r9, r1\n\
+ movs r2, 0x80\n\
+ negs r2, r2\n\
+ mov r8, r2\n\
+_080FA24A:\n\
+ ldr r2, [sp]\n\
+ mov r4, r10\n\
+ lsls r0, r4, 3\n\
+ ldr r1, _080FA28C @ =gSaveBlock1 + 0x2DD4\n\
+ adds r5, r0, r1\n\
+ ldrb r6, [r5, 0x1]\n\
+ movs r0, 0x40\n\
+ ands r0, r6\n\
+ cmp r0, 0\n\
+ bne _080FA2A0\n\
+ ldrb r4, [r5]\n\
+ lsls r3, r4, 25\n\
+ lsrs r1, r3, 25\n\
+ lsls r0, r2, 16\n\
+ lsrs r0, 16\n\
+ cmp r1, r0\n\
+ bcc _080FA290\n\
+ adds r0, r1, 0\n\
+ subs r0, r2\n\
+ mov r2, r9\n\
+ ands r0, r2\n\
+ mov r1, r8\n\
+ ands r1, r4\n\
+ orrs r1, r0\n\
+ strb r1, [r5]\n\
+ movs r0, 0x7F\n\
+ ands r1, r0\n\
+ cmp r1, 0\n\
+ bne _080FA336\n\
+ movs r0, 0x40\n\
+ orrs r0, r6\n\
+ b _080FA334\n\
+ .align 2, 0\n\
+_080FA28C: .4byte gSaveBlock1 + 0x2DD4\n\
+_080FA290:\n\
+ lsrs r0, r3, 25\n\
+ subs r2, r0\n\
+ mov r0, r8\n\
+ ands r0, r4\n\
+ strb r0, [r5]\n\
+ movs r0, 0x40\n\
+ orrs r0, r6\n\
+ strb r0, [r5, 0x1]\n\
+_080FA2A0:\n\
+ ldrb r7, [r5]\n\
+ lsls r0, r7, 25\n\
+ lsrs r0, 25\n\
+ adds r4, r0, r2\n\
+ ldrh r0, [r5]\n\
+ lsls r6, r0, 18\n\
+ lsls r0, r4, 16\n\
+ lsrs r0, 16\n\
+ lsrs r1, r6, 25\n\
+ cmp r0, r1\n\
+ bls _080FA310\n\
+ adds r0, r4, 0\n\
+ bl __umodsi3\n\
+ adds r3, r0, 0\n\
+ lsrs r1, r6, 25\n\
+ adds r0, r4, 0\n\
+ str r3, [sp, 0x4]\n\
+ bl __udivsi3\n\
+ adds r4, r0, 0\n\
+ movs r0, 0x1\n\
+ eors r4, r0\n\
+ ands r4, r0\n\
+ lsls r2, r4, 6\n\
+ ldrb r0, [r5, 0x1]\n\
+ movs r4, 0x41\n\
+ negs r4, r4\n\
+ adds r1, r4, 0\n\
+ ands r0, r1\n\
+ orrs r0, r2\n\
+ strb r0, [r5, 0x1]\n\
+ movs r1, 0x40\n\
+ ands r0, r1\n\
+ ldr r3, [sp, 0x4]\n\
+ cmp r0, 0\n\
+ beq _080FA2FA\n\
+ adds r1, r3, 0\n\
+ mov r0, r9\n\
+ ands r1, r0\n\
+ mov r0, r8\n\
+ ands r0, r7\n\
+ orrs r0, r1\n\
+ strb r0, [r5]\n\
+ b _080FA336\n\
+_080FA2FA:\n\
+ ldrh r0, [r5]\n\
+ lsls r0, 18\n\
+ lsrs r0, 25\n\
+ subs r0, r3\n\
+ mov r1, r9\n\
+ ands r0, r1\n\
+ mov r1, r8\n\
+ ands r1, r7\n\
+ orrs r1, r0\n\
+ strb r1, [r5]\n\
+ b _080FA336\n\
+_080FA310:\n\
+ mov r2, r9\n\
+ ands r4, r2\n\
+ mov r0, r8\n\
+ ands r0, r7\n\
+ orrs r0, r4\n\
+ strb r0, [r5]\n\
+ lsls r0, 25\n\
+ ldrh r1, [r5]\n\
+ lsls r1, 18\n\
+ lsrs r0, 25\n\
+ lsrs r1, 25\n\
+ cmp r0, r1\n\
+ bne _080FA336\n\
+ ldrb r0, [r5, 0x1]\n\
+ movs r4, 0x41\n\
+ negs r4, r4\n\
+ adds r1, r4, 0\n\
+ ands r0, r1\n\
+_080FA334:\n\
+ strb r0, [r5, 0x1]\n\
+_080FA336:\n\
+ mov r0, r10\n\
+ adds r0, 0x1\n\
+ lsls r0, 16\n\
+ lsrs r0, 16\n\
+ mov r10, r0\n\
+ cmp r0, 0x4\n\
+ bls _080FA24A\n\
+ ldr r0, _080FA360 @ =gSaveBlock1 + 0x2DD4\n\
+ movs r1, 0x5\n\
+ movs r2, 0\n\
+ bl sub_80FA46C\n\
+_080FA34E:\n\
+ add sp, 0x8\n\
+ pop {r3-r5}\n\
+ mov r8, r3\n\
+ mov r9, r4\n\
+ mov r10, r5\n\
+ pop {r4-r7}\n\
+ pop {r0}\n\
+ bx r0\n\
+ .align 2, 0\n\
+_080FA360: .4byte gSaveBlock1 + 0x2DD4\n\
+ .syntax divided\n");
+}
+#endif
+
+bool8 sub_80FA364(u16 *a)
+{
+ struct EasyChatPair s = {0};
+ u16 i;
+
+ if(!SB1ContainsWords(a))
+ {
+ if(!FlagGet(SYS_POPWORD_INPUT))
+ {
+ FlagSet(SYS_POPWORD_INPUT);
+ if(!FlagGet(SYS_MIX_RECORD))
+ {
+ gSaveBlock1.easyChatPairs[0].words[0] = a[0];
+ gSaveBlock1.easyChatPairs[0].words[1] = a[1];
+ return 1;
+ }
+ }
+
+ //_080FA3C8
+ s.words[0] = a[0];
+ s.words[1] = a[1];
+ s.unk1_6 = 1;
+ sub_80FA740(&s);
+
+ for(i = 0; i < 5; i++)
+ {
+ if(sub_80FA670(&s, &gSaveBlock1.easyChatPairs[i], 0))
+ {
+ u16 r3 = 4;
+
+ while(r3 > i)
+ {
+ gSaveBlock1.easyChatPairs[r3] = gSaveBlock1.easyChatPairs[r3 - 1];
+ r3--;
+ }
+ gSaveBlock1.easyChatPairs[i] = s;
+ return (i == 0);
+ }
+ //_080FA450
+ }
+ gSaveBlock1.easyChatPairs[4] = s;
+ }
+ return 0;
+}
+
+void sub_80FA46C(struct EasyChatPair *s, u16 b, u8 c)
+{
+ u16 h;
+
+ for(h = 0; h < b; h++)
+ {
+ u16 i;
+
+ for(i = h + 1; i < b; i++)
+ {
+ if(sub_80FA670(&s[i], &s[h], c))
+ {
+ struct EasyChatPair temp;
+
+ temp = s[i];
+ s[i] = s[h];
+ s[h] = temp;
+ }
+ }
+ }
+}
+
+#ifdef NONMATCHING
+void sub_80FA4E4(u8 *a, u32 b)
+{
+ u16 i;
+ u16 j;
+ u16 r7;
+ struct EasyChatPair *src;
+ struct EasyChatPair *dst;
+ u16 players = GetLinkPlayerCount();
+
+ for(i = 0; i < players; i++)
+ memcpy(&unk_2007800[i * 5], a + i * b, 40);
+
+ //_080FA520
+
+ src = unk_2007800;
+ //dst = unk_2007900
+ dst = (u8 *)src + 0x100; //ToDo: Get this part to match
+
+ r7 = 0;
+ //_080FA530
+ for(i = 0; i < players; i++)
+ {
+ for(j = 0; j < 5; j++)
+ {
+ s16 foo = sub_80FA828(src, r7);
+ if(foo < 0)
+ {
+ *(dst++) = *src;
+ r7++;
+ }
+ //_080FA558
+ else
+ {
+ if(unk_2007900[foo].unk0_0 < src->unk0_0)
+ {
+ unk_2007900[foo] = *src;
+ }
+ }
+ //_080FA572
+ src++;
+ }
+ }
+ //_080FA588
+ sub_80FA46C(unk_2007900, r7, 2);
+ src = unk_2007900;
+ dst = gSaveBlock1.easyChatPairs;
+ for(i = 0; i < 5; i++)
+ *(dst++) = *(src++);
+}
+#else
+__attribute__((naked))
+void sub_80FA4E4(u8 *a, u32 b)
+{
+ asm(".syntax unified\n\
+ push {r4-r7,lr}\n\
+ mov r7, r8\n\
+ push {r7}\n\
+ sub sp, 0x4\n\
+ adds r6, r0, 0\n\
+ adds r5, r1, 0\n\
+ bl GetLinkPlayerCount\n\
+ lsls r0, 24\n\
+ lsrs r0, 24\n\
+ mov r8, r0\n\
+ movs r4, 0\n\
+ cmp r4, r8\n\
+ bcs _080FA520\n\
+_080FA500:\n\
+ lsls r0, r4, 2\n\
+ adds r0, r4\n\
+ lsls r0, 3\n\
+ ldr r1, _080FA554 @ =0x02007800\n\
+ adds r0, r1\n\
+ adds r1, r4, 0\n\
+ muls r1, r5\n\
+ adds r1, r6, r1\n\
+ movs r2, 0x28\n\
+ bl memcpy\n\
+ adds r0, r4, 0x1\n\
+ lsls r0, 16\n\
+ lsrs r4, r0, 16\n\
+ cmp r4, r8\n\
+ bcc _080FA500\n\
+_080FA520:\n\
+ ldr r5, _080FA554 @ =0x02007800\n\
+ movs r0, 0x80\n\
+ lsls r0, 1\n\
+ adds r3, r5, r0\n\
+ movs r7, 0\n\
+ movs r4, 0\n\
+ cmp r4, r8\n\
+ bcs _080FA588\n\
+_080FA530:\n\
+ movs r6, 0\n\
+_080FA532:\n\
+ adds r0, r5, 0\n\
+ adds r1, r7, 0\n\
+ str r3, [sp]\n\
+ bl sub_80FA828\n\
+ lsls r0, 16\n\
+ asrs r0, 16\n\
+ ldr r3, [sp]\n\
+ cmp r0, 0\n\
+ bge _080FA558\n\
+ ldr r0, [r5]\n\
+ ldr r1, [r5, 0x4]\n\
+ stm r3!, {r0,r1}\n\
+ adds r0, r7, 0x1\n\
+ lsls r0, 16\n\
+ lsrs r7, r0, 16\n\
+ b _080FA572\n\
+ .align 2, 0\n\
+_080FA554: .4byte 0x02007800\n\
+_080FA558:\n\
+ lsls r1, r0, 3\n\
+ ldr r0, _080FA5B4 @ =0x02007900\n\
+ adds r2, r1, r0\n\
+ ldrb r1, [r2]\n\
+ lsls r1, 25\n\
+ ldrb r0, [r5]\n\
+ lsls r0, 25\n\
+ cmp r1, r0\n\
+ bcs _080FA572\n\
+ ldr r0, [r5]\n\
+ ldr r1, [r5, 0x4]\n\
+ str r0, [r2]\n\
+ str r1, [r2, 0x4]\n\
+_080FA572:\n\
+ adds r5, 0x8\n\
+ adds r0, r6, 0x1\n\
+ lsls r0, 16\n\
+ lsrs r6, r0, 16\n\
+ cmp r6, 0x4\n\
+ bls _080FA532\n\
+ adds r0, r4, 0x1\n\
+ lsls r0, 16\n\
+ lsrs r4, r0, 16\n\
+ cmp r4, r8\n\
+ bcc _080FA530\n\
+_080FA588:\n\
+ ldr r4, _080FA5B4 @ =0x02007900\n\
+ adds r0, r4, 0\n\
+ adds r1, r7, 0\n\
+ movs r2, 0x2\n\
+ bl sub_80FA46C\n\
+ adds r5, r4, 0\n\
+ ldr r3, _080FA5B8 @ =gSaveBlock1 + 0x2DD4\n\
+ movs r4, 0\n\
+_080FA59A:\n\
+ ldm r5!, {r0,r1}\n\
+ stm r3!, {r0,r1}\n\
+ adds r0, r4, 0x1\n\
+ lsls r0, 16\n\
+ lsrs r4, r0, 16\n\
+ cmp r4, 0x4\n\
+ bls _080FA59A\n\
+ add sp, 0x4\n\
+ pop {r3}\n\
+ mov r8, r3\n\
+ pop {r4-r7}\n\
+ pop {r0}\n\
+ bx r0\n\
+ .align 2, 0\n\
+_080FA5B4: .4byte 0x02007900\n\
+_080FA5B8: .4byte gSaveBlock1 + 0x2DD4\n\
+ .syntax divided\n");
+}
+#endif
+
+void sub_80FA5BC(void)
+{
+ struct EasyChatPair *s = &gSaveBlock1.easyChatPairs[gSpecialVar_0x8004];
+
+ ConvertEasyChatWordsToString(gStringVar1, s->words, 2, 1);
+}
+
+void sub_80FA5E4(void)
+{
+ u16 result = 0;
+
+ if (gSaveBlock1.easyChatPairs[0].unk0_0 - gSaveBlock1.easyChatPairs[1].unk0_0 < 2)
+ {
+ asm("":::"r2"); //Force the compiler to store address of gSaveBlock1 in r3 instead of r2
+ if (!gSaveBlock1.easyChatPairs[0].unk1_6 && gSaveBlock1.easyChatPairs[1].unk1_6)
+ result = 1;
+ }
+ gScriptResult = result;
+}
+
+void sub_80FA648(void)
+{
+ gScriptResult = (gSaveBlock1.easyChatPairs[0].words[0] + gSaveBlock1.easyChatPairs[0].words[1]) & 7;
+}
+
+bool8 sub_80FA670(struct EasyChatPair *a, struct EasyChatPair *b, u8 c)
+{
+ switch(c)
+ {
+ case 0:
+ if(a->unk0_0 > b->unk0_0)
+ return 1;
+ if(a->unk0_0 < b->unk0_0)
+ return 0;
+ if(a->unk0_7 > b->unk0_7)
+ return 1;
+ if(a->unk0_7 < b->unk0_7)
+ return 0;
+ break;
+ case 1:
+ if(a->unk0_7 > b->unk0_7)
+ return 1;
+ if(a->unk0_7 < b->unk0_7)
+ return 0;
+ if(a->unk0_0 > b->unk0_0)
+ return 1;
+ if(a->unk0_0 < b->unk0_0)
+ return 0;
+ break;
+ case 2:
+ if(a->unk0_0 > b->unk0_0)
+ return 1;
+ if(a->unk0_0 < b->unk0_0)
+ return 0;
+ if(a->unk0_7 > b->unk0_7)
+ return 1;
+ if(a->unk0_7 < b->unk0_7)
+ return 0;
+ if(a->unk2 > b->unk2)
+ return 1;
+ if(a->unk2 < b->unk2)
+ return 0;
+ if(a->words[0] > b->words[0])
+ return 1;
+ if(a->words[0] < b->words[0])
+ return 0;
+ if(a->words[1] > b->words[1])
+ return 1;
+ if(a->words[1] < b->words[1])
+ return 0;
+ return 1;
+ }
+ return Random() & 1;
+}
+
+void sub_80FA740(struct EasyChatPair *s)
+{
+ u16 r4;
+
+ r4 = Random() % 98;
+ if(r4 > 50)
+ {
+ r4 = Random() % 98;
+ if(r4 > 80)
+ r4 = Random() % 98;
+ }
+ s->unk0_7 = r4 + 30;
+ s->unk0_0 = (Random() % (r4 + 1)) + 30;
+ s->unk2 = Random();
+}
+
+bool8 SB1ContainsWords(u16 *a)
+{
+ u16 i;
+
+ for(i = 0; i < 5; i++)
+ {
+ if(IsEasyChatPairEqual(a, gSaveBlock1.easyChatPairs[i].words) != 0)
+ return TRUE;
+ }
+ return FALSE;
+}
+
+bool8 IsEasyChatPairEqual(u16 *words1, u16 *words2)
+{
+ u16 i;
+
+ for(i = 0; i < 2; i++)
+ {
+ if(*(words1++) != *(words2++))
+ return FALSE;
+ }
+ return TRUE;
+}
+
+s16 sub_80FA828(struct EasyChatPair *a, u16 b)
+{
+ s16 i;
+ struct EasyChatPair *s = unk_2007900;
+
+ for(i = 0; i < b; i++)
+ {
+ if(IsEasyChatPairEqual(a->words, s->words))
+ return i;
+ s++;
+ }
+ return -1;
+}
diff --git a/src/diploma.c b/src/diploma.c
index 7e3a94514..4d81ad4b0 100644
--- a/src/diploma.c
+++ b/src/diploma.c
@@ -7,7 +7,6 @@
#include "task.h"
#include "text.h"
-extern void LZ77UnCompVram(const void *src, void *dest);
extern void remove_some_task(void);
extern void sub_80546F0(void);
extern u16 sub_8090FF4(void);
diff --git a/src/field_camera.c b/src/field_camera.c
new file mode 100644
index 000000000..02db33bf2
--- /dev/null
+++ b/src/field_camera.c
@@ -0,0 +1,516 @@
+#include "global.h"
+#include "fieldmap.h"
+#include "sprite.h"
+#include "text.h"
+
+extern u16 gBGTilemapBuffers[4][0x400];
+
+
+//ToDo: argument types
+extern u8 MapGridGetMetatileLayerTypeAt();
+extern u8 player_get_direction_upper_nybble(void);
+extern void ResetBerryTreeSparkleFlags(void);
+extern void RotatingGatePuzzleCameraUpdate(s16, s16);
+extern int MapGridGetMetatileIdAt(int, int);
+extern int CameraMove(int, int);
+
+extern u8 gUnknown_0202E854;
+
+
+struct UnknownStruct
+{
+ u8 unk0;
+ u8 unk1;
+ u8 unk2;
+ u8 unk3;
+ bool8 unk4;
+};
+
+extern struct UnknownStruct gUnknown_03000590;
+extern u16 gUnknown_03000598;
+extern s16 gUnknown_0300059A;
+extern u8 gUnknown_0300059C;
+extern void (*gUnknown_030005A0)(void);
+
+struct CameraSomething
+{
+ void (*callback)(struct CameraSomething *);
+ u32 unk4;
+ s32 unk8;
+ s32 unkC;
+ s32 unk10;
+ s32 unk14;
+};
+
+extern struct CameraSomething gUnknown_03004880;
+extern u16 gUnknown_03004898;
+extern u16 gUnknown_0300489C;
+
+static void RedrawMapSliceNorth(struct UnknownStruct *a, struct MapData *mapData);
+static void RedrawMapSliceSouth(struct UnknownStruct *a, struct MapData *mapData);
+static void RedrawMapSliceEast(struct UnknownStruct *a, struct MapData *mapData);
+static void RedrawMapSliceWest(struct UnknownStruct *a, struct MapData *mapData);
+static s32 MapPosToBgTilemapOffset(struct UnknownStruct *a, s32 x, s32 y);
+void CameraUpdate(void);
+
+static void DrawWholeMapViewInternal(int x, int y, struct MapData *mapData);
+static void DrawMetatileAt(struct MapData *mapData, u16, int, int);
+static void DrawMetatile(s32 a, u16 *b, u16 c);
+u8 AddCameraObject(u8);
+void UpdateFieldObjectsForCameraUpdate(s16, s16);
+static void CameraPanningCB_PanAhead(void);
+
+static void move_tilemap_camera_to_upper_left_corner_(struct UnknownStruct *a)
+{
+ a->unk2 = 0;
+ a->unk3 = 0;
+ a->unk0 = 0;
+ a->unk1 = 0;
+ a->unk4 = TRUE;
+}
+
+static void tilemap_move_something(struct UnknownStruct *a, u32 b, u32 c)
+{
+ a->unk2 += b;
+ a->unk2 %= 32;
+ a->unk3 += c;
+ a->unk3 %= 32;
+}
+
+static void coords8_add(struct UnknownStruct *a, u32 b, u32 c)
+{
+ a->unk0 += b;
+ a->unk1 += c;
+}
+
+void move_tilemap_camera_to_upper_left_corner(void)
+{
+ move_tilemap_camera_to_upper_left_corner_(&gUnknown_03000590);
+ CpuFill16(0, gBGTilemapBuffers[2], 0x800);
+ CpuFill16(0, gBGTilemapBuffers[1], 0x800);
+ CpuFill16(0x3014, gBGTilemapBuffers[3], 0x800);
+}
+
+void sub_8057A58(void)
+{
+ *gBGHOffsetRegs[1] = gUnknown_03000590.unk0 + gUnknown_03000598;
+ *gBGVOffsetRegs[1] = gUnknown_03000590.unk1 + gUnknown_0300059A + 8;
+ *gBGHOffsetRegs[2] = gUnknown_03000590.unk0 + gUnknown_03000598;
+ *gBGVOffsetRegs[2] = gUnknown_03000590.unk1 + gUnknown_0300059A + 8;
+ *gBGHOffsetRegs[3] = gUnknown_03000590.unk0 + gUnknown_03000598;
+ *gBGVOffsetRegs[3] = gUnknown_03000590.unk1 + gUnknown_0300059A + 8;
+
+ if(gUnknown_03000590.unk4)
+ {
+ DmaCopy16(3, gBGTilemapBuffers[1], (void *)(VRAM + 0xE800), 0x800);
+ DmaCopy16(3, gBGTilemapBuffers[2], (void *)(VRAM + 0xE000), 0x800);
+ DmaCopy16(3, gBGTilemapBuffers[3], (void *)(VRAM + 0xF000), 0x800);
+ gUnknown_03000590.unk4 = FALSE;
+ }
+}
+
+void sub_8057B14(u16 *a, u16 *b)
+{
+ *a = gUnknown_03000590.unk0 + gUnknown_03000598;
+ *b = gUnknown_03000590.unk1 + gUnknown_0300059A + 8;
+}
+
+void DrawWholeMapView(void)
+{
+ DrawWholeMapViewInternal(gSaveBlock1.pos.x, gSaveBlock1.pos.y, gMapHeader.mapData);
+ gUnknown_03000590.unk4 = TRUE;
+}
+
+static void DrawWholeMapViewInternal(int x, int y, struct MapData *mapData)
+{
+ u8 i;
+ u8 j;
+ u32 r6;
+ u8 temp;
+
+ for(i = 0; i < 32; i += 2)
+ {
+ temp = gUnknown_03000590.unk3 + i;
+ if(temp >= 32)
+ temp -= 32;
+ r6 = temp * 32;
+ for(j = 0; j < 32; j += 2)
+ {
+ temp = gUnknown_03000590.unk2 + j;
+ if(temp >= 32)
+ temp -= 32;
+ DrawMetatileAt(mapData, r6 + temp, x + j / 2, y + i / 2);
+ }
+ }
+}
+
+static void RedrawMapSlicesForCameraUpdate(struct UnknownStruct *a, int x, int y)
+{
+ struct MapData *mapData = gMapHeader.mapData;
+
+ if(x > 0)
+ RedrawMapSliceWest(a, mapData);
+ if(x < 0)
+ RedrawMapSliceEast(a, mapData);
+ if(y > 0)
+ RedrawMapSliceNorth(a, mapData);
+ if(y < 0)
+ RedrawMapSliceSouth(a, mapData);
+ a->unk4 = TRUE;
+}
+
+static void RedrawMapSliceNorth(struct UnknownStruct *a, struct MapData *mapData)
+{
+ u8 i;
+ u8 temp;
+ u32 r7;
+
+ temp = a->unk3 + 28;
+ if(temp >= 32)
+ temp -= 32;
+ r7 = temp * 32;
+ for(i = 0; i < 32; i += 2)
+ {
+ temp = a->unk2 + i;
+ if(temp >= 32)
+ temp -= 32;
+ DrawMetatileAt(mapData, r7 + temp, gSaveBlock1.pos.x + i / 2, gSaveBlock1.pos.y + 14);
+ }
+}
+
+static void RedrawMapSliceSouth(struct UnknownStruct *a, struct MapData *mapData)
+{
+ u8 i;
+ u8 temp;
+ u32 r7 = a->unk3 * 32;
+
+ for(i = 0; i < 32; i += 2)
+ {
+ temp = a->unk2 + i;
+ if(temp >= 32)
+ temp -= 32;
+ DrawMetatileAt(mapData, r7 + temp, gSaveBlock1.pos.x + i / 2, gSaveBlock1.pos.y);
+ }
+}
+
+static void RedrawMapSliceEast(struct UnknownStruct *a, struct MapData *mapData)
+{
+ u8 i;
+ u8 temp;
+ u32 r6 = a->unk2;
+
+ for(i = 0; i < 32; i += 2)
+ {
+ temp = a->unk3 + i;
+ if(temp >= 32)
+ temp -= 32;
+ DrawMetatileAt(mapData, temp * 32 + r6, gSaveBlock1.pos.x, gSaveBlock1.pos.y + i / 2);
+ }
+}
+
+static void RedrawMapSliceWest(struct UnknownStruct *a, struct MapData *mapData)
+{
+ u8 i;
+ u8 temp;
+ u8 r5 = a->unk2 + 28;
+
+ if(r5 >= 32)
+ r5 -= 32;
+ for(i = 0; i < 32; i += 2)
+ {
+ temp = a->unk3 + i;
+ if(temp >= 32)
+ temp -= 32;
+ DrawMetatileAt(mapData, temp * 32 + r5, gSaveBlock1.pos.x + 14, gSaveBlock1.pos.y + i / 2);
+ }
+}
+
+void CurrentMapDrawMetatileAt(int a, int b)
+{
+ int offset = MapPosToBgTilemapOffset(&gUnknown_03000590, a, b);
+
+ if(offset >= 0)
+ {
+ DrawMetatileAt(gMapHeader.mapData, offset, a, b);
+ gUnknown_03000590.unk4 = TRUE;
+ }
+}
+
+void DrawDoorMetatileAt(int x, int y, u16 *arr)
+{
+ int offset = MapPosToBgTilemapOffset(&gUnknown_03000590, x, y);
+
+ if(offset >= 0)
+ {
+ DrawMetatile(1, arr, offset);
+ gUnknown_03000590.unk4 = TRUE;
+ }
+}
+
+static void DrawMetatileAt(struct MapData *mapData, u16 b, int c, int d)
+{
+ u16 metatileId = MapGridGetMetatileIdAt(c, d);
+ u16 *metatiles;
+
+ if(metatileId > 1024)
+ metatileId = 0;
+ if(metatileId < 512)
+ metatiles = mapData->primaryTileset->metatiles;
+ else
+ {
+ metatiles = mapData->secondaryTileset->metatiles;
+ metatileId -= 512;
+ }
+ DrawMetatile(MapGridGetMetatileLayerTypeAt(c, d), metatiles + metatileId * 8, b);
+}
+
+static void DrawMetatile(s32 a, u16 *b, u16 c)
+{
+ switch(a)
+ {
+ case 2:
+ gBGTilemapBuffers[3][c] = b[0];
+ gBGTilemapBuffers[3][c + 1] = b[1];
+ gBGTilemapBuffers[3][c + 0x20] = b[2];
+ gBGTilemapBuffers[3][c + 0x21] = b[3];
+
+ gBGTilemapBuffers[2][c] = 0;
+ gBGTilemapBuffers[2][c + 1] = 0;
+ gBGTilemapBuffers[2][c + 0x20] = 0;
+ gBGTilemapBuffers[2][c + 0x21] = 0;
+
+ gBGTilemapBuffers[1][c] = b[4];
+ gBGTilemapBuffers[1][c + 1] = b[5];
+ gBGTilemapBuffers[1][c + 0x20] = b[6];
+ gBGTilemapBuffers[1][c + 0x21] = b[7];
+ break;
+ case 1:
+ gBGTilemapBuffers[3][c] = b[0];
+ gBGTilemapBuffers[3][c + 1] = b[1];
+ gBGTilemapBuffers[3][c + 0x20] = b[2];
+ gBGTilemapBuffers[3][c + 0x21] = b[3];
+
+ gBGTilemapBuffers[2][c] = b[4];
+ gBGTilemapBuffers[2][c + 1] = b[5];
+ gBGTilemapBuffers[2][c + 0x20] = b[6];
+ gBGTilemapBuffers[2][c + 0x21] = b[7];
+
+ gBGTilemapBuffers[1][c] = 0;
+ gBGTilemapBuffers[1][c + 1] = 0;
+ gBGTilemapBuffers[1][c + 0x20] = 0;
+ gBGTilemapBuffers[1][c + 0x21] = 0;
+ break;
+ case 0:
+ gBGTilemapBuffers[3][c] = 0x3014;
+ gBGTilemapBuffers[3][c + 1] = 0x3014;
+ gBGTilemapBuffers[3][c + 0x20] = 0x3014;
+ gBGTilemapBuffers[3][c + 0x21] = 0x3014;
+
+ gBGTilemapBuffers[2][c] = b[0];
+ gBGTilemapBuffers[2][c + 1] = b[1];
+ gBGTilemapBuffers[2][c + 0x20] = b[2];
+ gBGTilemapBuffers[2][c + 0x21] = b[3];
+
+ gBGTilemapBuffers[1][c] = b[4];
+ gBGTilemapBuffers[1][c + 1] = b[5];
+ gBGTilemapBuffers[1][c + 0x20] = b[6];
+ gBGTilemapBuffers[1][c + 0x21] = b[7];
+ break;
+ }
+}
+
+static s32 MapPosToBgTilemapOffset(struct UnknownStruct *a, s32 x, s32 y)
+{
+ x -= gSaveBlock1.pos.x;
+ x *= 2;
+ if(x >= 32 || x < 0)
+ return -1;
+ x = x + a->unk2;
+ if(x >= 32)
+ x -= 32;
+
+ y = (y - gSaveBlock1.pos.y) * 2;
+ if(y >= 32 || y < 0)
+ return -1;
+ y = y + a->unk3;
+ if(y >= 32)
+ y -= 32;
+
+ return y * 32 + x;
+}
+
+static void CameraUpdateCallback(struct CameraSomething *a)
+{
+ if(a->unk4 != 0)
+ {
+ a->unk8 = gSprites[a->unk4].data2;
+ a->unkC = gSprites[a->unk4].data3;
+ }
+}
+
+void ResetCameraUpdateInfo(void)
+{
+ gUnknown_03004880.unk8 = 0;
+ gUnknown_03004880.unkC = 0;
+ gUnknown_03004880.unk10 = 0;
+ gUnknown_03004880.unk14 = 0;
+ gUnknown_03004880.unk4 = 0;
+ gUnknown_03004880.callback = NULL;
+}
+
+u32 InitCameraUpdateCallback(u8 a)
+{
+ if(gUnknown_03004880.unk4 != 0)
+ DestroySprite(&gSprites[gUnknown_03004880.unk4]);
+ gUnknown_03004880.unk4 = AddCameraObject(a);
+ gUnknown_03004880.callback = CameraUpdateCallback;
+ return 0;
+}
+
+void CameraUpdate(void)
+{
+ int deltaX;
+ int deltaY;
+ int r0;
+ int r1;
+ int r7;
+ int r8;
+
+ if(gUnknown_03004880.callback != NULL)
+ gUnknown_03004880.callback(&gUnknown_03004880);
+ r7 = gUnknown_03004880.unk8;
+ r8 = gUnknown_03004880.unkC;
+ deltaX = 0;
+ deltaY = 0;
+ r1 = gUnknown_03004880.unk10;
+ r0 = gUnknown_03004880.unk14;
+
+
+ if(r1 == 0 && r7 != 0)
+ {
+ if(r7 > 0)
+ deltaX = 1;
+ else
+ deltaX = -1;
+ }
+ if(r0 == 0 && r8 != 0)
+ {
+ if(r8 > 0)
+ deltaY = 1;
+ else
+ deltaY = -1;
+ }
+ if(r1 != 0 && r1 == -r7)
+ {
+ if(r7 > 0)
+ deltaX = 1;
+ else
+ deltaX = -1;
+ }
+ if(r0 != 0 && r0 == -r8)
+ {
+ if(r8 > 0)
+ deltaX = 1;
+ else
+ deltaX = -1;
+ }
+
+ gUnknown_03004880.unk10 += r7;
+ gUnknown_03004880.unk10 = gUnknown_03004880.unk10 - 16 * (gUnknown_03004880.unk10 / 16);
+ gUnknown_03004880.unk14 += r8;
+ gUnknown_03004880.unk14 = gUnknown_03004880.unk14 - 16 * (gUnknown_03004880.unk14 / 16);
+
+ if(deltaX != 0 || deltaY != 0)
+ {
+ CameraMove(deltaX, deltaY);
+ UpdateFieldObjectsForCameraUpdate(deltaX, deltaY);
+ RotatingGatePuzzleCameraUpdate(deltaX, deltaY);
+ ResetBerryTreeSparkleFlags();
+ tilemap_move_something(&gUnknown_03000590, deltaX * 2, deltaY * 2);
+ RedrawMapSlicesForCameraUpdate(&gUnknown_03000590, deltaX * 2, deltaY * 2);
+ }
+
+ coords8_add(&gUnknown_03000590, r7, r8);
+ gUnknown_0300489C -= r7;
+ gUnknown_03004898 -= r8;
+}
+
+static void camera_move_and_redraw(int a, int b)
+{
+ CameraMove(a, b);
+ UpdateFieldObjectsForCameraUpdate(a, b);
+ DrawWholeMapView();
+ gUnknown_0300489C -= a * 16;
+ gUnknown_03004898 -= b * 16;
+}
+
+void SetCameraPanningCallback(void (*a)(void))
+{
+ gUnknown_030005A0 = a;
+}
+
+void SetCameraPanning(s16 a, s16 b)
+{
+ gUnknown_03000598 = a;
+ gUnknown_0300059A = b + 32;
+}
+
+void InstallCameraPanAheadCallback(void)
+{
+ gUnknown_030005A0 = CameraPanningCB_PanAhead;
+ gUnknown_0300059C = 0;
+ gUnknown_03000598 = 0;
+ gUnknown_0300059A = 32;
+}
+
+void UpdateCameraPanning(void)
+{
+ if (gUnknown_030005A0 != NULL)
+ gUnknown_030005A0();
+ //Update sprite offset of overworld objects
+ gSpriteCoordOffsetX = gUnknown_0300489C - gUnknown_03000598;
+ gSpriteCoordOffsetY = gUnknown_03004898 - gUnknown_0300059A - 8;
+}
+
+static void CameraPanningCB_PanAhead(void)
+{
+ u8 var;
+
+ if (gUnknown_0202E854 == 0)
+ {
+ InstallCameraPanAheadCallback();
+ }
+ else
+ {
+ if (gPlayerAvatar.running1 == 1)
+ {
+ gUnknown_0300059C ^= 1;
+ if (gUnknown_0300059C == 0)
+ return;
+ }
+ else
+ {
+ gUnknown_0300059C = 0;
+ }
+
+ var = player_get_direction_upper_nybble();
+ if (var == 2)
+ {
+ if (gUnknown_0300059A > -8)
+ gUnknown_0300059A -= 2;
+ }
+ else if (var == 1)
+ {
+ if (gUnknown_0300059A < 72)
+ gUnknown_0300059A += 2;
+ }
+ else if (gUnknown_0300059A < 32)
+ {
+ gUnknown_0300059A += 2;
+ }
+ else if (gUnknown_0300059A > 32)
+ {
+ gUnknown_0300059A -= 2;
+ }
+ }
+}
diff --git a/src/field_door.c b/src/field_door.c
new file mode 100644
index 000000000..68c884af1
--- /dev/null
+++ b/src/field_door.c
@@ -0,0 +1,233 @@
+#include "global.h"
+#include "task.h"
+
+extern u8 MetatileBehavior_IsDoor(u8);
+
+struct DoorGraphics
+{
+ u16 metatileNum;
+ u8 unk2;
+ void *tiles;
+ void *palette;
+};
+
+struct DoorAnimFrame
+{
+ u8 time;
+ u16 offset;
+};
+
+extern struct DoorAnimFrame gDoorOpenAnimFrames[];
+extern struct DoorAnimFrame gDoorCloseAnimFrames[];
+extern struct DoorGraphics gDoorAnimGraphicsTable[];
+
+static void CopyDoorTilesToVram(void *src)
+{
+ CpuFastSet(src, (void *)(VRAM + 0x7F00), 0x40);
+}
+
+static void door_build_blockdef(u16 *a, u16 b, u8 *c)
+{
+ int i;
+ u16 unk;
+
+ for (i = 0; i < 4; i++)
+ {
+ unk = *(c++) << 12;
+ a[i] = unk | (b + i);
+ }
+ for (; i < 8; i++)
+ {
+ unk = *(c++) << 12;
+ a[i] = unk;
+ }
+}
+
+static void DrawCurrentDoorAnimFrame(u32 x, u32 y, u8 *c)
+{
+ u16 arr[8];
+
+ door_build_blockdef(arr, 0x3F8, c);
+ DrawDoorMetatileAt(x, y - 1, arr);
+ door_build_blockdef(arr, 0x3FC, c + 4);
+ DrawDoorMetatileAt(x, y, arr);
+}
+
+static void DrawClosedDoorTiles(u32 x, u32 y)
+{
+ CurrentMapDrawMetatileAt(x, y - 1);
+ CurrentMapDrawMetatileAt(x, y);
+}
+
+static void DrawDoor(struct DoorGraphics *gfx, struct DoorAnimFrame *frame, u32 x, u32 y)
+{
+ if (frame->offset == 0xFFFF)
+ DrawClosedDoorTiles(x, y);
+ else
+ {
+ CopyDoorTilesToVram(gfx->tiles + frame->offset);
+ DrawCurrentDoorAnimFrame(x, y, gfx->palette);
+ }
+}
+
+enum
+{
+ TD_FRAMELIST = 0,
+ TD_GFX = 2,
+ TD_FRAME = 4,
+ TD_COUNTER,
+ TD_X,
+ TD_Y
+};
+
+static bool32 sub_8058464(struct DoorGraphics *gfx, struct DoorAnimFrame *frames, s16 *taskData)
+{
+ if (taskData[TD_COUNTER] == 0)
+ DrawDoor(gfx, &frames[taskData[TD_FRAME]], taskData[TD_X], taskData[TD_Y]);
+ if (taskData[TD_COUNTER] == frames[taskData[TD_FRAME]].time)
+ {
+ taskData[TD_COUNTER] = 0;
+ taskData[TD_FRAME]++;
+ if (frames[taskData[TD_FRAME]].time == 0)
+ return FALSE;
+ else
+ return TRUE;
+ }
+ taskData[TD_COUNTER]++;
+ return TRUE;
+}
+
+static void Task_AnimateDoor(u8 taskId)
+{
+ u16 *taskData = gTasks[taskId].data;
+ struct DoorAnimFrame *frames = (struct DoorAnimFrame *)(taskData[TD_FRAMELIST] << 16 | taskData[TD_FRAMELIST + 1]);
+ struct DoorGraphics *gfx = (struct DoorGraphics *)(taskData[TD_GFX] << 16 | taskData[TD_GFX + 1]);
+
+ if (sub_8058464(gfx, frames, taskData) == FALSE)
+ DestroyTask(taskId);
+}
+
+static struct DoorAnimFrame *GetLastDoorFrame(struct DoorAnimFrame *frame, void *unused)
+{
+ while (frame->time != 0)
+ frame++;
+ return frame - 1;
+}
+
+static struct DoorGraphics *GetDoorGraphics(struct DoorGraphics *gfx, u16 metatileNum)
+{
+ while (gfx->tiles != NULL)
+ {
+ if (gfx->metatileNum == metatileNum)
+ return gfx;
+ gfx++;
+ }
+ return NULL;
+}
+
+static s8 StartDoorAnimationTask(struct DoorGraphics *gfx, struct DoorAnimFrame *frames, u32 x, u32 y)
+{
+ if (FuncIsActiveTask(Task_AnimateDoor) == TRUE)
+ return -1;
+ else
+ {
+ u8 taskId = CreateTask(Task_AnimateDoor, 0x50);
+ s16 *taskData = gTasks[taskId].data;
+
+ taskData[TD_X] = x;
+ taskData[TD_Y] = y;
+
+ taskData[TD_FRAMELIST + 1] = (u32)frames;
+ taskData[TD_FRAMELIST] = (u32)frames >> 16;
+
+ taskData[TD_GFX + 1] = (u32)gfx;
+ taskData[TD_GFX] = (u32)gfx >> 16;
+
+ return taskId;
+ }
+}
+
+static void DrawClosedDoor(struct DoorGraphics *unused, u32 x, u32 y)
+{
+ DrawClosedDoorTiles(x, y);
+}
+
+static void DrawOpenedDoor(struct DoorGraphics *gfx, u32 x, u32 y)
+{
+ gfx = GetDoorGraphics(gfx, MapGridGetMetatileIdAt(x, y));
+ if (gfx != NULL)
+ DrawDoor(gfx, GetLastDoorFrame(gDoorOpenAnimFrames, gDoorOpenAnimFrames), x, y);
+}
+
+static s8 StartDoorOpenAnimation(struct DoorGraphics *gfx, u32 x, u32 y)
+{
+ gfx = GetDoorGraphics(gfx, MapGridGetMetatileIdAt(x, y));
+ if (gfx == NULL)
+ return -1;
+ else
+ return StartDoorAnimationTask(gfx, gDoorOpenAnimFrames, x, y);
+}
+
+static s8 StartDoorCloseAnimation(struct DoorGraphics *gfx, u32 x, u32 y)
+{
+ gfx = GetDoorGraphics(gfx, MapGridGetMetatileIdAt(x, y));
+ if (gfx == NULL)
+ return -1;
+ else
+ return StartDoorAnimationTask(gfx, gDoorCloseAnimFrames, x, y);
+}
+
+static s8 cur_mapdata_get_door_x2_at(struct DoorGraphics *gfx, u32 x, u32 y)
+{
+ gfx = GetDoorGraphics(gfx, MapGridGetMetatileIdAt(x, y));
+ if (gfx == NULL)
+ return -1;
+ else
+ return gfx->unk2;
+}
+
+static void unref_sub_805869C(u32 x, u32 y)
+{
+ StartDoorOpenAnimation(gDoorAnimGraphicsTable, x, y);
+}
+
+void FieldSetDoorOpened(u32 x, u32 y)
+{
+ if (MetatileBehavior_IsDoor(MapGridGetMetatileBehaviorAt(x, y)))
+ DrawOpenedDoor(gDoorAnimGraphicsTable, x, y);
+}
+
+void FieldSetDoorClosed(u32 x, u32 y)
+{
+ if (MetatileBehavior_IsDoor(MapGridGetMetatileBehaviorAt(x, y)))
+ DrawClosedDoor(gDoorAnimGraphicsTable, x, y);
+}
+
+s8 FieldAnimateDoorClose(u32 x, u32 y)
+{
+ if (!MetatileBehavior_IsDoor(MapGridGetMetatileBehaviorAt(x, y)))
+ return -1;
+ else
+ return StartDoorCloseAnimation(gDoorAnimGraphicsTable, x, y);
+}
+
+s8 FieldAnimateDoorOpen(u32 x, u32 y)
+{
+ if (!MetatileBehavior_IsDoor(MapGridGetMetatileBehaviorAt(x, y)))
+ return -1;
+ else
+ return StartDoorOpenAnimation(gDoorAnimGraphicsTable, x, y);
+}
+
+bool8 FieldIsDoorAnimationRunning(void)
+{
+ return FuncIsActiveTask(Task_AnimateDoor);
+}
+
+u8 sub_8058790(u32 x, u32 y)
+{
+ if (cur_mapdata_get_door_x2_at(gDoorAnimGraphicsTable, x, y) == 0)
+ return 8;
+ else
+ return 18;
+}
diff --git a/src/field_effect.c b/src/field_effect.c
new file mode 100644
index 000000000..97301ab50
--- /dev/null
+++ b/src/field_effect.c
@@ -0,0 +1,218 @@
+#include "global.h"
+#include "sprite.h"
+
+typedef bool8 (*FldEffCmd)(u8 **, u32 *);
+
+static u8 sActiveList[32];
+
+extern u8 *gFieldEffectScriptPointers[];
+
+extern FldEffCmd gFieldEffectScriptFuncs[];
+
+void FieldEffectScript_LoadTiles(u8 **script);
+void FieldEffectScript_LoadFadedPalette(u8 **script);
+void FieldEffectScript_LoadPalette(u8 **script);
+void FieldEffectScript_CallNative(u8 **script, u32 *val);
+void FieldEffectFreeGraphicsResources(struct Sprite *sprite);
+void FieldEffectStop(struct Sprite *sprite, u8 id);
+void FieldEffectFreeTilesIfUnused(u16 tileStart);
+void FieldEffectFreePaletteIfUnused(u8 paletteNum);
+void FieldEffectActiveListClear(void);
+void FieldEffectActiveListAdd(u8 id);
+void FieldEffectActiveListRemove(u8 id);
+
+u32 FieldEffectStart(u8 id)
+{
+ u8 *script;
+ u32 val;
+
+ FieldEffectActiveListAdd(id);
+
+ script = gFieldEffectScriptPointers[id];
+
+ while (gFieldEffectScriptFuncs[*script](&script, &val))
+ ;
+
+ return val;
+}
+
+bool8 FieldEffectCmd_loadtiles(u8 **script, u32 *val)
+{
+ (*script)++;
+ FieldEffectScript_LoadTiles(script);
+ return TRUE;
+}
+
+bool8 FieldEffectCmd_loadfadedpal(u8 **script, u32 *val)
+{
+ (*script)++;
+ FieldEffectScript_LoadFadedPalette(script);
+ return TRUE;
+}
+
+bool8 FieldEffectCmd_loadpal(u8 **script, u32 *val)
+{
+ (*script)++;
+ FieldEffectScript_LoadPalette(script);
+ return TRUE;
+}
+
+bool8 FieldEffectCmd_callnative(u8 **script, u32 *val)
+{
+ (*script)++;
+ FieldEffectScript_CallNative(script, val);
+ return TRUE;
+}
+
+bool8 FieldEffectCmd_end(u8 **script, u32 *val)
+{
+ return FALSE;
+}
+
+bool8 FieldEffectCmd_loadgfx_callnative(u8 **script, u32 *val)
+{
+ (*script)++;
+ FieldEffectScript_LoadTiles(script);
+ FieldEffectScript_LoadFadedPalette(script);
+ FieldEffectScript_CallNative(script, val);
+ return TRUE;
+}
+
+bool8 FieldEffectCmd_loadtiles_callnative(u8 **script, u32 *val)
+{
+ (*script)++;
+ FieldEffectScript_LoadTiles(script);
+ FieldEffectScript_CallNative(script, val);
+ return TRUE;
+}
+
+bool8 FieldEffectCmd_loadfadedpal_callnative(u8 **script, u32 *val)
+{
+ (*script)++;
+ FieldEffectScript_LoadFadedPalette(script);
+ FieldEffectScript_CallNative(script, val);
+ return TRUE;
+}
+
+u32 FieldEffectScript_ReadWord(u8 **script)
+{
+ return (*script)[0]
+ + ((*script)[1] << 8)
+ + ((*script)[2] << 16)
+ + ((*script)[3] << 24);
+}
+
+void FieldEffectScript_LoadTiles(u8 **script)
+{
+ struct SpriteSheet *sheet = (struct SpriteSheet *)FieldEffectScript_ReadWord(script);
+ if (GetSpriteTileStartByTag(sheet->tag) == 0xFFFF)
+ LoadSpriteSheet(sheet);
+ (*script) += 4;
+}
+
+void FieldEffectScript_LoadFadedPalette(u8 **script)
+{
+ struct SpritePalette *palette = (struct SpritePalette *)FieldEffectScript_ReadWord(script);
+ LoadSpritePalette(palette);
+ sub_807D78C(IndexOfSpritePaletteTag(palette->tag));
+ (*script) += 4;
+}
+
+void FieldEffectScript_LoadPalette(u8 **script)
+{
+ struct SpritePalette *palette = (struct SpritePalette *)FieldEffectScript_ReadWord(script);
+ LoadSpritePalette(palette);
+ (*script) += 4;
+}
+
+void FieldEffectScript_CallNative(u8 **script, u32 *val)
+{
+ u32 (*func)(void) = (u32 (*)(void))FieldEffectScript_ReadWord(script);
+ *val = func();
+ (*script) += 4;
+}
+
+void FieldEffectFreeGraphicsResources(struct Sprite *sprite)
+{
+ u16 sheetTileStart = sprite->sheetTileStart;
+ u32 paletteNum = sprite->oam.paletteNum;
+ DestroySprite(sprite);
+ FieldEffectFreeTilesIfUnused(sheetTileStart);
+ FieldEffectFreePaletteIfUnused(paletteNum);
+}
+
+void FieldEffectStop(struct Sprite *sprite, u8 id)
+{
+ FieldEffectFreeGraphicsResources(sprite);
+ FieldEffectActiveListRemove(id);
+}
+
+void FieldEffectFreeTilesIfUnused(u16 tileStart)
+{
+ u8 i;
+ u16 tag = GetSpriteTileTagByTileStart(tileStart);
+
+ if (tag != 0xFFFF)
+ {
+ for (i = 0; i < MAX_SPRITES; i++)
+ if (gSprites[i].inUse && gSprites[i].usingSheet && tileStart == gSprites[i].sheetTileStart)
+ return;
+ FreeSpriteTilesByTag(tag);
+ }
+}
+
+void FieldEffectFreePaletteIfUnused(u8 paletteNum)
+{
+ u8 i;
+ u16 tag = GetSpritePaletteTagByPaletteNum(paletteNum);
+
+ if (tag != 0xFFFF)
+ {
+ for (i = 0; i < MAX_SPRITES; i++)
+ if (gSprites[i].inUse && gSprites[i].oam.paletteNum == paletteNum)
+ return;
+ FreeSpritePaletteByTag(tag);
+ }
+}
+
+void FieldEffectActiveListClear(void)
+{
+ u8 i;
+ for (i = 0; i < ARRAY_COUNT(sActiveList); i++)
+ sActiveList[i] = 0xFF;
+}
+
+void FieldEffectActiveListAdd(u8 id)
+{
+ u8 i;
+ for (i = 0; i < ARRAY_COUNT(sActiveList); i++)
+ {
+ if (sActiveList[i] == 0xFF)
+ {
+ sActiveList[i] = id;
+ return;
+ }
+ }
+}
+
+void FieldEffectActiveListRemove(u8 id)
+{
+ u8 i;
+ for (i = 0; i < ARRAY_COUNT(sActiveList); i++)
+ {
+ if (sActiveList[i] == id)
+ {
+ sActiveList[i] = 0xFF;
+ return;
+ }
+ }
+}
+
+bool8 FieldEffectActiveListContains(u8 id)
+{
+ u8 i;
+ for (i = 0; i < ARRAY_COUNT(sActiveList); i++)
+ if (sActiveList[i] == id)
+ return TRUE;
+ return FALSE;
+}
diff --git a/src/field_player_avatar.c b/src/field_player_avatar.c
new file mode 100644
index 000000000..6719f6c3a
--- /dev/null
+++ b/src/field_player_avatar.c
@@ -0,0 +1,1685 @@
+#include "global.h"
+#include "fieldmap.h"
+#include "flag.h"
+#include "main.h"
+#include "menu.h"
+#include "rng.h"
+#include "script.h"
+#include "songs.h"
+#include "sound.h"
+#include "sprite.h"
+#include "task.h"
+
+struct UnknownStruct
+{
+ u8 unk0;
+ u8 unk1;
+ u8 unk2;
+ s16 unk4;
+ s16 unk6;
+ u8 unk8;
+ u8 unk9;
+ u8 unkA_0:4;
+ u8 unkA_4:4;
+ u16 unkC;
+ u16 unkE;
+ u32 unk10;
+ u16 unk14;
+};
+
+extern u8 SpawnSpecialFieldObject(struct UnknownStruct *);
+extern u8 sub_8126B54(void);
+extern bool8 FieldObjectIsSpecialAnimOrDirectionSequenceAnimActive(struct MapObject *);
+extern u8 FieldObjectClearAnimIfSpecialAnimFinished(struct MapObject *);
+extern u8 FieldObjectGetSpecialAnim(struct MapObject *);
+extern bool8 FieldObjectSetSpecialAnim(struct MapObject *, u8);
+extern void FieldObjectClearAnim(struct MapObject *);
+extern u8 sub_80E5DEC(u8);
+extern s16 sub_80E6034(void);
+extern u8 player_get_direction_upper_nybble(void);
+extern u8 player_get_direction_lower_nybble(void);
+extern u8 MapGridGetMetatileBehaviorAt(s32, s32);
+extern u32 FieldEffectStart(u8);
+extern void PlayerGetDestCoords(s16 *, s16 *);
+extern bool8 MetatileBehavior_IsSurfableFishableWater(u8);
+extern bool8 FieldObjectCheckIfSpecialAnimFinishedOrInactive(struct MapObject *);
+extern void sub_806451C(void);
+extern void sub_805B980(struct MapObject *, u8);
+extern void sub_8127ED0(u8, u8);
+extern bool8 player_should_look_direction_be_enforced_upon_movement(void);
+extern bool8 is_tile_x69_2_warp_door(u8);
+extern bool8 pokemon_has_move(struct Pokemon *, u8);
+extern u8 GetSimpleGoAnimId(u8);
+extern u8 GetStepInPlaceDelay16AnimId(u8);
+extern u8 sub_806084C(u8);
+extern u8 GetOppositeDirection(u8);
+extern u8 GetFaceDirectionAnimId(u8);
+extern u8 sub_80608D0(u8);
+extern bool8 GetFishingWildMonListHeader(void);
+extern void FishingWildEncounter(u8);
+extern u8 npc_block_way(struct MapObject *, s16, s16, u8);
+extern u8 GetFieldObjectIdByXY(s16, s16);
+extern u8 sub_8056F08(u8);
+extern u8 GetLedgeJumpDirection(s16, s16, u8);
+extern u8 GetFieldObjectIdByXYZ(u16, u16, int);
+extern u8 MapGridGetZCoordAt();
+extern u32 CheckForRotatingGatePuzzleCollision(u8, s16, s16);
+extern u8 sub_805FDF8(u8);
+extern void sub_80BE97C(u8);
+extern void sub_8127F28(u8, u8, s16);
+extern u8 sub_805FE08(u8);
+extern void sav1_reset_battle_music_maybe(void);
+extern void FieldObjectClearAnimIfSpecialAnimActive(struct MapObject *);
+extern u8 FieldObjectDirectionToImageAnimId(u8);
+extern u8 sub_805FD98(u8);
+extern u8 sub_805FDE8(u8);
+extern void sub_8053F84(void);
+extern u8 sub_80609D8(u8);
+extern u8 sub_8060A04(u8);
+extern u8 sub_8060A30(u8);
+extern u8 sub_8060A5C(u8);
+extern u8 sub_8060A88(u8);
+extern u8 sub_8060AB4(u8);
+extern u8 sub_8060878(u8);
+extern u8 sub_8060AE0(u8);
+extern u8 sub_8060B0C(u8);
+extern u8 sub_8060B38(u8);
+extern u8 sub_8060B64(u8);
+extern void MovePlayerOnBike(u8, u16, u16);
+extern void objid_set_invisible(u8);
+extern void FieldObjectTurn(struct MapObject *, u8);
+
+extern u8 gOtherText_OhABite[];
+extern u8 gOtherText_PokeOnHook[];
+extern u8 gOtherText_NotEvenANibble[];
+extern u8 gOtherText_ItGotAway[];
+
+extern struct
+{
+ s32 x;
+ s32 y;
+ u32 unk8;
+ u32 unkC;
+} gUnknown_0202FF84;
+
+extern bool8 (*gUnknown_0830FB58[])(u8);
+extern u8 (*gUnknown_0830FBA0[])(void);
+extern void (*gUnknown_0830FBEC[])(u8, u16);
+extern bool8 (*gUnknown_0830FBF8[])(u8);
+extern u8 gUnknown_0830FC0C[];
+extern void (*gUnknown_0830FC14[])(struct MapObject *);
+extern bool8 (*gUnknown_0830FC34[])(u8);
+extern u8 gUnknown_0830FC44[][2];
+extern u8 gUnknown_0830FC54[][2];
+extern u8 gUnknown_0830FC64[2][5][2];
+extern bool8 (*gUnknown_0830FC78[])(u8); //Duplicate of gUnknown_0830FC34
+extern u8 (*gUnknown_0830FC88[])(struct Task *, struct MapObject *, struct MapObject *);
+extern u8 (*gUnknown_0830FC94[])(struct Task *, struct MapObject *);
+extern u8 (*gUnknown_0830FC98[])(struct Task *, struct MapObject *);
+extern u8 gUnknown_0830FCA8[];
+extern u8 gUnknown_0830FCAC[];
+extern u8 (*gUnknown_0830FCB4[])(struct Task *);
+extern s16 gUnknown_0830FCF4[];
+extern s16 gUnknown_0830FCFA[];
+extern u8 gUnknown_0830FD00[];
+extern s16 gUnknown_0830FD02[];
+extern s16 gUnknown_0830FD08[];
+
+//Functions
+static u32 sub_80587D8(void);
+static bool8 sub_8058854(struct MapObject *, u8);
+static void npc_clear_strange_bits(struct MapObject *a);
+static void MovePlayerAvatarUsingKeypadInput(u8 a, u16 b, u16 c);
+static void PlayerAllowForcedMovementIfMovingSameDirection(void);
+static u8 TryDoMetatileBehaviorForcedMovement(void);
+static u8 GetForcedMovementByMetatileBehavior(void);
+static void MovePlayerNotOnBike(u8 a, u16 b);
+static u8 CheckMovementInputNotOnBike(u8 a);
+static u8 CheckForPlayerAvatarCollision(u8 a);
+u8 CheckForFieldObjectCollision(struct MapObject *a, s16 b, s16 c, u8 d, u8 e);
+static u8 sub_8058EF0(s16 a, s16 b, u8 c);
+static bool8 ShouldJumpLedge(s16 a, s16 b, u8 c);
+static u8 sub_8058F6C(s16 a, s16 b, u8 c);
+static void check_acro_bike_metatile(int unused1, int unused2, u8 c, u8 *d);
+static void DoPlayerAvatarTransition(void);
+static bool8 player_is_anim_in_certain_ranges(void);
+static bool8 sub_80592A4(void);
+static bool8 PlayerIsAnimActive(void);
+static bool8 PlayerCheckIfAnimFinishedOrInactive(void);
+void PlayerGoSpeed0(u8 a);
+void sub_80593C4(u8 a);
+void npc_use_some_d2s(u8 a);
+void sub_805940C(u8 a);
+static void PlayerNotOnBikeCollide(u8 a);
+void PlayerFaceDirection(u8 a);
+void PlayerTurnInPlace(u8 a);
+void PlayerJumpLedge(u8 a);
+static void PlayCollisionSoundIfNotFacingWarp(u8 a);
+u8 GetPlayerAvatarGraphicsIdByStateId(u8 a);
+void SetPlayerAvatarStateMask(u8 a);
+static void sub_8059D60(struct MapObject *a);
+static void StartStrengthAnim(u8 a, u8 b);
+static void sub_8059F94(void);
+static void sub_805A06C(void);
+void sub_805A20C(u8 a);
+
+void sub_80587B4(struct Sprite *sprite)
+{
+ meta_step(&gMapObjects[sprite->data0], sprite, sub_80587D8);
+}
+
+static u32 sub_80587D8(void)
+{
+ return 0;
+}
+
+void player_step(u8 a, u16 b, u16 c)
+{
+ struct MapObject *playerMapObj = &gMapObjects[gPlayerAvatar.mapObjectId];
+
+ sub_8059D60(playerMapObj);
+ if (gPlayerAvatar.unk6 == 0)
+ {
+ sub_80E5B38(b, c);
+ if (sub_8058854(playerMapObj, a) == 0)
+ {
+ npc_clear_strange_bits(playerMapObj);
+ DoPlayerAvatarTransition();
+ if (TryDoMetatileBehaviorForcedMovement() == 0)
+ {
+ MovePlayerAvatarUsingKeypadInput(a, b, c);
+ PlayerAllowForcedMovementIfMovingSameDirection();
+ }
+ }
+ }
+}
+
+static bool8 sub_8058854(struct MapObject *a, u8 b)
+{
+ if (FieldObjectIsSpecialAnimOrDirectionSequenceAnimActive(a)
+ && !FieldObjectClearAnimIfSpecialAnimFinished(a))
+ {
+ u8 specialAnim = FieldObjectGetSpecialAnim(a);
+
+ if (specialAnim > 24 && specialAnim < 29 && b != 0 && a->placeholder18 != b)
+ {
+ FieldObjectClearAnim(a);
+ return FALSE;
+ }
+ else
+ {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+static void npc_clear_strange_bits(struct MapObject *a)
+{
+ a->mapobj_bit_12 = 0;
+ a->mapobj_bit_10 = 0;
+ a->mapobj_bit_9 = 0;
+ gPlayerAvatar.flags &= ~PLAYER_AVATAR_FLAG_7;
+}
+
+static void MovePlayerAvatarUsingKeypadInput(u8 a, u16 b, u16 c)
+{
+ if ((gPlayerAvatar.flags & PLAYER_AVATAR_FLAG_1) || (gPlayerAvatar.flags & PLAYER_AVATAR_FLAG_2))
+ MovePlayerOnBike(a, b, c);
+ else
+ MovePlayerNotOnBike(a, c);
+}
+
+static void PlayerAllowForcedMovementIfMovingSameDirection(void)
+{
+ if (gPlayerAvatar.running2 == 2)
+ gPlayerAvatar.flags &= ~PLAYER_AVATAR_FLAG_5;
+}
+
+static u8 TryDoMetatileBehaviorForcedMovement(void)
+{
+ return gUnknown_0830FBA0[GetForcedMovementByMetatileBehavior()]();
+}
+
+static u8 GetForcedMovementByMetatileBehavior(void)
+{
+ u8 i;
+
+ if (!(gPlayerAvatar.flags & PLAYER_AVATAR_FLAG_5))
+ {
+ u8 r5 = gMapObjects[gPlayerAvatar.mapObjectId].mapobj_unk_1E;
+
+ for (i = 0; i < 18; i++)
+ {
+ if (gUnknown_0830FB58[i](r5))
+ return i + 1;
+ }
+ }
+ return 0;
+}
+
+u8 ForcedMovement_None(void)
+{
+ if (gPlayerAvatar.flags & PLAYER_AVATAR_FLAG_6)
+ {
+ struct MapObject *playerMapObj = &gMapObjects[gPlayerAvatar.mapObjectId];
+
+ playerMapObj->mapobj_bit_9 = 0;
+ playerMapObj->mapobj_bit_11 = 1;
+ FieldObjectSetDirection(playerMapObj, playerMapObj->mapobj_unk_18);
+ gPlayerAvatar.flags &= ~PLAYER_AVATAR_FLAG_6;
+ }
+ return 0;
+}
+
+static u8 DoForcedMovement(u8 a, void (*b)(u8))
+{
+ struct PlayerAvatar *playerAvatar = &gPlayerAvatar;
+ u8 r7 = CheckForPlayerAvatarCollision(a);
+
+ playerAvatar->flags |= PLAYER_AVATAR_FLAG_6;
+ if (r7 != 0)
+ {
+ ForcedMovement_None();
+ if (r7 <= 4)
+ {
+ return 0;
+ }
+ else
+ {
+ if (r7 == 6)
+ PlayerJumpLedge(a);
+ playerAvatar->flags |= PLAYER_AVATAR_FLAG_6;
+ playerAvatar->running2 = 2;
+ return 1;
+ }
+ }
+ else
+ {
+ playerAvatar->running2 = 2;
+ b(a);
+ return 1;
+ }
+}
+
+static u8 DoForcedMovementInCurrentDirection(void (*a)(u8))
+{
+ struct MapObject *playerMapObj = &gMapObjects[gPlayerAvatar.mapObjectId];
+
+ playerMapObj->mapobj_bit_10 = 1;
+ return DoForcedMovement(playerMapObj->placeholder18, a);
+}
+
+u8 ForcedMovement_Slip(void)
+{
+ return DoForcedMovementInCurrentDirection(sub_80593C4);
+}
+
+u8 sub_8058AAC(void)
+{
+ return DoForcedMovement(1, PlayerGoSpeed0);
+}
+
+u8 sub_8058AC4(void)
+{
+ return DoForcedMovement(2, PlayerGoSpeed0);
+}
+
+u8 sub_8058ADC(void)
+{
+ return DoForcedMovement(3, PlayerGoSpeed0);
+}
+
+u8 sub_8058AF4(void)
+{
+ return DoForcedMovement(4, PlayerGoSpeed0);
+}
+
+u8 sub_8058B0C(void)
+{
+ return DoForcedMovement(1, npc_use_some_d2s);
+}
+
+u8 sub_8058B24(void)
+{
+ return DoForcedMovement(2, npc_use_some_d2s);
+}
+
+u8 sub_8058B3C(void)
+{
+ return DoForcedMovement(3, npc_use_some_d2s);
+}
+
+u8 sub_8058B54(void)
+{
+ return DoForcedMovement(4, npc_use_some_d2s);
+}
+
+static u8 ForcedMovement_Slide(u8 a, void (*b)(u8))
+{
+ struct MapObject *playerMapObj = &gMapObjects[gPlayerAvatar.mapObjectId];
+
+ playerMapObj->mapobj_bit_10 = 1;
+ playerMapObj->mapobj_bit_9 = 1;
+ return DoForcedMovement(a, b);
+}
+
+u8 ForcedMovement_SlideSouth(void)
+{
+ return ForcedMovement_Slide(1, sub_80593C4);
+}
+
+u8 ForcedMovement_SlideNorth(void)
+{
+ return ForcedMovement_Slide(2, sub_80593C4);
+}
+
+u8 ForcedMovement_SlideWest(void)
+{
+ return ForcedMovement_Slide(3, sub_80593C4);
+}
+
+u8 ForcedMovement_SlideEast(void)
+{
+ return ForcedMovement_Slide(4, sub_80593C4);
+}
+
+u8 sub_8058C04(void)
+{
+ sub_8059F94();
+ return 1;
+}
+
+u8 sub_8058C10(void)
+{
+ sub_805A06C();
+ return 1;
+}
+
+u8 ForcedMovement_MuddySlope(void)
+{
+ struct MapObject *playerMapObj = &gMapObjects[gPlayerAvatar.mapObjectId];
+
+ if (playerMapObj->placeholder18 != 2 || sub_80E6034() <= 3)
+ {
+ sub_80E6010(0);
+ playerMapObj->mapobj_bit_9 = 1;
+ return DoForcedMovement(1, sub_80593C4);
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+static void MovePlayerNotOnBike(u8 a, u16 b)
+{
+ gUnknown_0830FBEC[CheckMovementInputNotOnBike(a)](a, b);
+}
+
+static u8 CheckMovementInputNotOnBike(u8 a)
+{
+ if (a == 0)
+ {
+ gPlayerAvatar.running2 = 0;
+ return 0;
+ }
+ else if (a != player_get_direction_upper_nybble() && gPlayerAvatar.running2 != 2)
+ {
+ gPlayerAvatar.running2 = 1;
+ return 1;
+ }
+ else
+ {
+ gPlayerAvatar.running2 = 2;
+ return 2;
+ }
+}
+
+void PlayerNotOnBikeNotMoving(u8 a, u16 b)
+{
+ PlayerFaceDirection(player_get_direction_lower_nybble());
+}
+
+void PlayerNotOnBikeTurningInPlace(u8 a, u16 b)
+{
+ PlayerTurnInPlace(a);
+}
+
+void sub_8058D0C(u8 a, u16 b)
+{
+ u8 r1 = CheckForPlayerAvatarCollision(a);
+
+ switch (r1)
+ {
+ case 6:
+ PlayerJumpLedge(a);
+ return;
+ default:
+ if (r1 > 8 || r1 < 5)
+ PlayerNotOnBikeCollide(a);
+ return;
+ case 0:
+ if (gPlayerAvatar.flags & PLAYER_AVATAR_FLAG_3)
+ {
+ sub_80593C4(a);
+ return;
+ }
+ if (!(gPlayerAvatar.flags & PLAYER_AVATAR_FLAG_4) && (b & 2) && FlagGet(0x860)
+ && sub_80E5DEC(gMapObjects[gPlayerAvatar.mapObjectId].mapobj_unk_1E) == 0)
+ {
+ sub_805940C(a);
+ gPlayerAvatar.flags |= PLAYER_AVATAR_FLAG_7;
+ }
+ else
+ {
+ PlayerGoSpeed0(a);
+ }
+ }
+}
+
+static u8 CheckForPlayerAvatarCollision(u8 a)
+{
+ s16 x, y;
+ struct MapObject *playerMapObj = &gMapObjects[gPlayerAvatar.mapObjectId];
+
+ x = playerMapObj->coords2.x;
+ y = playerMapObj->coords2.y;
+ MoveCoords(a, &x, &y);
+ return CheckForFieldObjectCollision(playerMapObj, x, y, a, MapGridGetMetatileBehaviorAt(x, y));
+}
+
+u8 CheckForFieldObjectCollision(struct MapObject *a, s16 b, s16 c, u8 d, u8 e)
+{
+ u8 sp0;
+
+ sp0 = npc_block_way(a, b, c, d);
+ if (sp0 == 3 && sub_8058EF0(b, c, d))
+ return 5;
+ if (ShouldJumpLedge(b, c, d))
+ {
+ sav12_xor_increment(0x2B);
+ return 6;
+ }
+ if (sp0 == 4 && sub_8058F6C(b, c, d))
+ return 7;
+
+ if (sp0 == 0)
+ {
+ if (CheckForRotatingGatePuzzleCollision(d, b, c))
+ return 8;
+ check_acro_bike_metatile(b, c, e, &sp0);
+ }
+ return sp0;
+}
+
+static u8 sub_8058EF0(s16 a, s16 b, u8 c)
+{
+ if ((gPlayerAvatar.flags & PLAYER_AVATAR_FLAG_3)
+ && MapGridGetZCoordAt(a, b) == 3
+ && GetFieldObjectIdByXYZ(a, b, 3) == 16)
+ {
+ sub_805A20C(c);
+ return 1;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+static bool8 ShouldJumpLedge(s16 a, s16 b, u8 c)
+{
+ if (GetLedgeJumpDirection(a, b, c) != 0)
+ return 1;
+ else
+ return 0;
+}
+
+static u8 sub_8058F6C(s16 a, s16 b, u8 c)
+{
+ if (FlagGet(0x829))
+ {
+ u8 mapObjectId = GetFieldObjectIdByXY(a, b);
+
+ if (mapObjectId != 16)
+ {
+ if (gMapObjects[mapObjectId].graphicsId == 0x57)
+ {
+ a = gMapObjects[mapObjectId].coords2.x;
+ b = gMapObjects[mapObjectId].coords2.y;
+ MoveCoords(c, &a, &b);
+ if (npc_block_way(&gMapObjects[mapObjectId], a, b, c) == 0
+ && sub_8056F08(MapGridGetMetatileBehaviorAt(a, b)) == 0)
+ {
+ StartStrengthAnim(mapObjectId, c);
+ return 1;
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+static void check_acro_bike_metatile(int unused1, int unused2, u8 c, u8 *d)
+{
+ u8 i;
+
+ for (i = 0; i < 5; i++)
+ {
+ if (gUnknown_0830FBF8[i](c))
+ {
+ *d = gUnknown_0830FC0C[i];
+ return;
+ }
+ }
+}
+
+void SetPlayerAvatarTransitionFlags(u16 a)
+{
+ gPlayerAvatar.bike |= a;
+ DoPlayerAvatarTransition();
+}
+
+static void DoPlayerAvatarTransition(void)
+{
+ u8 i;
+ u32 flags = gPlayerAvatar.bike;
+
+ if (flags != 0)
+ {
+ for (i = 0; i < 8; i++, flags >>= 1)
+ {
+#ifdef NONMATCHING
+ if (flags & 1)
+ {
+ gUnknown_0830FC14[i](&gMapObjects[gPlayerAvatar.mapObjectId]);
+ }
+#else
+ if (flags & 1)
+ {
+ register void (**funcs)(struct MapObject *) asm("r0") = gUnknown_0830FC14;
+ funcs[i](&gMapObjects[gPlayerAvatar.mapObjectId]);
+ }
+#endif
+ }
+ gPlayerAvatar.bike = 0;
+ }
+}
+
+void nullsub_49(struct MapObject *a)
+{
+}
+
+void PlayerAvatarTransition_Normal(struct MapObject *a)
+{
+ sub_805B980(a, GetPlayerAvatarGraphicsIdByStateId(0));
+ FieldObjectTurn(a, a->placeholder18);
+ SetPlayerAvatarStateMask(1);
+}
+
+void PlayerAvatarTransition_MachBike(struct MapObject *a)
+{
+ sub_805B980(a, GetPlayerAvatarGraphicsIdByStateId(1));
+ FieldObjectTurn(a, a->placeholder18);
+ SetPlayerAvatarStateMask(2);
+ sub_80E5FCC(0, 0);
+}
+
+void PlayerAvatarTransition_AcroBike(struct MapObject *a)
+{
+ sub_805B980(a, GetPlayerAvatarGraphicsIdByStateId(2));
+ FieldObjectTurn(a, a->placeholder18);
+ SetPlayerAvatarStateMask(4);
+ sub_80E5FCC(0, 0);
+ sub_80E6084();
+}
+
+void PlayerAvatarTransition_Surfing(struct MapObject *a)
+{
+ u8 unk;
+
+ sub_805B980(a, GetPlayerAvatarGraphicsIdByStateId(3));
+ FieldObjectTurn(a, a->placeholder18);
+ SetPlayerAvatarStateMask(8);
+ gUnknown_0202FF84.x = a->coords2.x;
+ gUnknown_0202FF84.y = a->coords2.y;
+ gUnknown_0202FF84.unk8 = gPlayerAvatar.mapObjectId;
+ unk = FieldEffectStart(8);
+ a->mapobj_unk_1A = unk;
+ sub_8127ED0(unk, 1);
+}
+
+void PlayerAvatarTransition_Underwater(struct MapObject *a)
+{
+ sub_805B980(a, GetPlayerAvatarGraphicsIdByStateId(4));
+ FieldObjectTurn(a, a->placeholder18);
+ SetPlayerAvatarStateMask(16);
+ a->mapobj_unk_1A = sub_8128124(a->spriteId);
+}
+
+void sub_80591F4(struct MapObject *a)
+{
+ gPlayerAvatar.flags |= PLAYER_AVATAR_FLAG_5;
+}
+
+void sub_8059204(void)
+{
+ gPlayerAvatar.running1 = 0;
+ if (PlayerIsAnimActive())
+ {
+ if (!PlayerCheckIfAnimFinishedOrInactive())
+ {
+ if (!player_is_anim_in_certain_ranges())
+ gPlayerAvatar.running1 = 1;
+ }
+ else
+ {
+ if (!sub_80592A4())
+ gPlayerAvatar.running1 = 2;
+ }
+ }
+}
+
+static bool8 player_is_anim_in_certain_ranges(void)
+{
+ u8 unk = gMapObjects[gPlayerAvatar.mapObjectId].mapobj_unk_1C;
+
+ if (unk < 4
+ || (unk >= 16 && unk < 0x15)
+ || (unk >= 25 && unk < 41)
+ || (unk >= 98 && unk < 110)
+ || (unk >= 122 && unk < 126))
+ return TRUE;
+ else
+ return FALSE;
+}
+
+static bool8 sub_80592A4(void)
+{
+ if (player_is_anim_in_certain_ranges() && gPlayerAvatar.running2 != 1)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+static bool8 PlayerIsAnimActive(void)
+{
+ return FieldObjectIsSpecialAnimOrDirectionSequenceAnimActive(&gMapObjects[gPlayerAvatar.mapObjectId]);
+}
+
+static bool8 PlayerCheckIfAnimFinishedOrInactive(void)
+{
+ return FieldObjectCheckIfSpecialAnimFinishedOrInactive(&gMapObjects[gPlayerAvatar.mapObjectId]);
+}
+
+static void player_set_x22(u8 a)
+{
+ gMapObjects[gPlayerAvatar.mapObjectId].mapobj_unk_22 = a;
+}
+
+u8 player_get_x22(void)
+{
+ return gMapObjects[gPlayerAvatar.mapObjectId].mapobj_unk_22;
+}
+
+static void sub_8059348(u8 a)
+{
+ FieldObjectForceSetSpecialAnim(&gMapObjects[gPlayerAvatar.mapObjectId], a);
+}
+
+void player_npc_set_state_and_x22_etc(u8 a, u8 b)
+{
+ if (!PlayerIsAnimActive())
+ {
+ player_set_x22(b);
+ FieldObjectSetSpecialAnim(&gMapObjects[gPlayerAvatar.mapObjectId], a);
+ }
+}
+
+void PlayerGoSpeed0(u8 a)
+{
+ player_npc_set_state_and_x22_etc(GetGoSpeed0AnimId(a), 2);
+}
+
+void sub_80593C4(u8 a)
+{
+ player_npc_set_state_and_x22_etc(sub_8060744(a), 2);
+}
+
+void npc_use_some_d2s(u8 a)
+{
+ player_npc_set_state_and_x22_etc(d2s_08064034(a), 2);
+}
+
+void sub_80593F4(u8 a)
+{
+ player_npc_set_state_and_x22_etc(sub_806079C(a), 2);
+}
+
+void sub_805940C(u8 a)
+{
+ player_npc_set_state_and_x22_etc(sub_80607F4(a), 2);
+}
+
+void PlayerOnBikeCollide(u8 a)
+{
+ PlayCollisionSoundIfNotFacingWarp(a);
+ player_npc_set_state_and_x22_etc(GetStepInPlaceDelay16AnimId(a), 2);
+}
+
+static void PlayerNotOnBikeCollide(u8 a)
+{
+ PlayCollisionSoundIfNotFacingWarp(a);
+ player_npc_set_state_and_x22_etc(GetStepInPlaceDelay32AnimId(a), 2);
+}
+
+void PlayerFaceDirection(u8 a)
+{
+ player_npc_set_state_and_x22_etc(GetFaceDirectionAnimId(a), 1);
+}
+
+void PlayerTurnInPlace(u8 a)
+{
+ player_npc_set_state_and_x22_etc(GetStepInPlaceDelay8AnimId(a), 1);
+}
+
+void PlayerJumpLedge(u8 a)
+{
+ PlaySE(SE_DANSA);
+ player_npc_set_state_and_x22_etc(GetJumpLedgeAnimId(a), 8);
+}
+
+void sub_80594C0(void)
+{
+ if (gPlayerAvatar.running1 == 2 || gPlayerAvatar.running1 == 0)
+ {
+ if (player_should_look_direction_be_enforced_upon_movement())
+ sub_8059348(GetFaceDirectionAnimId(gMapObjects[gPlayerAvatar.mapObjectId].mapobj_unk_18));
+ }
+}
+
+void sub_8059504(u8 a)
+{
+ player_npc_set_state_and_x22_etc(sub_80609D8(a), 1);
+}
+
+void sub_805951C(u8 a)
+{
+ player_npc_set_state_and_x22_etc(sub_8060A04(a), 1);
+}
+
+void sub_8059534(u8 a)
+{
+ player_npc_set_state_and_x22_etc(sub_8060A30(a), 1);
+}
+
+void sub_805954C(u8 a)
+{
+ PlaySE(SE_JITE_PYOKO);
+ player_npc_set_state_and_x22_etc(sub_8060A5C(a), 1);
+}
+
+void sub_8059570(u8 a)
+{
+ PlaySE(SE_JITE_PYOKO);
+ player_npc_set_state_and_x22_etc(sub_8060A88(a), 2);
+}
+
+void sub_8059594(u8 a)
+{
+ PlaySE(SE_JITE_PYOKO);
+ player_npc_set_state_and_x22_etc(sub_8060AB4(a), 8);
+}
+
+void sub_80595B8(u8 a)
+{
+ PlaySE(SE_JITE_PYOKO);
+ player_npc_set_state_and_x22_etc(sub_8060878(a), 1);
+}
+
+void sub_80595DC(u8 a)
+{
+ PlaySE(SE_WALL_HIT);
+ player_npc_set_state_and_x22_etc(sub_8060AE0(a), 2);
+}
+
+void sub_8059600(u8 a)
+{
+ player_npc_set_state_and_x22_etc(sub_8060B0C(a), 2);
+}
+
+void sub_8059618(u8 a)
+{
+ player_npc_set_state_and_x22_etc(sub_8060B38(a), 2);
+}
+
+void sub_8059630(u8 a)
+{
+ player_npc_set_state_and_x22_etc(sub_8060B64(a), 2);
+}
+
+static void PlayCollisionSoundIfNotFacingWarp(u8 a)
+{
+ s16 x, y;
+ u8 unk = gMapObjects[gPlayerAvatar.mapObjectId].mapobj_unk_1E;
+
+ if (!gUnknown_0830FC34[a - 1](unk))
+ {
+ if (a == 2)
+ {
+ PlayerGetDestCoords(&x, &y);
+ MoveCoords(2, &x, &y);
+ if (is_tile_x69_2_warp_door(MapGridGetMetatileBehaviorAt(x, y)))
+ return;
+ }
+ PlaySE(SE_WALL_HIT);
+ }
+}
+
+void GetXYCoordsOneStepInFrontOfPlayer(s16 *x, s16 *y)
+{
+ *x = gMapObjects[gPlayerAvatar.mapObjectId].coords2.x;
+ *y = gMapObjects[gPlayerAvatar.mapObjectId].coords2.y;
+ MoveCoords(player_get_direction_lower_nybble(), x, y);
+}
+
+void PlayerGetDestCoords(s16 *x, s16 *y)
+{
+ *x = gMapObjects[gPlayerAvatar.mapObjectId].coords2.x;
+ *y = gMapObjects[gPlayerAvatar.mapObjectId].coords2.y;
+}
+
+u8 player_get_direction_lower_nybble(void)
+{
+ return gMapObjects[gPlayerAvatar.mapObjectId].mapobj_unk_18;
+}
+
+u8 player_get_direction_upper_nybble(void)
+{
+ return gMapObjects[gPlayerAvatar.mapObjectId].placeholder18;
+}
+
+u8 PlayerGetZCoord(void)
+{
+ return gMapObjects[gPlayerAvatar.mapObjectId].elevation;
+}
+
+static void unref_sub_8059790(s16 a, s16 b)
+{
+ sub_805C058(&gMapObjects[gPlayerAvatar.mapObjectId], a, b);
+}
+
+u8 TestPlayerAvatarFlags(u8 a)
+{
+ return gPlayerAvatar.flags & a;
+}
+
+u8 sub_80597D0(void)
+{
+ return gPlayerAvatar.flags;
+}
+
+u8 GetPlayerAvatarObjectId(void)
+{
+ return gPlayerAvatar.spriteId;
+}
+
+void sub_80597E8(void)
+{
+ ForcedMovement_None();
+}
+
+void sub_80597F4(void)
+{
+ struct MapObject *playerMapObj = &gMapObjects[gPlayerAvatar.mapObjectId];
+
+ npc_clear_strange_bits(playerMapObj);
+ FieldObjectSetDirection(playerMapObj, playerMapObj->mapobj_unk_18);
+ if (TestPlayerAvatarFlags(6))
+ {
+ sub_80E6084();
+ sub_80E6010(0);
+ }
+}
+
+u8 sub_805983C(u8 a, u8 b)
+{
+ return gUnknown_0830FC44[a][b];
+}
+
+static u8 GetPlayerAvatarGraphicsIdByStateIdAndGender(u8 a, u8 b)
+{
+ return gUnknown_0830FC54[a][b];
+}
+
+u8 GetPlayerAvatarGraphicsIdByStateId(u8 a)
+{
+ return GetPlayerAvatarGraphicsIdByStateIdAndGender(a, gPlayerAvatar.gender);
+}
+
+static u8 unref_sub_8059888(u8 a)
+{
+ switch (a)
+ {
+ case 0x69:
+ case 0x6A:
+ case 0x6B:
+ case 0x6C:
+ case 0x6D:
+ case 0x70:
+ case 0x8A:
+ case 0xC0:
+ return FEMALE;
+ default:
+ return MALE;
+ }
+}
+
+u8 GetPlayerAvatarGenderByGraphicsId(u8 a)
+{
+ switch (a)
+ {
+ case 0x59:
+ case 0x5A:
+ case 0x5B:
+ case 0x5C:
+ case 0x5D:
+ case 0x70:
+ case 0x8A:
+ case 0xC0:
+ return FEMALE;
+ default:
+ return MALE;
+ }
+}
+
+bool8 PartyHasMonWithSurf(void)
+{
+ u8 i;
+
+ if (!TestPlayerAvatarFlags(8))
+ {
+ for (i = 0; i < 6; i++)
+ {
+ if (GetMonData(&gPlayerParty[i], MON_DATA_SPECIES) == 0)
+ break;
+ if (pokemon_has_move(&gPlayerParty[i], 0x39))
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+bool8 IsPlayerSurfingNorth(void)
+{
+ if (player_get_direction_upper_nybble() == 2 && TestPlayerAvatarFlags(8))
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 IsPlayerFacingSurfableFishableWater(void)
+{
+ struct MapObject *playerMapObj = &gMapObjects[gPlayerAvatar.mapObjectId];
+ s16 x = playerMapObj->coords2.x;
+ s16 y = playerMapObj->coords2.y;
+
+ MoveCoords(playerMapObj->mapobj_unk_18, &x, &y);
+ if (npc_block_way(playerMapObj, x, y, playerMapObj->mapobj_unk_18) == 3 && PlayerGetZCoord() == 3
+ && MetatileBehavior_IsSurfableFishableWater(MapGridGetMetatileBehaviorAt(x, y)))
+ return TRUE;
+ else
+ return FALSE;
+}
+
+void ClearPlayerAvatarInfo(void)
+{
+ //TODO: 0x24 should be the size of gPlayerAvatar
+ memset(&gPlayerAvatar, 0, 0x24);
+}
+
+void SetPlayerAvatarStateMask(u8 a)
+{
+ gPlayerAvatar.flags &= 0xE0;
+ gPlayerAvatar.flags |= a;
+}
+
+static u8 GetPlayerAvatarStateTransitionByGraphicsId(u8 a, u8 gender)
+{
+ u8 i;
+
+ for (i = 0; i < 5; i++)
+ {
+ if (gUnknown_0830FC64[gender][i][0] == a)
+ return gUnknown_0830FC64[gender][i][1];
+ }
+ return 1;
+}
+
+u8 GetPlayerAvatarGraphicsIdByCurrentState(void)
+{
+ u8 i;
+ u8 r5 = gPlayerAvatar.flags;
+
+ for (i = 0; i < 5; i++)
+ {
+ if (gUnknown_0830FC64[gPlayerAvatar.gender][i][1] & r5)
+ return gUnknown_0830FC64[gPlayerAvatar.gender][i][0];
+ }
+ return 0;
+}
+
+void SetPlayerAvatarExtraStateTransition(u8 a, u8 b)
+{
+ u8 unk = GetPlayerAvatarStateTransitionByGraphicsId(a, gPlayerAvatar.gender);
+
+ gPlayerAvatar.bike |= unk | b;
+ DoPlayerAvatarTransition();
+}
+
+void InitPlayerAvatar(s16 a, s16 b, u8 c, u8 d)
+{
+ struct UnknownStruct s;
+ u8 mapObjectId;
+ struct MapObject *mapObject;
+
+ s.unk0 = 0xFF;
+ s.unk1 = GetPlayerAvatarGraphicsIdByStateIdAndGender(0, d);
+ s.unk4 = a - 7;
+ s.unk6 = b - 7;
+ s.unk8 = 0;
+ s.unk9 = 11;
+ s.unkA_0 = 0;
+ s.unkA_4 = 0;
+ s.unkC = 0;
+ s.unkE = 0;
+ s.unk10 = 0;
+ s.unk14 = 0;
+ mapObjectId = SpawnSpecialFieldObject(&s);
+ mapObject = &gMapObjects[mapObjectId];
+ mapObject->mapobj_bit_16 = 1;
+ mapObject->mapobj_unk_1B = sub_8126B54();
+ FieldObjectTurn(mapObject, c);
+ ClearPlayerAvatarInfo();
+ gPlayerAvatar.running2 = 0;
+ gPlayerAvatar.running1 = 0;
+ gPlayerAvatar.mapObjectId = mapObjectId;
+ gPlayerAvatar.spriteId = mapObject->spriteId;
+ gPlayerAvatar.gender = d;
+ SetPlayerAvatarStateMask(0x21);
+}
+
+void sub_8059B88(u8 a)
+{
+ gMapObjects[gPlayerAvatar.mapObjectId].mapobj_bit_13 = a;
+ if (TestPlayerAvatarFlags(8))
+ gSprites[gMapObjects[gPlayerAvatar.mapObjectId].mapobj_unk_1A].invisible = a;
+}
+
+void sub_8059BF4(void)
+{
+ sub_805B980(&gMapObjects[gPlayerAvatar.mapObjectId], GetPlayerAvatarGraphicsIdByStateId(5));
+ StartSpriteAnim(&gSprites[gPlayerAvatar.spriteId], 0);
+}
+
+void sub_8059C3C(u8 a)
+{
+ sub_805B980(&gMapObjects[gPlayerAvatar.mapObjectId], GetPlayerAvatarGraphicsIdByStateId(6));
+ StartSpriteAnim(&gSprites[gPlayerAvatar.spriteId], sub_805FDE8(a));
+}
+
+void sub_8059C94(u8 a)
+{
+ sub_805B980(&gMapObjects[gPlayerAvatar.mapObjectId], GetPlayerAvatarGraphicsIdByStateId(2));
+ StartSpriteAnim(&gSprites[gPlayerAvatar.spriteId], sub_805FD98(a));
+ SeekSpriteAnim(&gSprites[gPlayerAvatar.spriteId], 1);
+}
+
+void sub_8059D08(u8 a)
+{
+ sub_805B980(&gMapObjects[gPlayerAvatar.mapObjectId], GetPlayerAvatarGraphicsIdByStateId(7));
+ StartSpriteAnim(&gSprites[gPlayerAvatar.spriteId], FieldObjectDirectionToImageAnimId(a));
+}
+
+static void sub_8059D60(struct MapObject *a)
+{
+ s16 x;
+ s16 y;
+ u8 r6;
+ u8 r8 = a->mapobj_unk_1E;
+
+ for (x = 0, r6 = 1; x < 4; x++, r6++)
+ {
+ if (gUnknown_0830FC78[x](r8) && r6 == a->placeholder18)
+ {
+ x = a->coords2.x;
+ y = a->coords2.y;
+ MoveCoords(r6, &x, &y);
+ sub_8126BC4(a->mapobj_unk_1B, r6, x, y);
+ return;
+ }
+ }
+ objid_set_invisible(a->mapobj_unk_1B);
+}
+
+/* Strength */
+
+static void sub_8059E2C(u8 taskId);
+
+static void StartStrengthAnim(u8 a, u8 b)
+{
+ u8 taskId = CreateTask(sub_8059E2C, 0xFF);
+
+ gTasks[taskId].data[1] = a;
+ gTasks[taskId].data[2] = b;
+ sub_8059E2C(taskId);
+}
+
+static void sub_8059E2C(u8 taskId)
+{
+ while (gUnknown_0830FC88[gTasks[taskId].data[0]](&gTasks[taskId],
+ &gMapObjects[gPlayerAvatar.mapObjectId],
+ &gMapObjects[gTasks[taskId].data[1]]))
+ ;
+}
+
+u8 sub_8059E84(struct Task *task, struct MapObject *b, struct MapObject *c)
+{
+ ScriptContext2_Enable();
+ gPlayerAvatar.unk6 = 1;
+ task->data[0]++;
+ return 0;
+}
+
+u8 sub_8059EA4(struct Task *task, struct MapObject *b, struct MapObject *c)
+{
+ if (!FieldObjectIsSpecialAnimOrDirectionSequenceAnimActive(b)
+ && !FieldObjectIsSpecialAnimOrDirectionSequenceAnimActive(c))
+ {
+ FieldObjectClearAnimIfSpecialAnimFinished(b);
+ FieldObjectClearAnimIfSpecialAnimFinished(c);
+ FieldObjectSetSpecialAnim(b, GetStepInPlaceDelay16AnimId(task->data[2]));
+ FieldObjectSetSpecialAnim(c, GetSimpleGoAnimId(task->data[2]));
+ gUnknown_0202FF84.x = c->coords2.x;
+ gUnknown_0202FF84.y = c->coords2.y;
+ gUnknown_0202FF84.unk8 = c->elevation;
+ gUnknown_0202FF84.unkC = gSprites[c->spriteId].oam.priority;
+ FieldEffectStart(10);
+ PlaySE(SE_W070);
+ task->data[0]++;
+ }
+ return 0;
+}
+
+u8 sub_8059F40(struct Task *task, struct MapObject *b, struct MapObject *c)
+{
+ if (FieldObjectCheckIfSpecialAnimFinishedOrInactive(b)
+ && FieldObjectCheckIfSpecialAnimFinishedOrInactive(c))
+ {
+ FieldObjectClearAnimIfSpecialAnimFinished(b);
+ FieldObjectClearAnimIfSpecialAnimFinished(c);
+ gPlayerAvatar.unk6 = 0;
+ ScriptContext2_Disable();
+ DestroyTask(FindTaskIdByFunc(sub_8059E2C));
+ }
+ return 0;
+}
+
+/* Some field effect */
+
+static void sub_8059FB4(u8 taskId);
+
+static void sub_8059F94(void)
+{
+ u8 taskId = CreateTask(sub_8059FB4, 0xFF);
+
+ sub_8059FB4(taskId);
+}
+
+static void sub_8059FB4(u8 taskId)
+{
+ while (gUnknown_0830FC94[gTasks[taskId].data[0]](&gTasks[taskId], &gMapObjects[gPlayerAvatar.mapObjectId]))
+ ;
+}
+
+u8 sub_805A000(struct Task *task, struct MapObject *mapObject)
+{
+ gPlayerAvatar.unk6 = 1;
+ if (FieldObjectClearAnimIfSpecialAnimFinished(mapObject))
+ {
+ PlaySE(SE_DANSA);
+ FieldObjectSetSpecialAnim(mapObject, sub_806084C(mapObject->mapobj_unk_18));
+ task->data[1]++;
+ if (task->data[1] > 1)
+ {
+ gPlayerAvatar.unk6 = 0;
+ gPlayerAvatar.bike |= 0x20;
+ DestroyTask(FindTaskIdByFunc(sub_8059FB4));
+ }
+ }
+ return 0;
+}
+
+/* Some field effect */
+
+static void sub_805A08C(u8 taskId);
+
+static void sub_805A06C(void)
+{
+ u8 taskId = CreateTask(sub_805A08C, 0xFF);
+
+ sub_805A08C(taskId);
+}
+
+static void sub_805A08C(u8 taskId)
+{
+ while (gUnknown_0830FC98[gTasks[taskId].data[0]](&gTasks[taskId], &gMapObjects[gPlayerAvatar.mapObjectId]))
+ ;
+}
+
+u8 sub_805A0D8(struct Task *task, struct MapObject *mapObject)
+{
+ task->data[0]++;
+ task->data[1] = mapObject->placeholder18;
+ gPlayerAvatar.unk6 = 1;
+ ScriptContext2_Enable();
+ PlaySE(SE_TK_WARPIN);
+ return 1;
+}
+
+u8 sub_805A100(struct Task *task, struct MapObject *mapObject)
+{
+ u8 directions[4];
+
+ memcpy(directions, gUnknown_0830FCA8, sizeof(directions));
+ if (FieldObjectClearAnimIfSpecialAnimFinished(mapObject))
+ {
+ u8 direction;
+
+ FieldObjectSetSpecialAnim(mapObject, GetFaceDirectionAnimId(direction = directions[mapObject->placeholder18 - 1]));
+ if (direction == (u8)task->data[1])
+ task->data[2]++;
+ task->data[0]++;
+ if (task->data[2] > 3 && direction == GetOppositeDirection(task->data[1]))
+ task->data[0]++;
+ }
+ return 0;
+}
+
+u8 sub_805A178(struct Task *task, struct MapObject *mapObject)
+{
+ u8 arr[5];
+
+ memcpy(arr, gUnknown_0830FCAC, sizeof(arr));
+ if (FieldObjectClearAnimIfSpecialAnimFinished(mapObject))
+ {
+ FieldObjectSetSpecialAnim(mapObject, arr[task->data[2]]);
+ task->data[0] = 1;
+ }
+ return 0;
+}
+
+u8 sub_805A1B8(struct Task *task, struct MapObject *mapObject)
+{
+ if (FieldObjectClearAnimIfSpecialAnimFinished(mapObject))
+ {
+ FieldObjectSetSpecialAnim(mapObject, GetSimpleGoAnimId(GetOppositeDirection(task->data[1])));
+ ScriptContext2_Disable();
+ gPlayerAvatar.unk6 = 0;
+ DestroyTask(FindTaskIdByFunc(sub_805A08C));
+ }
+ return 0;
+}
+
+/* Some Field effect */
+
+static void taskFF_0805D1D4(u8 taskId);
+static void sub_805A2D0(u8 taskId);
+
+void sub_805A20C(u8 a)
+{
+ u8 taskId;
+
+ ScriptContext2_Enable();
+ sav1_reset_battle_music_maybe();
+ sub_8053F84();
+ gPlayerAvatar.flags &= ~PLAYER_AVATAR_FLAG_3;
+ gPlayerAvatar.flags |= PLAYER_AVATAR_FLAG_0;
+ gPlayerAvatar.unk6 = 1;
+ taskId = CreateTask(taskFF_0805D1D4, 0xFF);
+ gTasks[taskId].data[0] = a;
+ taskFF_0805D1D4(taskId);
+}
+
+static void taskFF_0805D1D4(u8 taskId)
+{
+ struct MapObject *playerMapObj = &gMapObjects[gPlayerAvatar.mapObjectId];
+
+ if (FieldObjectIsSpecialAnimOrDirectionSequenceAnimActive(playerMapObj))
+ {
+ if (!FieldObjectClearAnimIfSpecialAnimFinished(playerMapObj))
+ return;
+ }
+ sub_8127ED0(playerMapObj->mapobj_unk_1A, 2);
+ FieldObjectSetSpecialAnim(playerMapObj, sub_80608D0(gTasks[taskId].data[0]));
+ gTasks[taskId].func = sub_805A2D0;
+}
+
+static void sub_805A2D0(u8 taskId)
+{
+ struct MapObject *playerMapObj = &gMapObjects[gPlayerAvatar.mapObjectId];
+
+ if (FieldObjectClearAnimIfSpecialAnimFinished(playerMapObj))
+ {
+ sub_805B980(playerMapObj, GetPlayerAvatarGraphicsIdByStateId(0));
+ FieldObjectSetSpecialAnim(playerMapObj, GetFaceDirectionAnimId(playerMapObj->mapobj_unk_18));
+ gPlayerAvatar.unk6 = 0;
+ ScriptContext2_Disable();
+ DestroySprite(&gSprites[playerMapObj->mapobj_unk_1A]);
+ DestroyTask(taskId);
+ }
+}
+
+/* Fishing */
+
+static void Task_Fishing(u8 taskId);
+static void sub_805A954(void);
+
+void StartFishing(u8 a)
+{
+ u8 taskId = CreateTask(Task_Fishing, 0xFF);
+
+ gTasks[taskId].data[15] = a;
+ Task_Fishing(taskId);
+}
+
+static void Task_Fishing(u8 taskId)
+{
+ while (gUnknown_0830FCB4[gTasks[taskId].data[0]](&gTasks[taskId]))
+ ;
+}
+
+u8 Fishing1(struct Task *task)
+{
+ ScriptContext2_Enable();
+ gPlayerAvatar.unk6 = 1;
+ task->data[0]++;
+ return 0;
+}
+
+u8 Fishing2(struct Task *task)
+{
+ s16 arr1[3];
+ s16 arr2[3];
+ struct MapObject *playerMapObj;
+
+ memcpy(arr1, gUnknown_0830FCF4, sizeof(arr1));
+ memcpy(arr2, gUnknown_0830FCFA, sizeof(arr2));
+ task->data[12] = 0;
+ task->data[13] = arr1[task->data[15]] + (Random() % arr2[task->data[15]]);
+ task->data[14] = gMapObjects[gPlayerAvatar.mapObjectId].graphicsId;
+ playerMapObj = &gMapObjects[gPlayerAvatar.mapObjectId];
+ FieldObjectClearAnimIfSpecialAnimActive(playerMapObj);
+ playerMapObj->mapobj_bit_11 = 1;
+ sub_8059C3C(playerMapObj->mapobj_unk_18);
+ task->data[0]++;
+ return 0;
+}
+
+u8 Fishing3(struct Task *task)
+{
+ sub_805A954();
+ task->data[1]++;
+ if (task->data[1] > 0x3B)
+ task->data[0]++;
+ return 0;
+}
+
+u8 Fishing4(struct Task *task)
+{
+ u32 randVal;
+
+ MenuDisplayMessageBox();
+ task->data[0]++;
+ task->data[1] = 0;
+ task->data[2] = 0;
+ randVal = Random();
+ randVal %= 10;
+ task->data[3] = randVal + 1;
+ if (task->data[12] == 0)
+ task->data[3] = randVal + 4;
+ if (task->data[3] > 9)
+ task->data[3] = 10;
+ return 1;
+}
+
+u8 Fishing5(struct Task *task)
+{
+ u8 dot[2];
+
+ memcpy(dot, gUnknown_0830FD00, sizeof(dot));
+ sub_805A954();
+ task->data[1]++;
+ if (gMain.newKeys & A_BUTTON)
+ {
+ task->data[0] = 11;
+ if (task->data[12] != 0)
+ task->data[0] = 12;
+ return 1;
+ }
+ else
+ {
+ if (task->data[1] > 0x13)
+ {
+ task->data[1] = 0;
+ if (task->data[2] >= task->data[3])
+ {
+ task->data[0]++;
+ if (task->data[12] != 0)
+ task->data[0]++;
+ task->data[12]++;
+ }
+ else
+ {
+ MenuPrint(dot, task->data[2] + 4, 15);
+ task->data[2]++;
+ }
+ }
+ return 0;
+ }
+}
+
+u8 Fishing6(struct Task *task)
+{
+ sub_805A954();
+ task->data[0]++;
+ if (!GetFishingWildMonListHeader() || (Random() & 1))
+ task->data[0] = 11;
+ else
+ StartSpriteAnim(&gSprites[gPlayerAvatar.spriteId], sub_805FE08(player_get_direction_lower_nybble()));
+ return 1;
+}
+
+u8 Fishing7(struct Task *task)
+{
+ sub_805A954();
+ MenuPrint(gOtherText_OhABite, 4, 17);
+ task->data[0]++;
+ task->data[1] = 0;
+ return 0;
+}
+
+u8 Fishing8(struct Task *task)
+{
+ s16 arr[3];
+
+ memcpy(arr, gUnknown_0830FD02, sizeof(arr));
+ sub_805A954();
+ task->data[1]++;
+ if (task->data[1] >= arr[task->data[15]])
+ task->data[0] = 12;
+ else if (gMain.newKeys & A_BUTTON)
+ task->data[0]++;
+ return 0;
+}
+
+u8 Fishing9(struct Task *task)
+{
+ s16 arr[3][2];
+
+ memcpy(arr, gUnknown_0830FD08, sizeof(arr));
+ sub_805A954();
+ task->data[0]++;
+ if (task->data[12] < task->data[13])
+ {
+ task->data[0] = 3;
+ }
+ else if (task->data[12] < 2)
+ {
+ s16 randVal = Random() % 100;
+
+ if (arr[task->data[15]][task->data[12]] > randVal)
+ task->data[0] = 3;
+ }
+ return 0;
+}
+
+u8 Fishing10(struct Task *task)
+{
+ sub_805A954();
+ sub_8072044(gOtherText_PokeOnHook);
+ MenuDisplayMessageBox();
+ task->data[0]++;
+ task->data[1] = 0;
+ return 0;
+}
+
+u8 Fishing11(struct Task *task)
+{
+ if (task->data[1] == 0)
+ {
+ sub_805A954();
+ if (task->data[1] == 0)
+ {
+ if (MenuUpdateWindowText())
+ {
+ struct MapObject *playerMapObj = &gMapObjects[gPlayerAvatar.mapObjectId];
+
+ sub_805B980(playerMapObj, task->data[14]);
+ FieldObjectTurn(playerMapObj, playerMapObj->placeholder18);
+ if (gPlayerAvatar.flags & PLAYER_AVATAR_FLAG_3)
+ sub_8127F28(gMapObjects[gPlayerAvatar.mapObjectId].mapobj_unk_1A, 0, 0);
+ gSprites[gPlayerAvatar.spriteId].pos2.x = 0;
+ gSprites[gPlayerAvatar.spriteId].pos2.y = 0;
+ MenuZeroFillScreen();
+ task->data[1]++;
+ return 0;
+ }
+ else
+ {
+ if (task->data[1] == 0)
+ return 0;
+ }
+ }
+ }
+ gPlayerAvatar.unk6 = 0;
+ ScriptContext2_Disable();
+ FishingWildEncounter(task->data[15]);
+ sub_80BE97C(1);
+ DestroyTask(FindTaskIdByFunc(Task_Fishing));
+ return 0;
+}
+
+u8 Fishing12(struct Task *task)
+{
+ sub_805A954();
+ StartSpriteAnim(&gSprites[gPlayerAvatar.spriteId], sub_805FDF8(player_get_direction_lower_nybble()));
+ sub_8072044(gOtherText_NotEvenANibble);
+ task->data[0] = 13;
+ return 1;
+}
+
+u8 Fishing13(struct Task *task)
+{
+ sub_805A954();
+ StartSpriteAnim(&gSprites[gPlayerAvatar.spriteId], sub_805FDF8(player_get_direction_lower_nybble()));
+ sub_8072044(gOtherText_ItGotAway);
+ task->data[0]++;
+ return 1;
+}
+
+u8 Fishing14(struct Task *task)
+{
+ sub_805A954();
+ MenuDisplayMessageBox();
+ task->data[0]++;
+ return 0;
+}
+
+u8 Fishing15(struct Task *task)
+{
+ sub_805A954();
+ if (gSprites[gPlayerAvatar.spriteId].animEnded)
+ {
+ struct MapObject *playerMapObj = &gMapObjects[gPlayerAvatar.mapObjectId];
+
+ sub_805B980(playerMapObj, task->data[14]);
+ FieldObjectTurn(playerMapObj, playerMapObj->placeholder18);
+ if (gPlayerAvatar.flags & PLAYER_AVATAR_FLAG_3)
+ sub_8127F28(gMapObjects[gPlayerAvatar.mapObjectId].mapobj_unk_1A, 0, 0);
+ gSprites[gPlayerAvatar.spriteId].pos2.x = 0;
+ gSprites[gPlayerAvatar.spriteId].pos2.y = 0;
+ task->data[0]++;
+ }
+ return 0;
+}
+
+u8 Fishing16(struct Task *task)
+{
+ if (MenuUpdateWindowText())
+ {
+ gPlayerAvatar.unk6 = 0;
+ ScriptContext2_Disable();
+ sub_806451C();
+ MenuZeroFillScreen();
+ sub_80BE97C(0);
+ DestroyTask(FindTaskIdByFunc(Task_Fishing));
+ }
+ return 0;
+}
+
+static void sub_805A954(void)
+{
+ struct Sprite *playerSprite = &gSprites[gPlayerAvatar.spriteId];
+ u8 animCmdIndex;
+ u8 animType;
+
+ AnimateSprite(playerSprite);
+ playerSprite->pos2.x = 0;
+ playerSprite->pos2.y = 0;
+ animCmdIndex = playerSprite->animCmdIndex;
+ if (playerSprite->anims[playerSprite->animNum][animCmdIndex].type == -1)
+ {
+ animCmdIndex--;
+ }
+ else
+ {
+ playerSprite->animDelayCounter++;
+ if (playerSprite->anims[playerSprite->animNum][animCmdIndex].type == -1)
+ animCmdIndex--;
+ }
+ animType = playerSprite->anims[playerSprite->animNum][animCmdIndex].type;
+ if (animType == 1 || animType == 2 || animType == 3)
+ {
+ playerSprite->pos2.x = 8;
+ if (player_get_direction_lower_nybble() == 3)
+ playerSprite->pos2.x = -8;
+ }
+ if (animType == 5)
+ playerSprite->pos2.y = -8;
+ if (animType == 10 || animType == 11)
+ playerSprite->pos2.y = 8;
+ if (gPlayerAvatar.flags & PLAYER_AVATAR_FLAG_3)
+ sub_8127F28(gMapObjects[gPlayerAvatar.mapObjectId].mapobj_unk_1A, 1, playerSprite->pos2.y);
+}
diff --git a/src/field_poison.c b/src/field_poison.c
new file mode 100644
index 000000000..a51fe5546
--- /dev/null
+++ b/src/field_poison.c
@@ -0,0 +1,144 @@
+#include "global.h"
+#include "field_message_box.h"
+#include "pokemon.h"
+#include "script.h"
+#include "string_util.h"
+#include "task.h"
+
+extern void AdjustFriendship(struct Pokemon *, u8);
+extern u8 pokemon_ailments_get_primary(u32);
+extern void DoFieldPoisonEffect(void);
+
+extern struct Pokemon gPlayerParty[6];
+extern u16 gScriptResult;
+extern u8 fieldPoisonText_PokemonFainted[];
+
+bool32 CheckMonIsValid(struct Pokemon *pkmn)
+{
+ // UB: Too few arguments for function 'GetMonData'
+ u16 species2 = GetMonData(pkmn, MON_DATA_SPECIES2);
+
+ if (species2 == 0 || species2 == 0x19C)
+ return FALSE;
+ else
+ return TRUE;
+}
+
+bool32 AllMonsFainted(void)
+{
+ struct Pokemon *pkmn = &gPlayerParty[0];
+ int i;
+
+ for (i = 0; i < 6; i++, pkmn++)
+ {
+ // UB: Too few arguments for function 'GetMonData'
+ if (CheckMonIsValid(pkmn) && GetMonData(pkmn, MON_DATA_HP) != 0)
+ return FALSE;
+ }
+ return TRUE;
+}
+
+void MonFaintFromPoisonOnField(u8 partyMember)
+{
+ struct Pokemon *pkmn = &gPlayerParty[partyMember];
+ u32 val = 0;
+
+ AdjustFriendship(pkmn, 7);
+ SetMonData(pkmn, MON_DATA_STATUS, (u8*)&val);
+ GetMonData(pkmn, MON_DATA_NICKNAME, gStringVar1);
+ StringGetEnd10(gStringVar1);
+}
+
+bool32 CheckMonFaintedFromPoison(u8 partyMember)
+{
+ struct Pokemon *pkmn = &gPlayerParty[partyMember];
+
+ // UB: Too few arguments for function 'GetMonData'
+ if (CheckMonIsValid(pkmn) && GetMonData(pkmn, MON_DATA_HP) == 0
+ && pokemon_ailments_get_primary(GetMonData(pkmn, MON_DATA_STATUS)) == 1)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+//Task data
+enum
+{
+ TD_STATE,
+ TD_PARTY_MEMBER,
+};
+
+void Task_WhiteOut(u8 taskId)
+{
+ s16 *taskData = gTasks[taskId].data;
+
+ switch (taskData[TD_STATE])
+ {
+ case 0: //Check if Pokemon have fainted due to poison
+ while (taskData[TD_PARTY_MEMBER] < 6)
+ {
+ if (CheckMonFaintedFromPoison(taskData[TD_PARTY_MEMBER]))
+ {
+ MonFaintFromPoisonOnField(taskData[TD_PARTY_MEMBER]);
+ ShowFieldMessage(fieldPoisonText_PokemonFainted);
+ taskData[TD_STATE]++;
+ return;
+ }
+ taskData[TD_PARTY_MEMBER]++;
+ }
+ taskData[TD_STATE] = 2;
+ break;
+ case 1: //Wait for message box to disappear
+ if (IsFieldMessageBoxHidden())
+ taskData[TD_STATE]--; //Check next party member
+ break;
+ case 2: //Done checking Pokemon
+ if (AllMonsFainted())
+ gScriptResult = 1;
+ else
+ gScriptResult = 0;
+ EnableBothScriptContexts();
+ DestroyTask(taskId);
+ break;
+ }
+}
+
+void DoWhiteOut(void)
+{
+ CreateTask(Task_WhiteOut, 0x50);
+ ScriptContext1_Stop();
+}
+
+u8 overworld_poison(void)
+{
+ struct Pokemon *pkmn = &gPlayerParty[0];
+ u32 numPoisoned = 0;
+ u32 numFainting = 0;
+ int i;
+
+ for(i = 0; i < 6; i++)
+ {
+ u32 hp;
+
+ // UB: Too few arguments for function 'GetMonData'
+ if (GetMonData(pkmn, MON_DATA_SANITY_BIT2) != 0
+ && pokemon_ailments_get_primary(GetMonData(pkmn, MON_DATA_STATUS)) == 1)
+ {
+ hp = GetMonData(pkmn, MON_DATA_HP);
+ if(hp != 0)
+ hp--;
+ if(hp == 0)
+ numFainting++; //Pokemon will now faint due to poison
+ SetMonData(pkmn, MON_DATA_HP, (u8 *)&hp);
+ numPoisoned++;
+ }
+ pkmn++;
+ }
+ if(numFainting != 0 || numPoisoned != 0)
+ DoFieldPoisonEffect();
+ if(numFainting != 0)
+ return 2;
+ if(numPoisoned != 0)
+ return 1;
+ return 0;
+}
diff --git a/src/flag.c b/src/flag.c
index a4798fb49..e7347ad0d 100644
--- a/src/flag.c
+++ b/src/flag.c
@@ -1,4 +1,5 @@
#include "global.h"
+#include "flag.h"
extern u8 gUnknown_0202E8E2[];
diff --git a/src/heal_location.c b/src/heal_location.c
new file mode 100644
index 000000000..da2e466a9
--- /dev/null
+++ b/src/heal_location.c
@@ -0,0 +1,45 @@
+#include "global.h"
+
+#define NUM_HEAL_LOCATIONS 22
+
+struct HealLocation
+{
+ s8 group;
+ s8 map;
+ u16 x;
+ u16 y;
+};
+
+extern const struct HealLocation gHealLocations[];
+
+u32 GetHealLocationIndexByMap(u16 mapGroup, u16 mapNum)
+{
+ u32 i;
+
+ for (i = 0; i < NUM_HEAL_LOCATIONS; i++)
+ {
+ if(gHealLocations[i].group == mapGroup && gHealLocations[i].map == mapNum)
+ return i + 1;
+ }
+ return 0;
+}
+
+const struct HealLocation *GetHealLocationByMap(u16 mapGroup, u16 mapNum)
+{
+ u32 index = GetHealLocationIndexByMap(mapGroup, mapNum);
+
+ if (index == 0)
+ return NULL;
+ else
+ return &gHealLocations[index - 1];
+}
+
+const struct HealLocation *GetHealLocation(u32 index)
+{
+ if (index == 0)
+ return NULL;
+ else if (index > NUM_HEAL_LOCATIONS)
+ return NULL;
+ else
+ return &gHealLocations[index - 1];
+}
diff --git a/src/intro.c b/src/intro.c
index 0a91a4f93..e103109f9 100644
--- a/src/intro.c
+++ b/src/intro.c
@@ -141,7 +141,7 @@ void c2_copyright_1(void)
}
}
-void sub_813BA88(void)
+void CB2_InitCopyrightScreen(void)
{
SetUpCopyrightScreen();
}
diff --git a/src/item.c b/src/item.c
new file mode 100644
index 000000000..8bc0cf0f0
--- /dev/null
+++ b/src/item.c
@@ -0,0 +1,530 @@
+#include "global.h"
+#include "berry.h"
+#include "string_util.h"
+
+extern struct Berry *GetBerryInfo(u8 berry);
+
+extern u8 gOtherText_Berry2[];
+extern u8 gUnknown_02038560;
+
+typedef void (*ItemUseFunc)(u8);
+
+struct Item
+{
+ u8 name[14];
+ u16 itemId;
+ u16 price;
+ u8 holdEffect;
+ u8 holdEffectParam;
+ u8 *description;
+ u8 importance;
+ u8 unk19;
+ u8 pocket;
+ u8 type;
+ ItemUseFunc fieldUseFunc;
+ u8 battleUsage;
+ ItemUseFunc battleUseFunc;
+ u8 secondaryId;
+};
+
+extern struct Item gItems[];
+
+struct BagPocket
+{
+ struct ItemSlot *itemSlots;
+ u8 capacity;
+};
+
+extern struct BagPocket gBagPockets[5];
+
+enum
+{
+ ITEMS_POCKET,
+ BALLS_POCKET,
+ TMHM_POCKET,
+ BERRIES_POCKET,
+ KEYITEMS_POCKET
+};
+
+struct Item *ItemId_GetItem(u16);
+u8 ItemId_GetPocket(u16);
+static void CompactPCItems(void);
+
+void CopyItemName(u16 itemId, u8 *string)
+{
+ if (itemId == 0xAF)
+ {
+ StringCopy(string, GetBerryInfo(0x2B)->name);
+ StringAppend(string, gOtherText_Berry2);
+ }
+ else
+ StringCopy(string, ItemId_GetItem(itemId)->name);
+}
+
+//Unreferenced
+static s8 CountUsedBagPocketSlots(u8 pocket)
+{
+ u8 i;
+
+ for (i = 0; i < gBagPockets[pocket].capacity; i++)
+ {
+ if (gBagPockets[pocket].itemSlots[i].itemId == 0)
+ return i;
+ }
+ return -1;
+}
+
+bool8 IsBagPocketNonEmpty(u8 pocket)
+{
+ u8 i;
+
+ for (i = 0; i < gBagPockets[pocket - 1].capacity; i++)
+ {
+ if (gBagPockets[pocket - 1].itemSlots[i].itemId != 0)
+ return TRUE;
+ }
+ return FALSE;
+}
+
+bool8 CheckBagHasItem(u16 itemId, u16 count)
+{
+ u8 i;
+ u8 pocket;
+
+ if (ItemId_GetPocket(itemId) == 0)
+ return FALSE;
+ pocket = ItemId_GetPocket(itemId) - 1;
+ //Check for item slots that contain the item
+ for (i = 0; i < gBagPockets[pocket].capacity; i++)
+ {
+ if (gBagPockets[pocket].itemSlots[i].itemId == itemId)
+ {
+ //Does this item slot contain enough of the item?
+ if (gBagPockets[pocket].itemSlots[i].quantity >= count)
+ return TRUE;
+ count -= gBagPockets[pocket].itemSlots[i].quantity;
+ //Does this item slot and all previous slots contain enough of the item?
+ if (count == 0)
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+bool8 CheckBagHasSpace(u16 itemId, u16 count)
+{
+ u8 i;
+ u8 pocket;
+ u16 slotCapacity;
+
+ if (ItemId_GetPocket(itemId) == 0)
+ return FALSE;
+ pocket = ItemId_GetPocket(itemId) - 1;
+ if (pocket != BERRIES_POCKET)
+ slotCapacity = 99;
+ else
+ slotCapacity = 999;
+
+ //Check space in any existing item slots that already contain this item
+ for (i = 0; i < gBagPockets[pocket].capacity; i++)
+ {
+ if (gBagPockets[pocket].itemSlots[i].itemId == itemId)
+ {
+ if (gBagPockets[pocket].itemSlots[i].quantity + count <= slotCapacity)
+ return TRUE;
+ if (pocket == TMHM_POCKET || pocket == BERRIES_POCKET)
+ return FALSE;
+ count -= slotCapacity - gBagPockets[pocket].itemSlots[i].quantity;
+ if (count == 0)
+ return TRUE;
+ }
+ }
+
+ //Check space in empty item slots
+ if (count > 0)
+ {
+ for (i = 0; i < gBagPockets[pocket].capacity; i++)
+ {
+ if (gBagPockets[pocket].itemSlots[i].itemId == 0)
+ {
+ if (count <= slotCapacity)
+ return TRUE;
+ else
+ count -= slotCapacity;
+ }
+ }
+ if (count > 0)
+ return FALSE; //No more item slots. The bag is full
+ }
+
+ return TRUE;
+}
+
+bool8 AddBagItem(u16 itemId, u16 count)
+{
+ u8 i;
+ u8 pocket;
+ u16 slotCapacity;
+ struct ItemSlot newItems[64];
+
+ if (ItemId_GetPocket(itemId) == 0)
+ return FALSE;
+ pocket = ItemId_GetPocket(itemId) - 1;
+ //Copy the bag pocket
+ memcpy(newItems, gBagPockets[pocket].itemSlots, gBagPockets[pocket].capacity * sizeof(struct ItemSlot));
+ if (pocket != BERRIES_POCKET)
+ slotCapacity = 99;
+ else
+ slotCapacity = 999;
+
+ //Use any item slots that already contain this item
+ for (i = 0; i < gBagPockets[pocket].capacity; i++)
+ {
+ if (newItems[i].itemId == itemId)
+ {
+ if (newItems[i].quantity + count <= slotCapacity)
+ {
+ newItems[i].quantity += count;
+ //Copy pocket back into the bag.
+ memcpy(gBagPockets[pocket].itemSlots, newItems, gBagPockets[pocket].capacity * sizeof(struct ItemSlot));
+ return TRUE;
+ }
+ if (pocket == TMHM_POCKET || pocket == BERRIES_POCKET)
+ return FALSE;
+ count -= slotCapacity - newItems[i].quantity;
+ newItems[i].quantity = slotCapacity;
+ if (count == 0)
+ goto copy_items;
+ }
+ }
+
+ //Put any remaining items into new item slots.
+ if (count > 0)
+ {
+ for (i = 0; i < gBagPockets[pocket].capacity; i++)
+ {
+ if (newItems[i].itemId == 0)
+ {
+ newItems[i].itemId = itemId;
+ if (count <= slotCapacity)
+ {
+ newItems[i].quantity = count;
+ goto copy_items;
+ }
+ count -= slotCapacity;
+ newItems[i].quantity = slotCapacity;
+ }
+ }
+ if (count > 0)
+ return FALSE; //No more empty item slots. The bag is full.
+ }
+
+ copy_items:
+ //Copy pocket back into the bag.
+ memcpy(gBagPockets[pocket].itemSlots, newItems, gBagPockets[pocket].capacity * sizeof(struct ItemSlot));
+ return TRUE;
+}
+
+bool8 RemoveBagItem(u16 itemId, u16 count)
+{
+ u8 i;
+ u8 pocket;
+ u16 totalQuantity = 0;
+
+ if (ItemId_GetPocket(itemId) == 0 || itemId == 0)
+ return FALSE;
+ pocket = ItemId_GetPocket(itemId) - 1;
+
+ for (i = 0; i < gBagPockets[pocket].capacity; i++)
+ {
+ if (gBagPockets[pocket].itemSlots[i].itemId == itemId)
+ totalQuantity += gBagPockets[pocket].itemSlots[i].quantity;
+ }
+ if (totalQuantity < count)
+ return FALSE; //We don't have enough of the item
+
+ if (gBagPockets[pocket].capacity > gUnknown_02038560
+ && gBagPockets[pocket].itemSlots[gUnknown_02038560].itemId == itemId)
+ {
+ if (gBagPockets[pocket].itemSlots[gUnknown_02038560].quantity >= count)
+ {
+ gBagPockets[pocket].itemSlots[gUnknown_02038560].quantity -= count;
+ count = 0;
+ }
+ else
+ {
+ count -= gBagPockets[pocket].itemSlots[gUnknown_02038560].quantity;
+ gBagPockets[pocket].itemSlots[gUnknown_02038560].quantity = 0;
+ }
+ if (gBagPockets[pocket].itemSlots[gUnknown_02038560].quantity == 0)
+ gBagPockets[pocket].itemSlots[gUnknown_02038560].itemId = 0;
+ if (count == 0)
+ return TRUE;
+ }
+
+ for (i = 0; i < gBagPockets[pocket].capacity; i++)
+ {
+ if (gBagPockets[pocket].itemSlots[i].itemId == itemId)
+ {
+ if (gBagPockets[pocket].itemSlots[i].quantity >= count)
+ {
+ gBagPockets[pocket].itemSlots[i].quantity -= count;
+ count = 0;
+ }
+ else
+ {
+ count -= gBagPockets[pocket].itemSlots[i].quantity;
+ gBagPockets[pocket].itemSlots[i].quantity = 0;
+ }
+ if (gBagPockets[pocket].itemSlots[i].quantity == 0)
+ gBagPockets[pocket].itemSlots[i].itemId = 0;
+ if (count == 0)
+ return TRUE;
+ }
+ }
+ return TRUE;
+}
+
+u8 GetPocketByItemId(u16 itemId)
+{
+ return ItemId_GetPocket(itemId);
+}
+
+void ClearItemSlots(struct ItemSlot *itemSlots, u8 b)
+{
+ u16 i;
+
+ for (i = 0; i < b; i++)
+ {
+ itemSlots[i].itemId = 0;
+ itemSlots[i].quantity = 0;
+ }
+}
+
+static s32 FindFreePCItemSlot(void)
+{
+ s8 i;
+
+ for (i = 0; i < 50; i++)
+ {
+ if (gSaveBlock1.pcItems[i].itemId == 0)
+ return i;
+ }
+ return -1;
+}
+
+u8 CountUsedPCItemSlots(void)
+{
+ u8 usedSlots = 0;
+ u8 i;
+
+ for (i = 0; i < 50; i++)
+ {
+ if (gSaveBlock1.pcItems[i].itemId != 0)
+ usedSlots++;
+ }
+ return usedSlots;
+}
+
+bool8 CheckPCHasItem(u16 itemId, u16 count)
+{
+ u8 i;
+
+ for (i = 0; i < 50; i++)
+ {
+ if (gSaveBlock1.pcItems[i].itemId == itemId && gSaveBlock1.pcItems[i].quantity >= count)
+ return TRUE;
+ }
+ return FALSE;
+}
+
+bool8 AddPCItem(u16 itemId, u16 count)
+{
+ u8 i;
+ s8 freeSlot;
+ struct ItemSlot newItems[50];
+
+ //Copy PC items
+ memcpy(newItems, gSaveBlock1.pcItems, sizeof(newItems));
+
+ //Use any item slots that already contain this item
+ for (i = 0; i < 50; i++)
+ {
+ if (newItems[i].itemId == itemId)
+ {
+ if (newItems[i].quantity + count <= 999)
+ {
+ newItems[i].quantity += count;
+ memcpy(gSaveBlock1.pcItems, newItems, sizeof(gSaveBlock1.pcItems));
+ return TRUE;
+ }
+ count += newItems[i].quantity - 999;
+ newItems[i].quantity = 999;
+ if (count == 0)
+ {
+ memcpy(gSaveBlock1.pcItems, newItems, sizeof(gSaveBlock1.pcItems));
+ return TRUE;
+ }
+ }
+ }
+
+ //Put any remaining items into a new item slot.
+ if (count > 0)
+ {
+ freeSlot = FindFreePCItemSlot();
+ if (freeSlot == -1)
+ return FALSE;
+ newItems[freeSlot].itemId = itemId;
+ newItems[freeSlot].quantity = count;
+ }
+
+ //Copy items back to the PC
+ memcpy(gSaveBlock1.pcItems, newItems, sizeof(gSaveBlock1.pcItems));
+ return TRUE;
+}
+
+void RemovePCItem(u8 index, u16 count)
+{
+ gSaveBlock1.pcItems[index].quantity -= count;
+ if (gSaveBlock1.pcItems[index].quantity == 0)
+ {
+ gSaveBlock1.pcItems[index].itemId = 0;
+ CompactPCItems();
+ }
+}
+
+static void CompactPCItems(void)
+{
+ u16 i;
+ u16 j;
+
+ for (i = 0; i < 49; i++)
+ {
+ for (j = i + 1; j <= 49; j++)
+ {
+ if (gSaveBlock1.pcItems[i].itemId == 0)
+ {
+ struct ItemSlot temp = gSaveBlock1.pcItems[i];
+ gSaveBlock1.pcItems[i] = gSaveBlock1.pcItems[j];
+ gSaveBlock1.pcItems[j] = temp;
+ }
+ }
+ }
+}
+
+void SwapRegisteredBike(void)
+{
+ switch(gSaveBlock1.registeredItem)
+ {
+ case 0x103:
+ gSaveBlock1.registeredItem = 0x110;
+ break;
+ case 0x110:
+ gSaveBlock1.registeredItem = 0x103;
+ break;
+ }
+}
+
+static u16 SanitizeItemId(u16 itemId)
+{
+ if (itemId > 0x15C)
+ return 0;
+ else
+ return itemId;
+}
+
+struct Item *ItemId_GetItem(u16 itemId)
+{
+ return &gItems[SanitizeItemId(itemId)];
+}
+
+u16 ItemId_GetId(u16 itemId)
+{
+ return gItems[SanitizeItemId(itemId)].itemId;
+}
+
+u16 ItemId_GetPrice(u16 itemId)
+{
+ return gItems[SanitizeItemId(itemId)].price;
+}
+
+u8 ItemId_GetHoldEffect(u16 itemId)
+{
+ return gItems[SanitizeItemId(itemId)].holdEffect;
+}
+
+u8 ItemId_GetHoldEffectParam(u16 itemId)
+{
+ return gItems[SanitizeItemId(itemId)].holdEffectParam;
+}
+
+u8 *ItemId_GetDescription(u16 itemId)
+{
+ return gItems[SanitizeItemId(itemId)].description;
+}
+
+bool8 ItemId_CopyDescription(u8 *a, u32 itemId, u32 c)
+{
+ u32 r5 = c + 1;
+ u8 *description = gItems[SanitizeItemId(itemId)].description;
+ u8 *str = a;
+
+ for (;;)
+ {
+ if (*description == 0xFF || *description == 0xFE)
+ {
+ r5--;
+ if (r5 == 0)
+ {
+ *str = 0xFF;
+ return TRUE;
+ }
+ if (*description == 0xFF)
+ return FALSE;
+ str = a;
+ description++;
+ }
+ else
+ *(str++) = *(description++);
+ }
+}
+
+u8 ItemId_GetImportance(u16 itemId)
+{
+ return gItems[SanitizeItemId(itemId)].importance;
+}
+
+u8 ItemId_GetUnknownValue(u16 itemId)
+{
+ return gItems[SanitizeItemId(itemId)].unk19;
+}
+
+u8 ItemId_GetPocket(u16 itemId)
+{
+ return gItems[SanitizeItemId(itemId)].pocket;
+}
+
+u8 ItemId_GetType(u16 itemId)
+{
+ return gItems[SanitizeItemId(itemId)].type;
+}
+
+ItemUseFunc ItemId_GetFieldFunc(u16 itemId)
+{
+ return gItems[SanitizeItemId(itemId)].fieldUseFunc;
+}
+
+u8 ItemId_GetBattleUsage(u16 itemId)
+{
+ return gItems[SanitizeItemId(itemId)].battleUsage;
+}
+
+ItemUseFunc ItemId_GetBattleFunc(u16 itemId)
+{
+ return gItems[SanitizeItemId(itemId)].battleUseFunc;
+}
+
+u8 ItemId_GetSecondaryId(u16 itemId)
+{
+ return gItems[SanitizeItemId(itemId)].secondaryId;
+}
diff --git a/src/landmark.c b/src/landmark.c
new file mode 100644
index 000000000..aa4d8c6fa
--- /dev/null
+++ b/src/landmark.c
@@ -0,0 +1,72 @@
+#include "global.h"
+#include "flag.h"
+
+#define MAPSEC_NONE 0x58
+
+struct Landmark
+{
+ u8 *name;
+ u16 flag;
+};
+
+struct LandmarkList
+{
+ u8 mapSection;
+ u8 id;
+ const struct Landmark **landmarks;
+};
+
+extern const struct LandmarkList gLandmarkLists[];
+
+static const struct Landmark **GetLandmarks(u8 mapSection, u8 id);
+
+u8 *GetLandmarkName(u8 mapSection, u8 id, u8 count)
+{
+ const struct Landmark **landmarks = GetLandmarks(mapSection, id);
+
+ if (!landmarks)
+ return NULL;
+
+ while (1)
+ {
+ const struct Landmark *landmark = *landmarks;
+
+ if (landmark->flag == 0xFFFF || FlagGet(landmark->flag) == TRUE)
+ {
+ if (count == 0)
+ break;
+ else
+ count--;
+ }
+
+ landmarks++;
+ if (!*landmarks)
+ return NULL;
+ }
+
+ return (*landmarks)->name;
+}
+
+static const struct Landmark **GetLandmarks(u8 mapSection, u8 id)
+{
+ u16 i = 0;
+
+ for (; gLandmarkLists[i].mapSection != MAPSEC_NONE; i++)
+ {
+ if (gLandmarkLists[i].mapSection > mapSection)
+ return NULL;
+ if (gLandmarkLists[i].mapSection == mapSection)
+ break;
+ }
+
+ if (gLandmarkLists[i].mapSection == MAPSEC_NONE)
+ return NULL;
+
+ for (; gLandmarkLists[i].mapSection == mapSection; i++)
+ {
+ if (gLandmarkLists[i].id == id)
+ return gLandmarkLists[i].landmarks;
+ }
+
+ return NULL;
+}
diff --git a/src/libc.c b/src/libc.c
index e408ba51e..370981878 100644
--- a/src/libc.c
+++ b/src/libc.c
@@ -11,133 +11,133 @@
void *memcpy(void *dst0, const void *src0, size_t len0)
{
- char *dst = dst0;
- const char *src = src0;
- long *aligned_dst;
- const long *aligned_src;
- unsigned int len = len0;
-
- // If the size is small, or either src or dst is unaligned,
- // then go to the byte copy loop. This should be rare.
- if(len >= 16 && !(UNALIGNED(src) | UNALIGNED(dst)))
- {
- aligned_dst = (long *)dst;
- aligned_src = (long *)src;
-
- // Copy 4X long words at a time if possible.
- while(len >= 16)
- {
- *aligned_dst++ = *aligned_src++;
- *aligned_dst++ = *aligned_src++;
- *aligned_dst++ = *aligned_src++;
- *aligned_dst++ = *aligned_src++;
- len -= 16;
- }
-
- // Copy one long word at a time if possible
- while(len >= 4)
- {
- *aligned_dst++ = *aligned_src++;
- len -= 4;
- }
-
- dst = (char *)aligned_dst;
- src = (char *)aligned_src;
- }
-
- // Pick up any remaining bytes with a byte copier.
- while(len--)
- *dst++ = *src++;
-
- return dst0;
+ char *dst = dst0;
+ const char *src = src0;
+ long *aligned_dst;
+ const long *aligned_src;
+ unsigned int len = len0;
+
+ // If the size is small, or either src or dst is unaligned,
+ // then go to the byte copy loop. This should be rare.
+ if(len >= 16 && !(UNALIGNED(src) | UNALIGNED(dst)))
+ {
+ aligned_dst = (long *)dst;
+ aligned_src = (long *)src;
+
+ // Copy 4X long words at a time if possible.
+ while(len >= 16)
+ {
+ *aligned_dst++ = *aligned_src++;
+ *aligned_dst++ = *aligned_src++;
+ *aligned_dst++ = *aligned_src++;
+ *aligned_dst++ = *aligned_src++;
+ len -= 16;
+ }
+
+ // Copy one long word at a time if possible
+ while(len >= 4)
+ {
+ *aligned_dst++ = *aligned_src++;
+ len -= 4;
+ }
+
+ dst = (char *)aligned_dst;
+ src = (char *)aligned_src;
+ }
+
+ // Pick up any remaining bytes with a byte copier.
+ while(len--)
+ *dst++ = *src++;
+
+ return dst0;
}
void *memset(void *m, int c, size_t n)
{
- char *s = (char *)m;
- int count, i;
- unsigned long buffer;
- unsigned long *aligned_addr;
- unsigned char *unaligned_addr;
-
- // If the size is small or m is unaligned,
- // then go to the byte copy loop. This should be rare.
- if(n >= LBLOCKSIZE && !UNALIGNED(m))
- {
- // We know that n is large and m is word-aligned.
- aligned_addr = (unsigned long *)m;
-
- // Store C into each char sized location in buffer so that
- // we can set large blocks quickly.
- c &= 0xFF;
- if(LBLOCKSIZE == 4)
- {
- buffer = (c << 8) | c;
- buffer |= (buffer << 16);
- }
- else
- {
- buffer = 0;
- for(i = 0; i < LBLOCKSIZE; i++)
- buffer = (buffer << 8) | c;
- }
-
- while(n >= LBLOCKSIZE * 4)
- {
- *aligned_addr++ = buffer;
- *aligned_addr++ = buffer;
- *aligned_addr++ = buffer;
- *aligned_addr++ = buffer;
- n -= LBLOCKSIZE * 4;
- }
- while(n >= LBLOCKSIZE)
- {
- *aligned_addr++ = buffer;
- n -= LBLOCKSIZE;
- }
-
- s = (char *)aligned_addr;
- }
-
- // Pick up the remainder with a bytewise loop.
- while(n--)
- *s++ = (char)c;
-
- return m;
+ char *s = (char *)m;
+ int count, i;
+ unsigned long buffer;
+ unsigned long *aligned_addr;
+ unsigned char *unaligned_addr;
+
+ // If the size is small or m is unaligned,
+ // then go to the byte copy loop. This should be rare.
+ if(n >= LBLOCKSIZE && !UNALIGNED(m))
+ {
+ // We know that n is large and m is word-aligned.
+ aligned_addr = (unsigned long *)m;
+
+ // Store C into each char sized location in buffer so that
+ // we can set large blocks quickly.
+ c &= 0xFF;
+ if(LBLOCKSIZE == 4)
+ {
+ buffer = (c << 8) | c;
+ buffer |= (buffer << 16);
+ }
+ else
+ {
+ buffer = 0;
+ for(i = 0; i < LBLOCKSIZE; i++)
+ buffer = (buffer << 8) | c;
+ }
+
+ while(n >= LBLOCKSIZE * 4)
+ {
+ *aligned_addr++ = buffer;
+ *aligned_addr++ = buffer;
+ *aligned_addr++ = buffer;
+ *aligned_addr++ = buffer;
+ n -= LBLOCKSIZE * 4;
+ }
+ while(n >= LBLOCKSIZE)
+ {
+ *aligned_addr++ = buffer;
+ n -= LBLOCKSIZE;
+ }
+
+ s = (char *)aligned_addr;
+ }
+
+ // Pick up the remainder with a bytewise loop.
+ while(n--)
+ *s++ = (char)c;
+
+ return m;
}
int strcmp(const char *s1, const char *s2)
{
- unsigned long *a1;
- unsigned long *a2;
-
- // If s1 or s2 are unaligned, then skip this and compare bytes.
- if(!(UNALIGNED(s1) | UNALIGNED(s2)))
- {
- // Compare them a word at a time.
- a1 = (unsigned long *)s1;
- a2 = (unsigned long *)s2;
- while(*a1 == *a2)
- {
- // If *a1 == *a2, and we find a null in *a1,
- // then the strings must be equal, so return zero.
- if(CONTAINSNULL(*a1))
- return 0;
-
- a1++;
- a2++;
- }
-
- s1 = (char *)a1;
- s2 = (char *)a2;
- }
-
- // Check the remaining few bytes.
- while(*s1 != '\0' && *s1 == *s2)
- {
- s1++;
- s2++;
- }
-
- return (*(unsigned char *) s1) - (*(unsigned char *) s2);
+ unsigned long *a1;
+ unsigned long *a2;
+
+ // If s1 or s2 are unaligned, then skip this and compare bytes.
+ if(!(UNALIGNED(s1) | UNALIGNED(s2)))
+ {
+ // Compare them a word at a time.
+ a1 = (unsigned long *)s1;
+ a2 = (unsigned long *)s2;
+ while(*a1 == *a2)
+ {
+ // If *a1 == *a2, and we find a null in *a1,
+ // then the strings must be equal, so return zero.
+ if(CONTAINSNULL(*a1))
+ return 0;
+
+ a1++;
+ a2++;
+ }
+
+ s1 = (char *)a1;
+ s2 = (char *)a2;
+ }
+
+ // Check the remaining few bytes.
+ while(*s1 != '\0' && *s1 == *s2)
+ {
+ s1++;
+ s2++;
+ }
+
+ return (*(unsigned char *) s1) - (*(unsigned char *) s2);
}
diff --git a/src/link.c b/src/link.c
index 3f4ffe97d..47820185c 100644
--- a/src/link.c
+++ b/src/link.c
@@ -34,7 +34,7 @@ extern void sub_80516C4(u8, u16);
extern u8 unk_2000000[];
extern u8 unk_2004000[];
extern u16 gUnknown_020239F8;
-extern u16 word_203855E;
+extern u16 gScriptItemId;
extern u16 word_3004858;
@@ -370,7 +370,7 @@ static void TestBlockTransfer(u32 a1, u32 a2, u32 a3)
}
}
- val = GetBlockRecievedStatus();
+ val = GetBlockReceivedStatus();
if (val == 0xF)
{
@@ -619,7 +619,7 @@ static void BuildSendCmd(u16 code)
break;
case 0xAAAB:
gSendCmd[0] = 0xAAAB;
- gSendCmd[1] = word_203855E;
+ gSendCmd[1] = gScriptItemId;
break;
case 0xCCCC:
gSendCmd[0] = 0xCCCC;
@@ -889,7 +889,7 @@ bool8 sub_8007ECC(void)
return retVal;
}
-u8 GetBlockRecievedStatus(void)
+u8 GetBlockReceivedStatus(void)
{
return (gBlockReceived[3] << 3)
| (gBlockReceived[2] << 2)
@@ -975,7 +975,7 @@ void Task_PrintTestData(u8 taskId)
PrintHex(GetMultiplayerId(), 15, 12, 2);
PrintHex(gLastSendQueueCount, 25, 1, 2);
PrintHex(gLastRecvQueueCount, 25, 2, 2);
- PrintHex(GetBlockRecievedStatus(), 15, 5, 2);
+ PrintHex(GetBlockReceivedStatus(), 15, 5, 2);
PrintHex(gLinkDebugValue1, 2, 12, 8);
PrintHex(gLinkDebugValue2, 2, 13, 8);
PrintHex(GetSioMultiSI(), 25, 5, 1);
diff --git a/src/lottery_corner.c b/src/lottery_corner.c
index 4085bcff7..c807237af 100644
--- a/src/lottery_corner.c
+++ b/src/lottery_corner.c
@@ -2,17 +2,15 @@
#include "pokemon.h"
#include "rng.h"
#include "string_util.h"
-
-extern bool8 VarSet(u16 id, u16 value);
-extern u16 VarGet(u16 id);
+#include "var.h"
extern u16 gScriptResult;
-extern u16 gUnknown_0202E8CC;
+extern u16 gSpecialVar_0x8004;
extern struct Pokemon gPlayerParty[6];
extern struct PokemonStorage gPokemonStorage;
-extern u16 gUnknown_0202E8CE;
+extern u16 gSpecialVar_0x8005;
extern u16 gUnknown_0840CB04[];
-extern u16 gUnknown_0202E8D0;
+extern u16 gSpecialVar_0x8006;
static EWRAM_DATA u16 sWinNumberDigit = 0;
static EWRAM_DATA u16 sOtIdDigit = 0;
@@ -53,7 +51,7 @@ void PickLotteryCornerTicket(void)
u32 box;
u32 slot;
- gUnknown_0202E8CC = 0;
+ gSpecialVar_0x8004 = 0;
slot = 0;
box = 0;
for(i = 0; i < 6; i++)
@@ -68,9 +66,9 @@ void PickLotteryCornerTicket(void)
u32 otId = GetMonData(pkmn, MON_DATA_OT_ID);
u8 a = GetMatchingDigits(gScriptResult, otId);
- if(a > gUnknown_0202E8CC && a > 1)
+ if(a > gSpecialVar_0x8004 && a > 1)
{
- gUnknown_0202E8CC = a - 1;
+ gSpecialVar_0x8004 = a - 1;
box = 14;
slot = i;
}
@@ -93,9 +91,9 @@ void PickLotteryCornerTicket(void)
u32 otId = GetBoxMonData(pkmn, MON_DATA_OT_ID);
u8 a = GetMatchingDigits(gScriptResult, otId);
- if(a > gUnknown_0202E8CC && a > 1)
+ if(a > gSpecialVar_0x8004 && a > 1)
{
- gUnknown_0202E8CC = a - 1;
+ gSpecialVar_0x8004 = a - 1;
box = i;
slot = j;
}
@@ -103,18 +101,18 @@ void PickLotteryCornerTicket(void)
}
}
- if(gUnknown_0202E8CC != 0)
+ if(gSpecialVar_0x8004 != 0)
{
- gUnknown_0202E8CE = gUnknown_0840CB04[gUnknown_0202E8CC - 1];
+ gSpecialVar_0x8005 = gUnknown_0840CB04[gSpecialVar_0x8004 - 1];
if(box == 14)
{
- gUnknown_0202E8D0 = 0;
+ gSpecialVar_0x8006 = 0;
GetMonData(&gPlayerParty[slot], MON_DATA_NICKNAME, gStringVar1);
}
else
{
- gUnknown_0202E8D0 = 1;
+ gSpecialVar_0x8006 = 1;
GetBoxMonData(&gPokemonStorage.boxes[box][slot], MON_DATA_NICKNAME, gStringVar1);
}
StringGetEnd10(gStringVar1);
diff --git a/src/m4a_2.c b/src/m4a_2.c
index b046b3172..2d3c65848 100644
--- a/src/m4a_2.c
+++ b/src/m4a_2.c
@@ -11,6 +11,11 @@ void *gMPlayJumpTable[36];
struct CgbChannel gCgbChans[4];
struct MusicPlayerTrack gPokemonCryTracks[MAX_POKEMON_CRIES * 2];
struct PokemonCrySong gPokemonCrySong;
+struct MusicPlayerInfo gMPlay_BGM;
+struct MusicPlayerInfo gMPlay_SE1;
+struct MusicPlayerInfo gMPlay_SE2;
+struct MusicPlayerInfo gMPlay_SE3;
+u8 gMPlayMemAccArea[0x10];
u32 MidiKeyToFreq(struct WaveData *wav, u8 key, u8 fineAdjust)
{
diff --git a/src/m4a_tables.c b/src/m4a_tables.c
index c673f265c..91f00a31d 100644
--- a/src/m4a_tables.c
+++ b/src/m4a_tables.c
@@ -261,7 +261,7 @@ const struct PokemonCrySong gPokemonCrySongTemplate =
0, // block count
255, // priority
0, // reverb
- (struct ToneData *)&voicegroup_842FC88,
+ (struct ToneData *)&voicegroup_pokemon_cry,
NULL,
NULL,
0,
diff --git a/src/main_menu.c b/src/main_menu.c
index 9a5326ea1..966f93f0d 100644
--- a/src/main_menu.c
+++ b/src/main_menu.c
@@ -26,7 +26,6 @@ extern u16 GetPokedexSeenCount(void);
extern u8 GetBadgeCount(void);
extern void DoNamingScreen(u8 r0, struct SaveBlock2 *r1, u16 r2, u16 r3, u8 s0, MainCallback s4);
extern void CB2_NewGame(void);
-extern void LZ77UnCompVram(const void *src, void *dest);
extern void DecompressPicFromTable_2(const struct SpriteSheet *, u8, u8, void *, void *, u32);
extern void LoadCompressedObjectPalette(const struct SpritePalette *);
extern u8 CreateBirchSprite(u8, u8, u8);
diff --git a/src/map_obj_lock.c b/src/map_obj_lock.c
index d4115418b..422903a97 100644
--- a/src/map_obj_lock.c
+++ b/src/map_obj_lock.c
@@ -13,7 +13,7 @@ extern void sub_80A2178(void);
extern void sub_806451C(void);
extern u8 FieldObjectFaceOppositeDirection(void *, u8);
-extern u16 gUnknown_0202E8E0;
+extern u16 gScriptFacing;
bool8 walkrun_is_standing_still(void)
{
@@ -116,7 +116,7 @@ void unref_sub_8064E5C(void)
void sub_8064EAC(void)
{
- FieldObjectFaceOppositeDirection(&gMapObjects[gSelectedMapObject], gUnknown_0202E8E0);
+ FieldObjectFaceOppositeDirection(&gMapObjects[gSelectedMapObject], gScriptFacing);
}
void sub_8064ED4(void)
diff --git a/src/menu_cursor.c b/src/menu_cursor.c
new file mode 100644
index 000000000..21e4d9d58
--- /dev/null
+++ b/src/menu_cursor.c
@@ -0,0 +1,610 @@
+#include "global.h"
+#include "sprite.h"
+#include "palette.h"
+
+extern struct SpriteSheet gUnknown_0842F140[];
+extern struct SpriteSheet gUnknown_0842F1C0[];
+extern struct SpritePalette gUnknown_0842F240;
+extern struct SpritePalette gUnknown_0842F248;
+extern struct SpriteTemplate gSpriteTemplate_842F250[];
+extern struct SpriteTemplate gSpriteTemplate_842F298[];
+
+extern struct Subsprite *gUnknown_0842F5BC[];
+
+extern struct SubspriteTable gSubspriteTables_842F5C0[];
+extern struct SubspriteTable gUnknown_0842F6C0[];
+extern struct SubspriteTable gUnknown_0842F758[];
+
+extern struct Subsprite gUnknown_0842F780;
+extern struct Subsprite gUnknown_0842F788;
+extern struct Subsprite gUnknown_0842F790;
+
+extern u16 gUnknown_0203A360[];
+
+extern struct Subsprite gMenuCursorSubsprites[];
+
+extern u8 gUnknown_0203A3D0;
+extern u8 gUnknown_0203A3D1;
+extern u8 gUnknown_0203A3D2;
+extern u8 gUnknown_0203A3D3;
+extern u8 gUnknown_0203A3D4;
+
+void sub_814A7FC(void);
+void sub_814A958(u8 a1);
+void sub_814AD44(void);
+void sub_814ADF4(u8 a1);
+
+void sub_814A590(void)
+{
+ gUnknown_0203A3D0 = 0x40;
+ gUnknown_0203A3D1 = 0x40;
+ gUnknown_0203A3D2 = 0x40;
+ gUnknown_0203A3D3 = 0;
+ gUnknown_0203A3D4 = 0;
+}
+
+u8 sub_814A5C0(u8 a1, u16 a2, u8 a3, u16 a4, u8 a5)
+{
+ int v9;
+ struct Sprite *v10;
+
+ if (gUnknown_0203A3D0 != 0x40 || gUnknown_0203A3D1 != 0x40)
+ sub_814A7FC();
+
+ v9 = 1;
+ if (a2 == 0xFFFF)
+ {
+ gUnknown_0203A360[a3 & 0xF] = a4;
+ if (LoadSpritePalette(&gUnknown_0842F240) != 0xFF)
+ {
+ a2 = 0xFFF0;
+ v9 = 0;
+ }
+ }
+
+ LoadSpriteSheetDeferred(&gUnknown_0842F140[a3 & 0xF]);
+ gUnknown_0203A3D0 = CreateSprite(&gSpriteTemplate_842F250[v9], 0, 0xA0, a1);
+ gUnknown_0203A3D1 = CreateSprite(&gSpriteTemplate_842F250[2], 0, 0xA0, a1);
+ if (gUnknown_0203A3D0 != 0x40)
+ {
+ v10 = &gSprites[gUnknown_0203A3D0];
+ if (a2 == 0xFFFF)
+ v10->oam.paletteNum = 0;
+ else
+ v10->oam.paletteNum = IndexOfSpritePaletteTag(a2);
+ }
+ if (gUnknown_0203A3D1 != 0x40)
+ {
+ v10 = &gSprites[gUnknown_0203A3D1];
+ if (a2 == 0xFFFF)
+ v10->oam.paletteNum = 0;
+ else
+ v10->oam.paletteNum = IndexOfSpritePaletteTag(a2);
+
+ if (!(REG_DISPCNT & (DISPCNT_WIN0_ON | DISPCNT_WIN1_ON)))
+ *(u8 *)(REG_ADDR_WINOUT) |= 0x1F;
+ gUnknown_0203A3D3 = REG_DISPCNT >> 0xF;
+ gUnknown_0203A3D4 = *(u8 *)(REG_BASE + REG_OFFSET_WINOUT + 1);
+ REG_DISPCNT |= DISPCNT_OBJWIN_ON;
+ *(u8 *)(REG_ADDR_WINOUT + 1) = 0x10;
+ }
+ sub_814A958(a5);
+ return gUnknown_0203A3D0;
+}
+
+u8 sub_814A758(u8 a1, u8 a2, u8 a3, u8 a4)
+{
+ u8 result;
+ struct Sprite *spr;
+
+ result = sub_814A5C0(a1, 0, a3, 0, a4);
+ if (result != 0x40)
+ {
+ spr = &gSprites[gUnknown_0203A3D0];
+ spr->oam.paletteNum = a2;
+ }
+ return result;
+}
+
+u8 unref_sub_814A7AC(u8 a1, u16 a2, u8 a3)
+{
+ u16 i;
+ u8 val1 = 0;
+ u16 val2 = 0xF;
+
+ for (i = 0; i <= 0xFF; i++)
+ {
+ if (gPlttBufferUnfaded[i] == a2)
+ {
+ val1 = (u8)(i >> 4);
+ val2 = i & 0xF;
+ }
+ }
+
+ return sub_814A758(a1, val1, val2, a3);
+}
+
+void sub_814A7FC(void)
+{
+ if (gUnknown_0203A3D0 != 0x40)
+ {
+ LoadTilesForSpriteSheet(&gUnknown_0842F140[0]);
+ DestroySpriteAndFreeResources(&gSprites[gUnknown_0203A3D0]);
+ gUnknown_0203A3D0 = 0x40;
+ }
+
+ if (gUnknown_0203A3D1 != 0x40)
+ {
+ DestroySpriteAndFreeResources(&gSprites[gUnknown_0203A3D1]);
+ gUnknown_0203A3D1 = 0x40;
+ if (!gUnknown_0203A3D3)
+ REG_DISPCNT &= ~DISPCNT_OBJWIN_ON;
+ *(u8 *)(REG_BASE + REG_OFFSET_WINOUT + 1) = gUnknown_0203A3D4;
+ }
+
+ return;
+}
+
+void sub_814A880(u8 a1, u8 a2)
+{
+ struct Sprite *spr;
+
+ if (gUnknown_0203A3D0 != 0x40)
+ {
+ spr = &gSprites[gUnknown_0203A3D0];
+ spr->invisible = 0;
+ spr->centerToCornerVecX = 0;
+ spr->centerToCornerVecY = 0;
+ spr->pos1.x = a1;
+ spr->pos1.y = a2;
+ }
+
+ if (gUnknown_0203A3D1 != 0x40)
+ {
+ spr = &gSprites[gUnknown_0203A3D1];
+ spr->invisible = 0;
+ spr->centerToCornerVecX = 0;
+ spr->centerToCornerVecY = 0;
+ spr->pos1.x = a1;
+ spr->pos1.y = a2;
+ }
+
+ return;
+}
+
+void sub_814A904(void)
+{
+ struct Sprite *spr;
+
+ if (gUnknown_0203A3D0 != 0x40)
+ {
+ spr = &gSprites[gUnknown_0203A3D0];
+ spr->invisible = 1;
+ }
+
+ if (gUnknown_0203A3D1 != 0x40)
+ {
+ spr = &gSprites[gUnknown_0203A3D1];
+ spr->invisible = 1;
+ }
+
+ return;
+}
+
+#ifdef NONMATCHING
+// Fix pls
+void sub_814A958(u8 a1)
+{
+ struct Subsprite *cursub;
+ u8 v2; // r7@1
+ s16 v3; // r2@1
+ s32 v5; // r0@1
+ s32 v6; // r3@1
+ s32 v7; // r5@3
+ int v8; // r7@9
+ s16 negone;
+
+ cursub = &gMenuCursorSubsprites[0];
+ negone = -1;
+ cursub = (struct Subsprite){0,2};
+ cursub->x = negone;
+ cursub++;
+
+ v2 = 1;
+ v3 = 1;
+ v5 = (a1 - 1) << 0x10;
+ v6 = v5 >> 0x10;
+ if ((v5 >> 0x10) > 7)
+ {
+ do
+ {
+ if (v6 > 0x1F)
+ {
+ *cursub = gUnknown_0842F780;
+ cursub->x = v3;
+ v3 = ((v3 << 16) + 0x200000) >> 16;
+ v7 = a1 << 16;
+ }
+ else
+ {
+ v7 = a1 << 16;
+ if (a1 <= 0x27 || v6 <= 0x8)
+ {
+ *cursub = gUnknown_0842F788;
+ cursub->x = v3;
+ v3 = ((v3 << 16) + 0x80000) >> 16;
+ }
+ else
+ {
+ *cursub = gUnknown_0842F780;
+ cursub->x = v3 - 0x20 + (v6 & 0xFFF8);
+ v3 = (v3 + (v6 & 0x18)) & negone;
+ }
+ }
+
+ cursub++;
+ v2 = v2 + 1;
+ v6 = ((v7 >> 16) - v3) & 0xFFFF;
+ }
+ while (v7 - v3 > 7);
+ }
+ *cursub = gUnknown_0842F790;
+ cursub->x = v6 + v3 - 7;
+ v8 = v2 + 1;
+ if (gUnknown_0203A3D0 != 0x40)
+ SetSubspriteTables(&gSprites[gUnknown_0203A3D0], &gSubspriteTables_842F5C0[v8]);
+ if (gUnknown_0203A3D1 != 0x40)
+ SetSubspriteTables(&gSprites[gUnknown_0203A3D1], &gSubspriteTables_842F5C0[v8]);
+ return;
+}
+#else
+__attribute__((naked))
+void sub_814A958(u8 a1)
+{
+ asm(".syntax unified\n\
+ push {r4-r7,lr}\n\
+ mov r7, r10\n\
+ mov r6, r9\n\
+ mov r5, r8\n\
+ push {r5-r7}\n\
+ sub sp, 0x4\n\
+ lsls r0, 24\n\
+ ldr r4, _0814A9C4\n\
+ ldr r2, _0814A9C8\n\
+ lsrs r0, 24\n\
+ str r0, [sp]\n\
+ movs r0, 0\n\
+ movs r1, 0\n\
+ movs r1, 0x2\n\
+ str r0, [r4]\n\
+ str r1, [r4, 0x4]\n\
+ strh r2, [r4]\n\
+ adds r4, 0x8\n\
+ movs r7, 0x1\n\
+ movs r2, 0x1\n\
+ ldr r1, [sp]\n\
+ subs r0, r1, 0x1\n\
+ lsls r0, 16\n\
+ lsrs r3, r0, 16\n\
+ asrs r0, 16\n\
+ cmp r0, 0x7\n\
+ ble _0814AA3A\n\
+ ldr r0, _0814A9CC\n\
+ mov r12, r0\n\
+ mov r8, r1\n\
+ movs r1, 0x8\n\
+ negs r1, r1\n\
+ mov r10, r1\n\
+ ldr r5, _0814A9D0\n\
+ mov r9, r5\n\
+_0814A99E:\n\
+ lsls r0, r3, 16\n\
+ asrs r3, r0, 16\n\
+ cmp r3, 0x1F\n\
+ ble _0814A9D4\n\
+ mov r6, r12\n\
+ ldr r0, [r6]\n\
+ ldr r1, [r6, 0x4]\n\
+ str r0, [r4]\n\
+ str r1, [r4, 0x4]\n\
+ strh r2, [r4]\n\
+ lsls r0, r2, 16\n\
+ movs r1, 0x80\n\
+ lsls r1, 14\n\
+ adds r0, r1\n\
+ lsrs r2, r0, 16\n\
+ ldr r3, [sp]\n\
+ lsls r5, r3, 16\n\
+ b _0814AA20\n\
+ .align 2, 0\n\
+_0814A9C4: .4byte gMenuCursorSubsprites\n\
+_0814A9C8: .4byte 0x0000ffff\n\
+_0814A9CC: .4byte gUnknown_0842F780\n\
+_0814A9D0: .4byte gUnknown_0842F788\n\
+_0814A9D4:\n\
+ ldr r6, [sp]\n\
+ lsls r5, r6, 16\n\
+ mov r0, r8\n\
+ cmp r0, 0x27\n\
+ ble _0814AA0A\n\
+ cmp r3, 0x8\n\
+ ble _0814AA0A\n\
+ mov r6, r12\n\
+ ldr r0, [r6]\n\
+ ldr r1, [r6, 0x4]\n\
+ str r0, [r4]\n\
+ str r1, [r4, 0x4]\n\
+ lsls r1, r2, 16\n\
+ asrs r1, 16\n\
+ adds r2, r1, 0\n\
+ subs r2, 0x20\n\
+ adds r0, r3, 0\n\
+ mov r6, r10\n\
+ ands r0, r6\n\
+ adds r2, r0\n\
+ strh r2, [r4]\n\
+ movs r0, 0x18\n\
+ ands r0, r3\n\
+ adds r1, r0\n\
+ lsls r1, 16\n\
+ lsrs r2, r1, 16\n\
+ b _0814AA20\n\
+_0814AA0A:\n\
+ mov r3, r9\n\
+ ldr r0, [r3]\n\
+ ldr r1, [r3, 0x4]\n\
+ str r0, [r4]\n\
+ str r1, [r4, 0x4]\n\
+ strh r2, [r4]\n\
+ lsls r0, r2, 16\n\
+ movs r6, 0x80\n\
+ lsls r6, 12\n\
+ adds r0, r6\n\
+ lsrs r2, r0, 16\n\
+_0814AA20:\n\
+ adds r4, 0x8\n\
+ adds r0, r7, 0x1\n\
+ lsls r0, 24\n\
+ lsrs r7, r0, 24\n\
+ asrs r1, r5, 16\n\
+ lsls r0, r2, 16\n\
+ asrs r0, 16\n\
+ subs r1, r0\n\
+ lsls r1, 16\n\
+ lsrs r3, r1, 16\n\
+ asrs r1, 16\n\
+ cmp r1, 0x7\n\
+ bgt _0814A99E\n\
+_0814AA3A:\n\
+ ldr r5, _0814AAA8\n\
+ ldr r0, [r5]\n\
+ ldr r1, [r5, 0x4]\n\
+ str r0, [r4]\n\
+ str r1, [r4, 0x4]\n\
+ lsls r1, r2, 16\n\
+ asrs r1, 16\n\
+ subs r1, 0x7\n\
+ lsls r0, r3, 16\n\
+ asrs r0, 16\n\
+ adds r0, r1\n\
+ strh r0, [r4]\n\
+ adds r0, r7, 0x1\n\
+ lsls r0, 24\n\
+ lsrs r7, r0, 24\n\
+ ldr r6, _0814AAAC\n\
+ ldrb r0, [r6]\n\
+ cmp r0, 0x40\n\
+ beq _0814AA78\n\
+ adds r1, r0, 0\n\
+ lsls r0, r1, 4\n\
+ adds r0, r1\n\
+ lsls r0, 2\n\
+ ldr r1, _0814AAB0\n\
+ adds r2, r0, r1\n\
+ lsls r1, r7, 3\n\
+ ldr r0, _0814AAB4\n\
+ adds r1, r0\n\
+ adds r0, r2, 0\n\
+ bl SetSubspriteTables\n\
+_0814AA78:\n\
+ ldr r1, _0814AAB8\n\
+ ldrb r0, [r1]\n\
+ cmp r0, 0x40\n\
+ beq _0814AA98\n\
+ adds r1, r0, 0\n\
+ lsls r0, r1, 4\n\
+ adds r0, r1\n\
+ lsls r0, 2\n\
+ ldr r1, _0814AAB0\n\
+ adds r2, r0, r1\n\
+ lsls r1, r7, 3\n\
+ ldr r0, _0814AAB4\n\
+ adds r1, r0\n\
+ adds r0, r2, 0\n\
+ bl SetSubspriteTables\n\
+_0814AA98:\n\
+ add sp, 0x4\n\
+ pop {r3-r5}\n\
+ mov r8, r3\n\
+ mov r9, r4\n\
+ mov r10, r5\n\
+ pop {r4-r7}\n\
+ pop {r0}\n\
+ bx r0\n\
+ .align 2, 0\n\
+_0814AAA8: .4byte gUnknown_0842F790\n\
+_0814AAAC: .4byte gUnknown_0203A3D0\n\
+_0814AAB0: .4byte gSprites\n\
+_0814AAB4: .4byte gSubspriteTables_842F5C0\n\
+_0814AAB8: .4byte gUnknown_0203A3D1\n\
+ .syntax divided\n");
+}
+#endif
+
+void sub_814AABC(void (*callback)(struct Sprite *))
+{
+ struct Sprite *spr;
+
+ if (gUnknown_0203A3D0 != 0x40)
+ {
+ spr = &gSprites[gUnknown_0203A3D0];
+ spr->callback = callback;
+ }
+
+ if (gUnknown_0203A3D1 != 0x40)
+ {
+ spr = &gSprites[gUnknown_0203A3D1];
+ spr->callback = callback;
+ }
+
+ return;
+}
+
+void sub_814AAF8(u16 a1)
+{
+ struct Sprite *spr;
+ u8 v2;
+ u8 v3;
+ u16 v4;
+
+ if (gUnknown_0203A3D0 != 0x40)
+ {
+ spr = &gSprites[gUnknown_0203A3D0];
+ if (spr->template->paletteTag == 0xFFFF)
+ {
+ for (v2 = 0, v3 = 0xF, v4 = 0; v4 <= 0xFF; v4++)
+ {
+ if (gPlttBufferUnfaded[v4] == a1)
+ {
+ v2 = v4 >> 4;
+ v3 = v4 & 0xF;
+ }
+ }
+ spr->oam.paletteNum = v2;
+ RequestSpriteSheetCopy(&gUnknown_0842F140[v3 & 0xF]);
+ }
+ }
+ return;
+}
+
+void sub_814AB84(void)
+{
+ struct Sprite *spr;
+
+ if (gUnknown_0203A3D1 != 0x40)
+ {
+ spr = &gSprites[gUnknown_0203A3D1];
+ FreeSpriteOamMatrix(spr);
+ DestroySprite(spr);
+ gUnknown_0203A3D1 = 0x40;
+
+ if (!gUnknown_0203A3D3)
+ REG_DISPCNT &= ~DISPCNT_OBJWIN_ON;
+ *(u8 *)(REG_ADDR_WINOUT + 1) = gUnknown_0203A3D4;
+ }
+ return;
+}
+
+void unref_sub_814ABE4(int a1)
+{
+ struct Sprite *spr;
+
+ CpuSet(gUnknown_0842F5BC[a1], &gMenuCursorSubsprites, 0x28);
+
+ if (gUnknown_0203A3D0 != 0x40)
+ {
+ spr = &gSprites[gUnknown_0203A3D0];
+ SetSubspriteTables(spr, &gUnknown_0842F758[a1]);
+ }
+ if (gUnknown_0203A3D1 != 0x40)
+ {
+ spr = &gSprites[gUnknown_0203A3D1];
+ SetSubspriteTables(spr, &gUnknown_0842F758[a1]);
+ }
+ return;
+}
+
+u8 CreateBlendedOutlineCursor(u8 a1, u16 a2, u8 a3, u16 a4, u8 a5)
+{
+ int v8;
+ struct Sprite *spr;
+ u8 var1 = gUnknown_0203A3D2;
+
+ if (var1 != 0x40)
+ sub_814AD44();
+
+ v8 = 1;
+
+ if (a2 == 0xFFFF)
+ {
+ gUnknown_0203A360[a3 & 0xF] = a4;
+ if (LoadSpritePalette(&gUnknown_0842F248) != 0xFF )
+ {
+ a2 = 0xFFF1;
+ v8 = 0;
+ }
+ }
+
+ LoadSpriteSheetDeferred(&gUnknown_0842F1C0[a3 & 0xF]);
+ gUnknown_0203A3D2 = CreateSprite(&gSpriteTemplate_842F298[v8], 0, 0xA0, a1);
+
+ if (gUnknown_0203A3D2 != 0x40)
+ {
+ spr = &gSprites[gUnknown_0203A3D2];
+
+ if (a2 == 0xFFFF)
+ spr->oam.paletteNum = 0;
+ else
+ spr->oam.paletteNum = IndexOfSpritePaletteTag(a2);
+ }
+ sub_814ADF4(a5);
+
+ return gUnknown_0203A3D2;
+}
+
+void sub_814AD44(void)
+{
+ if (gUnknown_0203A3D2 != 0x40)
+ {
+ LoadTilesForSpriteSheet(&gUnknown_0842F1C0[0]);
+ DestroySpriteAndFreeResources(&gSprites[gUnknown_0203A3D2]);
+ gUnknown_0203A3D2 = 0x40;
+ }
+ return;
+}
+
+void sub_814AD7C(u8 a1, u8 a2)
+{
+ struct Sprite *spr;
+ if (gUnknown_0203A3D2 != 0x40)
+ {
+ spr = &gSprites[gUnknown_0203A3D2];
+ spr->invisible = 0;
+ spr->centerToCornerVecX = 0;
+ spr->centerToCornerVecY = 0;
+ spr->pos1.x = a1;
+ spr->pos1.y = a2;
+ }
+ return;
+}
+
+void sub_814ADC8()
+{
+ struct Sprite *spr;
+ if (gUnknown_0203A3D2 != 0x40)
+ {
+ spr = &gSprites[gUnknown_0203A3D2];
+ spr->invisible = 1;
+ }
+ return;
+}
+
+void sub_814ADF4(u8 a1)
+{
+ if (a1 > 0x12)
+ a1 = 0;
+
+ if (gUnknown_0203A3D2 != 0x40)
+ SetSubspriteTables(&gSprites[gUnknown_0203A3D2], &gUnknown_0842F6C0[a1]);
+ return;
+}
diff --git a/src/mori_debug_menu.c b/src/mori_debug_menu.c
new file mode 100644
index 000000000..139650c12
--- /dev/null
+++ b/src/mori_debug_menu.c
@@ -0,0 +1,157 @@
+#include "main.h"
+#include "string_util.h"
+#include "pokemon.h"
+
+extern void sub_8071C20(void);
+extern u16 sub_8041870(u16);
+extern void sub_810CA6C(s32);
+extern u8 (*gCallback_03004AE8)(void);
+
+extern u8 daycare_count_pokemon(u32);
+extern u8 daycare_relationship_score_from_savegame(void);
+
+struct DebugMenuAction
+{
+ u8 *text;
+ u8 (*func)(void);
+};
+
+extern u8 gUnknown_0839B24D[];
+extern u8 gUnknown_0839B255[];
+extern u8 gUnknown_0839B257[];
+
+extern struct DebugMenuAction gMoriDebugMenuActions[];
+
+extern u8 gSpeciesNames[][11];
+
+s8 sub_8083D4C(void)
+{
+ if ( gMain.newKeys & 1 )
+ {
+ sub_8071C20();
+ return 1;
+ }
+ else
+ return 0;
+}
+
+u8 MoriDebugMenu_SearchChild(u8 a1, u8 a2, u8 *ptr)
+{
+ u8 localPtr[52];
+ u16 monData;
+ u16 var;
+
+ monData = GetMonData(gPlayerParty, 11, ptr);
+ var = sub_8041870(monData);
+ StringCopy(localPtr, gSpeciesNames[monData]);
+ StringAppend(localPtr, gUnknown_0839B24D);
+ StringAppend(localPtr, gSpeciesNames[var]);
+ StringAppend(localPtr, gUnknown_0839B255);
+ MenuZeroFillScreen();
+ MenuDrawTextWindow(0, 14, 30, 19);
+ MenuPrint(localPtr, 1, 15);
+ gCallback_03004AE8 = sub_8083D4C;
+ return 0;
+}
+
+s8 MoriDebugMenu_Egg(void)
+{
+ if ( daycare_count_pokemon(gSaveBlock1.filler_2F9C) == 2 && daycare_relationship_score_from_savegame() )
+ sub_8041940();
+ sub_8071C20();
+
+ return 1;
+}
+
+s8 MoriDebugMenu_MaleEgg(void)
+{
+ if ( daycare_count_pokemon(gSaveBlock1.filler_2F9C) == 2 && daycare_relationship_score_from_savegame() )
+ sub_8041950();
+ sub_8071C20();
+
+ return 1;
+}
+
+s8 MoriDebugMenu_1000Steps(void)
+{
+ sub_8041790(1000);
+ sub_8071C20();
+ return 1;
+}
+
+s8 MoriDebugMenu_10000Steps(void)
+{
+ sub_8041790(10000);
+ sub_8071C20();
+ return 1;
+}
+
+s8 MoriDebugMenu_MoveTutor(void)
+{
+ sub_8132670();
+ sub_8071C20();
+ return 1;
+}
+
+s8 MoriDebugMenu_BreedEgg(void)
+{
+ u8 loopCounter;
+
+ for(loopCounter = 0; loopCounter <= 5; loopCounter++)
+ {
+ //UB: Too few arguments for function 'GetMonData'
+ if ( GetMonData(&gPlayerParty[loopCounter], MON_DATA_IS_EGG) )
+ {
+ u8 friendship = 0;
+ SetMonData(&gPlayerParty[loopCounter], MON_DATA_FRIENDSHIP, &friendship);
+ }
+ }
+ gSaveBlock1.filler_30B6 = -3;
+ sub_8071C20();
+ return 1;
+}
+
+s8 MoriDebugMenu_LongName(void)
+{
+ SetMonData(gPlayerParty, 2, &gUnknown_0839B257);
+ sub_8071C20();
+ return 1;
+}
+
+s8 MoriDebugMenu_PokeblockCase(void)
+{
+ s32 loopCounter;
+
+ for(loopCounter = 0; loopCounter <= 39; loopCounter++)
+ sub_810CA6C((u8)loopCounter);
+
+ sub_8071C20();
+ return 1;
+}
+
+s8 MoriDebugMenuProcessInput(void)
+{
+ s8 choice = ProcessMenuInput();
+
+ switch (choice)
+ {
+ default:
+ gCallback_03004AE8 = gMoriDebugMenuActions[choice].func;
+ return 0;
+ case -2:
+ return 0;
+ case -1:
+ sub_8071C20();
+ return 1;
+ }
+}
+
+s8 InitMoriDebugMenu(void)
+{
+ MenuZeroFillScreen();
+ MenuDrawTextWindow(0, 0, 10, 19);
+ PrintMenuItems(1, 1, 9, gMoriDebugMenuActions);
+ InitMenu(0, 1, 1, 9, 0, 9);
+ gCallback_03004AE8 = MoriDebugMenuProcessInput;
+ return 0;
+}
diff --git a/src/pokedex.c b/src/pokedex.c
index 2d7059395..8dfc4212c 100644
--- a/src/pokedex.c
+++ b/src/pokedex.c
@@ -9,30 +9,31 @@
#include "task.h"
#include "text.h"
-struct PokedexListItem {
- u16 a;
+struct PokedexListItem
+{
+ u16 dexNum;
u16 seen:1;
u16 owned:1;
- //u8 c;
};
-struct PokedexView {
- struct PokedexListItem unk0[386]; //data on the 386 different Pokemon
+struct PokedexView
+{
+ struct PokedexListItem unk0[386];
u16 unk608;
u8 unk60A_1:1;
u8 unk60A_2:1;
u8 unk60B;
u16 unk60C;
- u16 unk60E; //selected Pokemon (index of unk0)
+ u16 selectedPokemon;
u16 unk610;
- u16 unk612;
+ u16 dexMode; //National or Hoenn
u16 unk614;
- u16 unk616; //order
+ u16 dexOrder;
u16 unk618;
u16 unk61A;
u16 unk61C;
u16 unk61E[4];
- u16 unk626; //some sprite id
+ u16 unk626; //sprite id of selected Pokemon
u16 unk628;
u16 unk62A;
u8 unk62C;
@@ -49,20 +50,66 @@ struct PokedexView {
u8 unk64A;
u8 unk64B;
u8 unk64C_1:1;
- u8 unk64D;
+ u8 selectedScreen;
u8 unk64E;
u8 unk64F;
- u8 unk650; //menuIsOpen
+ u8 menuIsOpen; //menuIsOpen
u8 unk651;
- u16 unk652; //Menu cursor position
- s16 unk654; //Menu Y position (inverted because we use REG_BG0VOFS for this)
+ u16 menuCursorPos; //Menu cursor position
+ s16 menuY; //Menu Y position (inverted because we use REG_BG0VOFS for this)
u8 unk656[8];
u8 unk65E[8];
};
+// I'm #define-ing these just for now so I can keep using the old unkXXX member names
+#define unk60E selectedPokemon
+#define unk612 dexMode
+#define unk616 dexOrder
+#define unk64D selectedScreen
+#define unk650 menuIsOpen
+#define unk652 menuCursorPos
+#define unk654 menuY
+
+enum
+{
+ DEX_MODE_HOENN,
+ DEX_MODE_NATIONAL
+};
+
+enum
+{
+ PAGE_SCREEN,
+ AREA_SCREEN,
+ CRY_SCREEN,
+ SIZE_SCREEN
+};
+
+struct PokedexEntry
+{
+ /*0x00*/ u8 categoryName[12];
+ /*0x0C*/ u16 height; //in decimeters
+ /*0x0E*/ u16 weight; //in hectograms
+ /*0x10*/ u8 *descriptionPage1;
+ /*0x14*/ u8 *descriptionPage2;
+ /*0x18*/ u16 unused;
+ /*0x1A*/ u16 pokemonScale;
+ /*0x1C*/ u16 pokemonOffset;
+ /*0x1E*/ u16 trainerScale;
+ /*0x20*/ u16 trainerOffset;
+}; /*size = 0x24*/
+
+struct CryRelatedStruct
+{
+ u16 unk0;
+ u8 unk2;
+ u8 unk3;
+ u8 unk4;
+ u8 unk5;
+};
+
extern struct MusicPlayerInfo gMPlay_BGM;
extern u8 gReservedSpritePaletteCount;
-extern struct PokedexView *gUnknown_0202FFB4;
+extern struct PokedexView *gPokedexView;
extern u16 gUnknown_0202FFB8;
extern u8 gUnknown_0202FFBA;
extern u8 gUnknown_03005CE8;
@@ -87,6 +134,24 @@ extern struct SpriteTemplate gSpriteTemplate_83A0584;
extern struct SpriteTemplate gSpriteTemplate_83A059C;
extern struct SpriteTemplate gSpriteTemplate_83A05B4;
extern s16 gSineTable[];
+extern struct PokedexListItem *gUnknown_0202FFBC;
+extern IntrCallback gUnknown_03005CEC;
+extern u8 gUnknown_08E96BD4[];
+extern u8 gUnknown_083A05F8[];
+extern u8 gUnknown_0839F8A0[];
+extern u8 gUnknown_0839F988[];
+extern u8 gUnknown_03005E98;
+extern u8 gUnknown_083B4EC4[];
+extern u8 gUnknown_08E96ACC[];
+extern u8 gUnknown_08E96B58[];
+
+extern struct PokedexEntry gPokedexEntries[];
+extern u8 gDexText_UnknownPoke[];
+extern u8 gDexText_UnknownHeight[];
+extern u8 gDexText_UnknownWeight[];
+extern u8 gDexText_CryOf[];
+extern u8 gDexText_SizeComparedTo[];
+extern u8 gDexText_RegisterComplete[];
extern void m4aMPlayVolumeControl(struct MusicPlayerInfo *mplayInfo, u16 trackBits, u16 volume);
extern bool8 BeginNormalPaletteFade(u32, s8, u8, u8, u16);
@@ -97,7 +162,6 @@ extern u8 sub_8091E3C(void);
extern void sub_80690C8(void);
extern void sub_805469C(void);
extern void LoadCompressedObjectPic(void *);
-extern void LZ77UnCompVram(const void *, void *);
extern u16 HoennToNationalOrder(u16);
extern u16 NationalToHoennOrder(u16);
extern u16 gPokedexOrder_Alphabetical[];
@@ -126,12 +190,12 @@ bool8 sub_808E208(u8, u8, u8);
u8 sub_808E82C(void);
void sub_808E0CC(u16, u16);
u8 sub_808F210(struct PokedexListItem *, u8);
-void sub_808F284(struct PokedexListItem *, u8);
+u8 sub_808F284(struct PokedexListItem *, u8);
bool8 sub_808F250(u8);
bool8 sub_808E71C(void);
void sub_808CCC4(u8 taskId);
u16 GetHoennPokedexCount(u8);
-void sub_808D690(u8, u8);
+void SortPokedex(u8, u8);
void Task_PokedexResultsScreen(u8 taskId);
void sub_808D118(u8 taskId);
void Task_PokedexResultsScreenMenu(u8 taskId);
@@ -149,7 +213,29 @@ u16 sub_808E888(u16);
u32 sub_808E8C8(u16, u16, u16);
void sub_808EE28(struct Sprite *sprite);
u16 sub_8091818(u8, u16, u16, u16);
-u8 sub_80918EC(u16 a, s16 b, s16 c, u16 d);
+u16 sub_80918EC(u16 a, s16 b, s16 c, u16 d); //Not sure of return type
+void Task_InitPageScreenMultistep(u8 taskId);
+void Task_PageScreenProcessInput(u8 taskId);
+void Task_InitCryScreenMultistep(u8 taskId);
+void Task_InitAreaScreenMultistep(u8 taskId);
+void Task_ClosePageScreen(u8 taskId);
+void sub_808F888(u8 taskId);
+void Task_InitSizeScreenMultistep(u8 taskId);
+void Task_AreaScreenProcessInput(u8 taskId);
+void sub_808FA00(u8 taskId);
+void Task_CryScreenProcessInput(u8 taskId);
+void sub_808FFBC(u8 taskId);
+void Task_SizeScreenProcessInput(u8 taskId);
+void sub_8090040(u8);
+void sub_8090498(u8 taskId);
+void sub_80904FC(u16);
+void sub_8090540(u16);
+void sub_8090750(u8);
+void sub_8090A3C(u8);
+void sub_8091738(u16, u16, u16);
+u16 NationalPokedexNumToSpecies(u16);
+u8 sub_8119E3C(struct CryRelatedStruct *, u8);
+u8 ShowPokedexCryScreen(struct CryRelatedStruct *, u8);
void sub_808C02C(void)
{
@@ -195,7 +281,7 @@ void ClearPokedexView(struct PokedexView *pokedexView)
for(i = 0; i <= 385; i++)
{
- pokedexView->unk0[i].a |= 0x0000FFFF;
+ pokedexView->unk0[i].dexNum |= 0xFFFF;
pokedexView->unk0[i].seen = 0;
pokedexView->unk0[i].owned = 0;
}
@@ -203,11 +289,11 @@ void ClearPokedexView(struct PokedexView *pokedexView)
pokedexView->unk60A_1 = 0;
pokedexView->unk60A_2 = 0;
pokedexView->unk60C = 0;
- pokedexView->unk60E = 0;
+ pokedexView->selectedPokemon = 0;
pokedexView->unk610 = 0;
- pokedexView->unk612 = 0;
+ pokedexView->dexMode = 0;
pokedexView->unk614 = 0;
- pokedexView->unk616 = 0;
+ pokedexView->dexOrder = 0;
pokedexView->unk618 = 0;
pokedexView->unk61A = 0;
pokedexView->unk61C = 0;
@@ -229,11 +315,11 @@ void ClearPokedexView(struct PokedexView *pokedexView)
pokedexView->unk64A = 0;
pokedexView->unk64B = 0;
pokedexView->unk64C_1 = 0;
- pokedexView->unk64D = 0;
+ pokedexView->selectedScreen = 0;
pokedexView->unk64F = 0;
- pokedexView->unk650 = 0;
- pokedexView->unk652 = 0;
- pokedexView->unk654 = 0;
+ pokedexView->menuIsOpen = 0;
+ pokedexView->menuCursorPos = 0;
+ pokedexView->menuY = 0;
for(i = 0; i <= 7; i++)
pokedexView->unk656[i] = 0;
for(i = 0; i <= 7; i++)
@@ -286,39 +372,39 @@ void CB2_InitPokedex(void)
{
case 0:
default:
- gUnknown_0202FFB4 = (struct PokedexView *)0x02018000;
+ gPokedexView = (struct PokedexView *)0x02018000;
break;
case 1:
- gUnknown_0202FFB4 = (struct PokedexView *)0x02018800;
+ gPokedexView = (struct PokedexView *)0x02018800;
break;
case 2:
- gUnknown_0202FFB4 = (struct PokedexView *)0x02019000;
+ gPokedexView = (struct PokedexView *)0x02019000;
break;
case 3:
- gUnknown_0202FFB4 = (struct PokedexView *)0x02019800;
+ gPokedexView = (struct PokedexView *)0x02019800;
break;
}
- ClearPokedexView(gUnknown_0202FFB4);
+ ClearPokedexView(gPokedexView);
CreateTask(Task_PokedexShowMainScreen, 0);
- gUnknown_0202FFB4->unk612 = gSaveBlock2.pokedex.unknown1;
+ gPokedexView->dexMode = gSaveBlock2.pokedex.unknown1;
if(!IsNationalPokedex())
- gUnknown_0202FFB4->unk612 = 0;
- gUnknown_0202FFB4->unk616 = gSaveBlock2.pokedex.order;
- gUnknown_0202FFB4->unk60E = gUnknown_0202FFB8;
- gUnknown_0202FFB4->unk62C = gUnknown_0202FFBA;
- gUnknown_0202FFB4->unk64D = 0;
- gUnknown_0202FFB4->unk64E = 0;
+ gPokedexView->dexMode = DEX_MODE_HOENN;
+ gPokedexView->dexOrder = gSaveBlock2.pokedex.order;
+ gPokedexView->selectedPokemon = gUnknown_0202FFB8;
+ gPokedexView->unk62C = gUnknown_0202FFBA;
+ gPokedexView->selectedScreen = PAGE_SCREEN;
+ gPokedexView->unk64E = 0;
if(!IsNationalPokedex())
{
- gUnknown_0202FFB4->unk61A = GetHoennPokedexCount(0);
- gUnknown_0202FFB4->unk61C = GetHoennPokedexCount(1);
+ gPokedexView->unk61A = GetHoennPokedexCount(0);
+ gPokedexView->unk61C = GetHoennPokedexCount(1);
}
else
{
- gUnknown_0202FFB4->unk61A = GetNationalPokedexCount(0);
- gUnknown_0202FFB4->unk61C = GetNationalPokedexCount(1);
+ gPokedexView->unk61A = GetNationalPokedexCount(0);
+ gPokedexView->unk61C = GetNationalPokedexCount(1);
}
- gUnknown_0202FFB4->unk62D = 8;
+ gPokedexView->unk62D = 8;
gMain.state++;
break;
case 3:
@@ -332,7 +418,7 @@ void CB2_InitPokedex(void)
REG_DISPSTAT |= 8;
SetVBlankCallback(sub_808C0B8);
SetMainCallback2(MainCB);
- sub_808D690(gUnknown_0202FFB4->unk612, gUnknown_0202FFB4->unk616);
+ SortPokedex(gPokedexView->dexMode, gPokedexView->dexOrder);
m4aMPlayVolumeControl(&gMPlay_BGM, 0xFFFF, 0x80);
}
}
@@ -355,7 +441,7 @@ u8 unref_sub_808C540(void (*func)(u8))
REG_DISPSTAT |= 0x8;
SetVBlankCallback(sub_808C0B8);
SetMainCallback2(MainCB);
- if(!gUnknown_0202FFB4->unk64B)
+ if(!gPokedexView->unk64B)
taskId = CreateTask(sub_808CAE4, 0);
else
taskId = CreateTask(sub_808D198, 0);
@@ -373,7 +459,7 @@ void MainCB(void)
void Task_PokedexShowMainScreen(u8 taskId)
{
- gUnknown_0202FFB4->unk64C_1 = 0;
+ gPokedexView->unk64C_1 = 0;
if(sub_808D344(0))
{
gTasks[taskId].func = Task_PokedexMainScreen;
@@ -383,29 +469,29 @@ void Task_PokedexShowMainScreen(u8 taskId)
//Hide menu and process input on main screen
void Task_PokedexMainScreen(u8 taskId)
{
- REG_BG0VOFS = gUnknown_0202FFB4->unk654;
+ REG_BG0VOFS = gPokedexView->menuY;
//If menu is open, slide it down, off screen
- if(gUnknown_0202FFB4->unk654)
- gUnknown_0202FFB4->unk654 -= 8;
+ if(gPokedexView->menuY)
+ gPokedexView->menuY -= 8;
else
{
- if((gMain.newKeys & A_BUTTON) && gUnknown_0202FFB4->unk0[gUnknown_0202FFB4->unk60E].seen)
+ if((gMain.newKeys & A_BUTTON) && gPokedexView->unk0[gPokedexView->selectedPokemon].seen)
{
sub_808E6BC();
BeginNormalPaletteFade(
- ~(1 << (gSprites[gUnknown_0202FFB4->unk626].oam.paletteNum + 16)),
+ ~(1 << (gSprites[gPokedexView->unk626].oam.paletteNum + 16)),
0, 0, 0x10, 0);
- gSprites[gUnknown_0202FFB4->unk626].callback = sub_808EDB8;
+ gSprites[gPokedexView->unk626].callback = sub_808EDB8;
gTasks[taskId].func = sub_808CA64;
PlaySE(SE_PIN);
}
else if(gMain.newKeys & START_BUTTON)
{
//Open menu
- gUnknown_0202FFB4->unk654 = 0;
- gUnknown_0202FFB4->unk650 = 1;
- gUnknown_0202FFB4->unk652 = 0;
+ gPokedexView->menuY = 0;
+ gPokedexView->menuIsOpen = 1;
+ gPokedexView->menuCursorPos = 0;
gTasks[taskId].func = Task_PokedexMainScreenMenu;
PlaySE(SE_SELECT);
}
@@ -414,11 +500,11 @@ void Task_PokedexMainScreen(u8 taskId)
PlaySE(SE_SELECT);
BeginNormalPaletteFade(-1, 0, 0, 0x10, 0);
gTasks[taskId].data[0] = sub_8091E3C();
- gUnknown_0202FFB4->unk64F = 0;
- gUnknown_0202FFB4->unk62A = gUnknown_0202FFB4->unk62C;
- gUnknown_0202FFB4->unk610 = gUnknown_0202FFB4->unk60E;
- gUnknown_0202FFB4->unk614 = gUnknown_0202FFB4->unk612;
- gUnknown_0202FFB4->unk618 = gUnknown_0202FFB4->unk616;
+ gPokedexView->unk64F = 0;
+ gPokedexView->unk62A = gPokedexView->unk62C;
+ gPokedexView->unk610 = gPokedexView->selectedPokemon;
+ gPokedexView->unk614 = gPokedexView->dexMode;
+ gPokedexView->unk618 = gPokedexView->dexOrder;
gTasks[taskId].func = sub_808CB8C;
PlaySE(SE_PC_LOGON);
}
@@ -431,8 +517,8 @@ void Task_PokedexMainScreen(u8 taskId)
else
{
//Handle D-pad
- gUnknown_0202FFB4->unk60E = sub_808E48C(gUnknown_0202FFB4->unk60E, 0xE);
- if(gUnknown_0202FFB4->unk62E)
+ gPokedexView->selectedPokemon = sub_808E48C(gPokedexView->selectedPokemon, 0xE);
+ if(gPokedexView->unk62E)
gTasks[taskId].func = sub_808C898;
}
}
@@ -440,7 +526,7 @@ void Task_PokedexMainScreen(u8 taskId)
void sub_808C898(u8 taskId)
{
- if(sub_808E208(gUnknown_0202FFB4->unk62F, gUnknown_0202FFB4->unk634, gUnknown_0202FFB4->unk636))
+ if(sub_808E208(gPokedexView->unk62F, gPokedexView->unk634, gPokedexView->unk636))
{
gTasks[taskId].func = Task_PokedexMainScreen;
}
@@ -449,33 +535,33 @@ void sub_808C898(u8 taskId)
//Bring up menu and process menu input
void Task_PokedexMainScreenMenu(u8 taskId)
{
- REG_BG0VOFS = gUnknown_0202FFB4->unk654;
+ REG_BG0VOFS = gPokedexView->menuY;
//If menu is not open, slide it up, on screen
- if(gUnknown_0202FFB4->unk654 != 80)
- gUnknown_0202FFB4->unk654 += 8;
+ if(gPokedexView->menuY != 80)
+ gPokedexView->menuY += 8;
else
{
if(gMain.newKeys & A_BUTTON)
{
- switch(gUnknown_0202FFB4->unk652)
+ switch(gPokedexView->menuCursorPos)
{
case 0: //BACK TO LIST
default:
gMain.newKeys |= START_BUTTON; //Exit menu
break;
case 1: //LIST TOP
- gUnknown_0202FFB4->unk60E = 0;
- gUnknown_0202FFB4->unk62C = 0x40;
+ gPokedexView->selectedPokemon = 0;
+ gPokedexView->unk62C = 0x40;
sub_808E82C();
- sub_808E0CC(gUnknown_0202FFB4->unk60E, 0xE);
+ sub_808E0CC(gPokedexView->selectedPokemon, 0xE);
gMain.newKeys |= START_BUTTON; //Exit menu
break;
case 2: //LIST BOTTOM
- gUnknown_0202FFB4->unk60E = gUnknown_0202FFB4->unk60C - 1;
- gUnknown_0202FFB4->unk62C = gUnknown_0202FFB4->unk60C * 16 + 0x30;
+ gPokedexView->selectedPokemon = gPokedexView->unk60C - 1;
+ gPokedexView->unk62C = gPokedexView->unk60C * 16 + 0x30;
sub_808E82C();
- sub_808E0CC(gUnknown_0202FFB4->unk60E, 0xE);
+ sub_808E0CC(gPokedexView->selectedPokemon, 0xE);
gMain.newKeys |= START_BUTTON; //Exit menu
break;
case 3: //CLOSE POKEDEX
@@ -489,18 +575,18 @@ void Task_PokedexMainScreenMenu(u8 taskId)
//Exit menu when Start or B is pressed
if(gMain.newKeys & (START_BUTTON | B_BUTTON))
{
- gUnknown_0202FFB4->unk650 = 0;
+ gPokedexView->menuIsOpen = 0;
gTasks[taskId].func = Task_PokedexMainScreen;
PlaySE(SE_SELECT);
}
- else if((gMain.newAndRepeatedKeys & DPAD_UP) && gUnknown_0202FFB4->unk652 != 0)
+ else if((gMain.newAndRepeatedKeys & DPAD_UP) && gPokedexView->menuCursorPos != 0)
{
- gUnknown_0202FFB4->unk652--;
+ gPokedexView->menuCursorPos--;
PlaySE(SE_SELECT);
}
- else if((gMain.newAndRepeatedKeys & DPAD_DOWN) && gUnknown_0202FFB4->unk652 <= 2)
+ else if((gMain.newAndRepeatedKeys & DPAD_DOWN) && gPokedexView->menuCursorPos <= 2)
{
- gUnknown_0202FFB4->unk652++;
+ gPokedexView->menuCursorPos++;
PlaySE(SE_SELECT);
}
}
@@ -508,11 +594,11 @@ void Task_PokedexMainScreenMenu(u8 taskId)
void sub_808CA64(u8 taskId)
{
- if(gSprites[gUnknown_0202FFB4->unk626].pos1.x == 0x30 &&
- gSprites[gUnknown_0202FFB4->unk626].pos1.y == 0x38)
+ if(gSprites[gPokedexView->unk626].pos1.x == 0x30 &&
+ gSprites[gPokedexView->unk626].pos1.y == 0x38)
{
- gUnknown_0202FFB4->unk64B = gUnknown_0202FFB4->unk64A;
- gTasks[taskId].data[0] = sub_808F210(&gUnknown_0202FFB4->unk0[gUnknown_0202FFB4->unk60E], gUnknown_0202FFB4->unk626);
+ gPokedexView->unk64B = gPokedexView->unk64A;
+ gTasks[taskId].data[0] = sub_808F210(&gPokedexView->unk0[gPokedexView->selectedPokemon], gPokedexView->unk626);
gTasks[taskId].func = sub_808CAE4;
}
}
@@ -521,17 +607,17 @@ void sub_808CAE4(u8 taskId)
{
if(gTasks[gTasks[taskId].data[0]].isActive)
{
- if(gUnknown_0202FFB4->unk64A == 1 &&
+ if(gPokedexView->unk64A == 1 &&
!sub_808F250(gTasks[taskId].data[0]) &&
sub_808E71C())
{
- sub_808F284(&gUnknown_0202FFB4->unk0[gUnknown_0202FFB4->unk60E], gTasks[taskId].data[0]);
+ sub_808F284(&gPokedexView->unk0[gPokedexView->selectedPokemon], gTasks[taskId].data[0]);
}
}
else
{
- gUnknown_0202FFB8 = gUnknown_0202FFB4->unk60E;
- gUnknown_0202FFBA = gUnknown_0202FFB4->unk62C;
+ gUnknown_0202FFB8 = gPokedexView->selectedPokemon;
+ gUnknown_0202FFBA = gPokedexView->unk62C;
gTasks[taskId].func = Task_PokedexShowMainScreen;
}
}
@@ -542,20 +628,20 @@ void sub_808CB8C(u8 taskId)
if(!isActive)
{
- if(gUnknown_0202FFB4->unk64F)
+ if(gPokedexView->unk64F)
{
- gUnknown_0202FFB4->unk60E = isActive;
- gUnknown_0202FFB4->unk62C = 0x40;
+ gPokedexView->selectedPokemon = isActive;
+ gPokedexView->unk62C = 0x40;
gTasks[taskId].func = sub_808CCC4;
}
else
{
- gUnknown_0202FFB4->unk62C = gUnknown_0202FFB4->unk62A;
- gUnknown_0202FFB4->unk60E = gUnknown_0202FFB4->unk610;
- gUnknown_0202FFB4->unk612 = gUnknown_0202FFB4->unk614;
+ gPokedexView->unk62C = gPokedexView->unk62A;
+ gPokedexView->selectedPokemon = gPokedexView->unk610;
+ gPokedexView->dexMode = gPokedexView->unk614;
if(!IsNationalPokedex())
- gUnknown_0202FFB4->unk612 = 0;
- gUnknown_0202FFB4->unk616 = gUnknown_0202FFB4->unk618;
+ gPokedexView->dexMode = DEX_MODE_HOENN;
+ gPokedexView->dexOrder = gPokedexView->unk618;
gTasks[taskId].func = Task_PokedexShowMainScreen;
}
}
@@ -565,10 +651,10 @@ void Task_ClosePokedex(u8 taskId)
{
if(!gPaletteFade.active)
{
- gSaveBlock2.pokedex.unknown1 = gUnknown_0202FFB4->unk612;
+ gSaveBlock2.pokedex.unknown1 = gPokedexView->dexMode;
if(!IsNationalPokedex())
gSaveBlock2.pokedex.unknown1 = 0;
- gSaveBlock2.pokedex.order = gUnknown_0202FFB4->unk616;
+ gSaveBlock2.pokedex.order = gPokedexView->dexOrder;
DestroyTask(taskId);
SetMainCallback2(sub_805469C);
m4aMPlayVolumeControl(&gMPlay_BGM, 0xFFFF, 0x100);
@@ -577,35 +663,35 @@ void Task_ClosePokedex(u8 taskId)
void sub_808CCC4(u8 taskId)
{
- gUnknown_0202FFB4->unk64C_1 = 1;
+ gPokedexView->unk64C_1 = 1;
if(sub_808D344(3))
gTasks[taskId].func = Task_PokedexResultsScreen;
}
void Task_PokedexResultsScreen(u8 taskId)
{
- REG_BG0VOFS = gUnknown_0202FFB4->unk654;
+ REG_BG0VOFS = gPokedexView->menuY;
- if(gUnknown_0202FFB4->unk654)
- gUnknown_0202FFB4->unk654 -= 8;
+ if(gPokedexView->menuY)
+ gPokedexView->menuY -= 8;
else
{
- if((gMain.newKeys & A_BUTTON) && gUnknown_0202FFB4->unk0[gUnknown_0202FFB4->unk60E].seen)
+ if((gMain.newKeys & A_BUTTON) && gPokedexView->unk0[gPokedexView->selectedPokemon].seen)
{
u32 a;
sub_808E6BC();
- a = (1 << (gSprites[gUnknown_0202FFB4->unk626].oam.paletteNum + 16));
- gSprites[gUnknown_0202FFB4->unk626].callback = sub_808EDB8;
+ a = (1 << (gSprites[gPokedexView->unk626].oam.paletteNum + 16));
+ gSprites[gPokedexView->unk626].callback = sub_808EDB8;
BeginNormalPaletteFade(~a, 0, 0, 0x10, 0);
gTasks[taskId].func = sub_808D118;
PlaySE(SE_PIN);
}
else if(gMain.newKeys & START_BUTTON)
{
- gUnknown_0202FFB4->unk654 = 0;
- gUnknown_0202FFB4->unk650 = 1;
- gUnknown_0202FFB4->unk652 = 0;
+ gPokedexView->menuY = 0;
+ gPokedexView->menuIsOpen = 1;
+ gPokedexView->menuCursorPos = 0;
gTasks[taskId].func = Task_PokedexResultsScreenMenu;
PlaySE(SE_SELECT);
}
@@ -613,7 +699,7 @@ void Task_PokedexResultsScreen(u8 taskId)
{
BeginNormalPaletteFade(-1, 0, 0, 0x10, 0);
gTasks[taskId].data[0] = sub_8091E3C();
- gUnknown_0202FFB4->unk64F = 0;
+ gPokedexView->unk64F = 0;
gTasks[taskId].func = sub_808CB8C;
PlaySE(SE_PC_LOGON);
}
@@ -626,8 +712,8 @@ void Task_PokedexResultsScreen(u8 taskId)
else
{
//Handle D-pad
- gUnknown_0202FFB4->unk60E = sub_808E48C(gUnknown_0202FFB4->unk60E, 0xE);
- if(gUnknown_0202FFB4->unk62E)
+ gPokedexView->selectedPokemon = sub_808E48C(gPokedexView->selectedPokemon, 0xE);
+ if(gPokedexView->unk62E)
gTasks[taskId].func = sub_808CEF8;
}
}
@@ -635,38 +721,38 @@ void Task_PokedexResultsScreen(u8 taskId)
void sub_808CEF8(u8 taskId)
{
- if(sub_808E208(gUnknown_0202FFB4->unk62F, gUnknown_0202FFB4->unk634, gUnknown_0202FFB4->unk636))
+ if(sub_808E208(gPokedexView->unk62F, gPokedexView->unk634, gPokedexView->unk636))
gTasks[taskId].func = Task_PokedexResultsScreen;
}
void Task_PokedexResultsScreenMenu(u8 taskId)
{
- REG_BG0VOFS = gUnknown_0202FFB4->unk654;
+ REG_BG0VOFS = gPokedexView->menuY;
- if(gUnknown_0202FFB4->unk654 != 0x60)
- gUnknown_0202FFB4->unk654 += 8;
+ if(gPokedexView->menuY != 0x60)
+ gPokedexView->menuY += 8;
else
{
if(gMain.newKeys & A_BUTTON)
{
- switch(gUnknown_0202FFB4->unk652)
+ switch(gPokedexView->menuCursorPos)
{
case 0: //BACK TO LIST
default:
gMain.newKeys |= START_BUTTON;
break;
case 1: //LIST TOP
- gUnknown_0202FFB4->unk60E = 0;
- gUnknown_0202FFB4->unk62C = 0x40;
+ gPokedexView->selectedPokemon = 0;
+ gPokedexView->unk62C = 0x40;
sub_808E82C();
- sub_808E0CC(gUnknown_0202FFB4->unk60E, 0xE);
+ sub_808E0CC(gPokedexView->selectedPokemon, 0xE);
gMain.newKeys |= START_BUTTON;
break;
case 2: //LIST BOTTOM
- gUnknown_0202FFB4->unk60E = gUnknown_0202FFB4->unk60C - 1;
- gUnknown_0202FFB4->unk62C = gUnknown_0202FFB4->unk60C * 16 + 0x30;
+ gPokedexView->selectedPokemon = gPokedexView->unk60C - 1;
+ gPokedexView->unk62C = gPokedexView->unk60C * 16 + 0x30;
sub_808E82C();
- sub_808E0CC(gUnknown_0202FFB4->unk60E, 0xE);
+ sub_808E0CC(gPokedexView->selectedPokemon, 0xE);
gMain.newKeys |= START_BUTTON;
break;
case 3: //BACK TO POKEDEX
@@ -685,18 +771,18 @@ void Task_PokedexResultsScreenMenu(u8 taskId)
//Exit menu when Start or B is pressed
if(gMain.newKeys & (START_BUTTON | B_BUTTON))
{
- gUnknown_0202FFB4->unk650 = 0;
+ gPokedexView->menuIsOpen = 0;
gTasks[taskId].func = Task_PokedexResultsScreen;
PlaySE(SE_SELECT);
}
- else if((gMain.newAndRepeatedKeys & DPAD_UP) && gUnknown_0202FFB4->unk652)
+ else if((gMain.newAndRepeatedKeys & DPAD_UP) && gPokedexView->menuCursorPos)
{
- gUnknown_0202FFB4->unk652--;
+ gPokedexView->menuCursorPos--;
PlaySE(SE_SELECT);
}
- else if((gMain.newAndRepeatedKeys & DPAD_DOWN) && gUnknown_0202FFB4->unk652 <= 3)
+ else if((gMain.newAndRepeatedKeys & DPAD_DOWN) && gPokedexView->menuCursorPos <= 3)
{
- gUnknown_0202FFB4->unk652++;
+ gPokedexView->menuCursorPos++;
PlaySE(SE_SELECT);
}
}
@@ -704,11 +790,11 @@ void Task_PokedexResultsScreenMenu(u8 taskId)
void sub_808D118(u8 taskId)
{
- if(gSprites[gUnknown_0202FFB4->unk626].pos1.x == 0x30 &&
- gSprites[gUnknown_0202FFB4->unk626].pos1.y == 0x38)
+ if(gSprites[gPokedexView->unk626].pos1.x == 0x30 &&
+ gSprites[gPokedexView->unk626].pos1.y == 0x38)
{
- gUnknown_0202FFB4->unk64B = gUnknown_0202FFB4->unk64A;
- gTasks[taskId].data[0] = sub_808F210(&gUnknown_0202FFB4->unk0[gUnknown_0202FFB4->unk60E], gUnknown_0202FFB4->unk626);
+ gPokedexView->unk64B = gPokedexView->unk64A;
+ gTasks[taskId].data[0] = sub_808F210(&gPokedexView->unk0[gPokedexView->selectedPokemon], gPokedexView->unk626);
gTasks[taskId].func = sub_808D198;
}
}
@@ -717,11 +803,11 @@ void sub_808D198(u8 taskId)
{
if(gTasks[gTasks[taskId].data[0]].isActive)
{
- if(gUnknown_0202FFB4->unk64A == 1 &&
+ if(gPokedexView->unk64A == 1 &&
!sub_808F250(gTasks[taskId].data[0]) &&
sub_808E71C())
{
- sub_808F284(&gUnknown_0202FFB4->unk0[gUnknown_0202FFB4->unk60E], gTasks[taskId].data[0]);
+ sub_808F284(&gPokedexView->unk0[gPokedexView->selectedPokemon], gTasks[taskId].data[0]);
}
}
else
@@ -734,12 +820,12 @@ void Task_PokedexResultsScreenReturnToMainScreen(u8 taskId)
{
if(!gPaletteFade.active)
{
- gUnknown_0202FFB4->unk62C = gUnknown_0202FFB4->unk62A;
- gUnknown_0202FFB4->unk60E = gUnknown_0202FFB4->unk610;
- gUnknown_0202FFB4->unk612 = gUnknown_0202FFB4->unk614;
+ gPokedexView->unk62C = gPokedexView->unk62A;
+ gPokedexView->selectedPokemon = gPokedexView->unk610;
+ gPokedexView->dexMode = gPokedexView->unk614;
if(!IsNationalPokedex())
- gUnknown_0202FFB4->unk612 = 0;
- gUnknown_0202FFB4->unk616 = gUnknown_0202FFB4->unk618;
+ gPokedexView->dexMode = DEX_MODE_HOENN;
+ gPokedexView->dexOrder = gPokedexView->unk618;
gTasks[taskId].func = Task_PokedexShowMainScreen;
}
}
@@ -748,12 +834,12 @@ void Task_PokedexResultsScreenExitPokedex(u8 taskId)
{
if(!gPaletteFade.active)
{
- gUnknown_0202FFB4->unk62C = gUnknown_0202FFB4->unk62A;
- gUnknown_0202FFB4->unk60E = gUnknown_0202FFB4->unk610;
- gUnknown_0202FFB4->unk612 = gUnknown_0202FFB4->unk614;
+ gPokedexView->unk62C = gPokedexView->unk62A;
+ gPokedexView->selectedPokemon = gPokedexView->unk610;
+ gPokedexView->dexMode = gPokedexView->unk614;
if(!IsNationalPokedex())
- gUnknown_0202FFB4->unk612 = 0;
- gUnknown_0202FFB4->unk616 = gUnknown_0202FFB4->unk618;
+ gPokedexView->dexMode = DEX_MODE_HOENN;
+ gPokedexView->dexOrder = gPokedexView->unk618;
gTasks[taskId].func = Task_ClosePokedex;
}
}
@@ -769,9 +855,9 @@ bool8 sub_808D344(u8 a)
return 0;
//_0808D39E
SetVBlankCallback(NULL);
- gUnknown_0202FFB4->unk64A = a;
+ gPokedexView->unk64A = a;
sub_8091060(0);
- REG_BG2VOFS = gUnknown_0202FFB4->unk62D;
+ REG_BG2VOFS = gPokedexView->unk62D;
LZ77UnCompVram(gPokedexMenu_Gfx, (void *)(VRAM));
LZ77UnCompVram(gUnknown_08E96738, (void *)(VRAM + 0x6800));
LZ77UnCompVram(gUnknown_08E9C6DC, (void *)(VRAM + 0x7800));
@@ -782,9 +868,9 @@ bool8 sub_808D344(u8 a)
LZ77UnCompVram(gUnknown_08E96994, (void *)(VRAM + 0x6500));
ResetPaletteFade();
if(a == 0)
- gUnknown_0202FFB4->unk64C_1 = 0;
+ gPokedexView->unk64C_1 = 0;
else
- gUnknown_0202FFB4->unk64C_1 = 1;
+ gPokedexView->unk64C_1 = 1;
sub_808D640();
gMain.state = 1;
break;
@@ -805,10 +891,10 @@ bool8 sub_808D344(u8 a)
break;
case 3:
if(a == 0)
- sub_808D690(gUnknown_0202FFB4->unk612, gUnknown_0202FFB4->unk616);
- sub_808E0CC(gUnknown_0202FFB4->unk60E, 0xE);
- gUnknown_0202FFB4->unk650 = 0;
- gUnknown_0202FFB4->unk654 = 0;
+ SortPokedex(gPokedexView->dexMode, gPokedexView->dexOrder);
+ sub_808E0CC(gPokedexView->selectedPokemon, 0xE);
+ gPokedexView->menuIsOpen = 0;
+ gPokedexView->menuY = 0;
gMain.state++;
break;
case 4:
@@ -846,7 +932,7 @@ bool8 sub_808D344(u8 a)
void sub_808D640(void)
{
- if(gUnknown_0202FFB4->unk64C_1)
+ if(gPokedexView->unk64C_1)
LoadPalette(gUnknown_0839F67C + 0x2, 1, 0xBE);
else if(!IsNationalPokedex())
LoadPalette(gPokedexMenu_Pal + 0x2, 1, 0xBE);
@@ -854,22 +940,21 @@ void sub_808D640(void)
LoadPalette(gUnknown_0839F73C + 0x2, 1, 0xBE);
}
-//Pokedex sorting function
-void sub_808D690(u8 a, u8 mode)
+void SortPokedex(u8 dexMode, u8 sortMode)
{
u16 vars[3]; //I have no idea why three regular variables are stored in an array, but whatever.
s16 i;
- gUnknown_0202FFB4->unk60C = 0;
+ gPokedexView->unk60C = 0;
- switch(a)
+ switch(dexMode)
{
default:
- case 0:
+ case DEX_MODE_HOENN:
vars[0] = 202;
vars[1] = 1;
break;
- case 1:
+ case DEX_MODE_NATIONAL:
if(IsNationalPokedex())
{
vars[0] = 386;
@@ -878,12 +963,12 @@ void sub_808D690(u8 a, u8 mode)
else
{
vars[0] = 202;
- vars[1] = a;
+ vars[1] = 1;
}
break;
}
- switch(mode)
+ switch(sortMode)
{
case 0:
{
@@ -892,11 +977,11 @@ void sub_808D690(u8 a, u8 mode)
for(i = 0; i < vars[0]; i++)
{
vars[2] = HoennToNationalOrder(i + 1);
- gUnknown_0202FFB4->unk0[i].a = vars[2];
- gUnknown_0202FFB4->unk0[i].seen = sub_8090D90(vars[2], 0);
- gUnknown_0202FFB4->unk0[i].owned = sub_8090D90(vars[2], 1);
- if(gUnknown_0202FFB4->unk0[i].seen)
- gUnknown_0202FFB4->unk60C = i + 1;
+ gPokedexView->unk0[i].dexNum = vars[2];
+ gPokedexView->unk0[i].seen = sub_8090D90(vars[2], 0);
+ gPokedexView->unk0[i].owned = sub_8090D90(vars[2], 1);
+ if(gPokedexView->unk0[i].seen)
+ gPokedexView->unk60C = i + 1;
}
}
else
@@ -913,11 +998,11 @@ void sub_808D690(u8 a, u8 mode)
if(r10)
{
asm(""); //Needed to match for some reason
- gUnknown_0202FFB4->unk0[r5].a = vars[2];
- gUnknown_0202FFB4->unk0[r5].seen = sub_8090D90(vars[2], 0);
- gUnknown_0202FFB4->unk0[r5].owned = sub_8090D90(vars[2], 1);
- if(gUnknown_0202FFB4->unk0[r5].seen)
- gUnknown_0202FFB4->unk60C = r5 + 1;
+ gPokedexView->unk0[r5].dexNum = vars[2];
+ gPokedexView->unk0[r5].seen = sub_8090D90(vars[2], 0);
+ gPokedexView->unk0[r5].owned = sub_8090D90(vars[2], 1);
+ if(gPokedexView->unk0[r5].seen)
+ gPokedexView->unk60C = r5 + 1;
r5++;
}
}
@@ -931,10 +1016,10 @@ void sub_808D690(u8 a, u8 mode)
if(NationalToHoennOrder(vars[2]) <= vars[0] && sub_8090D90(vars[2], 0))
{
- gUnknown_0202FFB4->unk0[gUnknown_0202FFB4->unk60C].a = vars[2];
- gUnknown_0202FFB4->unk0[gUnknown_0202FFB4->unk60C].seen = 1;
- gUnknown_0202FFB4->unk0[gUnknown_0202FFB4->unk60C].owned = sub_8090D90(vars[2], 1);
- gUnknown_0202FFB4->unk60C++;
+ gPokedexView->unk0[gPokedexView->unk60C].dexNum = vars[2];
+ gPokedexView->unk0[gPokedexView->unk60C].seen = 1;
+ gPokedexView->unk0[gPokedexView->unk60C].owned = sub_8090D90(vars[2], 1);
+ gPokedexView->unk60C++;
}
}
break;
@@ -945,10 +1030,10 @@ void sub_808D690(u8 a, u8 mode)
if(NationalToHoennOrder(vars[2]) <= vars[0] && sub_8090D90(vars[2], 1))
{
- gUnknown_0202FFB4->unk0[gUnknown_0202FFB4->unk60C].a = vars[2];
- gUnknown_0202FFB4->unk0[gUnknown_0202FFB4->unk60C].seen = 1;
- gUnknown_0202FFB4->unk0[gUnknown_0202FFB4->unk60C].owned = 1;
- gUnknown_0202FFB4->unk60C++;
+ gPokedexView->unk0[gPokedexView->unk60C].dexNum = vars[2];
+ gPokedexView->unk0[gPokedexView->unk60C].seen = 1;
+ gPokedexView->unk0[gPokedexView->unk60C].owned = 1;
+ gPokedexView->unk60C++;
}
}
break;
@@ -959,10 +1044,10 @@ void sub_808D690(u8 a, u8 mode)
if(NationalToHoennOrder(vars[2]) <= vars[0] && sub_8090D90(vars[2], 1))
{
- gUnknown_0202FFB4->unk0[gUnknown_0202FFB4->unk60C].a = vars[2];
- gUnknown_0202FFB4->unk0[gUnknown_0202FFB4->unk60C].seen = 1;
- gUnknown_0202FFB4->unk0[gUnknown_0202FFB4->unk60C].owned = 1;
- gUnknown_0202FFB4->unk60C++;
+ gPokedexView->unk0[gPokedexView->unk60C].dexNum = vars[2];
+ gPokedexView->unk0[gPokedexView->unk60C].seen = 1;
+ gPokedexView->unk0[gPokedexView->unk60C].owned = 1;
+ gPokedexView->unk60C++;
}
}
break;
@@ -973,10 +1058,10 @@ void sub_808D690(u8 a, u8 mode)
if(NationalToHoennOrder(vars[2]) <= vars[0] && sub_8090D90(vars[2], 1))
{
- gUnknown_0202FFB4->unk0[gUnknown_0202FFB4->unk60C].a = vars[2];
- gUnknown_0202FFB4->unk0[gUnknown_0202FFB4->unk60C].seen = 1;
- gUnknown_0202FFB4->unk0[gUnknown_0202FFB4->unk60C].owned = 1;
- gUnknown_0202FFB4->unk60C++;
+ gPokedexView->unk0[gPokedexView->unk60C].dexNum = vars[2];
+ gPokedexView->unk0[gPokedexView->unk60C].seen = 1;
+ gPokedexView->unk0[gPokedexView->unk60C].owned = 1;
+ gPokedexView->unk60C++;
}
}
break;
@@ -987,19 +1072,19 @@ void sub_808D690(u8 a, u8 mode)
if(NationalToHoennOrder(vars[2]) <= vars[0] && sub_8090D90(vars[2], 1))
{
- gUnknown_0202FFB4->unk0[gUnknown_0202FFB4->unk60C].a = vars[2];
- gUnknown_0202FFB4->unk0[gUnknown_0202FFB4->unk60C].seen = 1;
- gUnknown_0202FFB4->unk0[gUnknown_0202FFB4->unk60C].owned = 1;
- gUnknown_0202FFB4->unk60C++;
+ gPokedexView->unk0[gPokedexView->unk60C].dexNum = vars[2];
+ gPokedexView->unk0[gPokedexView->unk60C].seen = 1;
+ gPokedexView->unk0[gPokedexView->unk60C].owned = 1;
+ gPokedexView->unk60C++;
}
}
break;
}
- for(i = gUnknown_0202FFB4->unk60C; i < 386; i++)
+ for(i = gPokedexView->unk60C; i < 386; i++)
{
- gUnknown_0202FFB4->unk0[i].a |= 0xFFFF;
- gUnknown_0202FFB4->unk0[i].seen = 0;
- gUnknown_0202FFB4->unk0[i].owned = 0;
+ gPokedexView->unk0[i].dexNum |= 0xFFFF;
+ gPokedexView->unk0[i].seen = 0;
+ gPokedexView->unk0[i].owned = 0;
}
}
@@ -1015,16 +1100,16 @@ void sub_808DBE8(u8 a, u16 b, u16 c)
for(i = 0; i <= 10; i++)
{
- if((u16)_b > 385 || gUnknown_0202FFB4->unk0[_b].a == 0xFFFF)
+ if((u16)_b > 385 || gPokedexView->unk0[_b].dexNum == 0xFFFF)
sub_808E090(0x11, i * 2, c);
else
{
sub_808E090(0x11, i * 2, c);
- if(gUnknown_0202FFB4->unk0[_b].seen)
+ if(gPokedexView->unk0[_b].seen)
{
sub_808DEB0(_b, 0x12, i * 2, c);
- sub_808DF88(gUnknown_0202FFB4->unk0[_b].owned, 0x11, i * 2, c);
- sub_808DFE4(gUnknown_0202FFB4->unk0[_b].a, 0x17, i * 2);
+ sub_808DF88(gPokedexView->unk0[_b].owned, 0x11, i * 2, c);
+ sub_808DFE4(gPokedexView->unk0[_b].dexNum, 0x17, i * 2);
}
else
{
@@ -1041,22 +1126,22 @@ void sub_808DBE8(u8 a, u16 b, u16 c)
{
s16 _b = b - 5;
- if((u16)_b > 385 || gUnknown_0202FFB4->unk0[_b].a == 0xFFFF)
- sub_808E090(0x11, gUnknown_0202FFB4->unk630 * 2, c);
+ if((u16)_b > 385 || gPokedexView->unk0[_b].dexNum == 0xFFFF)
+ sub_808E090(0x11, gPokedexView->unk630 * 2, c);
else
{
- sub_808E090(0x11, gUnknown_0202FFB4->unk630 * 2, c);
- if(gUnknown_0202FFB4->unk0[_b].seen)
+ sub_808E090(0x11, gPokedexView->unk630 * 2, c);
+ if(gPokedexView->unk0[_b].seen)
{
- sub_808DEB0(_b, 0x12, gUnknown_0202FFB4->unk630 * 2, c);
- sub_808DF88(gUnknown_0202FFB4->unk0[_b].owned, 0x11, gUnknown_0202FFB4->unk630 * 2, c);
- sub_808DFE4(gUnknown_0202FFB4->unk0[_b].a, 0x17, gUnknown_0202FFB4->unk630 * 2);
+ sub_808DEB0(_b, 0x12, gPokedexView->unk630 * 2, c);
+ sub_808DF88(gPokedexView->unk0[_b].owned, 0x11, gPokedexView->unk630 * 2, c);
+ sub_808DFE4(gPokedexView->unk0[_b].dexNum, 0x17, gPokedexView->unk630 * 2);
}
else
{
- sub_808DEB0(_b, 0x12, gUnknown_0202FFB4->unk630 * 2, c);
- sub_808DF88(0, 0x11, gUnknown_0202FFB4->unk630 * 2, c);
- sub_808DFE4(0, 0x17, gUnknown_0202FFB4->unk630 * 2);
+ sub_808DEB0(_b, 0x12, gPokedexView->unk630 * 2, c);
+ sub_808DF88(0, 0x11, gPokedexView->unk630 * 2, c);
+ sub_808DFE4(0, 0x17, gPokedexView->unk630 * 2);
}
}
break;
@@ -1064,20 +1149,20 @@ void sub_808DBE8(u8 a, u16 b, u16 c)
case 2:
{
s16 _b = b + 5;
- u16 r2 = gUnknown_0202FFB4->unk630 + 10;
+ u16 r2 = gPokedexView->unk630 + 10;
if(r2 > 15)
r2 -= 16;
- if((u16)_b > 385 || gUnknown_0202FFB4->unk0[_b].a == 0xFFFF)
+ if((u16)_b > 385 || gPokedexView->unk0[_b].dexNum == 0xFFFF)
sub_808E090(0x11, r2 * 2, c);
else
{
sub_808E090(0x11, r2 * 2, c);
- if(gUnknown_0202FFB4->unk0[_b].seen)
+ if(gPokedexView->unk0[_b].seen)
{
sub_808DEB0(_b, 0x12, r2 * 2, c);
- sub_808DF88(gUnknown_0202FFB4->unk0[_b].owned, 0x11, r2 * 2, c);
- sub_808DFE4(gUnknown_0202FFB4->unk0[_b].a, 0x17, r2 * 2);
+ sub_808DF88(gPokedexView->unk0[_b].owned, 0x11, r2 * 2, c);
+ sub_808DFE4(gPokedexView->unk0[_b].dexNum, 0x17, r2 * 2);
}
else
{
@@ -1095,9 +1180,9 @@ void sub_808DEB0(u16 a, u8 b, u8 c, u16 d)
{
u8 text[4];
u16 unk[2];
- u16 r7 = gUnknown_0202FFB4->unk0[a].a;
+ u16 r7 = gPokedexView->unk0[a].dexNum;
- if(gUnknown_0202FFB4->unk612 == 0)
+ if(gPokedexView->dexMode == DEX_MODE_HOENN)
r7 = NationalToHoennOrder(r7);
unk[0] = 0x3FC;
unk[1] = 0x3FD;
@@ -1267,10 +1352,10 @@ void sub_808E0CC(u16 a, u16 b)
u8 spriteId;
for(i = 0; i < 4; i++)
- gUnknown_0202FFB4->unk61E[i] |= 0xFFFF;
- gUnknown_0202FFB4->unk626 = 0xFFFF;
+ gPokedexView->unk61E[i] |= 0xFFFF;
+ gPokedexView->unk626 = 0xFFFF;
sub_808DBE8(0, a, b);
- REG_BG2VOFS = gUnknown_0202FFB4->unk62D;
+ REG_BG2VOFS = gPokedexView->unk62D;
unk = sub_808E888(a - 1);
if(unk != 0xFFFF)
{
@@ -1292,8 +1377,8 @@ void sub_808E0CC(u16 a, u16 b)
gSprites[spriteId].callback = sub_808EE28;
gSprites[spriteId].data5 = 32;
}
- gUnknown_0202FFB4->unk630 = 0;
- gUnknown_0202FFB4->unk632 = 0;
+ gPokedexView->unk630 = 0;
+ gPokedexView->unk632 = 0;
}
bool8 sub_808E208(u8 a, u8 b, u8 c)
@@ -1301,30 +1386,30 @@ bool8 sub_808E208(u8 a, u8 b, u8 c)
u16 i;
u8 foo;
- if(gUnknown_0202FFB4->unk62E)
+ if(gPokedexView->unk62E)
{
- gUnknown_0202FFB4->unk62E--;
+ gPokedexView->unk62E--;
switch(a)
{
case 1:
for(i = 0; i < 4; i++)
{
- if(gUnknown_0202FFB4->unk61E[i] != 0xFFFF)
- gSprites[gUnknown_0202FFB4->unk61E[i]].data5 += b;
+ if(gPokedexView->unk61E[i] != 0xFFFF)
+ gSprites[gPokedexView->unk61E[i]].data5 += b;
}
- foo = 16 * (c - gUnknown_0202FFB4->unk62E) / c;
- REG_BG2VOFS = gUnknown_0202FFB4->unk62D + gUnknown_0202FFB4->unk632 * 16 - foo;
- gUnknown_0202FFB4->unk62C -= gUnknown_0202FFB4->unk628;
+ foo = 16 * (c - gPokedexView->unk62E) / c;
+ REG_BG2VOFS = gPokedexView->unk62D + gPokedexView->unk632 * 16 - foo;
+ gPokedexView->unk62C -= gPokedexView->unk628;
break;
case 2:
for(i = 0; i < 4; i++)
{
- if(gUnknown_0202FFB4->unk61E[i] != 0xFFFF)
- gSprites[gUnknown_0202FFB4->unk61E[i]].data5 -= b;
+ if(gPokedexView->unk61E[i] != 0xFFFF)
+ gSprites[gPokedexView->unk61E[i]].data5 -= b;
}
- foo = 16 * (c - gUnknown_0202FFB4->unk62E) / c;
- REG_BG2VOFS = gUnknown_0202FFB4->unk62D + gUnknown_0202FFB4->unk632 * 16 + foo;
- gUnknown_0202FFB4->unk62C += gUnknown_0202FFB4->unk628;
+ foo = 16 * (c - gPokedexView->unk62E) / c;
+ REG_BG2VOFS = gPokedexView->unk62D + gPokedexView->unk632 * 16 + foo;
+ gPokedexView->unk62C += gPokedexView->unk628;
break;
}
return 0;
@@ -1332,7 +1417,7 @@ bool8 sub_808E208(u8 a, u8 b, u8 c)
//_0808E36C
else
{
- REG_BG2VOFS = gUnknown_0202FFB4->unk62D + gUnknown_0202FFB4->unk630 * 16;
+ REG_BG2VOFS = gPokedexView->unk62D + gPokedexView->unk630 * 16;
return 1;
}
}
@@ -1342,7 +1427,7 @@ void sub_808E398(u8 a, u16 b)
u16 unk;
u8 spriteId;
- gUnknown_0202FFB4->unk632 = gUnknown_0202FFB4->unk630;
+ gPokedexView->unk632 = gPokedexView->unk630;
switch(a)
{
case 1:
@@ -1354,10 +1439,10 @@ void sub_808E398(u8 a, u16 b)
gSprites[spriteId].callback = sub_808EE28;
gSprites[spriteId].data5 = 0xFFC0;
}
- if(gUnknown_0202FFB4->unk630 > 0)
- gUnknown_0202FFB4->unk630--;
+ if(gPokedexView->unk630 > 0)
+ gPokedexView->unk630--;
else
- gUnknown_0202FFB4->unk630 = 0xF;
+ gPokedexView->unk630 = 0xF;
break;
}
case 2:
@@ -1369,10 +1454,10 @@ void sub_808E398(u8 a, u16 b)
gSprites[spriteId].callback = sub_808EE28;
gSprites[spriteId].data5 = 0x40;
}
- if(gUnknown_0202FFB4->unk630 <= 0xE)
- gUnknown_0202FFB4->unk630++;
+ if(gPokedexView->unk630 <= 0xE)
+ gPokedexView->unk630++;
else
- gUnknown_0202FFB4->unk630 = 0;
+ gPokedexView->unk630 = 0;
break;
}
}
@@ -1392,7 +1477,7 @@ u16 sub_808E48C(u16 a, u16 b)
//_0808E4B6
if(gMain.heldKeys & 0x80)
{
- if(a < gUnknown_0202FFB4->unk60C - 1)
+ if(a < gPokedexView->unk60C - 1)
goto _0808E5C4;
}
//_0808E4CE
@@ -1403,69 +1488,69 @@ u16 sub_808E48C(u16 a, u16 b)
//_0808E4E0
for(i = 0; i < 7; i++)
{
- a = sub_8091818(1, a, 0, gUnknown_0202FFB4->unk60C - 1);
+ a = sub_8091818(1, a, 0, gPokedexView->unk60C - 1);
}
- gUnknown_0202FFB4->unk62C += (a - r6) * 16;
+ gPokedexView->unk62C += (a - r6) * 16;
sub_808E82C();
sub_808E0CC(a, 0xE);
- PlaySE(0x6D);
+ PlaySE(SE_Z_PAGE);
goto _0808E5A2;
}
//_0808E53C
- if(!(gMain.newKeys & 0x10) || a >= gUnknown_0202FFB4->unk60C - 1)
+ if(!(gMain.newKeys & 0x10) || a >= gPokedexView->unk60C - 1)
goto _0808E5A2;
r6 = a;
for(i = 0; i < 7; i++)
{
- a = sub_8091818(0, a, 0, gUnknown_0202FFB4->unk60C - 1);
+ a = sub_8091818(0, a, 0, gPokedexView->unk60C - 1);
}
- gUnknown_0202FFB4->unk62C += (a - r6) * 16;
+ gPokedexView->unk62C += (a - r6) * 16;
sub_808E82C();
sub_808E0CC(a, 0xE);
- PlaySE(0x6D);
+ PlaySE(SE_Z_PAGE);
goto _0808E5A2;
_0808E5A2:
if(r10 != 0)
goto _0808E628;
- gUnknown_0202FFB4->unk638 = r10;
+ gPokedexView->unk638 = r10;
return a;
_0808E5C4:
r10 = 2;
- a = sub_8091818(0, a, 0, gUnknown_0202FFB4->unk60C - 1);
+ a = sub_8091818(0, a, 0, gPokedexView->unk60C - 1);
sub_808E398(2, a);
//goto _0808E60E
sub_808DBE8(2, a, b);
- PlaySE(0x6C);
+ PlaySE(SE_Z_SCROLL);
}
//_0808E5E4
else
{
r10 = 1;
- a = sub_8091818(1, a, 0, gUnknown_0202FFB4->unk60C - 1);
+ a = sub_8091818(1, a, 0, gPokedexView->unk60C - 1);
sub_808E398(1, a);
//_0808E60E
sub_808DBE8(1, a, b);
- PlaySE(0x6C);
+ PlaySE(SE_Z_SCROLL);
}
//_0808E60E
goto _0808E5A2;
_0808E628:
- r5 = gUnknown_083A05EC[gUnknown_0202FFB4->unk638 / 4];
- r3 = gUnknown_083A05F1[gUnknown_0202FFB4->unk638 / 4];
- gUnknown_0202FFB4->unk62E = r3;
- gUnknown_0202FFB4->unk636 = r3;
- gUnknown_0202FFB4->unk634 = r5;
- gUnknown_0202FFB4->unk62F = r10;
- gUnknown_0202FFB4->unk628 = r5;
- sub_808E208(gUnknown_0202FFB4->unk62F, gUnknown_0202FFB4->unk634, gUnknown_0202FFB4->unk636);
- if(gUnknown_0202FFB4->unk638 <= 0xB)
- gUnknown_0202FFB4->unk638++;
+ r5 = gUnknown_083A05EC[gPokedexView->unk638 / 4];
+ r3 = gUnknown_083A05F1[gPokedexView->unk638 / 4];
+ gPokedexView->unk62E = r3;
+ gPokedexView->unk636 = r3;
+ gPokedexView->unk634 = r5;
+ gPokedexView->unk62F = r10;
+ gPokedexView->unk628 = r5;
+ sub_808E208(gPokedexView->unk62F, gPokedexView->unk634, gPokedexView->unk636);
+ if(gPokedexView->unk638 <= 0xB)
+ gPokedexView->unk638++;
return a;
}
#else
@@ -1473,262 +1558,262 @@ __attribute__((naked))
u16 sub_808E48C(u16 a, u16 b)
{
asm(".syntax unified\n\
- push {r4-r7,lr}\n\
- mov r7, r10\n\
- mov r6, r9\n\
- mov r5, r8\n\
- push {r5-r7}\n\
- lsls r0, 16\n\
- lsrs r7, r0, 16\n\
- lsls r1, 16\n\
- lsrs r4, r1, 16\n\
- movs r0, 0\n\
- mov r10, r0\n\
- ldr r1, _0808E52C\n\
- ldrh r2, [r1, 0x2C]\n\
- movs r0, 0x40\n\
- ands r0, r2\n\
- adds r3, r1, 0\n\
- cmp r0, 0\n\
- beq _0808E4B6\n\
- cmp r7, 0\n\
- beq _0808E4B6\n\
- b _0808E5E4\n\
+ push {r4-r7,lr}\n\
+ mov r7, r10\n\
+ mov r6, r9\n\
+ mov r5, r8\n\
+ push {r5-r7}\n\
+ lsls r0, 16\n\
+ lsrs r7, r0, 16\n\
+ lsls r1, 16\n\
+ lsrs r4, r1, 16\n\
+ movs r0, 0\n\
+ mov r10, r0\n\
+ ldr r1, _0808E52C\n\
+ ldrh r2, [r1, 0x2C]\n\
+ movs r0, 0x40\n\
+ ands r0, r2\n\
+ adds r3, r1, 0\n\
+ cmp r0, 0\n\
+ beq _0808E4B6\n\
+ cmp r7, 0\n\
+ beq _0808E4B6\n\
+ b _0808E5E4\n\
_0808E4B6:\n\
- movs r0, 0x80\n\
- ands r0, r2\n\
- cmp r0, 0\n\
- beq _0808E4CE\n\
- ldr r0, _0808E530\n\
- ldr r0, [r0]\n\
- ldr r1, _0808E534\n\
- adds r0, r1\n\
- ldrh r0, [r0]\n\
- subs r0, 0x1\n\
- cmp r7, r0\n\
- blt _0808E5C4\n\
+ movs r0, 0x80\n\
+ ands r0, r2\n\
+ cmp r0, 0\n\
+ beq _0808E4CE\n\
+ ldr r0, _0808E530\n\
+ ldr r0, [r0]\n\
+ ldr r1, _0808E534\n\
+ adds r0, r1\n\
+ ldrh r0, [r0]\n\
+ subs r0, 0x1\n\
+ cmp r7, r0\n\
+ blt _0808E5C4\n\
_0808E4CE:\n\
- ldrh r1, [r3, 0x2E]\n\
- movs r0, 0x20\n\
- ands r0, r1\n\
- cmp r0, 0\n\
- beq _0808E53C\n\
- cmp r7, 0\n\
- beq _0808E53C\n\
- adds r6, r7, 0\n\
- movs r4, 0\n\
+ ldrh r1, [r3, 0x2E]\n\
+ movs r0, 0x20\n\
+ ands r0, r1\n\
+ cmp r0, 0\n\
+ beq _0808E53C\n\
+ cmp r7, 0\n\
+ beq _0808E53C\n\
+ adds r6, r7, 0\n\
+ movs r4, 0\n\
_0808E4E0:\n\
- ldr r5, _0808E530\n\
- ldr r0, [r5]\n\
- ldr r2, _0808E534\n\
- adds r0, r2\n\
- ldrh r3, [r0]\n\
- subs r3, 0x1\n\
- lsls r3, 16\n\
- lsrs r3, 16\n\
- movs r0, 0x1\n\
- adds r1, r7, 0\n\
- movs r2, 0\n\
- bl sub_8091818\n\
- adds r7, r0, 0\n\
- adds r0, r4, 0x1\n\
- lsls r0, 24\n\
- lsrs r4, r0, 24\n\
- cmp r4, 0x6\n\
- bls _0808E4E0\n\
- ldr r1, [r5]\n\
- ldr r3, _0808E538\n\
- adds r1, r3\n\
- subs r0, r7, r6\n\
- lsls r0, 4\n\
- ldrb r2, [r1]\n\
- adds r0, r2\n\
- strb r0, [r1]\n\
- bl sub_808E82C\n\
- adds r0, r7, 0\n\
- movs r1, 0xE\n\
- bl sub_808E0CC\n\
- movs r0, 0x6D\n\
- bl PlaySE\n\
- b _0808E5A2\n\
- .align 2, 0\n\
+ ldr r5, _0808E530\n\
+ ldr r0, [r5]\n\
+ ldr r2, _0808E534\n\
+ adds r0, r2\n\
+ ldrh r3, [r0]\n\
+ subs r3, 0x1\n\
+ lsls r3, 16\n\
+ lsrs r3, 16\n\
+ movs r0, 0x1\n\
+ adds r1, r7, 0\n\
+ movs r2, 0\n\
+ bl sub_8091818\n\
+ adds r7, r0, 0\n\
+ adds r0, r4, 0x1\n\
+ lsls r0, 24\n\
+ lsrs r4, r0, 24\n\
+ cmp r4, 0x6\n\
+ bls _0808E4E0\n\
+ ldr r1, [r5]\n\
+ ldr r3, _0808E538\n\
+ adds r1, r3\n\
+ subs r0, r7, r6\n\
+ lsls r0, 4\n\
+ ldrb r2, [r1]\n\
+ adds r0, r2\n\
+ strb r0, [r1]\n\
+ bl sub_808E82C\n\
+ adds r0, r7, 0\n\
+ movs r1, 0xE\n\
+ bl sub_808E0CC\n\
+ movs r0, 0x6D\n\
+ bl PlaySE\n\
+ b _0808E5A2\n\
+ .align 2, 0\n\
_0808E52C: .4byte gMain\n\
-_0808E530: .4byte gUnknown_0202FFB4\n\
+_0808E530: .4byte gPokedexView\n\
_0808E534: .4byte 0x0000060c\n\
_0808E538: .4byte 0x0000062c\n\
_0808E53C:\n\
- ldrh r1, [r3, 0x2E]\n\
- movs r0, 0x10\n\
- ands r0, r1\n\
- cmp r0, 0\n\
- beq _0808E5A2\n\
- ldr r0, _0808E5B8\n\
- ldr r0, [r0]\n\
- ldr r3, _0808E5BC\n\
- adds r0, r3\n\
- ldrh r0, [r0]\n\
- subs r0, 0x1\n\
- cmp r7, r0\n\
- bge _0808E5A2\n\
- adds r6, r7, 0\n\
- movs r4, 0\n\
+ ldrh r1, [r3, 0x2E]\n\
+ movs r0, 0x10\n\
+ ands r0, r1\n\
+ cmp r0, 0\n\
+ beq _0808E5A2\n\
+ ldr r0, _0808E5B8\n\
+ ldr r0, [r0]\n\
+ ldr r3, _0808E5BC\n\
+ adds r0, r3\n\
+ ldrh r0, [r0]\n\
+ subs r0, 0x1\n\
+ cmp r7, r0\n\
+ bge _0808E5A2\n\
+ adds r6, r7, 0\n\
+ movs r4, 0\n\
_0808E55A:\n\
- ldr r5, _0808E5B8\n\
- ldr r0, [r5]\n\
- ldr r1, _0808E5BC\n\
- adds r0, r1\n\
- ldrh r3, [r0]\n\
- subs r3, 0x1\n\
- lsls r3, 16\n\
- lsrs r3, 16\n\
- movs r0, 0\n\
- adds r1, r7, 0\n\
- movs r2, 0\n\
- bl sub_8091818\n\
- adds r7, r0, 0\n\
- adds r0, r4, 0x1\n\
- lsls r0, 24\n\
- lsrs r4, r0, 24\n\
- cmp r4, 0x6\n\
- bls _0808E55A\n\
- ldr r1, [r5]\n\
- ldr r2, _0808E5C0\n\
- adds r1, r2\n\
- subs r0, r7, r6\n\
- lsls r0, 4\n\
- ldrb r3, [r1]\n\
- adds r0, r3\n\
- strb r0, [r1]\n\
- bl sub_808E82C\n\
- adds r0, r7, 0\n\
- movs r1, 0xE\n\
- bl sub_808E0CC\n\
- movs r0, 0x6D\n\
- bl PlaySE\n\
+ ldr r5, _0808E5B8\n\
+ ldr r0, [r5]\n\
+ ldr r1, _0808E5BC\n\
+ adds r0, r1\n\
+ ldrh r3, [r0]\n\
+ subs r3, 0x1\n\
+ lsls r3, 16\n\
+ lsrs r3, 16\n\
+ movs r0, 0\n\
+ adds r1, r7, 0\n\
+ movs r2, 0\n\
+ bl sub_8091818\n\
+ adds r7, r0, 0\n\
+ adds r0, r4, 0x1\n\
+ lsls r0, 24\n\
+ lsrs r4, r0, 24\n\
+ cmp r4, 0x6\n\
+ bls _0808E55A\n\
+ ldr r1, [r5]\n\
+ ldr r2, _0808E5C0\n\
+ adds r1, r2\n\
+ subs r0, r7, r6\n\
+ lsls r0, 4\n\
+ ldrb r3, [r1]\n\
+ adds r0, r3\n\
+ strb r0, [r1]\n\
+ bl sub_808E82C\n\
+ adds r0, r7, 0\n\
+ movs r1, 0xE\n\
+ bl sub_808E0CC\n\
+ movs r0, 0x6D\n\
+ bl PlaySE\n\
_0808E5A2:\n\
- mov r0, r10\n\
- cmp r0, 0\n\
- bne _0808E628\n\
- ldr r0, _0808E5B8\n\
- ldr r0, [r0]\n\
- movs r1, 0xC7\n\
- lsls r1, 3\n\
- adds r0, r1\n\
- mov r2, r10\n\
- strh r2, [r0]\n\
- b _0808E68E\n\
- .align 2, 0\n\
-_0808E5B8: .4byte gUnknown_0202FFB4\n\
+ mov r0, r10\n\
+ cmp r0, 0\n\
+ bne _0808E628\n\
+ ldr r0, _0808E5B8\n\
+ ldr r0, [r0]\n\
+ movs r1, 0xC7\n\
+ lsls r1, 3\n\
+ adds r0, r1\n\
+ mov r2, r10\n\
+ strh r2, [r0]\n\
+ b _0808E68E\n\
+ .align 2, 0\n\
+_0808E5B8: .4byte gPokedexView\n\
_0808E5BC: .4byte 0x0000060c\n\
_0808E5C0: .4byte 0x0000062c\n\
_0808E5C4:\n\
- movs r3, 0x2\n\
- mov r10, r3\n\
- lsls r3, r0, 16\n\
- lsrs r3, 16\n\
- movs r0, 0\n\
- adds r1, r7, 0\n\
- movs r2, 0\n\
- bl sub_8091818\n\
- adds r7, r0, 0\n\
- movs r0, 0x2\n\
- adds r1, r7, 0\n\
- bl sub_808E398\n\
- movs r0, 0x2\n\
- b _0808E60E\n\
+ movs r3, 0x2\n\
+ mov r10, r3\n\
+ lsls r3, r0, 16\n\
+ lsrs r3, 16\n\
+ movs r0, 0\n\
+ adds r1, r7, 0\n\
+ movs r2, 0\n\
+ bl sub_8091818\n\
+ adds r7, r0, 0\n\
+ movs r0, 0x2\n\
+ adds r1, r7, 0\n\
+ bl sub_808E398\n\
+ movs r0, 0x2\n\
+ b _0808E60E\n\
_0808E5E4:\n\
- movs r0, 0x1\n\
- mov r10, r0\n\
- ldr r0, _0808E620\n\
- ldr r0, [r0]\n\
- ldr r1, _0808E624\n\
- adds r0, r1\n\
- ldrh r3, [r0]\n\
- subs r3, 0x1\n\
- lsls r3, 16\n\
- lsrs r3, 16\n\
- movs r0, 0x1\n\
- adds r1, r7, 0\n\
- movs r2, 0\n\
- bl sub_8091818\n\
- adds r7, r0, 0\n\
- movs r0, 0x1\n\
- adds r1, r7, 0\n\
- bl sub_808E398\n\
- movs r0, 0x1\n\
+ movs r0, 0x1\n\
+ mov r10, r0\n\
+ ldr r0, _0808E620\n\
+ ldr r0, [r0]\n\
+ ldr r1, _0808E624\n\
+ adds r0, r1\n\
+ ldrh r3, [r0]\n\
+ subs r3, 0x1\n\
+ lsls r3, 16\n\
+ lsrs r3, 16\n\
+ movs r0, 0x1\n\
+ adds r1, r7, 0\n\
+ movs r2, 0\n\
+ bl sub_8091818\n\
+ adds r7, r0, 0\n\
+ movs r0, 0x1\n\
+ adds r1, r7, 0\n\
+ bl sub_808E398\n\
+ movs r0, 0x1\n\
_0808E60E:\n\
- adds r1, r7, 0\n\
- adds r2, r4, 0\n\
- bl sub_808DBE8\n\
- movs r0, 0x6C\n\
- bl PlaySE\n\
- b _0808E5A2\n\
- .align 2, 0\n\
-_0808E620: .4byte gUnknown_0202FFB4\n\
+ adds r1, r7, 0\n\
+ adds r2, r4, 0\n\
+ bl sub_808DBE8\n\
+ movs r0, 0x6C\n\
+ bl PlaySE\n\
+ b _0808E5A2\n\
+ .align 2, 0\n\
+_0808E620: .4byte gPokedexView\n\
_0808E624: .4byte 0x0000060c\n\
_0808E628:\n\
- ldr r1, _0808E6A0\n\
- ldr r6, _0808E6A4\n\
- ldr r2, [r6]\n\
- movs r3, 0xC7\n\
- lsls r3, 3\n\
- mov r9, r3\n\
- adds r0, r2, r3\n\
- ldrh r0, [r0]\n\
- lsrs r0, 2\n\
- adds r1, r0, r1\n\
- ldrb r5, [r1]\n\
- ldr r1, _0808E6A8\n\
- adds r0, r1\n\
- ldrb r3, [r0]\n\
- ldr r0, _0808E6AC\n\
- adds r2, r0\n\
- strb r3, [r2]\n\
- ldr r1, [r6]\n\
- ldr r2, _0808E6B0\n\
- mov r8, r2\n\
- adds r0, r1, r2\n\
- strh r3, [r0]\n\
- ldr r4, _0808E6B4\n\
- adds r0, r1, r4\n\
- strh r5, [r0]\n\
- ldr r3, _0808E6B8\n\
- adds r1, r3\n\
- mov r0, r10\n\
- strb r0, [r1]\n\
- ldr r2, [r6]\n\
- lsrs r5, 1\n\
- movs r1, 0xC5\n\
- lsls r1, 3\n\
- adds r0, r2, r1\n\
- strh r5, [r0]\n\
- adds r3, r2, r3\n\
- ldrb r0, [r3]\n\
- adds r4, r2, r4\n\
- ldrb r1, [r4]\n\
- add r2, r8\n\
- ldrb r2, [r2]\n\
- bl sub_808E208\n\
- ldr r0, [r6]\n\
- mov r2, r9\n\
- adds r1, r0, r2\n\
- ldrh r0, [r1]\n\
- cmp r0, 0xB\n\
- bhi _0808E68E\n\
- adds r0, 0x1\n\
- strh r0, [r1]\n\
+ ldr r1, _0808E6A0\n\
+ ldr r6, _0808E6A4\n\
+ ldr r2, [r6]\n\
+ movs r3, 0xC7\n\
+ lsls r3, 3\n\
+ mov r9, r3\n\
+ adds r0, r2, r3\n\
+ ldrh r0, [r0]\n\
+ lsrs r0, 2\n\
+ adds r1, r0, r1\n\
+ ldrb r5, [r1]\n\
+ ldr r1, _0808E6A8\n\
+ adds r0, r1\n\
+ ldrb r3, [r0]\n\
+ ldr r0, _0808E6AC\n\
+ adds r2, r0\n\
+ strb r3, [r2]\n\
+ ldr r1, [r6]\n\
+ ldr r2, _0808E6B0\n\
+ mov r8, r2\n\
+ adds r0, r1, r2\n\
+ strh r3, [r0]\n\
+ ldr r4, _0808E6B4\n\
+ adds r0, r1, r4\n\
+ strh r5, [r0]\n\
+ ldr r3, _0808E6B8\n\
+ adds r1, r3\n\
+ mov r0, r10\n\
+ strb r0, [r1]\n\
+ ldr r2, [r6]\n\
+ lsrs r5, 1\n\
+ movs r1, 0xC5\n\
+ lsls r1, 3\n\
+ adds r0, r2, r1\n\
+ strh r5, [r0]\n\
+ adds r3, r2, r3\n\
+ ldrb r0, [r3]\n\
+ adds r4, r2, r4\n\
+ ldrb r1, [r4]\n\
+ add r2, r8\n\
+ ldrb r2, [r2]\n\
+ bl sub_808E208\n\
+ ldr r0, [r6]\n\
+ mov r2, r9\n\
+ adds r1, r0, r2\n\
+ ldrh r0, [r1]\n\
+ cmp r0, 0xB\n\
+ bhi _0808E68E\n\
+ adds r0, 0x1\n\
+ strh r0, [r1]\n\
_0808E68E:\n\
- adds r0, r7, 0\n\
- pop {r3-r5}\n\
- mov r8, r3\n\
- mov r9, r4\n\
- mov r10, r5\n\
- pop {r4-r7}\n\
- pop {r1}\n\
- bx r1\n\
- .align 2, 0\n\
+ adds r0, r7, 0\n\
+ pop {r3-r5}\n\
+ mov r8, r3\n\
+ mov r9, r4\n\
+ mov r10, r5\n\
+ pop {r4-r7}\n\
+ pop {r1}\n\
+ bx r1\n\
+ .align 2, 0\n\
_0808E6A0: .4byte gUnknown_083A05EC\n\
-_0808E6A4: .4byte gUnknown_0202FFB4\n\
+_0808E6A4: .4byte gPokedexView\n\
_0808E6A8: .4byte gUnknown_083A05F1\n\
_0808E6AC: .4byte 0x0000062e\n\
_0808E6B0: .4byte 0x00000636\n\
@@ -1744,10 +1829,10 @@ void sub_808E6BC(void)
for(i = 0; i < 4; i++)
{
- u16 spriteId = gUnknown_0202FFB4->unk61E[i];
+ u16 spriteId = gPokedexView->unk61E[i];
if(gSprites[spriteId].pos2.x == 0 && gSprites[spriteId].pos2.y == 0 && spriteId != 0xFFFF)
- gUnknown_0202FFB4->unk626 = spriteId;
+ gPokedexView->unk626 = spriteId;
}
}
@@ -1755,54 +1840,51 @@ u8 sub_808E71C(void)
{
u16 r2;
u16 r3;
- u16 r4 = gUnknown_0202FFB4->unk60E;
+ u16 r4 = gPokedexView->selectedPokemon;
- if((gMain.newKeys & 0x40) && r4)
+ if((gMain.newKeys & DPAD_UP) && r4)
{
r2 = r4;
while(r2 != 0)
{
- r2 = sub_8091818(1, r2, 0, gUnknown_0202FFB4->unk60C - 1);
+ r2 = sub_8091818(1, r2, 0, gPokedexView->unk60C - 1);
- if(gUnknown_0202FFB4->unk0[r2].seen)
+ if(gPokedexView->unk0[r2].seen)
{
- //goto _0808E78C;
r4 = r2;
break;
}
}
- if(gUnknown_0202FFB4->unk60E == r4)
+ if(gPokedexView->selectedPokemon == r4)
return 0;
else
{
- gUnknown_0202FFB4->unk60E = r4;
- //goto _0808E80C
- gUnknown_0202FFB4->unk62C -= 16;
+ gPokedexView->selectedPokemon = r4;
+ gPokedexView->unk62C -= 16;
return 1;
}
}
- //_0808E7A4
- else if((gMain.newKeys & 0x80) && r4 < gUnknown_0202FFB4->unk60C - 1)
+ else if((gMain.newKeys & DPAD_DOWN) && r4 < gPokedexView->unk60C - 1)
{
r2 = r4;
- while(r2 < gUnknown_0202FFB4->unk60C - 1)
+ while(r2 < gPokedexView->unk60C - 1)
{
- r2 = sub_8091818(0, r2, 0, gUnknown_0202FFB4->unk60C - 1);
+ r2 = sub_8091818(0, r2, 0, gPokedexView->unk60C - 1);
- if(gUnknown_0202FFB4->unk0[r2].seen)
+ if(gPokedexView->unk0[r2].seen)
{
r4 = r2;
break;
}
}
- if(gUnknown_0202FFB4->unk60E == r4)
+ if(gPokedexView->selectedPokemon == r4)
return 0;
else
{
- gUnknown_0202FFB4->unk60E = r4;
- gUnknown_0202FFB4->unk62C += 16;
+ gPokedexView->selectedPokemon = r4;
+ gPokedexView->unk62C += 16;
return 1;
}
}
@@ -1815,10 +1897,10 @@ u8 sub_808E82C(void)
for(i = 0; i < 4; i++)
{
- if(gUnknown_0202FFB4->unk61E[i] != 0xFFFF)
+ if(gPokedexView->unk61E[i] != 0xFFFF)
{
- DestroySprite(&gSprites[gUnknown_0202FFB4->unk61E[i]]);
- gUnknown_0202FFB4->unk61E[i] |= 0xFFFF;
+ DestroySprite(&gSprites[gPokedexView->unk61E[i]]);
+ gPokedexView->unk61E[i] |= 0xFFFF;
}
}
return 0;
@@ -1826,10 +1908,10 @@ u8 sub_808E82C(void)
u16 sub_808E888(u16 a1)
{
- if(a1 > 385 || gUnknown_0202FFB4->unk0[a1].a == 0xFFFF)
+ if(a1 > 385 || gPokedexView->unk0[a1].dexNum == 0xFFFF)
return 0xFFFF;
- else if(gUnknown_0202FFB4->unk0[a1].seen)
- return gUnknown_0202FFB4->unk0[a1].a;
+ else if(gPokedexView->unk0[a1].seen)
+ return gPokedexView->unk0[a1].dexNum;
else
return 0;
}
@@ -1840,7 +1922,7 @@ u32 sub_808E8C8(u16 a, u16 b, u16 c)
for(i = 0; i < 4; i++)
{
- if(gUnknown_0202FFB4->unk61E[i] == 0xFFFF)
+ if(gPokedexView->unk61E[i] == 0xFFFF)
{
u8 spriteId = sub_80918EC(a, (s16)b, (s16)c, i);
@@ -1849,7 +1931,7 @@ u32 sub_808E8C8(u16 a, u16 b, u16 c)
gSprites[spriteId].data0 = 0;
gSprites[spriteId].data1 = i;
gSprites[spriteId].data2 = NationalPokedexNumToSpecies(a);
- gUnknown_0202FFB4->unk61E[i] = spriteId;
+ gPokedexView->unk61E[i] = spriteId;
return spriteId;
}
}
@@ -1904,7 +1986,7 @@ void sub_808E978(u8 a)
_a = 0;
spriteId = CreateSprite(&gSpriteTemplate_83A059C, 0x1C, 0x30, 1);
- r5 = gUnknown_0202FFB4->unk61A / 100;
+ r5 = gPokedexView->unk61A / 100;
StartSpriteAnim(&gSprites[spriteId], r5);
if(r5 != 0)
_a = 1;
@@ -1912,19 +1994,19 @@ void sub_808E978(u8 a)
gSprites[spriteId].invisible = 1;
spriteId = CreateSprite(&gSpriteTemplate_83A059C, 0x22, 0x30, 1);
- r5 = (gUnknown_0202FFB4->unk61A % 100) / 10;
+ r5 = (gPokedexView->unk61A % 100) / 10;
if(r5 != 0 || _a != 0)
StartSpriteAnim(&gSprites[spriteId], r5);
else
gSprites[spriteId].invisible = 1;
spriteId = CreateSprite(&gSpriteTemplate_83A059C, 0x28, 0x30, 1);
- r5 = (gUnknown_0202FFB4->unk61A % 100) % 10;
+ r5 = (gPokedexView->unk61A % 100) % 10;
StartSpriteAnim(&gSprites[spriteId], r5);
_a = 0;
spriteId = CreateSprite(&gSpriteTemplate_83A059C, 0x1C, 0x50, 1);
- r5 = gUnknown_0202FFB4->unk61C / 100;
+ r5 = gPokedexView->unk61C / 100;
StartSpriteAnim(&gSprites[spriteId], r5);
if(r5 != 0)
_a = 1;
@@ -1932,14 +2014,14 @@ void sub_808E978(u8 a)
gSprites[spriteId].invisible = 1;
spriteId = CreateSprite(&gSpriteTemplate_83A059C, 0x22, 0x50, 1);
- r5 = (gUnknown_0202FFB4->unk61C % 100) / 10;
+ r5 = (gPokedexView->unk61C % 100) / 10;
if(r5 != 0 || _a != 0)
StartSpriteAnim(&gSprites[spriteId], r5);
else
gSprites[spriteId].invisible = 1;
spriteId = CreateSprite(&gSpriteTemplate_83A059C, 0x28, 0x50, 1);
- r5 = (gUnknown_0202FFB4->unk61C % 100) % 10;
+ r5 = (gPokedexView->unk61C % 100) % 10;
StartSpriteAnim(&gSprites[spriteId], r5);
spriteId = CreateSprite(&gSpriteTemplate_83A05B4, 0x8C, 0x60, 1);
@@ -1958,10 +2040,11 @@ void nullsub_58(struct Sprite *sprite)
void sub_808ED94(struct Sprite *sprite)
{
- if(gUnknown_0202FFB4->unk64A != 0)
+ if(gPokedexView->unk64A != 0)
DestroySprite(sprite);
}
+//Move Pokemon into position for description page
void sub_808EDB8(struct Sprite *sprite)
{
sprite->oam.priority = 0;
@@ -1988,10 +2071,10 @@ void sub_808EE28(struct Sprite *sprite)
{
u8 data1 = sprite->data1;
- if(gUnknown_0202FFB4->unk64A != 0 && gUnknown_0202FFB4->unk64A != 3)
+ if(gPokedexView->unk64A != 0 && gPokedexView->unk64A != 3)
{
DestroySprite(sprite);
- gUnknown_0202FFB4->unk61E[data1] = 0xFFFF;
+ gPokedexView->unk61E[data1] = 0xFFFF;
}
else
{
@@ -2019,7 +2102,7 @@ void sub_808EE28(struct Sprite *sprite)
if((u16)(sprite->data5 + 0x3F) > 0x7E && sprite->data0 != 0)
{
DestroySprite(sprite);
- gUnknown_0202FFB4->unk61E[data1] = 0xFFFF;
+ gPokedexView->unk61E[data1] = 0xFFFF;
}
}
//_0808EF16
@@ -2027,15 +2110,15 @@ void sub_808EE28(struct Sprite *sprite)
void sub_808EF38(struct Sprite *sprite)
{
- if(gUnknown_0202FFB4->unk64A != 0 && gUnknown_0202FFB4->unk64A != 3)
+ if(gPokedexView->unk64A != 0 && gPokedexView->unk64A != 3)
DestroySprite(sprite);
else
- sprite->pos2.y = gUnknown_0202FFB4->unk60E * 120 / (gUnknown_0202FFB4->unk60C - 1);
+ sprite->pos2.y = gPokedexView->selectedPokemon * 120 / (gPokedexView->unk60C - 1);
}
void sub_808EF8C(struct Sprite *sprite)
{
- if(gUnknown_0202FFB4->unk64A != 0 && gUnknown_0202FFB4->unk64A != 3)
+ if(gPokedexView->unk64A != 0 && gPokedexView->unk64A != 3)
DestroySprite(sprite);
else
{
@@ -2043,7 +2126,7 @@ void sub_808EF8C(struct Sprite *sprite)
if(sprite->data1 != 0)
{
- if(gUnknown_0202FFB4->unk60E == gUnknown_0202FFB4->unk60C - 1)
+ if(gPokedexView->selectedPokemon == gPokedexView->unk60C - 1)
sprite->invisible = 1;
else
sprite->invisible = 0;
@@ -2051,7 +2134,7 @@ void sub_808EF8C(struct Sprite *sprite)
}
else
{
- if(gUnknown_0202FFB4->unk60E == 0)
+ if(gPokedexView->selectedPokemon == 0)
sprite->invisible = 1;
else
sprite->invisible = 0;
@@ -2059,7 +2142,7 @@ void sub_808EF8C(struct Sprite *sprite)
}
sprite->pos2.y = gSineTable[r0] / 64;
sprite->data2 = sprite->data2 + 8;
- if(gUnknown_0202FFB4->unk650 == 0 && gUnknown_0202FFB4->unk654 == 0 && sprite->invisible == 0)
+ if(gPokedexView->menuIsOpen == 0 && gPokedexView->menuY == 0 && sprite->invisible == 0)
sprite->invisible = 0;
else
sprite->invisible = 1;
@@ -2068,29 +2151,1150 @@ void sub_808EF8C(struct Sprite *sprite)
void sub_808F08C(struct Sprite *sprite)
{
- if(gUnknown_0202FFB4->unk64A != 0 && gUnknown_0202FFB4->unk64A != 3)
+ if(gPokedexView->unk64A != 0 && gPokedexView->unk64A != 3)
DestroySprite(sprite);
}
-/*
-//FixMe
+#ifdef NONMATCHING
void sub_808F0B4(struct Sprite *sprite)
{
- if(gUnknown_0202FFB4->unk64A != 0 && gUnknown_0202FFB4->unk64A != 3)
+ if(gPokedexView->unk64A != 0 && gPokedexView->unk64A != 3)
DestroySprite(sprite);
else
{
s16 r3;
- u8 unk = gUnknown_0202FFB4->unk62C + sprite->data1;
+
+ u8 unk = gPokedexView->unk62C + sprite->data1;
u16 foo = gSineTable[unk];
- u16 bar = gSineTable[unk + 0x40];
- u8 unk2 = sprite->data0;
+ //u8 unk2 = sprite->data0;
+ //u16 bar = gSineTable[unk + 0x40];
- SetOamMatrix(unk2, foo, bar, -foo, bar);
+ SetOamMatrix(sprite->data0, foo, gSineTable[unk + 0x40], (-(u16)foo) >> 16, gSineTable[unk + 0x40]);
- r3 = gSineTable[sprite->data1 + gUnknown_0202FFB4->unk62C];
- sprite->pos2.x = gSineTable[sprite->data1 + gUnknown_0202FFB4->unk62C + 0x40] * 5 / 256;
- sprite->pos2.y = r3 / 8;
+ r3 = gSineTable[sprite->data1 + gPokedexView->unk62C];
+ sprite->pos2.x = gSineTable[sprite->data1 + gPokedexView->unk62C + 0x40] * 5 / 256;
+ sprite->pos2.y = r3 * 40 / 256;
+ }
+}
+#else
+__attribute__((naked))
+void sub_808F0B4(struct Sprite *sprite)
+{
+ asm(".syntax unified\n\
+ push {r4-r7,lr}\n\
+ sub sp, 0x4\n\
+ adds r6, r0, 0\n\
+ ldr r1, _0808F0D8 @ =gPokedexView\n\
+ ldr r0, [r1]\n\
+ ldr r2, _0808F0DC @ =0x0000064a\n\
+ adds r0, r2\n\
+ ldrb r0, [r0]\n\
+ adds r7, r1, 0\n\
+ cmp r0, 0\n\
+ beq _0808F0E0\n\
+ cmp r0, 0x3\n\
+ beq _0808F0E0\n\
+ adds r0, r6, 0\n\
+ bl DestroySprite\n\
+ b _0808F158\n\
+ .align 2, 0\n\
+_0808F0D8: .4byte gPokedexView\n\
+_0808F0DC: .4byte 0x0000064a\n\
+_0808F0E0:\n\
+ ldr r0, [r7]\n\
+ ldr r5, _0808F160 @ =0x0000062c\n\
+ adds r0, r5\n\
+ ldrb r1, [r0]\n\
+ ldrh r0, [r6, 0x30]\n\
+ adds r1, r0\n\
+ lsls r1, 24\n\
+ lsrs r1, 24\n\
+ ldr r4, _0808F164 @ =gSineTable\n\
+ lsls r0, r1, 1\n\
+ adds r0, r4\n\
+ ldrh r3, [r0]\n\
+ adds r1, 0x40\n\
+ lsls r1, 1\n\
+ adds r1, r4\n\
+ ldrh r0, [r6, 0x2E]\n\
+ lsls r0, 24\n\
+ lsrs r0, 24\n\
+ ldrh r1, [r1]\n\
+ lsls r3, 16\n\
+ lsrs r2, r3, 16\n\
+ negs r3, r3\n\
+ lsrs r3, 16\n\
+ str r1, [sp]\n\
+ bl SetOamMatrix\n\
+ ldr r1, [r7]\n\
+ adds r1, r5\n\
+ ldrh r0, [r6, 0x30]\n\
+ adds r0, 0x40\n\
+ ldrb r1, [r1]\n\
+ adds r0, r1\n\
+ lsls r0, 24\n\
+ lsrs r0, 24\n\
+ lsls r1, r0, 1\n\
+ adds r1, r4\n\
+ ldrh r3, [r1]\n\
+ adds r0, 0x40\n\
+ lsls r0, 1\n\
+ adds r0, r4\n\
+ movs r2, 0\n\
+ ldrsh r1, [r0, r2]\n\
+ lsls r0, r1, 2\n\
+ adds r0, r1\n\
+ lsls r0, 3\n\
+ cmp r0, 0\n\
+ bge _0808F140\n\
+ adds r0, 0xFF\n\
+_0808F140:\n\
+ asrs r0, 8\n\
+ strh r0, [r6, 0x24]\n\
+ lsls r1, r3, 16\n\
+ asrs r1, 16\n\
+ lsls r0, r1, 2\n\
+ adds r0, r1\n\
+ lsls r0, 3\n\
+ cmp r0, 0\n\
+ bge _0808F154\n\
+ adds r0, 0xFF\n\
+_0808F154:\n\
+ asrs r0, 8\n\
+ strh r0, [r6, 0x26]\n\
+_0808F158:\n\
+ add sp, 0x4\n\
+ pop {r4-r7}\n\
+ pop {r0}\n\
+ bx r0\n\
+ .align 2, 0\n\
+_0808F160: .4byte 0x0000062c\n\
+_0808F164: .4byte gSineTable\n\
+ .syntax divided\n");
+}
+#endif
+
+void sub_808F168(struct Sprite *sprite)
+{
+ if(gPokedexView->unk64A != 0 && gPokedexView->unk64A != 3)
+ DestroySprite(sprite);
+ else
+ {
+ u16 r1 = gPokedexView->unk64A == 0 ? 0x50 : 0x60;
+
+ if(gPokedexView->menuIsOpen != 0 && gPokedexView->menuY == r1)
+ {
+ u8 data2;
+
+ sprite->invisible = 0;
+ sprite->pos2.y = gPokedexView->menuCursorPos * 16;
+ sprite->pos2.x = gSineTable[(u8)sprite->data2] / 64;
+ sprite->data2 += 8;
+ }
+ else
+ sprite->invisible = 1;
+ }
+}
+
+u8 sub_808F210(struct PokedexListItem *item, u8 b)
+{
+ u8 taskId;
+
+ gUnknown_0202FFBC = item;
+ taskId = CreateTask(Task_InitPageScreenMultistep, 0);
+ gTasks[taskId].data[0] = 0;
+ gTasks[taskId].data[1] = 1;
+ gTasks[taskId].data[2] = 0;
+ gTasks[taskId].data[3] = 0;
+ gTasks[taskId].data[4] = b;
+ return taskId;
+}
+
+bool8 sub_808F250(u8 taskId)
+{
+ if(gTasks[taskId].data[0] == 0 && gTasks[taskId].func == Task_PageScreenProcessInput)
+ return 0;
+ else
+ return 1;
+}
+
+u8 sub_808F284(struct PokedexListItem *item, u8 b)
+{
+ gUnknown_0202FFBC = item;
+ gTasks[b].data[0] = 1;
+ gTasks[b].data[1] = 0;
+ gTasks[b].data[2] = 0;
+ gTasks[b].data[3] = 0;
+ return b;
+}
+
+void Task_InitPageScreenMultistep(u8 taskId)
+{
+ switch(gMain.state)
+ {
+ case 0:
+ default:
+ if(!gPaletteFade.active)
+ {
+ u16 r2;
+
+ gPokedexView->unk64A = 1;
+ gPokedexView->unk64E = 0;
+ gUnknown_03005CEC = gMain.vblankCallback;
+ SetVBlankCallback(NULL);
+ r2 = 0;
+ if(gTasks[taskId].data[1] != 0)
+ r2 += 0x1000;
+ if(gTasks[taskId].data[2] != 0)
+ r2 |= 0x200;
+ sub_8091060(r2);
+ gMain.state = 1;
+ }
+ break;
+ case 1:
+ LZ77UnCompVram(gPokedexMenu_Gfx, (void *)VRAM);
+ LZ77UnCompVram(gUnknown_08E96BD4, (void *)(VRAM + 0x7800));
+ sub_8091738(gUnknown_0202FFBC->dexNum, 2, 0x3FC);
+ gMain.state++;
+ break;
+ case 2:
+ sub_80904FC(0xD);
+ sub_8090584(gPokedexView->selectedScreen, 0xD);
+ sub_808D640();
+ gMain.state++;
+ break;
+ case 3:
+ SetUpWindowConfig(&gWindowConfig_81E7064);
+ InitMenuWindow(&gWindowConfig_81E7064);
+ gMain.state++;
+ break;
+ case 4:
+ if(gPokedexView->dexMode == DEX_MODE_HOENN)
+ sub_8091154(NationalToHoennOrder(gUnknown_0202FFBC->dexNum), 0xD, 3);
+ else
+ sub_8091154(gUnknown_0202FFBC->dexNum, 0xD, 3);
+ //_0808F45A
+ sub_80911C8(gUnknown_0202FFBC->dexNum, 0x10, 3);
+ MenuPrint(gDexText_UnknownPoke, 11, 5);
+ MenuPrint(gDexText_UnknownHeight, 16, 7);
+ MenuPrint(gDexText_UnknownWeight, 16, 9);
+ if(gUnknown_0202FFBC->owned)
+ {
+ sub_8091304(gPokedexEntries[gUnknown_0202FFBC->dexNum].categoryName, 11, 5);
+ sub_8091458(gPokedexEntries[gUnknown_0202FFBC->dexNum].height, 16, 7);
+ sub_8091564(gPokedexEntries[gUnknown_0202FFBC->dexNum].weight, 16, 9);
+ MenuPrint(gPokedexEntries[gUnknown_0202FFBC->dexNum].descriptionPage1, 2, 13);
+ sub_80917CC(14, 0x3FC);
+ }
+ //_0808F50C
+ else
+ {
+ MenuPrint(gUnknown_083A05F8, 2, 13);
+ LoadPalette(gPlttBufferUnfaded + 1, 0x31, 0x1E);
+ }
+ gMain.state++;
+ break;
+ case 5:
+ if(gTasks[taskId].data[1] == 0)
+ {
+ //_0808F540
+ gTasks[taskId].data[4] = (u16)sub_80918EC(gUnknown_0202FFBC->dexNum, 0x30, 0x38, 0);
+ gSprites[gTasks[taskId].data[4]].oam.priority = 0;
+ }
+ gMain.state++;
+ break;
+ case 6:
+ {
+ u32 r3 = 0;
+
+ if(gTasks[taskId].data[2] != 0)
+ r3 = 0x14;
+ if(gTasks[taskId].data[1] != 0)
+ {
+ r3 |= (1 << (gSprites[gTasks[taskId].data[4]].oam.paletteNum + 0x10));
+ }
+ BeginNormalPaletteFade(~r3, 0, 0x10, 0, 0);
+ SetVBlankCallback(gUnknown_03005CEC);
+ gMain.state++;
+ break;
+ }
+ case 7:
+ REG_BLDCNT = 0;
+ REG_BLDALPHA = 0;
+ REG_BLDY = 0;
+ REG_BG3CNT = 0xF03;
+ REG_BG1CNT = 0xD00;
+ REG_DISPCNT = DISPCNT_MODE_0 | DISPCNT_OBJ_1D_MAP | DISPCNT_BG1_ON | DISPCNT_BG2_ON | DISPCNT_BG3_ON | DISPCNT_OBJ_ON;
+ gMain.state++;
+ break;
+ case 8:
+ if(!gPaletteFade.active)
+ {
+ gMain.state++;
+ if(gTasks[taskId].data[3] == 0)
+ {
+ StopCryAndClearCrySongs();
+ PlayCry2(NationalPokedexNumToSpecies(gUnknown_0202FFBC->dexNum), 0, 0x7D, 0xA);
+ }
+ else
+ gMain.state++;
+ }
+ break;
+ case 9:
+ if(!IsCryPlayingOrClearCrySongs())
+ gMain.state++;
+ break;
+ case 10:
+ gTasks[taskId].data[0] = 0;
+ gTasks[taskId].data[1] = 0;
+ gTasks[taskId].data[2] = 1;
+ gTasks[taskId].data[3] = 1;
+ gTasks[taskId].func = Task_PageScreenProcessInput;
+ gMain.state = 0;
+ break;
+ }
+}
+
+void Task_PageScreenProcessInput(u8 taskId)
+{
+ if (gTasks[taskId].data[0] != 0)
+ {
+ BeginNormalPaletteFade(-1, 0, 0, 0x10, 0);
+ gTasks[taskId].func = sub_808F888;
+ PlaySE(SE_Z_SCROLL);
+ }
+ else if (gMain.newKeys & B_BUTTON)
+ {
+ BeginNormalPaletteFade(-1, 0, 0, 0x10, 0);
+ gTasks[taskId].func = Task_ClosePageScreen;
+ PlaySE(SE_PC_OFF);
+ }
+ else if (gMain.newKeys & A_BUTTON)
+ {
+ switch (gPokedexView->selectedScreen)
+ {
+ case PAGE_SCREEN:
+ sub_8090C68();
+ break;
+ case AREA_SCREEN:
+ BeginNormalPaletteFade(-0x15, 0, 0, 0x10, 0);
+ gTasks[taskId].func = Task_InitAreaScreenMultistep;
+ PlaySE(SE_PIN);
+ break;
+ case CRY_SCREEN:
+ BeginNormalPaletteFade(-0x15, 0, 0, 0x10, 0);
+ gTasks[taskId].func = Task_InitCryScreenMultistep;
+ PlaySE(SE_PIN);
+ break;
+ case SIZE_SCREEN:
+ if (!gUnknown_0202FFBC->owned)
+ PlaySE(SE_HAZURE);
+ else
+ {
+ BeginNormalPaletteFade(-0x15, 0, 0, 0x10, 0);
+ gTasks[taskId].func = Task_InitSizeScreenMultistep;
+ PlaySE(SE_PIN);
+ }
+ break;
+ }
+ }
+ else if (((gMain.newKeys & DPAD_LEFT)
+ || ((gMain.newKeys & L_BUTTON) && gSaveBlock2.optionsButtonMode == OPTIONS_BUTTON_MODE_LR))
+ && gPokedexView->selectedScreen > 0)
+ {
+ gPokedexView->selectedScreen--;
+ sub_8090584(gPokedexView->selectedScreen, 0xD);
+ PlaySE(SE_Z_PAGE);
+ }
+ else if (((gMain.newKeys & DPAD_RIGHT)
+ || ((gMain.newKeys & R_BUTTON) && gSaveBlock2.optionsButtonMode == OPTIONS_BUTTON_MODE_LR))
+ && gPokedexView->selectedScreen < 3)
+ {
+ gPokedexView->selectedScreen++;
+ sub_8090584(gPokedexView->selectedScreen, 0xD);
+ PlaySE(SE_Z_PAGE);
+ }
+}
+
+void sub_808F888(u8 taskId)
+{
+ if(!gPaletteFade.active)
+ gTasks[taskId].func = Task_InitPageScreenMultistep;
+}
+
+void Task_ClosePageScreen(u8 taskId)
+{
+ if(!gPaletteFade.active)
+ DestroyTask(taskId);
+}
+
+void Task_InitAreaScreenMultistep(u8 taskId)
+{
+ switch (gMain.state)
+ {
+ case 0:
+ default:
+ if (!gPaletteFade.active)
+ {
+ gPokedexView->unk64A = 5;
+ gUnknown_03005CEC = gMain.vblankCallback;
+ SetVBlankCallback(NULL);
+ sub_8091060(0x200);
+ gPokedexView->selectedScreen = AREA_SCREEN;
+ gMain.state = 1;
+ }
+ break;
+ case 1:
+ sub_8090540(0xD);
+ sub_8090644(1, 0xD);
+ sub_808D640();
+ REG_BG1CNT = 0xD00;
+ gMain.state++;
+ break;
+ case 2:
+ ShowPokedexAreaScreen(NationalPokedexNumToSpecies(gUnknown_0202FFBC->dexNum), &gPokedexView->unk64F);
+ SetVBlankCallback(gUnknown_03005CEC);
+ gPokedexView->unk64F = 0;
+ gMain.state = 0;
+ gTasks[taskId].func = Task_AreaScreenProcessInput;
+ break;
+ }
+}
+
+void Task_AreaScreenProcessInput(u8 taskId)
+{
+ if(gPokedexView->unk64F != 0)
+ gTasks[taskId].func = sub_808FA00;
+}
+
+void sub_808FA00(u8 taskId)
+{
+ if(!gPaletteFade.active)
+ {
+ switch(gPokedexView->unk64F)
+ {
+ case 1:
+ default:
+ gTasks[taskId].func = Task_InitPageScreenMultistep;
+ break;
+ case 2:
+ gTasks[taskId].func = Task_InitCryScreenMultistep;
+ break;
+ }
+ }
+}
+
+void Task_InitCryScreenMultistep(u8 taskId)
+{
+ switch(gMain.state)
+ {
+ case 0:
+ default:
+ if(!gPaletteFade.active)
+ {
+ m4aMPlayStop(&gMPlay_BGM);
+ gPokedexView->unk64A = 6;
+ gUnknown_03005CEC = gMain.vblankCallback;
+ SetVBlankCallback(NULL);
+ sub_8091060(0x200);
+ gPokedexView->selectedScreen = CRY_SCREEN;
+ gMain.state = 1;
+ }
+ break;
+ case 1:
+ LZ77UnCompVram(gPokedexMenu_Gfx, (void *)VRAM);
+ LZ77UnCompVram(gUnknown_0839F8A0, (void *)(VRAM + 0x7000));
+ gMain.state++;
+ break;
+ case 2:
+ sub_8090540(0xD);
+ sub_8090644(2, 0xD);
+ sub_808D640();
+ DmaClear16(3, (void *)(VRAM + 0xF800), 0x500);
+ gMain.state++;
+ break;
+ case 3:
+ SetUpWindowConfig(&gWindowConfig_81E702C);
+ InitMenuWindow(&gWindowConfig_81E702C);
+ ResetPaletteFade();
+ gMain.state++;
+ break;
+ case 4:
+ MenuPrint(gDexText_CryOf, 10, 4);
+ sub_8091260(gUnknown_0202FFBC->dexNum, 10, 6, 2);
+ gMain.state++;
+ break;
+ case 5:
+ gTasks[taskId].data[4] = sub_80918EC(gUnknown_0202FFBC->dexNum, 0x30, 0x38, 0);
+ gSprites[gTasks[taskId].data[4]].oam.priority = 0;
+ gUnknown_03005E98 = 0;
+ gMain.state++;
+ break;
+ case 6:
+ {
+ struct CryRelatedStruct sp8;
+
+ sp8.unk0 = 0x4020;
+ sp8.unk2 = 0x1F;
+ sp8.unk3 = 8;
+ sp8.unk5 = 0x1E;
+ sp8.unk4 = 0xC;
+ if(sub_8119E3C(&sp8, 0) != 0)
+ {
+ gMain.state++;
+ gUnknown_03005E98 = 0;
+ }
+ break;
+ }
+ case 7:
+ {
+ struct CryRelatedStruct sp10;
+
+ sp10.unk0 = 0x3000;
+ sp10.unk2 = 0xE;
+ sp10.unk3 = 9;
+ sp10.unk4 = 0x12;
+ sp10.unk5 = 3;
+ if(ShowPokedexCryScreen(&sp10, 1) != 0)
+ {
+ gMain.state++;
+ }
+ break;
+ }
+ case 8:
+ BeginNormalPaletteFade(-0x15, 0, 0x10, 0, 0);
+ SetVBlankCallback(gUnknown_03005CEC);
+ gMain.state++;
+ break;
+ case 9:
+ REG_BLDCNT = 0;
+ REG_BLDALPHA = 0;
+ REG_BLDY = 0;
+ REG_BG2CNT = 0xE02;
+ REG_BG0CNT = 0x1F07;
+ REG_BG1CNT = 0xD00;
+ REG_DISPCNT = 0x1F07 + 0x39;
+ gMain.state++;
+ break;
+ case 10:
+ gPokedexView->unk64F = 0;
+ gMain.state = 0;
+ gTasks[taskId].func = Task_CryScreenProcessInput;
+ break;
+ }
+}
+
+void Task_CryScreenProcessInput(u8 taskId)
+{
+ sub_8119F88(0);
+
+ if (IsCryPlaying())
+ sub_8090040(1);
+ else
+ sub_8090040(0);
+
+ if (gMain.newKeys & A_BUTTON)
+ {
+ sub_8090040(1);
+ sub_811A050(NationalPokedexNumToSpecies(gUnknown_0202FFBC->dexNum));
+ return;
+ }
+ else if (!gPaletteFade.active)
+ {
+ if (gMain.newKeys & B_BUTTON)
+ {
+ BeginNormalPaletteFade(-0x15, 0, 0, 0x10, 0);
+ m4aMPlayContinue(&gMPlay_BGM);
+ gPokedexView->unk64F = 1;
+ gTasks[taskId].func = sub_808FFBC;
+ PlaySE(SE_PC_OFF);
+ }
+ else if ((gMain.newKeys & DPAD_LEFT)
+ || ((gMain.newKeys & L_BUTTON) && gSaveBlock2.optionsButtonMode == OPTIONS_BUTTON_MODE_LR))
+ {
+ BeginNormalPaletteFade(-0x15, 0, 0, 0x10, 0);
+ m4aMPlayContinue(&gMPlay_BGM);
+ gPokedexView->unk64F = 2;
+ gTasks[taskId].func = sub_808FFBC;
+ PlaySE(SE_Z_PAGE);
+ }
+ else if ((gMain.newKeys & DPAD_RIGHT)
+ || ((gMain.newKeys & R_BUTTON) && gSaveBlock2.optionsButtonMode == OPTIONS_BUTTON_MODE_LR))
+ {
+ if (!gUnknown_0202FFBC->owned)
+ PlaySE(SE_HAZURE);
+ else
+ {
+ BeginNormalPaletteFade(-0x15, 0, 0, 0x10, 0);
+ m4aMPlayContinue(&gMPlay_BGM);
+ gPokedexView->unk64F = 3;
+ gTasks[taskId].func = sub_808FFBC;
+ PlaySE(SE_Z_PAGE);
+ }
+ }
+ }
+}
+
+void sub_808FFBC(u8 taskId)
+{
+ if(!gPaletteFade.active)
+ {
+ DestroyCryMeterNeedleSprite();
+ switch(gPokedexView->unk64F)
+ {
+ default:
+ case 1:
+ gTasks[taskId].func = Task_InitPageScreenMultistep;
+ break;
+ case 2:
+ gTasks[taskId].func = Task_InitAreaScreenMultistep;
+ break;
+ case 3:
+ gTasks[taskId].func = Task_InitSizeScreenMultistep;
+ }
+ }
+}
+
+void sub_8090040(u8 a)
+{
+ u16 unk;
+
+ if(a != 0)
+ unk = 0x392;
+ else
+ unk = 0x2AF;
+ LoadPalette(&unk, 0x5D, 2);
+}
+
+void Task_InitSizeScreenMultistep(u8 taskId)
+{
+ u8 spriteId;
+
+ switch(gMain.state)
+ {
+ default:
+ case 0:
+ if(!gPaletteFade.active)
+ {
+ gPokedexView->unk64A = 7;
+ gUnknown_03005CEC = gMain.vblankCallback;
+ SetVBlankCallback(NULL);
+ sub_8091060(0x200);
+ gPokedexView->selectedScreen = SIZE_SCREEN;
+ gMain.state = 1;
+ }
+ break;
+ case 1:
+ LZ77UnCompVram(gPokedexMenu_Gfx, (void *)VRAM);
+ LZ77UnCompVram(gUnknown_0839F988, (void *)(VRAM + 0x7000));
+ gMain.state++;
+ break;
+ case 2:
+ sub_8090540(0xD);
+ sub_8090644(3, 0xD);
+ sub_808D640();
+ gMain.state++;
+ break;
+ case 3:
+ {
+ u8 string[40]; //I hope this is the correct size
+
+ SetUpWindowConfig(&gWindowConfig_81E702C);
+ InitMenuWindow(&gWindowConfig_81E702C);
+ string[0] = EOS;
+ StringAppend(string, gDexText_SizeComparedTo);
+ StringAppend(string, gSaveBlock2.playerName);
+ sub_8072BD8(string, 3, 15, 0xC0);
+ gMain.state++;
+ break;
+ }
+ case 4:
+ ResetPaletteFade();
+ gMain.state++;
+ break;
+ case 5:
+ spriteId = sub_8091A4C(gSaveBlock2.playerGender, 0x98, 0x38, 0);
+ gSprites[spriteId].oam.affineMode = 1;
+ gSprites[spriteId].oam.matrixNum = 1;
+ gSprites[spriteId].oam.priority = 0;
+ gSprites[spriteId].pos2.y = gPokedexEntries[gUnknown_0202FFBC->dexNum].trainerOffset;
+ SetOamMatrix(1, gPokedexEntries[gUnknown_0202FFBC->dexNum].trainerScale, 0, 0, gPokedexEntries[gUnknown_0202FFBC->dexNum].trainerScale);
+ LoadPalette(gUnknown_083B4EC4, (gSprites[spriteId].oam.paletteNum + 16) * 16, 0x20);
+ gMain.state++;
+ break;
+ case 6:
+ spriteId = sub_80918EC(gUnknown_0202FFBC->dexNum, 0x58, 0x38, 1);
+ gSprites[spriteId].oam.affineMode = 1;
+ gSprites[spriteId].oam.matrixNum = 2;
+ gSprites[spriteId].oam.priority = 0;
+ gSprites[spriteId].pos2.y = gPokedexEntries[gUnknown_0202FFBC->dexNum].pokemonOffset;
+ SetOamMatrix(2, gPokedexEntries[gUnknown_0202FFBC->dexNum].pokemonScale, 0, 0, gPokedexEntries[gUnknown_0202FFBC->dexNum].pokemonScale);
+ LoadPalette(gUnknown_083B4EC4, (gSprites[spriteId].oam.paletteNum + 16) * 16, 0x20);
+ gMain.state++;
+ break;
+ case 7:
+ BeginNormalPaletteFade(-0x15, 0, 0x10, 0, 0);
+ SetVBlankCallback(gUnknown_03005CEC);
+ gMain.state++;
+ break;
+ case 8:
+ REG_BLDCNT = 0;
+ REG_BLDALPHA = 0;
+ REG_BLDY = 0;
+ REG_BG2CNT = 0xE03;
+ REG_DISPCNT = 0x1E40;
+ gMain.state++;
+ break;
+ case 9:
+ if(!gPaletteFade.active)
+ {
+ gPokedexView->unk64F = 0;
+ gMain.state = 0;
+ gTasks[taskId].func = Task_SizeScreenProcessInput;
+ }
+ break;
+ }
+}
+
+void Task_SizeScreenProcessInput(u8 taskId)
+{
+ if(gMain.newKeys & B_BUTTON)
+ {
+ BeginNormalPaletteFade(-0x15, 0, 0, 0x10, 0);
+ gPokedexView->unk64F = 1;
+ gTasks[taskId].func = sub_8090498;
+ PlaySE(SE_PC_OFF);
+ }
+ //_08090430
+ else if((gMain.newKeys & DPAD_LEFT)
+ || ((gMain.newKeys & L_BUTTON) && gSaveBlock2.optionsButtonMode == OPTIONS_BUTTON_MODE_LR))
+ {
+ BeginNormalPaletteFade(-0x15, 0, 0, 0x10, 0);
+ gPokedexView->unk64F = 2;
+ gTasks[taskId].func = sub_8090498;
+ PlaySE(SE_Z_PAGE);
+ }
+}
+
+void sub_8090498(u8 taskId)
+{
+ if(!gPaletteFade.active)
+ {
+ switch(gPokedexView->unk64F)
+ {
+ default:
+ case 1:
+ gTasks[taskId].func = Task_InitPageScreenMultistep;
+ break;
+ case 2:
+ gTasks[taskId].func = Task_InitCryScreenMultistep;
+ break;
+ }
+ }
+}
+
+void sub_80904FC(u16 a)
+{
+ LZ77UnCompVram(gUnknown_08E96ACC, (void *)(VRAM + a * 0x800));
+ DmaClear16(3, (void *)(VRAM + a * 0x800 + 0xC0), 0x440);
+}
+
+void sub_8090540(u16 a)
+{
+ LZ77UnCompVram(gUnknown_08E96B58, (void *)(VRAM + a * 0x800));
+ DmaClear16(3, (void *)(VRAM + a * 0x800 + 0xC0), 0x440);
+}
+
+#ifdef NONMATCHING
+void sub_8090584(u8 a, u16 b)
+{
+ u8 i; //r1
+ u8 j; //r3
+ u32 r6;
+ register u8 r7;
+
+ for(i = 0; i < 4; i++)
+ {
+ r7 = i * 5 + 1;
+ r6 = 0x4000;
+
+ if(i == a)
+ r6 = 0x2000;
+
+ for(j = 0; j < 5; j++)
+ {
+ u32 r0 = b * 0x800 + (r7 + j) * 2;
+ u8 *ptr;
+
+ ptr = VRAM;
+ *(u16 *)(ptr + r0) = *(u16 *)(ptr + r0) & 0xFFF | r6;
+ ptr = VRAM + 0x40;
+ *(u16 *)(ptr + r0) = *(u16 *)(ptr + r0) & 0xFFF | r6;
+ }
+ }
+ r6 = 0x4000;
+ for(j = 0; j < 5; j++)
+ {
+ u32 r0 = b * 0x800 + j * 2;
+ u8 *ptr;
+
+ ptr = VRAM + 0x32;
+ *(u16 *)(ptr + r0) = *(u16 *)(ptr + r0) & 0xFFF | r6;
+ ptr = VRAM + 0x72;
+ *(u16 *)(ptr + r0) = *(u16 *)(ptr + r0) & 0xFFF | r6;
+ }
+}
+#else
+__attribute__((naked))
+void sub_8090584(u8 a, u16 b)
+{
+ asm(".syntax unified\n\
+ push {r4-r7,lr}\n\
+ mov r7, r10\n\
+ mov r6, r9\n\
+ mov r5, r8\n\
+ push {r5-r7}\n\
+ lsls r0, 24\n\
+ lsrs r0, 24\n\
+ mov r10, r0\n\
+ lsls r1, 16\n\
+ lsrs r1, 16\n\
+ mov r9, r1\n\
+ movs r1, 0\n\
+_0809059C:\n\
+ lsls r0, r1, 2\n\
+ adds r0, r1\n\
+ adds r0, 0x1\n\
+ lsls r0, 24\n\
+ lsrs r7, r0, 24\n\
+ movs r6, 0x80\n\
+ lsls r6, 7\n\
+ cmp r1, r10\n\
+ bne _080905B2\n\
+ movs r6, 0x80\n\
+ lsls r6, 6\n\
+_080905B2:\n\
+ movs r3, 0\n\
+ mov r0, r9\n\
+ lsls r0, 11\n\
+ mov r12, r0\n\
+ adds r1, 0x1\n\
+ mov r8, r1\n\
+ mov r5, r12\n\
+ ldr r4, _08090634 @ =0x00000fff\n\
+_080905C2:\n\
+ adds r0, r7, r3\n\
+ lsls r0, 1\n\
+ adds r0, r5, r0\n\
+ movs r2, 0xC0\n\
+ lsls r2, 19\n\
+ adds r1, r0, r2\n\
+ ldrh r2, [r1]\n\
+ ands r2, r4\n\
+ orrs r2, r6\n\
+ strh r2, [r1]\n\
+ ldr r1, _08090638 @ =0x06000040\n\
+ adds r0, r1\n\
+ ldrh r2, [r0]\n\
+ ands r2, r4\n\
+ orrs r2, r6\n\
+ strh r2, [r0]\n\
+ adds r0, r3, 0x1\n\
+ lsls r0, 24\n\
+ lsrs r3, r0, 24\n\
+ cmp r3, 0x4\n\
+ bls _080905C2\n\
+ mov r2, r8\n\
+ lsls r0, r2, 24\n\
+ lsrs r1, r0, 24\n\
+ cmp r1, 0x3\n\
+ bls _0809059C\n\
+ movs r6, 0x80\n\
+ lsls r6, 7\n\
+ movs r3, 0\n\
+ mov r5, r12\n\
+ ldr r4, _08090634 @ =0x00000fff\n\
+_08090600:\n\
+ lsls r0, r3, 1\n\
+ adds r0, r5, r0\n\
+ ldr r2, _0809063C @ =0x06000032\n\
+ adds r1, r0, r2\n\
+ ldrh r2, [r1]\n\
+ ands r2, r4\n\
+ orrs r2, r6\n\
+ strh r2, [r1]\n\
+ ldr r1, _08090640 @ =0x06000072\n\
+ adds r0, r1\n\
+ ldrh r2, [r0]\n\
+ ands r2, r4\n\
+ orrs r2, r6\n\
+ strh r2, [r0]\n\
+ adds r0, r3, 0x1\n\
+ lsls r0, 24\n\
+ lsrs r3, r0, 24\n\
+ cmp r3, 0x4\n\
+ bls _08090600\n\
+ pop {r3-r5}\n\
+ mov r8, r3\n\
+ mov r9, r4\n\
+ mov r10, r5\n\
+ pop {r4-r7}\n\
+ pop {r0}\n\
+ bx r0\n\
+ .align 2, 0\n\
+_08090634: .4byte 0x00000fff\n\
+_08090638: .4byte 0x06000040\n\
+_0809063C: .4byte 0x06000032\n\
+_08090640: .4byte 0x06000072\n\
+ .syntax divided\n");
+}
+#endif
+
+//Nope, can't get this one to match, either.
+#ifdef NONMATCHING
+void sub_8090644(u8 a, u16 b)
+{
+ u8 i;
+ u8 j;
+
+ for(i = 0; i < 4; i++)
+ {
+ u8 r8 = i * 5 + 1;
+ u32 r5;
+
+ if(i == a || i == 0)
+ r5 = 0x2000;
+ else if(a != 0)
+ r5 = 0x4000;
+
+ for(j = 0; j < 5; j++)
+ {
+ u16 (*vramData)[0x400];
+
+ vramData = (u16 (*)[])VRAM;
+ vramData[b][r8 + j] = vramData[b][r8 + j] & 0xFFF | r5;
+ vramData = (u16 (*)[])(VRAM + 0x40);
+ vramData[b][r8 + j] = vramData[b][r8 + j] & 0xFFF | r5;
+ }
+ }
+
+ for(j = 0; j < 5; j++)
+ {
+ u16 (*vramData)[0x400];
+
+ vramData = (u16 (*)[])(VRAM + 0x32);
+ vramData[b][j] = vramData[b][j] & 0xFFF | 0x4000;
+ vramData = (u16 (*)[])(VRAM + 0x72);
+ vramData[b][j] = vramData[b][j] & 0xFFF | 0x4000;
+ }
+}
+#else
+__attribute__((naked))
+void sub_8090644(u8 a, u16 b)
+{
+ asm(".syntax unified\n\
+ push {r4-r7,lr}\n\
+ mov r7, r10\n\
+ mov r6, r9\n\
+ mov r5, r8\n\
+ push {r5-r7}\n\
+ lsls r0, 24\n\
+ lsrs r0, 24\n\
+ mov r10, r0\n\
+ lsls r1, 16\n\
+ lsrs r1, 16\n\
+ mov r9, r1\n\
+ movs r1, 0\n\
+_0809065C:\n\
+ lsls r0, r1, 2\n\
+ adds r0, r1\n\
+ adds r0, 0x1\n\
+ lsls r0, 24\n\
+ lsrs r0, 24\n\
+ mov r8, r0\n\
+ cmp r1, r10\n\
+ beq _08090670\n\
+ cmp r1, 0\n\
+ bne _08090676\n\
+_08090670:\n\
+ movs r5, 0x80\n\
+ lsls r5, 6\n\
+ b _0809067A\n\
+_08090676:\n\
+ movs r5, 0x80\n\
+ lsls r5, 7\n\
+_0809067A:\n\
+ movs r3, 0\n\
+ mov r0, r9\n\
+ lsls r7, r0, 11\n\
+ adds r1, 0x1\n\
+ mov r12, r1\n\
+ adds r6, r7, 0\n\
+ ldr r4, _080906FC @ =0x00000fff\n\
+_08090688:\n\
+ mov r1, r8\n\
+ adds r0, r1, r3\n\
+ lsls r0, 1\n\
+ adds r0, r6, r0\n\
+ movs r2, 0xC0\n\
+ lsls r2, 19\n\
+ adds r1, r0, r2\n\
+ ldrh r2, [r1]\n\
+ ands r2, r4\n\
+ orrs r2, r5\n\
+ strh r2, [r1]\n\
+ ldr r1, _08090700 @ =0x06000040\n\
+ adds r0, r1\n\
+ ldrh r2, [r0]\n\
+ ands r2, r4\n\
+ orrs r2, r5\n\
+ strh r2, [r0]\n\
+ adds r0, r3, 0x1\n\
+ lsls r0, 24\n\
+ lsrs r3, r0, 24\n\
+ cmp r3, 0x4\n\
+ bls _08090688\n\
+ mov r2, r12\n\
+ lsls r0, r2, 24\n\
+ lsrs r1, r0, 24\n\
+ cmp r1, 0x3\n\
+ bls _0809065C\n\
+ movs r5, 0x80\n\
+ lsls r5, 7\n\
+ movs r3, 0\n\
+ adds r6, r7, 0\n\
+ ldr r4, _080906FC @ =0x00000fff\n\
+_080906C8:\n\
+ lsls r0, r3, 1\n\
+ adds r0, r6, r0\n\
+ ldr r2, _08090704 @ =0x06000032\n\
+ adds r1, r0, r2\n\
+ ldrh r2, [r1]\n\
+ ands r2, r4\n\
+ orrs r2, r5\n\
+ strh r2, [r1]\n\
+ ldr r1, _08090708 @ =0x06000072\n\
+ adds r0, r1\n\
+ ldrh r2, [r0]\n\
+ ands r2, r4\n\
+ orrs r2, r5\n\
+ strh r2, [r0]\n\
+ adds r0, r3, 0x1\n\
+ lsls r0, 24\n\
+ lsrs r3, r0, 24\n\
+ cmp r3, 0x4\n\
+ bls _080906C8\n\
+ pop {r3-r5}\n\
+ mov r8, r3\n\
+ mov r9, r4\n\
+ mov r10, r5\n\
+ pop {r4-r7}\n\
+ pop {r0}\n\
+ bx r0\n\
+ .align 2, 0\n\
+_080906FC: .4byte 0x00000fff\n\
+_08090700: .4byte 0x06000040\n\
+_08090704: .4byte 0x06000032\n\
+_08090708: .4byte 0x06000072\n\
+ .syntax divided\n");
+}
+#endif
+
+u8 sub_809070C(u16 dexNum, u32 b, u32 c)
+{
+ u8 taskId = CreateTask(sub_8090750, 0);
+
+ gTasks[taskId].data[0] = 0;
+ gTasks[taskId].data[1] = dexNum;
+ gTasks[taskId].data[12] = b;
+ gTasks[taskId].data[13] = b >> 16;
+ gTasks[taskId].data[14] = c;
+ gTasks[taskId].data[15] = c >> 16;
+ return taskId;
+}
+
+/*
+void sub_8090750(u8 taskId)
+{
+ u16 dexNum = gTasks[taskId].data[1];
+
+ switch(gTasks[taskId].data[0])
+ {
+ default:
+ case 0:
+ if(!gPaletteFade.active)
+ {
+ gUnknown_03005CEC = gMain.vblankCallback;
+ SetVBlankCallback(NULL);
+ sub_8091060(0x100);
+ gTasks[taskId].data[0] = 1;
+ }
+ break;
+ case 1:
+ {
+ u16 i;
+
+ LZ77UnCompVram(gPokedexMenu_Gfx, (void *)(VRAM + 0x4000));
+ LZ77UnCompVram(gUnknown_08E96BD4, (void *)(VRAM + 0x7800));
+ for(i = 0; i < 0x280; i++)
+ ((u16 *)(VRAM + 0x7800))[i] += 0x2000;
+ sub_8091738(gTasks[taskId].data[1], 2, 0x3FC);
+ ResetPaletteFade();
+ LoadPalette(gPokedexMenu_Pal + 2, 0x21, 0x9E);
+ gTasks[taskId].data[0]++;
+ break;
+ }
+ case 2:
+ SetUpWindowConfig(&gWindowConfig_81E7064);
+ InitMenuWindow(&gWindowConfig_81E7064);
+ DmaClear16(3, (void *)(VRAM + 0xC000), 0x200);
+ gTasks[taskId].data[0]++;
+ break;
+ case 3:
+ sub_8072BD8(gDexText_RegisterComplete, 2, 0, 0xD0);
+ if(!IsNationalPokedex())
+ sub_8091154(NationalToHoennOrder(dexNum), 13, 3);
+ else
+ sub_8091154(dexNum, 13, 3);
+ sub_80911C8(dexNum, 16, 3);
+ MenuPrint(gDexText_UnknownPoke, 11, 5);
+ MenuPrint(gDexText_UnknownHeight, 16, 7);
+ MenuPrint(gDexText_UnknownWeight, 16, 9);
+ sub_8091304(&gPokedexEntries[dexNum], 11, 5);
+ sub_8091458(gPokedexEntries[dexNum].height, 16, 7);
+ sub_8091564(gPokedexEntries[dexNum].weight, 16, 9);
+ MenuPrint(gPokedexEntries[dexNum].descriptionPage1, 2, 13);
+ sub_80917CC(14, 0x3FC);
+ gTasks[taskId].data[0]++;
+ break;
+ case 4:
+ {
+ u8 spriteId = sub_80918EC(dexNum, 0x30, 0x38, 0);
+
+ gSprites[spriteId].oam.priority = 0;
+ BeginNormalPaletteFade(-1, 0, 0x10, 0, 0);
+ SetVBlankCallback(gUnknown_03005CEC);
+ gTasks[taskId].data[3] = spriteId;
+ gTasks[taskId].data[0]++;
+ break;
+ }
+ case 5:
+ REG_BLDCNT = 0;
+ REG_BLDALPHA = 0;
+ REG_BLDY = 0;
+ REG_BG3CNT = 0xF07;
+ REG_DISPCNT = 0x1C40;
+ gTasks[taskId].data[0]++;
+ break;
+ case 6:
+ if(!gPaletteFade.active)
+ {
+ PlayCry1(NationalPokedexNumToSpecies(dexNum), 0);
+ gTasks[taskId].data[2] = 0;
+ gTasks[taskId].data[4] = 0;
+ gTasks[taskId].func = sub_8090A3C;
+ }
+ break;
}
}
-*/
+*/ \ No newline at end of file
diff --git a/src/pokemon_2.c b/src/pokemon_2.c
index 588b01168..c8d07f88d 100644
--- a/src/pokemon_2.c
+++ b/src/pokemon_2.c
@@ -6,6 +6,7 @@
#include "main.h"
#include "sprite.h"
#include "berry.h"
+#include "flag.h"
extern u8 gPlayerPartyCount;
extern struct Pokemon gPlayerParty[6];
@@ -52,7 +53,6 @@ extern u8 gHoldEffectToType[][2];
extern u8 battle_side_get_owner(u8);
extern u8 battle_get_side_with_given_state(u8);
extern u32 battle_get_per_side_status(u8);
-extern u8 FlagGet(u16);
extern u8 sub_8018324(u8, u8, u8, u8, u16);
extern u8 sub_803C348(u8);
diff --git a/src/pokemon_size_record.c b/src/pokemon_size_record.c
new file mode 100644
index 000000000..6381881b7
--- /dev/null
+++ b/src/pokemon_size_record.c
@@ -0,0 +1,195 @@
+#include "gba/gba.h"
+#include "global.h"
+#include "pokemon.h"
+#include "species.h"
+#include "flag.h"
+#include "var.h"
+
+extern u16 SpeciesToNationalPokedexNum(u16);
+extern u16 sub_8090D54(u16, u8);
+
+struct UnknownStruct
+{
+ u16 unk0;
+ u8 unk2;
+ u16 unk4;
+};
+
+extern struct UnknownStruct gUnknown_083D180C[];
+extern u8 gOtherText_DecimalPoint[];
+extern u8 gOtherText_Marco[];
+extern u16 gScriptResult;
+extern u8 gSpeciesNames[][11];
+extern u8 gUnknown_083D188E[];
+
+#define VAR_SHROOMISH_SIZE_RECORD 0x4047
+#define VAR_BARBOACH_SIZE_RECORD 0x404F
+#define CM_PER_INCH 2.54
+
+static u32 GetMonSizeHash(struct Pokemon *pkmn)
+{
+ // UB: Too few arguments for function 'GetMonData'
+ u16 personality = GetMonData(pkmn, MON_DATA_PERSONALITY);
+ u16 hpIV = GetMonData(pkmn, MON_DATA_HP_IV) & 0xF;
+ u16 attackIV = GetMonData(pkmn, MON_DATA_ATK_IV) & 0xF;
+ u16 defenseIV = GetMonData(pkmn, MON_DATA_DEF_IV) & 0xF;
+ u16 speedIV = GetMonData(pkmn, MON_DATA_SPD_IV) & 0xF;
+ u16 spAtkIV = GetMonData(pkmn, MON_DATA_SPATK_IV) & 0xF;
+ u16 spDefIV = GetMonData(pkmn, MON_DATA_SPDEF_IV) & 0xF;
+ u32 hibyte = ((attackIV ^ defenseIV) * hpIV) ^ (personality & 0xFF);
+ u32 lobyte = ((spAtkIV ^ spDefIV) * speedIV) ^ (personality >> 8);
+
+ return (hibyte << 8) + lobyte;
+}
+
+static u8 TranslateBigMonSizeTableIndex(u16 a)
+{
+ u8 i;
+
+ for(i = 1; i < 15; i++)
+ {
+ if(a < gUnknown_083D180C[i].unk4)
+ return i - 1;
+ }
+ return i;
+}
+
+static u32 GetMonSize(u16 species, u16 b)
+{
+ u64 unk2;
+ u64 unk4;
+ u64 unk0;
+ u32 r7;
+ u32 var;
+ struct UnknownStruct *s;
+
+ r7 = sub_8090D54(SpeciesToNationalPokedexNum(species), 0);
+ var = TranslateBigMonSizeTableIndex(b);
+ unk0 = gUnknown_083D180C[var].unk0;
+ unk2 = gUnknown_083D180C[var].unk2;
+ unk4 = gUnknown_083D180C[var].unk4;
+ unk0 += (b - unk4) / unk2;
+ return r7 * unk0 / 10;
+}
+
+static void FormatMonSizeRecord(u8 *string, u32 size)
+{
+ u8 decimalPoint[2];
+
+ memcpy(decimalPoint, gOtherText_DecimalPoint, 2);
+ //Convert size from centimeters to inches
+ size = (double)(size * 10) / (CM_PER_INCH * 10);
+ string = ConvertIntToDecimalStringN(string, size / 10, 0, 8);
+ string = StringAppend(string, decimalPoint);
+ ConvertIntToDecimalStringN(string, size % 10, 0, 1);
+}
+
+static u8 CompareMonSize(u16 species, u16 *sizeRecord)
+{
+ if(gScriptResult == 0xFF)
+ return 0;
+ else
+ {
+ struct Pokemon *pkmn = &gPlayerParty[gScriptResult];
+
+ // UB: Too few arguments for function 'GetMonData'
+ if(GetMonData(pkmn, MON_DATA_IS_EGG) == TRUE || GetMonData(pkmn, MON_DATA_SPECIES) != species)
+ return 1;
+ else
+ {
+ u32 oldSize;
+ u32 newSize;
+ u16 sizeParams;
+ u16 *ptr = &sizeParams; //Why the pointer?
+
+ *ptr = GetMonSizeHash(pkmn);
+ newSize = GetMonSize(species, sizeParams);
+ oldSize = GetMonSize(species, *sizeRecord);
+ FormatMonSizeRecord(gStringVar2, newSize);
+ if(newSize <= oldSize)
+ return 2;
+ else
+ {
+ *sizeRecord = sizeParams;
+ return 3;
+ }
+ }
+ }
+}
+
+//Stores species name in gStringVar1, trainer's name in gStringVar2, and size in gStringVar3
+static void GetMonSizeRecordInfo(u16 species, u16 *sizeRecord)
+{
+ u32 size = GetMonSize(species, *sizeRecord);
+
+ FormatMonSizeRecord(gStringVar3, size);
+ StringCopy(gStringVar1, gSpeciesNames[species]);
+ if(*sizeRecord == 0x8100)
+ StringCopy(gStringVar2, gOtherText_Marco);
+ else
+ StringCopy(gStringVar2, gSaveBlock2.playerName);
+}
+
+void InitShroomishSizeRecord(void)
+{
+ VarSet(VAR_SHROOMISH_SIZE_RECORD, 0x8100);
+}
+
+void GetShroomishSizeRecordInfo(void)
+{
+ u16 *sizeRecord = GetVarPointer(VAR_SHROOMISH_SIZE_RECORD);
+
+ GetMonSizeRecordInfo(SPECIES_SHROOMISH, sizeRecord);
+}
+
+void CompareShroomishSize(void)
+{
+ u16 *sizeRecord = GetVarPointer(VAR_SHROOMISH_SIZE_RECORD);
+
+ gScriptResult = CompareMonSize(SPECIES_SHROOMISH, sizeRecord);
+}
+
+void InitBarboachSizeRecord(void)
+{
+ VarSet(VAR_BARBOACH_SIZE_RECORD, 0x8100);
+}
+
+void GetBarboachSizeRecordInfo(void)
+{
+ u16 *sizeRecord = GetVarPointer(VAR_BARBOACH_SIZE_RECORD);
+
+ GetMonSizeRecordInfo(SPECIES_BARBOACH, sizeRecord);
+}
+
+void CompareBarboachSize(void)
+{
+ u16 *sizeRecord = GetVarPointer(VAR_BARBOACH_SIZE_RECORD);
+
+ gScriptResult = CompareMonSize(SPECIES_BARBOACH, sizeRecord);
+}
+
+void GiveGiftRibbonToParty(u8 index, u8 ribbonId)
+{
+ s32 i;
+ u8 arr[7];
+ bool32 gotRibbon = FALSE;
+ u8 data = 1;
+
+ memcpy(arr, gUnknown_083D188E, 7);
+ if(index < 11 && ribbonId < 65)
+ {
+ gSaveBlock1.giftRibbons[index] = ribbonId;
+ for(i = 0; i < 6; i++)
+ {
+ struct Pokemon *pkmn = &gPlayerParty[i];
+
+ if(GetMonData(pkmn, MON_DATA_SPECIES) != 0 && GetMonData(pkmn, MON_DATA_SANITY_BIT3) == 0)
+ {
+ SetMonData(pkmn, arr[index], &data);
+ gotRibbon = TRUE;
+ }
+ }
+ if(gotRibbon)
+ FlagSet(SYS_RIBBON_GET);
+ }
+}
diff --git a/src/record_mixing.c b/src/record_mixing.c
new file mode 100644
index 000000000..4996dc01f
--- /dev/null
+++ b/src/record_mixing.c
@@ -0,0 +1,735 @@
+#include "global.h"
+#include "link.h"
+#include "menu.h"
+#include "pokemon.h"
+#include "rng.h"
+#include "script.h"
+#include "songs.h"
+#include "sound.h"
+#include "string_util.h"
+#include "task.h"
+#include "flag.h"
+#include "var.h"
+
+extern void *recordMixingSecretBases;
+extern void *recordMixingTvShows;
+extern void *gUnknown_083D0274;
+extern void *gUnknown_083D0278;
+extern void *recordMixingEasyChatPairs;
+extern void *gUnknown_083D0280;
+extern void *gUnknown_083D0284;
+extern u8 gUnknown_083D0288[2];
+extern u8 gUnknown_083D028A[2][3];
+extern u8 gUnknown_083D0290[9][4];
+
+extern u8 gUnknown_02038738[]; //Don't know what type this points to
+extern u16 gSpecialVar_0x8005;
+extern u32 gUnknown_03005D2C;
+extern u8 gUnknown_03000718;
+extern u8 gUnknown_0300071C[];
+extern u8 gOtherText_MixingComplete[];
+extern u8 gOtherText_MixingRecordsWithFriend[];
+extern bool8 gReceivedRemoteLinkPlayers;
+extern u8 gBlockSendBuffer[BLOCK_BUFFER_SIZE];
+extern u16 gBlockRecvBuffer[MAX_LINK_PLAYERS][BLOCK_BUFFER_SIZE / 2];
+
+extern void sub_8083A84(TaskFunc);
+extern void sub_8041324(struct BoxPokemon *, void *);
+extern void sub_80BD674(void *, u32, u8);
+extern void sub_80BFD44(void *, u32, u8);
+extern void sub_80C0514(void *, u32, u8);
+// UB: sub_80FA4E4 declared with 3 arguments instead of 2
+extern void sub_80FA4E4(void *, u32, u8);
+extern void sub_80B9C6C(void *, u32, u8, void *);
+extern void sub_80B9F3C(void *, u8);
+extern u16 sub_8126338(void);
+extern u8 sub_8083664(void);
+extern void sub_80720B0(void);
+extern void CreateRecordMixingSprite(void);
+extern void DestroyRecordMixingSprite(void);
+extern u16 sub_8055588(void);
+extern void sub_80F7F30(void);
+extern void sub_8134AC0(void *);
+
+void sub_80B9484(u8);
+void sub_80B95F0(u8);
+void sub_80BA00C(u8);
+void sub_80B97DC(u8);
+void Task_CopyRecvBuffer(u8);
+void sub_80B9A1C(u8);
+u8 GetMultiplayerId_(void);
+void StorePtrInTaskData(void *, u16 *);
+void *LoadPtrFromTaskData(u16 *);
+void sub_80B9B1C(u8 *, size_t, u8);
+void sub_80B9B70(u8 *, size_t, u8);
+u16 *GetPlayerRecvBuffer(u8 player);
+void sub_80B9A78(void);
+
+#define BUFFER_CHUNK_SIZE 200
+
+void sub_80B929C(void)
+{
+ sub_8083A84(sub_80B9484);
+}
+
+struct PlayerRecords {
+ struct SecretBaseRecord secretBases[20];
+ u8 tvShows[25][36];
+ u8 filler1004[0x40];
+ u8 filler1044[0x40];
+ struct EasyChatPair easyChatPairs[5];
+ u8 filler10AC[0x78];
+ u8 filler1124[0xA4];
+ u16 filler11C8[0x34];
+};
+
+extern struct PlayerRecords unk_2008000;
+extern struct PlayerRecords unk_2018000;
+
+#ifdef NONMATCHING
+void sub_80B92AC(void)
+{
+ sub_80BC300();
+ sub_80C045C();
+
+ memcpy(unk_2018000.secretBases, recordMixingSecretBases, sizeof(unk_2018000.secretBases));
+ memcpy(unk_2018000.tvShows, recordMixingTvShows, sizeof(unk_2018000.tvShows));
+ memcpy(unk_2018000.filler1004, gUnknown_083D0274, 0x40);
+ memcpy(unk_2018000.filler1044, gUnknown_083D0278, 0x40);
+ memcpy(unk_2018000.easyChatPairs, recordMixingEasyChatPairs, 0x28);
+ memcpy(gUnknown_02038738, gSaveBlock1.filler_303C, 0x38);
+ memcpy(gUnknown_02038738 + 0x38, gSaveBlock1.filler_3074, 0x38);
+ sub_8041324(gSaveBlock1.filler_2F9C, gUnknown_02038738);
+ memcpy(unk_2018000.filler10AC, gUnknown_083D0280, 0x78);
+ memcpy(unk_2018000.filler1124, gUnknown_083D0284, 0xA4);
+
+ if(GetMultiplayerId() == 0)
+ unk_2018000.filler11C8[0] = sub_8126338();
+}
+#else
+__attribute__((naked))
+void sub_80B92AC(void)
+{
+ asm(".syntax unified\n\
+ push {r4-r6,lr}\n\
+ bl sub_80BC300\n\
+ bl sub_80C045C\n\
+ ldr r6, _080B9364 @ =0x02018000\n\
+ ldr r0, _080B9368 @ =recordMixingSecretBases\n\
+ ldr r1, [r0]\n\
+ movs r2, 0xC8\n\
+ lsls r2, 4\n\
+ adds r0, r6, 0\n\
+ bl memcpy\n\
+ movs r1, 0xC8\n\
+ lsls r1, 4\n\
+ adds r0, r6, r1\n\
+ ldr r1, _080B936C @ =recordMixingTvShows\n\
+ ldr r1, [r1]\n\
+ movs r2, 0xE1\n\
+ lsls r2, 2\n\
+ bl memcpy\n\
+ ldr r2, _080B9370 @ =0x00001004\n\
+ adds r0, r6, r2\n\
+ ldr r1, _080B9374 @ =gUnknown_083D0274\n\
+ ldr r1, [r1]\n\
+ movs r2, 0x40\n\
+ bl memcpy\n\
+ ldr r1, _080B9378 @ =0x00001044\n\
+ adds r0, r6, r1\n\
+ ldr r1, _080B937C @ =gUnknown_083D0278\n\
+ ldr r1, [r1]\n\
+ movs r2, 0x40\n\
+ bl memcpy\n\
+ ldr r2, _080B9380 @ =0x00001084\n\
+ adds r0, r6, r2\n\
+ ldr r1, _080B9384 @ =recordMixingEasyChatPairs\n\
+ ldr r1, [r1]\n\
+ movs r2, 0x28\n\
+ bl memcpy\n\
+ ldr r5, _080B9388 @ =gUnknown_02038738\n\
+ ldr r4, _080B938C @ =gSaveBlock1\n\
+ ldr r0, _080B9390 @ =0x0000303c\n\
+ adds r1, r4, r0\n\
+ adds r0, r5, 0\n\
+ movs r2, 0x38\n\
+ bl memcpy\n\
+ ldr r2, _080B9394 @ =0x00003074\n\
+ adds r1, r4, r2\n\
+ adds r0, r5, 0\n\
+ adds r0, 0x38\n\
+ movs r2, 0x38\n\
+ bl memcpy\n\
+ ldr r0, _080B9398 @ =0x00002f9c\n\
+ adds r4, r0\n\
+ adds r0, r4, 0\n\
+ adds r1, r5, 0\n\
+ bl sub_8041324\n\
+ ldr r1, _080B939C @ =0x000010ac\n\
+ adds r0, r6, r1\n\
+ ldr r1, _080B93A0 @ =gUnknown_083D0280\n\
+ ldr r1, [r1]\n\
+ movs r2, 0x78\n\
+ bl memcpy\n\
+ ldr r2, _080B93A4 @ =0x00001124\n\
+ adds r0, r6, r2\n\
+ ldr r1, _080B93A8 @ =gUnknown_083D0284\n\
+ ldr r1, [r1]\n\
+ movs r2, 0xA4\n\
+ bl memcpy\n\
+ bl GetMultiplayerId\n\
+ lsls r0, 24\n\
+ cmp r0, 0\n\
+ bne _080B935C\n\
+ bl sub_8126338\n\
+ ldr r2, _080B93AC @ =0x000011c8\n\
+ adds r1, r6, r2\n\
+ strh r0, [r1]\n\
+_080B935C:\n\
+ pop {r4-r6}\n\
+ pop {r0}\n\
+ bx r0\n\
+ .align 2, 0\n\
+_080B9364: .4byte 0x02018000\n\
+_080B9368: .4byte recordMixingSecretBases\n\
+_080B936C: .4byte recordMixingTvShows\n\
+_080B9370: .4byte 0x00001004\n\
+_080B9374: .4byte gUnknown_083D0274\n\
+_080B9378: .4byte 0x00001044\n\
+_080B937C: .4byte gUnknown_083D0278\n\
+_080B9380: .4byte 0x00001084\n\
+_080B9384: .4byte recordMixingEasyChatPairs\n\
+_080B9388: .4byte gUnknown_02038738\n\
+_080B938C: .4byte gSaveBlock1\n\
+_080B9390: .4byte 0x0000303c\n\
+_080B9394: .4byte 0x00003074\n\
+_080B9398: .4byte 0x00002f9c\n\
+_080B939C: .4byte 0x000010ac\n\
+_080B93A0: .4byte gUnknown_083D0280\n\
+_080B93A4: .4byte 0x00001124\n\
+_080B93A8: .4byte gUnknown_083D0284\n\
+_080B93AC: .4byte 0x000011c8\n\
+ .syntax divided\n");
+}
+#endif
+
+#undef NONMATCHING
+
+void sub_80B93B0(u32 a)
+{
+ sub_80BD674(unk_2008000.secretBases, sizeof(struct PlayerRecords), a);
+ sub_80BFD44(unk_2008000.tvShows, sizeof(struct PlayerRecords), a);
+ sub_80C0514(unk_2008000.filler1004, sizeof(struct PlayerRecords), a);
+ sub_80B9B1C(unk_2008000.filler1044, sizeof(struct PlayerRecords), a);
+ //UB: Too many arguments for function "sub_80FA4E4"
+ sub_80FA4E4(unk_2008000.easyChatPairs, sizeof(struct PlayerRecords), a);
+ sub_80B9C6C(unk_2008000.filler10AC, sizeof(struct PlayerRecords), a, unk_2008000.tvShows);
+ sub_80B9B70(unk_2008000.filler1124, sizeof(struct PlayerRecords), a);
+ sub_80B9F3C(unk_2008000.filler11C8, a);
+}
+
+void sub_80B9450(u8 taskId)
+{
+ gTasks[taskId].data[0]++;
+ if(gTasks[taskId].data[0] == 50)
+ {
+ PlaySE(SE_W213);
+ gTasks[taskId].data[0] = 0;
+ }
+}
+
+#define TD_STATE 0
+
+void sub_80B9484(u8 taskId)
+{
+ s16 *taskData = gTasks[taskId].data;
+
+ switch(taskData[TD_STATE])
+ {
+ case 0:
+ sub_8007270(gSpecialVar_0x8005);
+ VarSet(0x4000, 1);
+ gUnknown_03000718 = 0;
+ sub_80B92AC();
+ CreateRecordMixingSprite();
+ taskData[TD_STATE] = 1;
+ taskData[10] = CreateTask(sub_80B95F0, 0x50);
+ taskData[15] = CreateTask(sub_80B9450, 0x51);
+ break;
+ case 1:
+ if(!gTasks[taskData[10]].isActive)
+ {
+ taskData[TD_STATE] = 2;
+ FlagSet(SYS_MIX_RECORD);
+ DestroyRecordMixingSprite();
+ DestroyTask(taskData[15]);
+ }
+ break;
+ case 2:
+ taskData[10] = CreateTask(sub_80BA00C, 10);
+ taskData[TD_STATE] = 3;
+ PlaySE(SE_W226);
+ break;
+ case 3:
+ if(!gTasks[taskData[10]].isActive)
+ {
+ taskData[TD_STATE] = 4;
+ taskData[10] = sub_8083664();
+ sub_80720B0();
+ MenuPrint(gOtherText_MixingComplete, 2, 15);
+ taskData[8] = 0;
+ }
+ break;
+ case 4:
+ taskData[8]++;
+ if(taskData[8] > 60)
+ taskData[TD_STATE] = 5;
+ break;
+ case 5:
+ if(!gTasks[taskData[10]].isActive)
+ {
+ sub_8055588();
+ MenuZeroFillScreen();
+ DestroyTask(taskId);
+ EnableBothScriptContexts();
+ }
+ break;
+ }
+}
+
+void sub_80B95F0(u8 taskId)
+{
+ struct Task *task = &gTasks[taskId];
+
+ switch(task->data[TD_STATE])
+ {
+ case 0:
+ sub_80B9A78();
+ MenuDisplayMessageBox();
+ MenuPrint(gOtherText_MixingRecordsWithFriend, 2, 15);
+ task->data[8] = 0x708;
+ task->data[TD_STATE] = 0x190;
+ ClearLinkCallback_2();
+ break;
+ case 100:
+ task->data[12]++;
+ if(task->data[12] > 20)
+ {
+ task->data[12] = 0;
+ task->data[TD_STATE] = 101;
+ }
+ break;
+ case 101:
+ {
+ u8 players = GetLinkPlayerCount_2();
+
+ if(IsLinkMaster() == 1)
+ {
+ if(players == sub_800820C())
+ {
+ PlaySE(0x15);
+ task->data[TD_STATE] = 201;
+ task->data[12] = 0;
+ }
+ }
+ else
+ {
+ PlaySE(0x16);
+ task->data[TD_STATE] = 301;
+ }
+ break;
+ }
+ case 201:
+ if(sub_800820C() == GetLinkPlayerCount_2())
+ {
+ if(++task->data[12] > GetLinkPlayerCount_2() * 30)
+ {
+ sub_8007F4C();
+ task->data[TD_STATE] = 1;
+ }
+ }
+ break;
+ case 301:
+ if(sub_800820C() == GetLinkPlayerCount_2())
+ task->data[TD_STATE] = 1;
+ break;
+ case 400:
+ task->data[12]++;
+ if(task->data[12] > 20)
+ {
+ task->data[TD_STATE] = 1;
+ task->data[12] = 0;
+ }
+ break;
+ case 1:
+ if(gReceivedRemoteLinkPlayers)
+ {
+ ConvertIntToDecimalStringN(gStringVar1, GetMultiplayerId_(), 2, 2);
+ task->data[TD_STATE] = 5;
+ }
+ break;
+ case 2:
+ {
+ u8 subTaskId;
+
+ task->data[6] = GetLinkPlayerCount_2();
+ task->data[TD_STATE] = 0;
+ task->data[5] = GetMultiplayerId_();
+ task->func = sub_80B97DC;
+ StorePtrInTaskData(&unk_2018000, &task->data[2]);
+ subTaskId = CreateTask(Task_CopyRecvBuffer, 0x50);
+ task->data[10] = subTaskId;
+ gTasks[subTaskId].data[0] = taskId;
+ //StorePtrInTaskData((void*)0x2008000, &gTasks[subTaskId].data[5]);
+ StorePtrInTaskData((u8 *)&unk_2018000 - 0x10000, &gTasks[subTaskId].data[5]);
+ break;
+ }
+ case 5:
+ task->data[10]++;
+ if(task->data[10] > 60)
+ {
+ task->data[10] = 0;
+ task->data[TD_STATE] = 2;
+ }
+ break;
+ }
+}
+
+void sub_80B97DC(u8 taskId)
+{
+ struct Task *task = &gTasks[taskId];
+
+ switch(task->data[TD_STATE])
+ {
+ case 0: //Copy record data to send buffer
+ {
+ void *recordData = (u8 *)LoadPtrFromTaskData(&task->data[2]) + BUFFER_CHUNK_SIZE * task->data[4];
+
+ memcpy(gBlockSendBuffer, recordData, BUFFER_CHUNK_SIZE);
+ task->data[TD_STATE]++;
+ break;
+ }
+ case 1:
+ if(GetMultiplayerId() == 0)
+ sub_8007E9C(1);
+ task->data[TD_STATE]++;
+ break;
+ case 2:
+ break;
+ case 3:
+ task->data[4]++;
+ if((u16)task->data[4] == 24)
+ task->data[TD_STATE]++;
+ else
+ task->data[TD_STATE] = 0;
+ break;
+ case 4:
+ if(!gTasks[task->data[10]].isActive)
+ task->func = sub_80B9A1C;
+ }
+}
+
+void Task_CopyRecvBuffer(u8 taskId)
+{
+ struct Task *task = &gTasks[taskId];
+ s32 recvStatus = GetBlockReceivedStatus();
+ u32 sp8 = 0;
+
+ if(recvStatus == sub_8008198())
+ {
+ u8 player;
+
+ for(player = 0; player < GetLinkPlayerCount(); player++)
+ {
+ //_080B98D4
+ u8 *ptr;
+ void *src;
+ u8 *dst;
+
+ if((recvStatus >> player) & 1)
+ {
+ ptr = LoadPtrFromTaskData(&task->data[5]);
+ dst = ptr + task->data[player + 1] * BUFFER_CHUNK_SIZE + player * sizeof(struct PlayerRecords);
+ src = GetPlayerRecvBuffer(player);
+ if((u32)(task->data[player + 1] + 1) * BUFFER_CHUNK_SIZE > sizeof(struct PlayerRecords))
+ memcpy(dst, src, sizeof(struct PlayerRecords) - task->data[player + 1] * BUFFER_CHUNK_SIZE);
+ else
+ memcpy(dst, src, BUFFER_CHUNK_SIZE);
+ //_080B993C
+ ResetBlockReceivedFlag(player);
+ task->data[player + 1]++;
+ if((u16)task->data[player + 1] == 0x18)
+ sp8 = (u8)(sp8 + 1);
+ }
+ }
+ //line 828
+ gTasks[task->data[0]].data[0]++;
+ }
+ //_080B998A
+ if(sp8 == GetLinkPlayerCount())
+ DestroyTask(taskId);
+}
+
+void sub_80B99B4(u8 taskId)
+{
+ struct Task *task = &gTasks[taskId];
+
+ if(!gTasks[task->data[10]].isActive)
+ DestroyTask(taskId);
+}
+
+void sub_80B99E8(u8 taskId)
+{
+ struct Task *task = &gTasks[taskId];
+
+ task->func = sub_80B99B4;
+ if(gUnknown_03000718 == 1)
+ sub_80B93B0(task->data[5]);
+}
+
+void sub_80B9A1C(u8 taskId)
+{
+ gTasks[taskId].func = sub_80B99E8;
+ gUnknown_03000718 = 1;
+}
+
+void *LoadPtrFromTaskData(u16 *ptr)
+{
+ return (void *)(*ptr | *(ptr + 1) << 16);
+}
+
+void StorePtrInTaskData(void *ptr, u16 *data)
+{
+ *data = (u32)ptr;
+ *(data + 1) = (u32)ptr >> 16;
+}
+
+u8 GetMultiplayerId_(void)
+{
+ return GetMultiplayerId();
+}
+
+u16 *GetPlayerRecvBuffer(u8 player)
+{
+ return gBlockRecvBuffer[player];
+}
+
+void sub_80B9A78(void)
+{
+ gUnknown_03005D2C = sizeof(struct PlayerRecords);
+}
+
+void sub_80B9A88(u8 *a)
+{
+ u32 i;
+ u32 id;
+ u32 players = GetLinkPlayerCount();
+
+ switch(players)
+ {
+ case 2:
+ for(i = 0; i < 2; i++)
+ a[i] = gUnknown_083D0288[i];
+ break;
+ case 3:
+ id = GetLinkPlayerTrainerId(0) % 2;
+ for(i = 0; i < 3; i++)
+ a[i] = gUnknown_083D028A[id][i];
+ break;
+ case 4:
+ id = GetLinkPlayerTrainerId(0) % 9;
+ for(i = 0; i < 4; i++)
+ a[i] = gUnknown_083D0290[id][i];
+ break;
+ default:
+ break;
+ }
+}
+
+void sub_80B9B1C(u8 *a, size_t size, u8 index)
+{
+ u8 arr[4];
+ u8 *ptr;
+
+ sub_80B9A88(arr);
+ //Probably not how it was originally written, but this matches.
+ memcpy(a + index * size, (ptr = gUnknown_083D0278), 0x40);
+ memcpy(ptr, a + arr[index] * size, 0x40);
+ sub_80F7F30();
+}
+
+void sub_80B9B70(u8 *a, size_t size, u8 index)
+{
+ sub_80B9A88(gUnknown_0300071C);
+ memcpy(a + size * index, a + size * gUnknown_0300071C[index], 0xA4);
+ sub_8134AC0(a + size * index);
+}
+
+u8 sub_80B9BBC(u16 *a)
+{
+ return a[16];
+}
+
+#ifdef NONMATCHING
+
+void sub_80B9BC4(u32 a, u32 b, u32 c, u32 d)
+{
+ //ToDo: Figure out what this strange stack usage is
+}
+
+#else
+__attribute__((naked))
+void sub_80B9BC4(u32 a, u32 b, u32 c, u32 d)
+{
+ asm(".syntax unified\n\
+ push {r4-r6,lr}\n\
+ mov r6, r10\n\
+ mov r5, r9\n\
+ mov r4, r8\n\
+ push {r4-r6}\n\
+ sub sp, 0x38\n\
+ mov r8, r0\n\
+ mov r10, r1\n\
+ mov r9, r2\n\
+ adds r4, r3, 0\n\
+ ldr r5, [sp, 0x54]\n\
+ lsls r4, 24\n\
+ lsls r5, 24\n\
+ lsrs r5, 24\n\
+ lsrs r4, 23\n\
+ add r4, r9\n\
+ ldrb r0, [r4]\n\
+ mov r6, r10\n\
+ muls r6, r0\n\
+ add r6, r8\n\
+ ldrb r0, [r4, 0x1]\n\
+ lsls r1, r0, 3\n\
+ subs r1, r0\n\
+ lsls r1, 3\n\
+ adds r1, r6, r1\n\
+ mov r0, sp\n\
+ movs r2, 0x38\n\
+ bl memcpy\n\
+ lsls r5, 1\n\
+ add r5, r9\n\
+ ldrb r0, [r5]\n\
+ mov r1, r10\n\
+ muls r1, r0\n\
+ adds r0, r1, 0\n\
+ add r8, r0\n\
+ ldrb r1, [r4, 0x1]\n\
+ lsls r0, r1, 3\n\
+ subs r0, r1\n\
+ lsls r0, 3\n\
+ adds r6, r0\n\
+ ldrb r0, [r5, 0x1]\n\
+ lsls r1, r0, 3\n\
+ subs r1, r0\n\
+ lsls r1, 3\n\
+ add r1, r8\n\
+ adds r0, r6, 0\n\
+ movs r2, 0x38\n\
+ bl memcpy\n\
+ ldrb r1, [r5, 0x1]\n\
+ lsls r0, r1, 3\n\
+ subs r0, r1\n\
+ lsls r0, 3\n\
+ add r8, r0\n\
+ mov r0, r8\n\
+ mov r1, sp\n\
+ movs r2, 0x38\n\
+ bl memcpy\n\
+ add sp, 0x38\n\
+ pop {r3-r5}\n\
+ mov r8, r3\n\
+ mov r9, r4\n\
+ mov r10, r5\n\
+ pop {r4-r6}\n\
+ pop {r0}\n\
+ bx r0\n\
+ .syntax divided\n");
+}
+#endif
+
+u8 sub_80B9C4C(u8 *a)
+{
+ int i;
+ u8 r2 = 0;
+
+ for(i = 0; i < 0x100; i++)
+ r2 += a[i];
+ return r2;
+}
+
+struct UnkStruct1
+{
+ u8 unk0[4];
+ u8 unk4[4];
+ u8 unk8[4];
+ u8 fillerC[0x10];
+ u8 unk1C[4][2];
+ u8 filler24[8];
+ void *unk2C;
+ u32 unk30;
+ u32 unk34;
+ void *unk38;
+ u32 unk3C;
+ u32 unk40;
+ u8 filler44[4];
+ u32 unk48;
+ u32 unk4C;
+ u32 unk50;
+
+};
+
+/*
+//Not finished
+extern void sub_80B9C6C(void *a, u32 b, u8 c, void *d)
+{
+ struct UnkStruct1 s;
+ u16 r8;
+ u16 r3;
+
+ s.unk2C = a;
+ s.unk30 = b;
+ s.unk38 = d;
+ s.unk34 = c;
+ s.unk40 = Random();
+ SeedRng(gLinkPlayers[0].trainerId);
+ r8 = GetLinkPlayerCount();
+ r3 = 0;
+
+ s.unk4C = 12;
+
+ while(r3 < 4)
+ {
+
+ s.unk4[r3] |= 0xFF;
+ s.unk8[r3] = 0;
+
+ s.unk1C[r3][0] = 0;
+ s.unk1C[r3][1] = 0;
+ r3++;
+ }
+ s.unk3C = 0;
+ r3 = 0;
+ s.unk50 = r8 << 16;
+ s.unk48 = s.unk30 * s.unk34;
+
+ if(s.unk3C < r8)
+ {
+ do //_080B9D00
+ {
+ u32 *r6 = (u32 *)(s.unk2C + s.unk30 * r3);
+ if(r6[0x1C] != 0 && r6[0x1C] > 0)
+ {
+
+ }
+ //_080B9D3C
+ }
+ while(r3 < r8);
+ }
+ //_080B9D46
+}
+*/
+
diff --git a/src/rom4.c b/src/rom4.c
index e23e5d2fc..15041cb39 100644
--- a/src/rom4.c
+++ b/src/rom4.c
@@ -9,6 +9,8 @@
#include "text.h"
#include "link.h"
#include "sprite.h"
+#include "flag.h"
+#include "var.h"
#ifdef SAPPHIRE
#define LEGENDARY_MUSIC BGM_OOAME // Heavy Rain
@@ -133,14 +135,12 @@ extern s32 gUnknown_0839ACE8;
extern u32 gUnknown_08216694[];
extern struct UnkWarpStruct *GetHealLocation(u8);
-extern u16 VarGet(u16);
-extern u8 FlagGet(u16);
extern u8 GetSav1Weather(void);
extern void PlayerGetDestCoords(u16 *, u16 *);
extern u8 sub_810D32C(void);
extern u16 GetLocalWildMon(bool8 *);
extern u16 GetMirageIslandMon(void);
-extern void sub_80C76A0(void);
+extern void ExecuteTruckSequence(void);
extern void sub_8080B60(void);
extern void sub_810CC80(void);
extern void sub_8080AC4(void);
@@ -172,7 +172,7 @@ u8 sub_8053B60(struct UnkPlayerStruct *playerStruct, u8, u16, u8);
u8 MetatileBehavior_IsSurfableWaterOrUnderwater(u8);
bool8 sub_8056F24(u8);
bool8 sub_8056F08(u8);
-bool8 sub_8056EAC(u8);
+bool8 MetatileBehavior_IsDoor(u8);
bool8 MetatileBehavior_IsSouthArrowWarp(u8);
bool8 MetatileBehavior_IsNorthArrowWarp(u8);
bool8 MetatileBehavior_IsWestArrowWarp(u8);
@@ -260,47 +260,47 @@ void sub_8052F5C(void)
void flag_var_implications_of_teleport_(void)
{
player_avatar_init_params_reset();
- FlagReset(2091);
- FlagReset(2093);
- FlagReset(2092);
- FlagReset(2089);
- FlagReset(2088);
+ FlagReset(SYS_CYCLING_ROAD);
+ FlagReset(SYS_CRUISE_MODE);
+ FlagReset(SYS_SAFARI_MODE);
+ FlagReset(SYS_USE_STRENGTH);
+ FlagReset(SYS_USE_FLASH);
}
void new_game(void)
{
player_avatar_init_params_reset();
- FlagReset(2091);
- FlagReset(2093);
- FlagReset(2092);
- FlagReset(2089);
- FlagReset(2088);
+ FlagReset(SYS_CYCLING_ROAD);
+ FlagReset(SYS_CRUISE_MODE);
+ FlagReset(SYS_SAFARI_MODE);
+ FlagReset(SYS_USE_STRENGTH);
+ FlagReset(SYS_USE_FLASH);
ScriptContext2_RunNewScript(gUnknown_0819FC9F);
}
void sub_8053014(void)
{
player_avatar_init_params_reset();
- FlagReset(2091);
- FlagReset(2093);
- FlagReset(2092);
- FlagReset(2089);
- FlagReset(2088);
+ FlagReset(SYS_CYCLING_ROAD);
+ FlagReset(SYS_CRUISE_MODE);
+ FlagReset(SYS_SAFARI_MODE);
+ FlagReset(SYS_USE_STRENGTH);
+ FlagReset(SYS_USE_FLASH);
}
void sub_8053050(void)
{
player_avatar_init_params_reset();
- FlagReset(2091);
- FlagReset(2093);
- FlagReset(2092);
- FlagReset(2089);
- FlagReset(2088);
+ FlagReset(SYS_CYCLING_ROAD);
+ FlagReset(SYS_CRUISE_MODE);
+ FlagReset(SYS_SAFARI_MODE);
+ FlagReset(SYS_USE_STRENGTH);
+ FlagReset(SYS_USE_FLASH);
}
void sub_805308C(void)
{
- FlagReset(2092);
+ FlagReset(SYS_SAFARI_MODE);
sub_8054164();
ResetCyclingRoadChallengeData();
mapnumbers_history_shift_sav1_0_2_4_out();
@@ -698,7 +698,7 @@ void sub_8053994(u32 a1)
sub_80806E4();
sub_8054164();
if (v2)
- FlagReset(2088);
+ FlagReset(SYS_USE_FLASH);
sub_8053C98();
sav1_reset_battle_music_maybe();
mapheader_run_script_with_tag_x3();
@@ -748,7 +748,7 @@ struct UnkPlayerStruct *sub_8053AA8(void)
u8 sub_8053B00(struct UnkPlayerStruct *playerStruct, u16 a2, u8 a3)
{
- if (a3 != 8 && FlagGet(2093))
+ if (a3 != 8 && FlagGet(SYS_CRUISE_MODE))
return 1;
if (a3 == 5)
return 16;
@@ -765,11 +765,11 @@ u8 sub_8053B00(struct UnkPlayerStruct *playerStruct, u16 a2, u8 a3)
u8 sub_8053B60(struct UnkPlayerStruct *playerStruct, u8 a2, u16 a3, u8 a4)
{
- if (FlagGet(2093) && a4 == 6)
+ if (FlagGet(SYS_CRUISE_MODE) && a4 == 6)
return 4;
if (sub_8056F24(a3) == TRUE)
return 2;
- if (sub_8056F08(a3) == TRUE || sub_8056EAC(a3) == TRUE)
+ if (sub_8056F08(a3) == TRUE || MetatileBehavior_IsDoor(a3) == TRUE)
return 1;
if (MetatileBehavior_IsSouthArrowWarp(a3) == TRUE)
return 2;
@@ -813,7 +813,7 @@ void sub_8053C98(void)
{
if (!gMapHeader.cave)
gSaveBlock1.flashUsed = 0;
- else if (FlagGet(2088))
+ else if (FlagGet(SYS_USE_FLASH))
gSaveBlock1.flashUsed = 1;
else
gSaveBlock1.flashUsed = gUnknown_0839ACE8;
@@ -839,7 +839,7 @@ void sub_8053D14(u16 mapDataId)
bool16 sub_8053D30(struct WarpData *warp)
{
- if (!FlagGet(2090))
+ if (!FlagGet(SYS_WEATHER_CTRL))
return FALSE;
if (warp->mapGroup != 0)
return FALSE;
@@ -955,7 +955,7 @@ void sav1_reset_battle_music_maybe(void)
void sub_8053F0C(void)
{
- if (FlagGet(16385) != TRUE)
+ if (FlagGet(SPECIAL_FLAG_1) != TRUE)
{
u16 newMusic = warp1_target_get_music();
u16 currentMusic = GetCurrentMapMusic();
@@ -1002,7 +1002,7 @@ u8 is_warp1_light_level_8_or_9(void)
void sub_8053FF8(void)
{
u16 music = warp1_target_get_music();
- if (FlagGet(16385) != TRUE && music != GetCurrentMapMusic())
+ if (FlagGet(SPECIAL_FLAG_1) != TRUE && music != GetCurrentMapMusic())
{
u8 speed = is_warp1_light_level_8_or_9();
FadeOutMapMusic(speed);
@@ -1230,7 +1230,7 @@ void CB2_NewGame(void)
PlayTimeCounter_Start();
ScriptContext1_Init();
ScriptContext2_Disable();
- gUnknown_0300485C = sub_80C76A0;
+ gUnknown_0300485C = ExecuteTruckSequence;
do_load_map_stuff_loop(&gMain.state);
SetFieldVBlankCallback();
set_callback1(c1_overworld);
diff --git a/src/safari_zone.c b/src/safari_zone.c
new file mode 100644
index 000000000..600ba95d2
--- /dev/null
+++ b/src/safari_zone.c
@@ -0,0 +1,256 @@
+#include "global.h"
+#include "flag.h"
+#include "main.h"
+#include "script.h"
+#include "string_util.h"
+
+struct PokeblockFeeder
+{
+ /*0x00*/ s16 x;
+ /*0x02*/ s16 y;
+ /*0x04*/ s8 mapNum;
+ /*0x05*/ u8 stepCounter;
+ /*0x08*/ struct Pokeblock pokeblock;
+};
+
+#define NUM_POKEBLOCK_FEEDERS 10
+
+void ClearAllPokeblockFeeders(void);
+void DecrementFeederStepCounters(void);
+extern void c2_exit_to_overworld_2_switch(void);
+extern void c2_exit_to_overworld_1_continue_scripts_restart_music(void);
+extern void sub_8080E44(void);
+extern void CB2_LoadMap(void);
+extern void sav12_xor_increment(u8);
+extern void warp_in(void);
+extern void GetXYCoordsOneStepInFrontOfPlayer(void *, void *);
+extern void PlayerGetDestCoords(u16 *, u16 *);
+
+extern u8 gUnknown_02024D26;
+
+EWRAM_DATA u8 gNumSafariBalls = 0;
+EWRAM_DATA static u16 gSafariZoneStepCounter = 0;
+EWRAM_DATA static struct PokeblockFeeder gPokeblockFeeders[NUM_POKEBLOCK_FEEDERS] = {0};
+
+extern void (*gUnknown_0300485C)(void);
+
+extern u8 gUnknown_081C340A;
+extern u8 gUnknown_081C342D;
+extern u8 gUnknown_081C3448;
+extern u8 gUnknown_081C3459;
+extern u8 *gPokeblockNames[];
+
+extern u16 gScriptResult;
+
+bool32 GetSafariZoneFlag(void)
+{
+ return FlagGet(SYS_SAFARI_MODE);
+}
+
+void SetSafariZoneFlag(void)
+{
+ FlagSet(SYS_SAFARI_MODE);
+}
+
+void ResetSafariZoneFlag(void)
+{
+ FlagReset(SYS_SAFARI_MODE);
+}
+
+void EnterSafariMode(void)
+{
+ sav12_xor_increment(0x11);
+ SetSafariZoneFlag();
+ ClearAllPokeblockFeeders();
+ gNumSafariBalls = 30;
+ gSafariZoneStepCounter = 500;
+}
+
+void ExitSafariMode(void)
+{
+ ResetSafariZoneFlag();
+ ClearAllPokeblockFeeders();
+ gNumSafariBalls = 0;
+ gSafariZoneStepCounter = 0;
+}
+
+bool8 SafariZoneTakeStep(void)
+{
+ if (GetSafariZoneFlag() == FALSE)
+ {
+ return FALSE;
+ }
+
+ DecrementFeederStepCounters();
+ gSafariZoneStepCounter--;
+ if (gSafariZoneStepCounter == 0)
+ {
+ ScriptContext1_SetupScript(&gUnknown_081C3448);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+void SafariZoneRetirePrompt(void)
+{
+ ScriptContext1_SetupScript(&gUnknown_081C342D);
+}
+
+void sub_80C824C(void)
+{
+ if (gNumSafariBalls != 0)
+ {
+ SetMainCallback2(c2_exit_to_overworld_2_switch);
+ }
+ else if (gUnknown_02024D26 == 8)
+ {
+ ScriptContext2_RunNewScript(&gUnknown_081C340A);
+ warp_in();
+ gUnknown_0300485C = sub_8080E44;
+ SetMainCallback2(CB2_LoadMap);
+ }
+ else if (gUnknown_02024D26 == 7)
+ {
+ ScriptContext1_SetupScript(&gUnknown_081C3459);
+ ScriptContext1_Stop();
+ SetMainCallback2(c2_exit_to_overworld_1_continue_scripts_restart_music);
+ }
+}
+
+static void ClearPokeblockFeeder(u8 index)
+{
+ memset(&gPokeblockFeeders[index], 0, sizeof(struct PokeblockFeeder));
+}
+
+static void ClearAllPokeblockFeeders(void)
+{
+ memset(gPokeblockFeeders, 0, sizeof(gPokeblockFeeders));
+}
+
+void SafariZoneGetPokeblockNameInFeeder(void)
+{
+ s16 x, y;
+ u16 i;
+
+ GetXYCoordsOneStepInFrontOfPlayer(&x, &y);
+
+ for (i = 0; i < NUM_POKEBLOCK_FEEDERS; i++)
+ {
+ if (gSaveBlock1.location.mapNum == gPokeblockFeeders[i].mapNum
+ && gPokeblockFeeders[i].x == x
+ && gPokeblockFeeders[i].y == y)
+ {
+ gScriptResult = i;
+ StringCopy(gStringVar1, gPokeblockNames[gPokeblockFeeders[i].pokeblock.color]);
+ return;
+ }
+ }
+
+ gScriptResult = -1;
+}
+
+static void GetPokeblockFeederWithinRange(void)
+{
+ s16 x, y;
+ u16 i;
+
+ PlayerGetDestCoords(&x, &y);
+
+ for (i = 0; i < NUM_POKEBLOCK_FEEDERS; i++)
+ {
+ if (gSaveBlock1.location.mapNum == gPokeblockFeeders[i].mapNum)
+ {
+ //Get absolute value of x and y distance from Pokeblock feeder on current map
+ x -= gPokeblockFeeders[i].x;
+ y -= gPokeblockFeeders[i].y;
+ if (x < 0)
+ x *= -1;
+ if (y < 0)
+ y *= -1;
+ if ((x + y) <= 5)
+ {
+ gScriptResult = i;
+ return;
+ }
+ }
+ }
+
+ gScriptResult = -1;
+}
+
+struct Pokeblock *unref_sub_80C8418(void)
+{
+ SafariZoneGetPokeblockNameInFeeder();
+
+ if (gScriptResult == 0xFFFF)
+ return NULL;
+ else
+ return &gPokeblockFeeders[gScriptResult].pokeblock;
+}
+
+
+struct Pokeblock *SafariZoneGetActivePokeblock(void)
+{
+ GetPokeblockFeederWithinRange();
+
+ if (gScriptResult == 0xFFFF)
+ return NULL;
+ else
+ return &gPokeblockFeeders[gScriptResult].pokeblock;
+}
+
+
+void SafariZoneActivatePokeblockFeeder(u8 pokeblock_index)
+{
+ s16 x, y;
+ u8 i;
+
+ for (i = 0; i < NUM_POKEBLOCK_FEEDERS; i++)
+ {
+ //Find free entry in gPokeblockFeeders
+ if (gPokeblockFeeders[i].mapNum == 0
+ && gPokeblockFeeders[i].x == 0
+ && gPokeblockFeeders[i].y == 0)
+ {
+ //Initialize Pokeblock feeder
+ GetXYCoordsOneStepInFrontOfPlayer(&x, &y);
+ gPokeblockFeeders[i].mapNum = gSaveBlock1.location.mapNum;
+ gPokeblockFeeders[i].pokeblock = gSaveBlock1.pokeblocks[pokeblock_index];
+ gPokeblockFeeders[i].stepCounter = 100;
+ gPokeblockFeeders[i].x = x;
+ gPokeblockFeeders[i].y = y;
+ break;
+ }
+ }
+}
+
+static void DecrementFeederStepCounters(void)
+{
+ u8 i;
+
+ for (i = 0; i < NUM_POKEBLOCK_FEEDERS; i++)
+ {
+ if (gPokeblockFeeders[i].stepCounter != 0)
+ {
+ gPokeblockFeeders[i].stepCounter--;
+ if (gPokeblockFeeders[i].stepCounter == 0)
+ ClearPokeblockFeeder(i);
+ }
+ }
+}
+
+bool8 unref_sub_80C853C(void)
+{
+ SafariZoneGetPokeblockNameInFeeder();
+
+ if (gScriptResult == 0xFFFF)
+ {
+ return FALSE;
+ }
+
+ ConvertIntToDecimalStringN(gStringVar2,
+ gPokeblockFeeders[gScriptResult].stepCounter,
+ STR_CONV_MODE_LEADING_ZEROS, 3);
+
+ return TRUE;
+}
diff --git a/src/save_menu_util.c b/src/save_menu_util.c
index c5c00500e..c811f5244 100644
--- a/src/save_menu_util.c
+++ b/src/save_menu_util.c
@@ -1,7 +1,7 @@
#include "global.h"
#include "menu.h"
+#include "flag.h"
-extern u8 FlagGet(u16);
extern u8 gOtherText_Player[];
extern u8 gOtherText_Badges[];
extern u8 gOtherText_Pokedex[];
@@ -25,7 +25,7 @@ void HandleDrawSaveWindowInfo(s16 left, s16 top)
if (sub_809473C())
width = 13;
- if (FlagGet(2049)) // player has Pokédex?
+ if (FlagGet(SYS_POKEDEX_GET))
{
// print info + dex information.
MenuDrawTextWindow(left, top, left + width, top + 11);
@@ -53,7 +53,7 @@ void sub_80946C8(u16 left, u16 top)
if (sub_809473C())
width = 13;
- if (FlagGet(2049)) // player has Pokédex?
+ if (FlagGet(SYS_POKEDEX_GET))
MenuZeroFillWindowRect(left, top, left + width, top + 11);
else
MenuZeroFillWindowRect(left, top, left + width, top + 9);
@@ -73,7 +73,7 @@ void PrintSavePlayerName(s16 x, s16 y)
void PrintSaveMapName(s16 x, s16 y)
{
char name[32];
-
+
CopyMapName(name, gMapHeader.name);
MenuPrint(name, x, y);
}
@@ -82,7 +82,7 @@ void PrintSaveBadges(s16 x, s16 y)
{
char badges[16];
u8 badgeCount;
-
+
MenuPrint(gOtherText_Badges, x, y);
badgeCount = GetBadgeCount();
ConvertIntToDecimalString(badges, badgeCount);
@@ -93,7 +93,7 @@ void PrintSavePokedexCount(s16 x, s16 y)
{
char pokedex[16];
u16 pokedexCount;
-
+
MenuPrint(gOtherText_Pokedex, x, y);
pokedexCount = GetPokedexSeenCount();
ConvertIntToDecimalStringN(pokedex, pokedexCount, 1, 3);
@@ -103,7 +103,7 @@ void PrintSavePokedexCount(s16 x, s16 y)
void PrintSavePlayTime(s16 x, s16 y)
{
char playtime[16];
-
+
MenuPrint(gOtherText_PlayTime, x, y);
FormatPlayTime(playtime, gSaveBlock2.playTimeHours, gSaveBlock2.playTimeMinutes, 1);
MenuPrint_RightAligned(playtime, x + 12, y);
@@ -112,26 +112,24 @@ void PrintSavePlayTime(s16 x, s16 y)
u8 GetBadgeCount(void)
{
u8 badgeCount = 0;
- int badgeFlag = 0x807; // first badge flag is located here.
-
- for(;badgeFlag <= 0x80E; badgeFlag++)
- {
- if ( FlagGet(badgeFlag) )
+ int badgeFlag;
+
+ for (badgeFlag = BADGE01_GET; badgeFlag <= BADGE08_GET; badgeFlag++)
+ if (FlagGet(badgeFlag))
badgeCount++;
- }
-
+
return badgeCount;
}
u16 GetPokedexSeenCount()
{
u16 pokedexSeenCount;
-
- if ( IsNationalPokedex() ) // national dex check?
+
+ if (IsNationalPokedex())
pokedexSeenCount = GetNationalPokedexCount(1);
else
pokedexSeenCount = GetHoennPokedexCount(1);
-
+
return pokedexSeenCount;
}
@@ -139,18 +137,18 @@ void FormatPlayTime(char *playtime, u16 hours, u16 minutes, u16 unk)
{
s16 colon = unk;
playtime = ConvertIntToDecimalString(playtime, hours);
-
+
// playtime[0] is hours.
// playtime[1] is the character to render between hours and minutes.
// playtime[2] is minutes.
-
+
playtime[0] = 0;
-
+
if (colon)
playtime[1] = 0xF0; // set middle character to ":"
else
playtime[1] = 0;
-
+
playtime[2] = 0;
playtime += 3;
diff --git a/src/scrcmd.c b/src/scrcmd.c
index d25ce88e0..9d6f36a54 100644
--- a/src/scrcmd.c
+++ b/src/scrcmd.c
@@ -11,10 +11,10 @@
#include "field_message_box.h"
#include "sound.h"
#include "string_util.h"
+#include "flag.h"
+#include "var.h"
extern void ClearRamScript(void);
-extern u16 *GetVarPointer(u16);
-extern u16 VarGet(u16);
extern void sub_8126160(u8);
extern u8 AddBagItem(u16, u16);
extern u8 RemoveBagItem(u16, u16);
@@ -27,9 +27,6 @@ extern u8 IsThereStorageSpaceForDecoration(u8);
extern s8 sub_81340A8(u8);
extern u8 sub_8134074(u8);
extern u8 sub_8133FE4(u8);
-extern void FlagSet(u16);
-extern void FlagReset(u16);
-extern u8 FlagGet(u16);
extern void sav12_xor_increment(u8);
extern void sub_8081594(u8);
extern void sub_8053CE4(u32);
@@ -115,7 +112,7 @@ extern void CreatePokemartMenu(void *);
extern void CreateDecorationShop1Menu(void *);
extern void CreateDecorationShop2Menu(void *);
extern void PlaySlotMachine(u8, void *);
-extern void PlantBerryTree(u8, u8, u8, u8);
+extern void PlantBerryTree(u8, u8, u8, bool8);
extern bool8 GetPriceReduction(u8);
extern void sub_80F99CC(void);
extern void sub_80C48C8(void);
@@ -126,11 +123,11 @@ extern bool8 FieldEffectActiveListContains(u8);
extern void sub_8053588(u8);
extern void MapGridSetMetatileIdAt(u32, u32, u16);
extern u16 sub_8058790(u32, u32);
-extern bool8 task_overworld_door_add_if_role_69_for_opening_door_at(u32, u32);
-extern bool8 sub_805870C(u32, u32);
-extern bool8 sub_805877C(void);
-extern void sub_80586B4(u32, u32);
-extern void sub_80586E0(u32, u32);
+extern bool8 FieldAnimateDoorOpen(u32, u32);
+extern bool8 FieldAnimateDoorClose(u32, u32);
+extern bool8 FieldIsDoorAnimationRunning(void);
+extern void FieldSetDoorOpened(u32, u32);
+extern void FieldSetDoorClosed(u32, u32);
extern void ScriptAddElevatorMenuItem(u8, u8, u8, u8);
extern void ScriptShowElevatorMenu(void);
extern u16 GetCoins(void);
@@ -155,16 +152,16 @@ extern u16 gUnknown_0202E8B6;
extern u16 gUnknown_0202E8B8;
extern u16 gUnknown_0202E8BA;
extern u16 gUnknown_0202E8BC;
-extern u16 gUnknown_0202E8C4;
-extern u16 gUnknown_0202E8C6;
-extern u16 gUnknown_0202E8C8;
-extern u16 gUnknown_0202E8CC;
+extern u16 gSpecialVar_0x8000;
+extern u16 gSpecialVar_0x8001;
+extern u16 gSpecialVar_0x8002;
+extern u16 gSpecialVar_0x8004;
extern u16 gScriptResult;
extern u32 gUnknown_0202FF84[];
-extern u16 gUnknown_0203869C;
+extern u16 gScriptContestCategory;
extern SpecialFunc gSpecials[];
extern u8 *gStdScripts[];
@@ -717,9 +714,9 @@ bool8 ScrCmd_checkdailyflags(struct ScriptContext *ctx)
bool8 ScrCmd_resetvars(struct ScriptContext *ctx)
{
RtcCalcLocalTime();
- gUnknown_0202E8C4 = gLocalTime.hours;
- gUnknown_0202E8C6 = gLocalTime.minutes;
- gUnknown_0202E8C8 = gLocalTime.seconds;
+ gSpecialVar_0x8000 = gLocalTime.hours;
+ gSpecialVar_0x8001 = gLocalTime.minutes;
+ gSpecialVar_0x8002 = gLocalTime.seconds;
return FALSE;
}
@@ -1574,7 +1571,7 @@ bool8 ScrCmd_checkattack(struct ScriptContext *ctx)
if (!GetMonData(&gPlayerParty[i], MON_DATA_IS_EGG) && pokemon_has_move(&gPlayerParty[i], moveId) == TRUE)
{
gScriptResult = i;
- gUnknown_0202E8CC = species;
+ gSpecialVar_0x8004 = species;
break;
}
}
@@ -1759,9 +1756,9 @@ bool8 ScrCmd_event_8a(struct ScriptContext *ctx)
u8 v3 = ScriptReadByte(ctx);
u8 v4 = ScriptReadByte(ctx);
if (!v3)
- PlantBerryTree(v2, 0, v4, 0);
+ PlantBerryTree(v2, 0, v4, FALSE);
else
- PlantBerryTree(v2, v3, v4, 0);
+ PlantBerryTree(v2, v3, v4, FALSE);
return FALSE;
}
@@ -1795,7 +1792,7 @@ bool8 ScrCmd_showcontestresults(struct ScriptContext *ctx)
bool8 ScrCmd_contestlinktransfer(struct ScriptContext *ctx)
{
- sub_80C4980(gUnknown_0203869C);
+ sub_80C4980(gScriptContestCategory);
ScriptContext1_Stop();
return TRUE;
}
@@ -1874,28 +1871,28 @@ bool8 ScrCmd_setmaptile(struct ScriptContext *ctx)
bool8 ScrCmd_setdooropened(struct ScriptContext *ctx)
{
- u16 v3 = VarGet(ScriptReadHalfword(ctx));
- u16 v4 = VarGet(ScriptReadHalfword(ctx));
- v3 += 7;
- v4 += 7;
- PlaySE(sub_8058790(v3, v4));
- task_overworld_door_add_if_role_69_for_opening_door_at(v3, v4);
+ u16 x = VarGet(ScriptReadHalfword(ctx));
+ u16 y = VarGet(ScriptReadHalfword(ctx));
+ x += 7;
+ y += 7;
+ PlaySE(sub_8058790(x, y));
+ FieldAnimateDoorOpen(x, y);
return FALSE;
}
bool8 ScrCmd_setdoorclosed(struct ScriptContext *ctx)
{
- u16 v3 = VarGet(ScriptReadHalfword(ctx));
- u16 v5 = VarGet(ScriptReadHalfword(ctx));
- v3 += 7;
- v5 += 7;
- sub_805870C(v3, v5);
+ u16 x = VarGet(ScriptReadHalfword(ctx));
+ u16 y = VarGet(ScriptReadHalfword(ctx));
+ x += 7;
+ y += 7;
+ FieldAnimateDoorClose(x, y);
return FALSE;
}
-bool8 sub_8067D2C()
+bool8 IsDoorAnimationStopped()
{
- if (!sub_805877C())
+ if (!FieldIsDoorAnimationRunning())
return TRUE;
else
return FALSE;
@@ -1903,27 +1900,27 @@ bool8 sub_8067D2C()
bool8 ScrCmd_doorchange(struct ScriptContext *ctx)
{
- SetupNativeScript(ctx, sub_8067D2C);
+ SetupNativeScript(ctx, IsDoorAnimationStopped);
return TRUE;
}
bool8 ScrCmd_setdooropened2(struct ScriptContext *ctx)
{
- u16 v3 = VarGet(ScriptReadHalfword(ctx));
- u16 v5 = VarGet(ScriptReadHalfword(ctx));
- v3 += 7;
- v5 += 7;
- sub_80586B4(v3, v5);
+ u16 x = VarGet(ScriptReadHalfword(ctx));
+ u16 y = VarGet(ScriptReadHalfword(ctx));
+ x += 7;
+ y += 7;
+ FieldSetDoorOpened(x, y);
return FALSE;
}
bool8 ScrCmd_setdoorclosed2(struct ScriptContext *ctx)
{
- u16 v3 = VarGet(ScriptReadHalfword(ctx));
- u16 v5 = VarGet(ScriptReadHalfword(ctx));
- v3 += 7;
- v5 += 7;
- sub_80586E0(v3, v5);
+ u16 x = VarGet(ScriptReadHalfword(ctx));
+ u16 y = VarGet(ScriptReadHalfword(ctx));
+ x += 7;
+ y += 7;
+ FieldSetDoorClosed(x, y);
return FALSE;
}
diff --git a/src/script.c b/src/script.c
index fdce4f7d2..8e07a580e 100644
--- a/src/script.c
+++ b/src/script.c
@@ -1,11 +1,10 @@
#include "global.h"
#include "script.h"
#include "fieldmap.h"
+#include "var.h"
#define RAM_SCRIPT_MAGIC 51
-extern u16 VarGet(u16);
-
extern u8 *gUnknown_0202E8AC;
extern u32 gUnknown_0202E8B0;
diff --git a/src/sprite.c b/src/sprite.c
index 7a654472c..12c62145e 100644
--- a/src/sprite.c
+++ b/src/sprite.c
@@ -530,7 +530,7 @@ static void AddSpritesToOamBuffer(void)
}
}
-u8 CreateSprite(struct SpriteTemplate *template, u16 x, u16 y, u8 subpriority)
+u8 CreateSprite(struct SpriteTemplate *template, s16 x, s16 y, u8 subpriority)
{
u8 i;
diff --git a/src/start_menu.c b/src/start_menu.c
index 3c5971dd4..c8e77af66 100644
--- a/src/start_menu.c
+++ b/src/start_menu.c
@@ -8,6 +8,7 @@
#include "sprite.h"
#include "string_util.h"
#include "task.h"
+#include "flag.h"
//External functions
extern void sub_8064E2C(void);
@@ -25,7 +26,7 @@ extern void save_serialize_map(void);
extern void PlayRainSoundEffect(void);
extern void sub_8093130(u8, void (*)(void));
extern void sub_805469C(void);
-extern void sub_80C823C(void);
+extern void SafariZoneRetirePrompt(void);
extern void CB2_InitOptionMenu(void);
extern void sub_8093110(void (*)(void));
extern void sub_80EBA5C(void);
@@ -40,7 +41,6 @@ extern void sub_80597F4(void);
extern void player_bitmagic(void);
extern bool32 GetSafariZoneFlag(void);
extern u8 *sub_8072C44(u8 *, s32, u8, u8);
-extern u8 FlagGet(u16);
extern bool32 is_c1_link_related_active(void);
//Menu actions
@@ -72,7 +72,7 @@ extern u16 gScriptResult;
extern u8 (*gCallback_03004AE8)(void);
extern u8 gUnknown_03004860;
extern struct MenuItem gStartMenuItems[];
-extern u8 gUnknown_02038808;
+extern u8 gNumSafariBalls;
EWRAM_DATA static u8 sStartMenuCursorPos = 0;
EWRAM_DATA static u8 sNumStartMenuActions = 0;
@@ -170,12 +170,12 @@ static void AddStartMenuAction(u8 action)
static void BuildStartMenuActions_Normal(void)
{
- if(FlagGet(0x801) == TRUE)
+ if(FlagGet(SYS_POKEDEX_GET) == TRUE)
AddStartMenuAction(MENU_ACTION_POKEDEX);
- if(FlagGet(0x800) == TRUE)
+ if(FlagGet(SYS_POKEMON_GET) == TRUE)
AddStartMenuAction(MENU_ACTION_POKEMON);
AddStartMenuAction(MENU_ACTION_BAG);
- if(FlagGet(0x802) == TRUE)
+ if(FlagGet(SYS_POKENAV_GET) == TRUE)
AddStartMenuAction(MENU_ACTION_POKENAV);
AddStartMenuAction(MENU_ACTION_PLAYER);
AddStartMenuAction(MENU_ACTION_SAVE);
@@ -198,7 +198,7 @@ static void BuildStartMenuActions_Link(void)
{
AddStartMenuAction(MENU_ACTION_POKEMON);
AddStartMenuAction(MENU_ACTION_BAG);
- if(FlagGet(0x802) == TRUE)
+ if(FlagGet(SYS_POKENAV_GET) == TRUE)
AddStartMenuAction(MENU_ACTION_POKENAV);
AddStartMenuAction(MENU_ACTION_PLAYER_LINK);
AddStartMenuAction(MENU_ACTION_OPTION);
@@ -208,7 +208,7 @@ static void BuildStartMenuActions_Link(void)
//Show number of safari balls left
static void DisplaySafariBallsWindow(void)
{
- sub_8072C44(gStringVar1, gUnknown_02038808, 12, 1);
+ sub_8072C44(gStringVar1, gNumSafariBalls, 12, 1);
MenuDrawTextWindow(0, 0, 10, 5);
MenuPrint(gOtherText_SafariStock, 1, 1);
}
@@ -456,7 +456,7 @@ u8 StartMenu_ExitCallback(void)
u8 StartMenu_RetireCallback(void)
{
sub_8071C20();
- sub_80C823C();
+ SafariZoneRetirePrompt();
return 1;
}
@@ -473,7 +473,8 @@ u8 StartMenu_PlayerLinkCallback(void)
}
//Save dialog status
-enum {
+enum
+{
SAVE_IN_PROGRESS,
SAVE_SUCCESS,
SAVE_CANCELED,
diff --git a/src/starter_choose.c b/src/starter_choose.c
index d4580cd94..a80401e8b 100644
--- a/src/starter_choose.c
+++ b/src/starter_choose.c
@@ -12,7 +12,6 @@
#include "trig.h"
//Functions that need to be put in headers
-void LZ77UnCompVram(const void *src, void *dest);
void remove_some_task(void);
void LoadCompressedObjectPic(void *);
void LoadCompressedObjectPalette(const struct SpritePalette *);
diff --git a/src/text.c b/src/text.c
index 4f2581af6..885fb7547 100644
--- a/src/text.c
+++ b/src/text.c
@@ -177,10 +177,7 @@ static u8 sWaitType;
static u8 sLineLength;
static struct GlyphBuffer sGlyphBuffer;
-EWRAM_DATA u16 gBG0TilemapBuffer[0x400] = {0};
-EWRAM_DATA u16 gBG1TilemapBuffer[0x400] = {0};
-EWRAM_DATA u16 gBG2TilemapBuffer[0x400] = {0};
-EWRAM_DATA u16 gBG3TilemapBuffer[0x400] = {0};
+EWRAM_DATA u16 gBGTilemapBuffers[4][0x400] = {0};
EWRAM_DATA u8 gStringVar1[0x100] = {0};
EWRAM_DATA u8 gStringVar2[0x100] = {0};
diff --git a/src/tileset_anim.c b/src/tileset_anim.c
new file mode 100644
index 000000000..96030f037
--- /dev/null
+++ b/src/tileset_anim.c
@@ -0,0 +1,596 @@
+#include "global.h"
+
+extern u8 *gTilesetAnimTable_General_0[];
+extern u8 *gTilesetAnimTable_General_1[];
+extern u8 *gTilesetAnimTable_General_2[];
+extern u8 *gTilesetAnimTable_General_3[];
+extern u8 *gTilesetAnimTable_General_4[];
+extern u8 *gTilesetAnimTable_Lavaridge[];
+extern u8 *gTilesetAnimTable_Pacifidlog_0[];
+extern u8 *gTilesetAnimTable_Underwater[];
+extern u8 *gTilesetAnimTable_Pacifidlog_1[];
+extern u8 *gUnknown_0837BAE4[];
+extern u8 *gUnknown_0837BB04[];
+extern u8 *gTilesetAnimTable_Mauville_0A[];
+extern u8 *gTilesetAnimTable_Mauville_1A[];
+extern u8 *gTilesetAnimTable_Mauville_0B[];
+extern u8 *gTilesetAnimTable_Mauville_1B[];
+extern u8 *gUnknown_0837BFA4[];
+extern u8 *gTilesetAnimTable_Rustboro_0[];
+extern u8 *gTilesetAnimTable_Rustboro_1[];
+extern u8 *gTilesetAnimTable_Cave[];
+extern u8 *gUnknown_0837C93C[];
+extern u8 *gTilesetAnimTable_EverGrande[];
+extern u8 *gTilesetAnimTable_Building[];
+extern u8 *gTilesetAnimTable_SootopolisGym_0[];
+extern u8 *gTilesetAnimTable_SootopolisGym_1[];
+extern u8 *gTilesetAnimTable_EliteFour_0[];
+extern u8 *gTilesetAnimTable_EliteFour_1[];
+extern u8 *gTilesetAnimTable_MauvilleGym[];
+extern u8 *gTilesetAnimTable_BikeShop[];
+
+struct Dma {
+ u8 *src;
+ u8 *dest;
+ u16 size;
+};
+
+EWRAM_DATA static struct Dma gTilesetAnimDmas[20] = {0};
+
+static u8 gNumTilesetAnimDmas;
+static u16 gTileset1AnimFrame;
+static u16 gTileset1AnimLength;
+static u16 gTileset2AnimFrame;
+static u16 gTileset2AnimLength;
+static void (*gTileset1AnimCallback)(u16);
+static void (*gTileset2AnimCallback)(u16);
+
+static void StartTileset1Animation(void);
+static void StartTileset2Animation(void);
+
+static void sub_8073014(u16);
+static void sub_8073058(u16);
+
+static void sub_8073070(u16);
+static void sub_8073098(u16);
+static void sub_80730C0(u16);
+static void sub_80730E8(u16);
+static void sub_807361C(u16);
+
+static void sub_8073424(u16);
+static void sub_80734A0(u16);
+static void sub_8073514(u16);
+static void sub_8073540(u16);
+static void sub_80735B4(u16);
+static void sub_80735E4(u16);
+static void sub_80738A8(u16);
+static void sub_8073600(u16);
+static void sub_80738C0(u16);
+static void sub_8073890(u16);
+static void sub_80738EC(u16);
+
+static void sub_80737A4(u16, u8);
+static void sub_80737E0(u16);
+static void sub_8073704(u16, u8);
+static void sub_8073644(u8);
+static void sub_8073808(u16);
+static void sub_8073830(u16, u8);
+static void sub_807368C(u8);
+static void sub_80736DC(u8);
+static void sub_80736B4(u8);
+static void sub_8073868(u16);
+
+static void sub_8073904(u16);
+static void sub_80739C4(u16);
+static void sub_807392C(u16);
+static void sub_807399C(u16);
+static void sub_8073974(u16);
+static void sub_80739EC(u16);
+
+static void ClearTilesetAnimDmas(void) {
+ gNumTilesetAnimDmas = 0;
+ CpuFill32(0, &gTilesetAnimDmas, sizeof(gTilesetAnimDmas));
+}
+
+static void QueueTilesetAnimDma(u8 *src, u8 *dest, u16 size) {
+ if (gNumTilesetAnimDmas < 20) {
+ gTilesetAnimDmas[gNumTilesetAnimDmas].src = src;
+ gTilesetAnimDmas[gNumTilesetAnimDmas].dest = dest;
+ gTilesetAnimDmas[gNumTilesetAnimDmas].size = size;
+ gNumTilesetAnimDmas++;
+ }
+}
+
+void sub_8072E74(void) {
+ int i;
+ for (i = 0; i < gNumTilesetAnimDmas; i++) {
+ DmaCopy16(3,
+ gTilesetAnimDmas[i].src,
+ gTilesetAnimDmas[i].dest,
+ gTilesetAnimDmas[i].size);
+ }
+ gNumTilesetAnimDmas = 0;
+}
+
+void cur_mapheader_run_tileset_funcs_after_some_cpuset(void) {
+ ClearTilesetAnimDmas();
+ StartTileset1Animation();
+ StartTileset2Animation();
+}
+
+void sub_8072ED0(void) {
+ StartTileset2Animation();
+}
+
+void sub_8072EDC(void) {
+ ClearTilesetAnimDmas();
+ if (++gTileset1AnimFrame >= gTileset1AnimLength) {
+ gTileset1AnimFrame = 0;
+ }
+ if (++gTileset2AnimFrame >= gTileset2AnimLength) {
+ gTileset2AnimFrame = 0;
+ }
+ if (gTileset1AnimCallback) {
+ gTileset1AnimCallback(gTileset1AnimFrame);
+ }
+ if (gTileset2AnimCallback) {
+ gTileset2AnimCallback(gTileset2AnimFrame);
+ }
+}
+
+static void StartTileset1Animation(void) {
+ gTileset1AnimFrame = 0;
+ gTileset1AnimLength = 0;
+ gTileset1AnimCallback = 0;
+ if (gMapHeader.mapData->primaryTileset) {
+ if (gMapHeader.mapData->primaryTileset->callback) {
+ gMapHeader.mapData->primaryTileset->callback();
+ }
+ }
+}
+
+static void StartTileset2Animation(void) {
+ gTileset2AnimFrame = 0;
+ gTileset2AnimLength = 0;
+ gTileset2AnimCallback = 0;
+ if (gMapHeader.mapData->secondaryTileset) {
+ if (gMapHeader.mapData->secondaryTileset->callback) {
+ gMapHeader.mapData->secondaryTileset->callback();
+ }
+ }
+}
+
+void TilesetCB_General(void) {
+ gTileset1AnimFrame = 0;
+ gTileset1AnimLength = 0x100;
+ gTileset1AnimCallback = sub_8073014;
+}
+
+void TilesetCB_Building(void) {
+ gTileset1AnimFrame = 0;
+ gTileset1AnimLength = 0x100;
+ gTileset1AnimCallback = sub_8073058;
+}
+
+static void sub_8073014(u16 a1) {
+ int v1;
+ v1 = a1 % 0x10;
+ if (v1 == 0) sub_8073070(a1 / 0x10);
+ if (v1 == 1) sub_8073098(a1 / 0x10);
+ if (v1 == 2) sub_80730C0(a1 / 0x10);
+ if (v1 == 3) sub_80730E8(a1 / 0x10);
+ if (v1 == 4) sub_807361C(a1 / 0x10);
+}
+
+static void sub_8073058(u16 a1) {
+ if (a1 % 8 == 0) {
+ sub_8073904(a1 / 8);
+ }
+}
+
+static void sub_8073070(u16 a1) {
+ int v1;
+ v1 = a1 % 4;
+ QueueTilesetAnimDma(gTilesetAnimTable_General_0[v1],
+ (u8 *)(BG_VRAM + 0x3f80),
+ 0x80);
+}
+
+static void sub_8073098(u16 a1) {
+ u8 v1;
+ v1 = a1 % 8;
+ QueueTilesetAnimDma(gTilesetAnimTable_General_1[v1],
+ (u8 *)(BG_VRAM + 0x3600),
+ 0x3c0);
+}
+
+static void sub_80730C0(u16 a1) {
+ int v1;
+ v1 = a1 % 8;
+ QueueTilesetAnimDma(gTilesetAnimTable_General_2[v1],
+ (u8 *)(BG_VRAM + 0x3a00),
+ 0x140);
+}
+
+static void sub_80730E8(u16 a1) {
+ int v1;
+ v1 = a1 % 4;
+ QueueTilesetAnimDma(gTilesetAnimTable_General_3[v1],
+ (u8 *)(BG_VRAM + 0x3e00),
+ 0xc0);
+}
+
+void TilesetCB_Petalburg(void) {
+ gTileset2AnimFrame = 0;
+ gTileset2AnimLength = gTileset1AnimLength;
+ gTileset2AnimCallback = 0;
+}
+
+void TilesetCB_Rustboro(void) {
+ gTileset2AnimFrame = 0;
+ gTileset2AnimLength = gTileset1AnimLength;
+ gTileset2AnimCallback = sub_8073424;
+}
+
+void TilesetCB_Dewford(void) {
+ gTileset2AnimFrame = 0;
+ gTileset2AnimLength = gTileset1AnimLength;
+ gTileset2AnimCallback = 0;
+}
+
+void TilesetCB_Slateport(void) {
+ gTileset2AnimFrame = 0;
+ gTileset2AnimLength = gTileset1AnimLength;
+ gTileset2AnimCallback = 0;
+}
+
+void TilesetCB_Mauville(void) {
+ gTileset2AnimFrame = gTileset1AnimFrame;
+ gTileset2AnimLength = gTileset1AnimLength;
+ gTileset2AnimCallback = sub_80734A0;
+}
+
+void TilesetCB_Lavaridge(void) {
+ gTileset2AnimFrame = 0;
+ gTileset2AnimLength = gTileset1AnimLength;
+ gTileset2AnimCallback = sub_8073514;
+}
+
+void TilesetCB_Fallarbor(void) {
+ gTileset2AnimFrame = 0;
+ gTileset2AnimLength = gTileset1AnimLength;
+ gTileset2AnimCallback = 0;
+}
+
+void TilesetCB_Fortree(void) {
+ gTileset2AnimFrame = 0;
+ gTileset2AnimLength = gTileset1AnimLength;
+ gTileset2AnimCallback = 0;
+}
+
+void TilesetCB_Lilycove(void) {
+ gTileset2AnimFrame = 0;
+ gTileset2AnimLength = gTileset1AnimLength;
+ gTileset2AnimCallback = 0;
+}
+
+void TilesetCB_Mossdeep(void) {
+ gTileset2AnimFrame = 0;
+ gTileset2AnimLength = gTileset1AnimLength;
+ gTileset2AnimCallback = 0;
+}
+
+void TilesetCB_EverGrande(void) {
+ gTileset2AnimFrame = 0;
+ gTileset2AnimLength = gTileset1AnimLength;
+ gTileset2AnimCallback = sub_8073540;
+}
+
+void TilesetCB_Pacifidlog(void) {
+ gTileset2AnimFrame = gTileset1AnimFrame;
+ gTileset2AnimLength = gTileset1AnimLength;
+ gTileset2AnimCallback = sub_80735B4;
+}
+
+void TilesetCB_Sootopolis(void) {
+ gTileset2AnimFrame = 0;
+ gTileset2AnimLength = gTileset1AnimLength;
+ gTileset2AnimCallback = 0;
+}
+
+void TilesetCB_Underwater(void) {
+ gTileset2AnimFrame = 0;
+ gTileset2AnimLength = 0x80;
+ gTileset2AnimCallback = sub_80735E4;
+}
+
+void TilesetCB_SootopolisGym(void) {
+ gTileset2AnimFrame = 0;
+ gTileset2AnimLength = 0xf0;
+ gTileset2AnimCallback = sub_80738A8;
+}
+
+void TilesetCB_Cave(void) {
+ gTileset2AnimFrame = 0;
+ gTileset2AnimLength = gTileset1AnimLength;
+ gTileset2AnimCallback = sub_8073600;
+}
+
+void TilesetCB_EliteFour(void) {
+ gTileset2AnimFrame = 0;
+ gTileset2AnimLength = 0x80;
+ gTileset2AnimCallback = sub_80738C0;
+}
+
+void TilesetCB_MauvilleGym(void) {
+ gTileset2AnimFrame = 0;
+ gTileset2AnimLength = gTileset1AnimLength;
+ gTileset2AnimCallback = sub_8073890;
+}
+
+void TilesetCB_BikeShop(void) {
+ gTileset2AnimFrame = 0;
+ gTileset2AnimLength = gTileset1AnimLength;
+ gTileset2AnimCallback = sub_80738EC;
+}
+
+static void sub_8073424(u16 a1) {
+ int v1;
+ v1 = a1 % 8;
+ if (v1 == 0) {
+ sub_80737A4(a1 / 8, 0);
+ sub_80737E0(a1 / 8);
+ }
+ if (v1 == 1) sub_80737A4(a1 / 8, 1);
+ if (v1 == 2) sub_80737A4(a1 / 8, 2);
+ if (v1 == 3) sub_80737A4(a1 / 8, 3);
+ if (v1 == 4) sub_80737A4(a1 / 8, 4);
+ if (v1 == 5) sub_80737A4(a1 / 8, 5);
+ if (v1 == 6) sub_80737A4(a1 / 8, 6);
+ if (v1 == 7) sub_80737A4(a1 / 8, 7);
+}
+
+static void sub_80734A0(u16 a1) {
+ int v1;
+ v1 = a1 % 8;
+ if (v1 == 0) sub_8073704(a1 / 8, 0);
+ if (v1 == 1) sub_8073704(a1 / 8, 1);
+ if (v1 == 2) sub_8073704(a1 / 8, 2);
+ if (v1 == 3) sub_8073704(a1 / 8, 3);
+ if (v1 == 4) sub_8073704(a1 / 8, 4);
+ if (v1 == 5) sub_8073704(a1 / 8, 5);
+ if (v1 == 6) sub_8073704(a1 / 8, 6);
+ if (v1 == 7) sub_8073704(a1 / 8, 7);
+}
+
+static void sub_8073514(u16 a1) {
+ int v1;
+ v1 = a1 % 0x10;
+ if (v1 == 0) sub_8073644(a1 / 0x10);
+ if (v1 == 1) sub_8073808(a1 / 0x10);
+}
+
+static void sub_8073540(u16 a1) {
+ int v1;
+ v1 = a1 % 8;
+ if (v1 == 0) sub_8073830(a1 / 8, 0);
+ if (v1 == 1) sub_8073830(a1 / 8, 1);
+ if (v1 == 2) sub_8073830(a1 / 8, 2);
+ if (v1 == 3) sub_8073830(a1 / 8, 3);
+ if (v1 == 4) sub_8073830(a1 / 8, 4);
+ if (v1 == 5) sub_8073830(a1 / 8, 5);
+ if (v1 == 6) sub_8073830(a1 / 8, 6);
+ if (v1 == 7) sub_8073830(a1 / 8, 7);
+}
+
+static void sub_80735B4(u16 a1) {
+ int v1;
+ v1 = a1 % 0x10;
+ if (v1 == 0) sub_807368C(a1 / 0x10);
+ if (v1 == 1) sub_80736DC(a1 / 0x10);
+}
+
+static void sub_80735E4(u16 a1) {
+ int v1;
+ v1 = a1 % 0x10;
+ if (v1 == 0) sub_80736B4(a1 / 0x10);
+}
+
+static void sub_8073600(u16 a1) {
+ int v1;
+ v1 = a1 % 0x10;
+ if (v1 == 1) sub_8073868(a1 / 0x10);
+}
+
+static void sub_807361C(u16 a1) {
+ int v1;
+ v1 = a1 % 4;
+ QueueTilesetAnimDma(gTilesetAnimTable_General_4[v1],
+ (u8 *)(BG_VRAM + 0x3c00),
+ 0x140);
+}
+
+static void sub_8073644(u8 a1) {
+ u8 v1;
+ v1 = a1 % 4;
+ QueueTilesetAnimDma(gTilesetAnimTable_Lavaridge[v1],
+ (u8 *)(BG_VRAM + 0x6400),
+ 0x80);
+ v1 = (a1 + 2) % 4;
+ QueueTilesetAnimDma(gTilesetAnimTable_Lavaridge[v1],
+ (u8 *)(BG_VRAM + 0x6480),
+ 0x80);
+}
+
+static void sub_807368C(u8 a1) {
+ int v1;
+ v1 = a1 % 4;
+ QueueTilesetAnimDma(gTilesetAnimTable_Pacifidlog_0[v1],
+ (u8 *)(BG_VRAM + 0x7a00),
+ 0x3c0);
+}
+
+static void sub_80736B4(u8 a1) {
+ int v1;
+ v1 = a1 % 4;
+ QueueTilesetAnimDma(gTilesetAnimTable_Underwater[v1],
+ (u8 *)(BG_VRAM + 0x7e00),
+ 0x80);
+}
+
+static void sub_80736DC(u8 a1) {
+ int v1;
+ v1 = a1 % 8;
+ QueueTilesetAnimDma(gTilesetAnimTable_Pacifidlog_1[v1],
+ (u8 *)(BG_VRAM + 0x7e00),
+ 0x100);
+}
+
+static void sub_8073704(u16 a1, u8 a2) {
+ int v1;
+ a1 -= a2;
+ if (a1 < 12) {
+ v1 = a1 % 12;
+ QueueTilesetAnimDma(gTilesetAnimTable_Mauville_0A[v1],
+ gUnknown_0837BAE4[a2],
+ 0x80);
+ QueueTilesetAnimDma(gTilesetAnimTable_Mauville_1A[v1],
+ gUnknown_0837BB04[a2],
+ 0x80);
+ } else {
+ v1 = a1 % 4;
+ QueueTilesetAnimDma(gTilesetAnimTable_Mauville_0B[v1],
+ gUnknown_0837BAE4[a2],
+ 0x80);
+ QueueTilesetAnimDma(gTilesetAnimTable_Mauville_1B[v1],
+ gUnknown_0837BB04[a2],
+ 0x80);
+ }
+}
+
+static void sub_80737A4(u16 a1, u8 a2) {
+ int v1;
+ a1 -= a2;
+
+ v1 = a1 % 8;
+ if (gTilesetAnimTable_Rustboro_0[v1]) {
+ QueueTilesetAnimDma(gTilesetAnimTable_Rustboro_0[v1],
+ gUnknown_0837BFA4[a2],
+ 0x80);
+ }
+}
+
+static void sub_80737E0(u16 a1) {
+ int v1;
+ v1 = a1 % 2;
+ QueueTilesetAnimDma(gTilesetAnimTable_Rustboro_1[v1],
+ (u8 *)(BG_VRAM + 0x7800),
+ 0x80);
+}
+
+static void sub_8073808(u16 a1) {
+ int v1;
+ v1 = a1 % 4;
+ QueueTilesetAnimDma(gTilesetAnimTable_Cave[v1],
+ (u8 *)(BG_VRAM + 0x5400),
+ 0x80);
+}
+
+static void sub_8073830(u16 a1, u8 a2) {
+ int v1;
+ a1 -= a2;
+ v1 = a1 % 8;
+ QueueTilesetAnimDma(gTilesetAnimTable_EverGrande[v1],
+ gUnknown_0837C93C[a2],
+ 0x80);
+}
+
+static void sub_8073868(u16 a1) {
+ int v1;
+ v1 = a1 % 4;
+ QueueTilesetAnimDma(gTilesetAnimTable_Cave[v1],
+ (u8 *)(BG_VRAM + 0x7400),
+ 0x80);
+}
+
+static void sub_8073890(u16 a1) {
+ int v1;
+ v1 = a1 % 2;
+ if (!v1) {
+ sub_80739C4(a1 / 2);
+ }
+}
+
+static void sub_80738A8(u16 a1) {
+ int v1;
+ v1 = a1 % 8;
+ if (!v1) {
+ sub_807392C(a1 / 8);
+ }
+}
+
+static void sub_80738C0(u16 a1) {
+ if (a1 % 0x40 == 0) {
+ sub_807399C(a1 / 0x40);
+ }
+ if (a1 % 8 == 1) {
+ sub_8073974(a1 / 8);
+ }
+}
+
+static void sub_80738EC(u16 a1) {
+ if (a1 % 4 == 0) {
+ sub_80739EC(a1 / 4);
+ }
+}
+
+static void sub_8073904(u16 a1) {
+ int v1;
+ v1 = a1 % 2;
+ QueueTilesetAnimDma(gTilesetAnimTable_Building[v1],
+ (u8 *)(BG_VRAM + 0x3e00),
+ 0x80);
+}
+
+static void sub_807392C(u16 a1) {
+ int v1;
+ v1 = a1 % 3;
+ QueueTilesetAnimDma(gTilesetAnimTable_SootopolisGym_0[v1],
+ (u8 *)(BG_VRAM + 0x7e00),
+ 0x180);
+ QueueTilesetAnimDma(gTilesetAnimTable_SootopolisGym_1[v1],
+ (u8 *)(BG_VRAM + 0x7a00),
+ 0x280);
+}
+
+static void sub_8073974(u16 a1) {
+ int v1;
+ v1 = a1 % 4;
+ QueueTilesetAnimDma(gTilesetAnimTable_EliteFour_0[v1],
+ (u8 *)(BG_VRAM + 0x7f00),
+ 0x20);
+}
+
+static void sub_807399C(u16 a1) {
+ int v1;
+ v1 = a1 % 2;
+ QueueTilesetAnimDma(gTilesetAnimTable_EliteFour_1[v1],
+ (u8 *)(BG_VRAM + 0x7c00),
+ 0x80);
+}
+
+static void sub_80739C4(u16 a1) {
+ int v1;
+ v1 = a1 % 2;
+ QueueTilesetAnimDma(gTilesetAnimTable_MauvilleGym[v1],
+ (u8 *)(BG_VRAM + 0x5200),
+ 0x200);
+}
+
+static void sub_80739EC(u16 a1) {
+ int v1;
+ v1 = a1 % 2;
+ QueueTilesetAnimDma(gTilesetAnimTable_BikeShop[v1],
+ (u8 *)(BG_VRAM + 0x7e00),
+ 0x120);
+}
diff --git a/src/title_screen.c b/src/title_screen.c
new file mode 100644
index 000000000..d5cfa032b
--- /dev/null
+++ b/src/title_screen.c
@@ -0,0 +1,496 @@
+#include "global.h"
+#include "gba/m4a_internal.h"
+#include "main.h"
+#include "palette.h"
+#include "sound.h"
+#include "sprite.h"
+#include "task.h"
+
+extern void m4aSongNumStart(u16);
+extern void LoadCompressedObjectPic(void *);
+extern void CB2_InitCopyrightScreen(void);
+extern void CB2_InitMainMenu(void);
+extern void CB2_InitClearSaveDataScreen(void);
+extern void CB2_InitResetRtcScreen(void);
+
+extern u8 gReservedSpritePaletteCount;
+extern struct MusicPlayerInfo gMPlay_BGM;
+extern u8 gUnknown_0202F7E4;
+extern u16 gUnknown_030041B4;
+extern u16 gUnknown_030042C0;
+extern u8 gUnknown_08393210[];
+extern u8 gUnknown_08393250[];
+extern u8 gUnknown_083939EC[];
+extern u8 gUnknown_08393BF8[];
+extern u16 gUnknown_08393E64[];
+extern struct SpriteTemplate gSpriteTemplate_8393ECC;
+extern struct SpriteTemplate gSpriteTemplate_8393EE4;
+extern u8 gUnknown_08393EFC[];
+extern struct SpriteTemplate gSpriteTemplate_8393F74;
+extern u8 gUnknown_08393F8C[];
+extern u8 gUnknown_08393F9C[];
+extern struct SpriteTemplate gSpriteTemplate_8393FC0;
+extern u8 gUnknown_08393FD8[];
+extern u8 gUnknown_08E9D8CC[];
+extern u8 gUnknown_08E9F624[];
+extern u8 gUnknown_08E9F7E4[];
+
+static void MainCB2(void);
+static void Task_TitleScreenPhase1(u8);
+static void Task_TitleScreenPhase2(u8);
+static void Task_TitleScreenPhase3(u8);
+static void CB2_GoToMainMenu(void);
+static void CB2_GoToClearSaveDataScreen(void);
+static void CB2_GoToResetRtcScreen(void);
+static void CB2_GoToCopyrightScreen(void);
+static void UpdateLegendaryMarkingColor(u8);
+
+#define _RGB(r, g, b) ((((b) & 31) << 10) + (((g) & 31) << 5) + ((r) & 31))
+
+#ifdef SAPPHIRE
+//Red Kyogre markings
+#define LEGENDARY_MARKING_COLOR(c) RGB((c), 0, 0)
+#else
+//Blue Groundon markings
+#define LEGENDARY_MARKING_COLOR(c) RGB(0, 0, (c))
+#endif
+
+#ifdef SAPPHIRE
+#define PLTT_BUFFER_INDEX 26
+#else
+#define PLTT_BUFFER_INDEX 21
+#endif
+
+#define CLEAR_SAVE_BUTTON_COMBO (B_BUTTON | SELECT_BUTTON | DPAD_UP)
+#define RESET_RTC_BUTTON_COMBO (B_BUTTON | SELECT_BUTTON | DPAD_LEFT)
+#define A_B_START_SELECT (A_BUTTON | B_BUTTON | START_BUTTON | SELECT_BUTTON)
+
+void SpriteCallback_VersionBannerLeft(struct Sprite *sprite)
+{
+ struct Task *task = &gTasks[sprite->data1];
+
+ if (task->data[1] != 0)
+ {
+ sprite->oam.objMode = 0;
+ sprite->pos1.y = 66;
+ sprite->invisible = FALSE;
+ }
+ else
+ {
+ if (task->data[5] != 0)
+ task->data[5]--;
+ if (task->data[5] < 64)
+ {
+ sprite->invisible = FALSE;
+ if (sprite->pos1.y != 66)
+ sprite->pos1.y++;
+ REG_BLDALPHA = gUnknown_08393E64[task->data[5] / 2];
+ }
+ }
+}
+
+void SpriteCallback_VersionBannerRight(struct Sprite *sprite)
+{
+ struct Task *task = &gTasks[sprite->data1];
+
+ if (task->data[1] != 0)
+ {
+ sprite->oam.objMode = 0;
+ sprite->pos1.y = 66;
+ sprite->invisible = FALSE;
+ }
+ else
+ {
+ if (task->data[5] < 64)
+ {
+ sprite->invisible = FALSE;
+ if (sprite->pos1.y != 66)
+ sprite->pos1.y++;
+ }
+ }
+}
+
+void SpriteCallback_PressStartCopyrightBanner(struct Sprite *sprite)
+{
+ if (sprite->data0 == 1)
+ {
+ sprite->data1++;
+ //Alternate between hidden and shown every 16th frame
+ if (sprite->data1 & 16)
+ sprite->invisible = FALSE;
+ else
+ sprite->invisible = TRUE;
+ }
+ else
+ sprite->invisible = FALSE;
+}
+
+static void CreatePressStartBanner(s16 x, s16 y)
+{
+ u8 i;
+ u8 spriteId;
+
+ x -= 32;
+ for (i = 0; i < 3; i++, x += 32)
+ {
+ spriteId = CreateSprite(&gSpriteTemplate_8393F74, x, y, 0);
+ StartSpriteAnim(&gSprites[spriteId], i);
+ gSprites[spriteId].data0 = 1;
+ }
+}
+
+static void CreateCopyrightBanner(s16 x, s16 y)
+{
+ u8 i;
+ u8 spriteId;
+
+ x -= 64;
+ for (i = 0; i < 5; i++, x += 32)
+ {
+ spriteId = CreateSprite(&gSpriteTemplate_8393F74, x, y, 0);
+ StartSpriteAnim(&gSprites[spriteId], i + 3);
+ }
+}
+
+void SpriteCallback_PokemonLogoShine(struct Sprite *sprite)
+{
+ if (gTasks[gUnknown_0202F7E4].data[1] == 0 && sprite->pos1.x < 272)
+ {
+ if (sprite->data0) //Flash background
+ {
+ u16 backgroundColor;
+
+ if (sprite->pos1.x < DISPLAY_WIDTH / 2)
+ {
+ //Brighten background color
+ if (sprite->data1 < 31)
+ sprite->data1++;
+ if (sprite->data1 < 31)
+ sprite->data1++;
+ }
+ else
+ {
+ //Darken background color
+ if (sprite->data1 != 0)
+ sprite->data1--;
+ if (sprite->data1 != 0)
+ sprite->data1--;
+ }
+ backgroundColor = _RGB(sprite->data1, sprite->data1, sprite->data1);
+ gPlttBufferFaded[0] = backgroundColor;
+ gPlttBufferFaded[PLTT_BUFFER_INDEX] = backgroundColor;
+ }
+ sprite->pos1.x += 4;
+ }
+ else
+ {
+ gPlttBufferFaded[0] = RGB_BLACK;
+ gPlttBufferFaded[PLTT_BUFFER_INDEX] = RGB_BLACK;
+ DestroySprite(sprite);
+ }
+}
+
+static void StartPokemonLogoShine(bool8 flashBackground)
+{
+ u8 spriteId = CreateSprite(&gSpriteTemplate_8393FC0, 0, 68, 0);
+
+ gSprites[spriteId].oam.objMode = 2;
+ gSprites[spriteId].data0 = flashBackground;
+}
+
+static void VBlankCB(void)
+{
+ sub_8089668();
+ LoadOam();
+ ProcessSpriteCopyRequests();
+ TransferPlttBuffer();
+ REG_BG1VOFS = gUnknown_030041B4;
+}
+
+enum
+{
+ TD_COUNTER,
+ TD_SKIP,
+};
+
+void CB2_InitTitleScreen(void)
+{
+ switch (gMain.state)
+ {
+ default:
+ case 0:
+ SetVBlankCallback(NULL);
+ REG_BLDCNT = 0;
+ REG_BLDALPHA = 0;
+ REG_BLDY = 0;
+ *((u16 *)PLTT) = RGB_WHITE;
+ REG_DISPCNT = 0;
+ REG_BG2CNT = 0;
+ REG_BG1CNT = 0;
+ REG_BG0CNT = 0;
+ REG_BG2HOFS = 0;
+ REG_BG2VOFS = 0;
+ REG_BG1HOFS = 0;
+ REG_BG1VOFS = 0;
+ REG_BG0HOFS = 0;
+ REG_BG0VOFS = 0;
+ DmaFill16(3, 0, (void *)VRAM, 0x18000);
+ DmaFill32(3, 0, (void *)OAM, 0x400);
+ DmaFill16(3, 0, (void *)(PLTT + 2), 0x3FE);
+ ResetPaletteFade();
+ gMain.state = 1;
+ break;
+ case 1:
+ LZ77UnCompVram(gUnknown_08E9D8CC, (void *)VRAM);
+ LZ77UnCompVram(gUnknown_08E9F7E4, (void *)(VRAM + 0x4800));
+ LoadPalette(gUnknown_08E9F624, 0, 0x1C0);
+ LZ77UnCompVram(gUnknown_08393250, (void *)(VRAM + 0x8000));
+ LZ77UnCompVram(gUnknown_083939EC, (void *)(VRAM + 0xC000));
+ LZ77UnCompVram(gUnknown_08393BF8, (void *)(VRAM + 0xC800));
+ LoadPalette(gUnknown_08393210, 0xE0, 0x40);
+ remove_some_task();
+ ResetTasks();
+ ResetSpriteData();
+ FreeAllSpritePalettes();
+ gReservedSpritePaletteCount = 14;
+ LoadCompressedObjectPic(gUnknown_08393EFC);
+ LoadCompressedObjectPic(gUnknown_08393F8C);
+ LoadCompressedObjectPic(gUnknown_08393FD8);
+ LoadPalette(gUnknown_08E9F624, 0x100, 0x1C0);
+ LoadSpritePalette(gUnknown_08393F9C);
+ gMain.state = 2;
+ break;
+ case 2:
+ {
+ u8 taskId = CreateTask(Task_TitleScreenPhase1, 0);
+
+ gTasks[taskId].data[TD_COUNTER] = 0x100;
+ gTasks[taskId].data[TD_SKIP] = FALSE;
+ gTasks[taskId].data[2] = -16;
+ gTasks[taskId].data[3] = -32;
+ gUnknown_0202F7E4 = taskId;
+ gMain.state = 3;
+ break;
+ }
+ case 3:
+ BeginNormalPaletteFade(-1, 1, 0x10, 0, 0xFFFF);
+ SetVBlankCallback(VBlankCB);
+ gMain.state = 4;
+ break;
+ case 4:
+ {
+ u16 savedIme;
+
+ sub_813CE30(0x78, 0x50, 0x100, 0);
+ REG_BG2X = -29 * 256;
+ REG_BG2Y = -33 * 256;
+ REG_WIN0H = 0;
+ REG_WIN0V = 0;
+ REG_WIN1H = 0;
+ REG_WIN1V = 0;
+ REG_WININ = 0x1F1F;
+ REG_WINOUT = 0x3F1F;
+ REG_BLDCNT = 0x84;
+ REG_BLDALPHA = 0;
+ REG_BLDY = 0x8;
+ REG_BG0CNT = 0x180B;
+ REG_BG1CNT = 0x190A;
+ REG_BG2CNT = 0x4981;
+ savedIme = REG_IME;
+ REG_IME = 0;
+ REG_IE |= INTR_FLAG_VBLANK;
+ REG_IME = savedIme;
+ REG_DISPSTAT |= DISPSTAT_VBLANK_INTR;
+ REG_DISPCNT = DISPCNT_MODE_1
+ | DISPCNT_OBJ_1D_MAP
+ | DISPCNT_BG2_ON
+ | DISPCNT_OBJ_ON
+ | DISPCNT_WIN0_ON
+ | DISPCNT_OBJWIN_ON;
+ m4aSongNumStart(0x19D);
+ gMain.state = 5;
+ break;
+ }
+ case 5:
+ if (!UpdatePaletteFade())
+ {
+ StartPokemonLogoShine(FALSE);
+ sub_8089944(0, 0xA0, 4, 4, 0, 4, 1);
+ SetMainCallback2(MainCB2);
+ }
+ break;
+ }
+}
+
+static void MainCB2(void)
+{
+ RunTasks();
+ AnimateSprites();
+ BuildOamBuffer();
+ UpdatePaletteFade();
+}
+
+//Shine the Pokemon logo two more times, and fade in the version banner
+static void Task_TitleScreenPhase1(u8 taskId)
+{
+ //Skip to next phase when A, B, Start, or Select is pressed
+ if ((gMain.newKeys & A_B_START_SELECT) || gTasks[taskId].data[1] != 0)
+ {
+ gTasks[taskId].data[TD_SKIP] = TRUE;
+ gTasks[taskId].data[TD_COUNTER] = 0;
+ }
+
+ if (gTasks[taskId].data[TD_COUNTER] != 0)
+ {
+ u16 frameNum = gTasks[taskId].data[TD_COUNTER];
+
+ if (frameNum == 160 || frameNum == 64)
+ StartPokemonLogoShine(TRUE);
+ gTasks[taskId].data[TD_COUNTER]--;
+ }
+ else
+ {
+ u8 spriteId;
+
+ REG_DISPCNT = DISPCNT_MODE_1 | DISPCNT_OBJ_1D_MAP | DISPCNT_BG2_ON | DISPCNT_OBJ_ON;
+ REG_WININ = 0;
+ REG_WINOUT = 0;
+ REG_BLDCNT = 0x3F50;
+ REG_BLDALPHA = 0x1F;
+ REG_BLDY = 0;
+
+ //Create left side of version banner
+ spriteId = CreateSprite(&gSpriteTemplate_8393ECC, 0x62, 0x1A, 0);
+ gSprites[spriteId].invisible = TRUE;
+ gSprites[spriteId].data1 = taskId;
+
+ //Create right side of version banner
+ spriteId = CreateSprite(&gSpriteTemplate_8393EE4, 0xA2, 0x1A, 0);
+ gSprites[spriteId].invisible = TRUE;
+ gSprites[spriteId].data1 = taskId;
+
+ gTasks[taskId].data[5] = 88;
+ gTasks[taskId].data[TD_COUNTER] = 144;
+ gTasks[taskId].func = Task_TitleScreenPhase2;
+ }
+}
+
+//Create "Press Start" and copyright banners, and slide Pokemon logo up
+static void Task_TitleScreenPhase2(u8 taskId)
+{
+ //Skip to next phase when A, B, Start, or Select is pressed
+ if ((gMain.newKeys & A_B_START_SELECT) || gTasks[taskId].data[TD_SKIP])
+ {
+ gTasks[taskId].data[TD_SKIP] = TRUE;
+ gTasks[taskId].data[TD_COUNTER] = 0;
+ }
+
+ if (gTasks[taskId].data[TD_COUNTER] != 0)
+ gTasks[taskId].data[TD_COUNTER]--;
+ else
+ {
+ gTasks[taskId].data[TD_SKIP] = TRUE;
+ REG_DISPCNT = DISPCNT_MODE_1
+ | DISPCNT_OBJ_1D_MAP
+ | DISPCNT_BG0_ON
+ | DISPCNT_BG1_ON
+ | DISPCNT_BG2_ON
+ | DISPCNT_OBJ_ON;
+ CreatePressStartBanner(DISPLAY_WIDTH / 2, 108);
+ CreateCopyrightBanner(DISPLAY_WIDTH / 2, 148);
+ gTasks[taskId].data[4] = 0;
+ gTasks[taskId].func = Task_TitleScreenPhase3;
+ }
+
+ if (!(gTasks[taskId].data[TD_COUNTER] & 1) && gTasks[taskId].data[3] != 0)
+ gTasks[taskId].data[3]++;
+
+ //Slide Pokemon logo up
+ REG_BG2Y = gTasks[taskId].data[3] * 256;
+}
+
+//Show Kyogre/Groundon silhouette and process main title screen input
+static void Task_TitleScreenPhase3(u8 taskId)
+{
+ REG_BLDCNT = 0x2142;
+ REG_BLDALPHA = 0x1F0F;
+ REG_BLDY = 0;
+
+ if ((gMain.newKeys & A_BUTTON) || (gMain.newKeys & START_BUTTON))
+ {
+ FadeOutBGM(4);
+ BeginNormalPaletteFade(-1, 0, 0, 0x10, 0xFFFF);
+ SetMainCallback2(CB2_GoToMainMenu);
+ }
+ else
+ {
+ if ((gMain.heldKeys & CLEAR_SAVE_BUTTON_COMBO) == CLEAR_SAVE_BUTTON_COMBO)
+ SetMainCallback2(CB2_GoToClearSaveDataScreen);
+ if ((gMain.heldKeys & RESET_RTC_BUTTON_COMBO) == RESET_RTC_BUTTON_COMBO
+ && sub_80691DC() == 1)
+ {
+ FadeOutBGM(4);
+ BeginNormalPaletteFade(-1, 0, 0, 0x10, 0);
+ SetMainCallback2(CB2_GoToResetRtcScreen);
+ }
+ else
+ {
+ REG_BG2Y = 0;
+ gTasks[taskId].data[TD_COUNTER]++;
+ if (gTasks[taskId].data[TD_COUNTER] & 1)
+ {
+ gTasks[taskId].data[4]++;
+ gUnknown_030041B4 = gTasks[taskId].data[4];
+ gUnknown_030042C0 = 0;
+ }
+ UpdateLegendaryMarkingColor(gTasks[taskId].data[TD_COUNTER]);
+ if ((gMPlay_BGM.status & 0xFFFF) == 0)
+ {
+ BeginNormalPaletteFade(-1, 0, 0, 0x10, 0xFFFF);
+ SetMainCallback2(CB2_GoToCopyrightScreen);
+ }
+ }
+ }
+}
+
+static void CB2_GoToMainMenu(void)
+{
+ if (!UpdatePaletteFade())
+ SetMainCallback2(CB2_InitMainMenu);
+}
+
+static void CB2_GoToCopyrightScreen(void)
+{
+ if (!UpdatePaletteFade())
+ SetMainCallback2(CB2_InitCopyrightScreen);
+}
+
+static void CB2_GoToClearSaveDataScreen(void)
+{
+ if (!UpdatePaletteFade())
+ SetMainCallback2(CB2_InitClearSaveDataScreen);
+}
+
+static void CB2_GoToResetRtcScreen(void)
+{
+ if (!UpdatePaletteFade())
+ SetMainCallback2(CB2_InitResetRtcScreen);
+}
+
+static void UpdateLegendaryMarkingColor(u8 frameNum)
+{
+ u16 palette;
+
+ if ((frameNum % 4) == 0) //Change color every 4th frame
+ {
+ u8 colorIntensity = (frameNum >> 2) & 31; //Take bits 2-6 of frameNum the color intensity
+ u8 fadeDarker = (frameNum >> 2) & 32;
+
+ if (!fadeDarker)
+ palette = LEGENDARY_MARKING_COLOR(colorIntensity);
+ else
+ palette = LEGENDARY_MARKING_COLOR(31 - colorIntensity);
+ LoadPalette(&palette, 0xEF, sizeof(palette));
+ }
+}
+
diff --git a/src/trainer_see.c b/src/trainer_see.c
new file mode 100644
index 000000000..968f7c0a1
--- /dev/null
+++ b/src/trainer_see.c
@@ -0,0 +1,404 @@
+#include "global.h"
+#include "fieldmap.h"
+#include "task.h"
+#include "sprite.h"
+
+extern u8 * GetFieldObjectScriptPointerByFieldObjectId(u8);
+extern u8 * GetTrainerFlagFromScriptPointer(u8 *);
+extern u8 TrainerCanApproachPlayer(struct MapObject *);
+extern u8 sub_8060024(struct MapObject *, s16, s16, u8);
+extern u8 npc_block_way(struct MapObject *, s16, s16, u8);
+extern u8 npc_running_behaviour_by_direction(u8);
+extern u8 GetGoSpeed0AnimId(u8);
+extern u8 GetOppositeDirection(u8);
+extern u8 GetFaceDirectionAnimId(u8);
+extern bool8 FieldEffectActiveListContains(u8);
+extern bool8 FieldObjectIsSpecialAnimOrDirectionSequenceAnimActive(struct MapObject *);
+extern bool8 FieldObjectCheckIfSpecialAnimFinishedOrInactive(struct MapObject *);
+extern bool8 FieldObjectClearAnimIfSpecialAnimFinished(struct MapObject *);
+extern void FieldObjectClearAnim(struct MapObject *);
+extern void TrainerWantsBattle(u8, u8 *);
+extern void FieldObjectSetSpecialAnim(struct MapObject *, u8);
+extern void LoadWordFromTwoHalfwords(u32, u8 *);
+extern void StoreWordInTwoHalfwords(u32, u8 *);
+
+extern void sub_80842FC(void (*func)(u8));
+
+extern bool8 (*gIsTrainerInRange[])(struct MapObject *, u16, s16, s16);
+extern bool8 (*gTrainerSeeFuncList[])(u8, struct Task *, struct MapObject *);
+extern bool8 (*gTrainerSeeFuncList2[])(u8, struct Task *, struct MapObject *);
+
+extern u32 gUnknown_0202FF84[];
+
+bool8 CheckTrainer(u8);
+bool8 CheckPathBetweenTrainerAndPlayer(struct MapObject2 *, u8, u8);
+void sub_80842C8(struct MapObject *, u8);
+void RunTrainerSeeFuncList(u8);
+void sub_80847D8(u8);
+
+bool8 CheckTrainers(void)
+{
+ u8 i;
+
+ for(i = 0; i < 16; i++)
+ {
+ if ( gMapObjects[i].active )
+ if ( gMapObjects[i].trainerType == 1 || gMapObjects[i].trainerType == 3 )
+ if ( CheckTrainer(i) )
+ return TRUE;
+ }
+ return FALSE;
+}
+
+bool8 CheckTrainer(u8 trainer)
+{
+ u8 *scriptPtr = GetFieldObjectScriptPointerByFieldObjectId(trainer);
+
+ if(GetTrainerFlagFromScriptPointer(scriptPtr))
+ return FALSE;
+ else
+ {
+ struct MapObject *trainerObj = &gMapObjects[trainer];
+ u8 canApproach = TrainerCanApproachPlayer(trainerObj);
+
+ if(canApproach != 0)
+ {
+ TrainerWantsBattle(trainer, scriptPtr);
+ sub_80842C8(trainerObj, (canApproach - 1));
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+ }
+}
+
+bool8 TrainerCanApproachPlayer(struct MapObject *trainerObj)
+{
+ s16 x, y;
+ u8 i;
+ u8 playerCoord;
+
+ PlayerGetDestCoords(&x, &y);
+ if ( trainerObj->trainerType == 1 ) // trainers that don't spin
+ {
+ playerCoord = gIsTrainerInRange[trainerObj->mapobj_unk_18 - 1](trainerObj, trainerObj->trainerRange_berryTreeId, x, y);
+ return CheckPathBetweenTrainerAndPlayer(trainerObj, playerCoord, trainerObj->mapobj_unk_18);
+ }
+ else // spinners
+ {
+ for(i = 0; i < 4; i++)
+ {
+ playerCoord = gIsTrainerInRange[i](trainerObj, trainerObj->trainerRange_berryTreeId, x, y);
+ if ( CheckPathBetweenTrainerAndPlayer(trainerObj, playerCoord, i + 1) ) // directions are 1-4 instead of 0-3. south north west east
+ return playerCoord;
+ }
+ return FALSE;
+ }
+}
+
+bool8 IsTrainerInRangeSouth(struct MapObject *trainerObj, s16 vision, s16 x, s16 y)
+{
+ if ( trainerObj->coords2.x == x
+ && y > trainerObj->coords2.y
+ && y <= trainerObj->coords2.y + vision )
+ return (y - trainerObj->coords2.y);
+ else
+ return FALSE;
+}
+
+bool8 IsTrainerInRangeNorth(struct MapObject *trainerObj, s16 vision, s16 x, s16 y)
+{
+ if ( trainerObj->coords2.x == x
+ && y < trainerObj->coords2.y
+ && y >= trainerObj->coords2.y - vision )
+ return (trainerObj->coords2.y - y);
+ else
+ return FALSE;
+}
+
+bool8 IsTrainerInRangeWest(struct MapObject *trainerObj, s16 vision, s16 x, s16 y)
+{
+ if ( trainerObj->coords2.y == y
+ && x < trainerObj->coords2.x
+ && x >= trainerObj->coords2.x - vision )
+ return (trainerObj->coords2.x - x);
+ else
+ return FALSE;
+}
+
+bool8 IsTrainerInRangeEast(struct MapObject *trainerObj, s16 vision, s16 x, s16 y)
+{
+ if ( trainerObj->coords2.y == y
+ && x > trainerObj->coords2.x
+ && x <= trainerObj->coords2.x + vision )
+ return (x - trainerObj->coords2.x);
+ else
+ return FALSE;
+}
+
+bool8 CheckPathBetweenTrainerAndPlayer(struct MapObject2 *trainerObj, u8 playerCoord, u8 direction)
+{
+ s16 x, y;
+ u8 unk19_temp;
+ u8 unk19b_temp;
+ u8 i;
+ u8 var;
+
+ if ( !playerCoord )
+ return FALSE;
+
+ x = trainerObj->coords2.x;
+ y = trainerObj->coords2.y;
+
+ for(i = 0; i <= playerCoord - 1;)
+ {
+ var = sub_8060024(trainerObj, x, y, direction);
+
+ if (var != 0 && (var & 1) != 0 )
+ return FALSE;
+
+ i++;
+ MoveCoords(direction, &x, &y);
+ }
+
+ // preserve mapobj_unk_19 before clearing.
+ unk19_temp = trainerObj->mapobj_unk_19;
+ unk19b_temp = trainerObj->mapobj_unk_19b;
+ trainerObj->mapobj_unk_19 = 0;
+ trainerObj->mapobj_unk_19b = 0;
+
+ var = npc_block_way(trainerObj, x, y, direction);
+
+ trainerObj->mapobj_unk_19 = unk19_temp;
+ trainerObj->mapobj_unk_19b = unk19b_temp;
+ if ( var == 4 )
+ return playerCoord;
+
+ return FALSE;
+}
+
+void sub_80842C8(struct MapObject *trainerObj, u8 taskId)
+{
+ struct Task *task = &gTasks[CreateTask(RunTrainerSeeFuncList, 0x50)];
+
+ task->data[1] = (u32)(trainerObj) >> 16;
+ task->data[2] = (u32)(trainerObj);
+ task->data[3] = taskId;
+}
+
+void sub_80842FC(TaskFunc func)
+{
+ TaskFunc func2 = RunTrainerSeeFuncList;
+ u8 taskId = FindTaskIdByFunc(func2);
+
+ SetTaskFuncWithFollowupFunc(taskId, RunTrainerSeeFuncList, func);
+ gTasks[taskId].data[0] = 1;
+ func2(taskId);
+}
+
+void RunTrainerSeeFuncList(u8 taskId)
+{
+ struct Task *task = &gTasks[taskId];
+ struct MapObject *trainerObj = (task->data[1] << 16) | (task->data[2]);
+
+ if (!trainerObj->active)
+ SwitchTaskToFollowupFunc(taskId);
+ else
+ while (gTrainerSeeFuncList[task->data[0]](taskId, task, trainerObj));
+}
+
+u8 sub_8084394() // cant be void because it is called with RunTrainerSeeFuncList with arguments.
+{
+ return 0;
+}
+
+s8 sub_8084398(u8 taskId, struct Task *task, struct MapObject *trainerObj)
+{
+ u8 direction;
+
+ FieldObjectGetLocalIdAndMap(trainerObj, &gUnknown_0202FF84[0], &gUnknown_0202FF84[1], &gUnknown_0202FF84[2]);
+ FieldEffectStart(0);
+
+ direction = GetFaceDirectionAnimId(trainerObj->mapobj_unk_18);
+
+ FieldObjectSetSpecialAnim(trainerObj, direction);
+ task->data[0]++;
+ return 1;
+}
+
+s8 sub_80843DC(u8 taskId, struct Task *task, struct MapObject *trainerObj)
+{
+ if (FieldEffectActiveListContains(0))
+ return 0;
+ else
+ {
+ task->data[0]++;
+ if ((u8)(trainerObj->animPattern - 57) <= 1)
+ task->data[0] = 6;
+ if (trainerObj->animPattern == 63)
+ task->data[0] = 8;
+ return 1;
+ }
+}
+
+s8 sub_808441C(u8 taskId, struct Task *task, struct MapObject *trainerObj)
+{
+ if (!(FieldObjectIsSpecialAnimOrDirectionSequenceAnimActive(trainerObj)) || FieldObjectClearAnimIfSpecialAnimFinished(trainerObj))
+ {
+ if(task->data[3])
+ {
+ FieldObjectSetSpecialAnim(trainerObj, GetGoSpeed0AnimId(trainerObj->mapobj_unk_18));
+ task->data[3]--;
+ }
+ else
+ {
+ FieldObjectSetSpecialAnim(trainerObj, 0x3E);
+ task->data[0]++;
+ }
+ }
+ return 0;
+}
+
+s8 sub_8084478(u8 taskId, struct Task *task, struct MapObject *trainerObj)
+{
+ struct MapObject *playerObj;
+
+ if (FieldObjectIsSpecialAnimOrDirectionSequenceAnimActive(trainerObj) && !FieldObjectClearAnimIfSpecialAnimFinished(trainerObj))
+ return 0;
+
+ npc_set_running_behaviour_etc(trainerObj, npc_running_behaviour_by_direction(trainerObj->mapobj_unk_18));
+ sub_805C774(trainerObj, npc_running_behaviour_by_direction(trainerObj->mapobj_unk_18));
+ sub_805C754(trainerObj);
+
+ playerObj = &gMapObjects[gPlayerAvatar.mapObjectId];
+ if (FieldObjectIsSpecialAnimOrDirectionSequenceAnimActive(playerObj)
+ && !FieldObjectClearAnimIfSpecialAnimFinished(playerObj))
+ return 0;
+
+ sub_80597E8();
+ FieldObjectSetSpecialAnim(&gMapObjects[gPlayerAvatar.mapObjectId], GetFaceDirectionAnimId(GetOppositeDirection(trainerObj->mapobj_unk_18)));
+ task->data[0]++;
+ return 0;
+}
+
+s8 sub_8084534(u8 taskId, struct Task *task, struct MapObject *trainerObj) // technically only 1 parameter, but needs all 3 for TrainerSeeFuncList call.
+{
+ struct MapObject *playerObj = &gMapObjects[gPlayerAvatar.mapObjectId];
+
+ if ( !FieldObjectIsSpecialAnimOrDirectionSequenceAnimActive(playerObj)
+ || FieldObjectClearAnimIfSpecialAnimFinished(playerObj) )
+ SwitchTaskToFollowupFunc(taskId);
+
+ return 0;
+}
+
+s8 sub_8084578(u8 taskId, struct Task *task, struct MapObject *trainerObj)
+{
+ if(!FieldObjectIsSpecialAnimOrDirectionSequenceAnimActive(trainerObj)
+ || FieldObjectClearAnimIfSpecialAnimFinished(trainerObj))
+ {
+ FieldObjectSetSpecialAnim(trainerObj, 0x59);
+ task->data[0]++;
+ }
+ return 0;
+}
+
+s8 sub_80845AC(u8 taskId, struct Task *task, struct MapObject *trainerObj)
+{
+ if ( FieldObjectClearAnimIfSpecialAnimFinished(trainerObj) )
+ task->data[0] = 3;
+
+ return 0;
+}
+
+s8 sub_80845C8(u8 taskId, struct Task *task, struct MapObject *trainerObj)
+{
+ if(!FieldObjectIsSpecialAnimOrDirectionSequenceAnimActive(trainerObj)
+ || FieldObjectClearAnimIfSpecialAnimFinished(trainerObj))
+ {
+ FieldObjectSetSpecialAnim(trainerObj, 0x3E);
+ task->data[0]++;
+ }
+ return 0;
+}
+
+s8 sub_80845FC(u8 taskId, struct Task *task, struct MapObject *trainerObj)
+{
+ if(FieldObjectCheckIfSpecialAnimFinishedOrInactive(trainerObj))
+ {
+ gUnknown_0202FF84[0] = trainerObj->coords2.x;
+ gUnknown_0202FF84[1] = trainerObj->coords2.y;
+ gUnknown_0202FF84[2] = gSprites[trainerObj->spriteId].subpriority - 1;
+ gUnknown_0202FF84[3] = 2;
+ task->data[4] = FieldEffectStart(49);
+ task->data[0]++;
+ }
+ return 0;
+}
+
+s8 sub_8084654(u8 taskId, struct Task *task, struct MapObject *trainerObj)
+{
+ struct Sprite *sprite;
+
+ if(gSprites[task->data[4]].animCmdIndex == 2)
+ {
+ trainerObj->mapobj_bit_26 = 0;
+ trainerObj->mapobj_bit_2 = 1;
+
+ sprite = &gSprites[trainerObj->spriteId];
+ sprite->oam.priority = 2;
+ FieldObjectClearAnimIfSpecialAnimFinished(trainerObj);
+ FieldObjectSetSpecialAnim(trainerObj, sub_806084C(trainerObj->mapobj_unk_18));
+ task->data[0]++;
+ }
+ return 0;
+}
+
+s8 sub_80846C8(u8 taskId, struct Task *task, struct MapObject *trainerObj)
+{
+ if(!FieldEffectActiveListContains(49))
+ task->data[0] = 3;
+
+ return 0;
+}
+
+void sub_80846E4(u8 taskId)
+{
+ struct Task *task = &gTasks[taskId];
+ struct MapObject *mapObj;
+
+ // another mapObj loaded into by loadword?
+ LoadWordFromTwoHalfwords(&task->data[1], &mapObj);
+ if(!task->data[7])
+ {
+ FieldObjectClearAnim(mapObj);
+ task->data[7]++;
+ }
+ gTrainerSeeFuncList2[task->data[0]](taskId, task, mapObj);
+ if(task->data[0] == 3 && !FieldEffectActiveListContains(49))
+ {
+ npc_set_running_behaviour_etc(mapObj, npc_running_behaviour_by_direction(mapObj->mapobj_unk_18));
+ sub_805C774(mapObj, npc_running_behaviour_by_direction(mapObj->mapobj_unk_18));
+ DestroyTask(taskId);
+ }
+ else
+ mapObj->mapobj_bit_7 = 0;
+}
+
+void sub_8084794(u32 var)
+{
+ StoreWordInTwoHalfwords(&gTasks[CreateTask(sub_80846E4, 0)].data[1], var);
+}
+
+void sub_80847C8(void)
+{
+ sub_80842FC(sub_80847D8);
+}
+
+void sub_80847D8(u8 taskId)
+{
+ DestroyTask(taskId);
+ EnableBothScriptContexts();
+}
diff --git a/src/truck_scene.c b/src/truck_scene.c
new file mode 100644
index 000000000..565851856
--- /dev/null
+++ b/src/truck_scene.c
@@ -0,0 +1,229 @@
+#include "global.h"
+#include "palette.h"
+#include "task.h"
+#include "script.h"
+#include "songs.h"
+#include "sound.h"
+
+extern s8 gTruckCamera_HorizontalTable[];
+
+extern void SetCameraPanning(s16 a1, s16 a2);
+extern void sub_805BD90(u8 localId, u8 mapNum, u8 mapGroup, s16 x, s16 y);
+
+void Task_Truck1(u8 taskId);
+void Task_Truck2(u8 taskId);
+void Task_Truck3(u8 taskId);
+void ExecuteTruckSequence(void);
+
+s32 GetTruckCameraBobbingY(int a1)
+{
+ s32 result;
+
+ if (!(a1 % 120))
+ return -1;
+ else if ((a1 % 10) <= 4)
+ return 1;
+
+ return 0;
+}
+
+s32 GetTruckBoxMovement(int a1) // for the box movement?
+{
+ s32 result;
+
+ if (!((a1 + 120) % 180))
+ return -1;
+
+ return 0;
+}
+
+void Task_Truck1(u8 taskId)
+{
+ s16 *data = gTasks[taskId].data;
+ s16 cameraYpan;
+ s16 box1 = 0;
+ s16 box2 = 0;
+ s16 box3 = 0;
+ u8 mapNum, mapGroup;
+ register s16 zero asm("r4");
+
+ box1 = GetTruckBoxMovement(data[0] + 30) * 4; // box 1 happens 30 frames earlier than the other 2.
+ sub_805BD90(1, gSaveBlock1.location.mapNum, gSaveBlock1.location.mapGroup, 3, box1 + 3);
+ box2 = GetTruckBoxMovement(data[0]) * 2;
+ sub_805BD90(2, gSaveBlock1.location.mapNum, gSaveBlock1.location.mapGroup, 0, box2 - 3);
+ box3 = GetTruckBoxMovement(data[0]) * 4;
+ mapNum = gSaveBlock1.location.mapNum;
+ mapGroup = gSaveBlock1.location.mapGroup;
+ zero = 0;
+ sub_805BD90(3, mapNum, mapGroup, -3, box3);
+
+ data[0]++;
+
+ if (data[0] == 0x7530) // timer?
+ data[0] = zero;
+
+ cameraYpan = GetTruckCameraBobbingY(data[0]);
+ SetCameraPanning(0, cameraYpan);
+}
+
+void Task_Truck2(u8 taskId)
+{
+ s16 *data = gTasks[taskId].data;
+ s16 cameraYpan;
+ s16 cameraXpan;
+ s16 box1;
+ s16 box2;
+ s16 box3;
+
+ data[0]++;
+ data[2]++;
+
+ if (data[0] > 5)
+ {
+ data[0] = 0;
+ data[1]++;
+ }
+ if ((u16)data[1] == 19)
+ {
+ DestroyTask(taskId);
+ }
+ else
+ {
+ if (gTruckCamera_HorizontalTable[data[1]] == 2)
+ gTasks[taskId].func = Task_Truck3;
+
+ cameraXpan = gTruckCamera_HorizontalTable[data[1]];
+ cameraYpan = GetTruckCameraBobbingY(data[2]);
+ SetCameraPanning(cameraXpan, cameraYpan);
+ box1 = GetTruckBoxMovement(data[2] + 30) * 4;
+ sub_805BD90(1, gSaveBlock1.location.mapNum, gSaveBlock1.location.mapGroup, 3 - cameraXpan, box1 + 3);
+ box2 = GetTruckBoxMovement(data[2]) * 2;
+ sub_805BD90(2, gSaveBlock1.location.mapNum, gSaveBlock1.location.mapGroup, -cameraXpan, box2 - 3);
+ box3 = GetTruckBoxMovement(data[2]) * 4;
+ sub_805BD90(3, gSaveBlock1.location.mapNum, gSaveBlock1.location.mapGroup, -3 - cameraXpan, box3);
+ }
+}
+
+void Task_Truck3(u8 taskId)
+{
+ s16 *data = gTasks[taskId].data;
+ s16 cameraXpan;
+ s16 cameraYpan;
+
+ data[0]++;
+
+ if (data[0] > 5)
+ {
+ data[0] = 0;
+ data[1]++;
+ }
+
+ if ((u16)data[1] == 19)
+ {
+ DestroyTask(taskId);
+ }
+ else
+ {
+ cameraXpan = gTruckCamera_HorizontalTable[data[1]];
+ cameraYpan = 0;
+ SetCameraPanning(cameraXpan, 0);
+ sub_805BD90(1, gSaveBlock1.location.mapNum, gSaveBlock1.location.mapGroup, 3 - cameraXpan, cameraYpan + 3);
+ sub_805BD90(2, gSaveBlock1.location.mapNum, gSaveBlock1.location.mapGroup, -cameraXpan, cameraYpan - 3);
+ sub_805BD90(3, gSaveBlock1.location.mapNum, gSaveBlock1.location.mapGroup, -3 - cameraXpan, cameraYpan);
+ }
+}
+
+void Task_HandleTruckSequence(u8 taskId)
+{
+ s16 *data = gTasks[taskId].data;
+
+ switch (data[0])
+ {
+ /*
+ Each case has a timer which is handled with data[1], incrementing
+ until it reaches the if function's condition, which sets the next task up.
+ */
+ case 0:
+ data[1]++;
+ if (data[1] == 90)
+ {
+ SetCameraPanningCallback(0);
+ data[1] = 0; // reset the timer.
+ data[2] = CreateTask(Task_Truck1, 0xA);
+ data[0] = 1; // run the next case.
+ PlaySE(SE_TRACK_MOVE);
+ }
+ break;
+ case 1:
+ data[1]++;
+ if (data[1] == 150)
+ {
+ pal_fill_black();
+ data[1] = 0;
+ data[0] = 2;
+ }
+ break;
+ case 2:
+ data[1]++;
+ if(!gPaletteFade.active && data[1] > 300)
+ {
+ data[1] = 0;
+ DestroyTask(data[2]);
+ data[3] = CreateTask(Task_Truck2, 0xA);
+ data[0] = 3;
+ PlaySE(SE_TRACK_STOP);
+ }
+ break;
+ case 3:
+ if (!gTasks[data[3]].isActive) // is Truck2 no longer active (is Truck3 active?)
+ {
+ InstallCameraPanAheadCallback();
+ data[1] = 0;
+ data[0] = 4;
+ }
+ break;
+ case 4:
+ data[1]++;
+ if (data[1] == 90)
+ {
+ PlaySE(SE_TRACK_HAIK);
+ data[1] = 0;
+ data[0] = 5;
+ }
+ break;
+ case 5:
+ data[1]++;
+ if (data[1] == 120)
+ {
+ MapGridSetMetatileIdAt(11, 8, 520);
+ MapGridSetMetatileIdAt(11, 9, 528);
+ MapGridSetMetatileIdAt(11, 10, 536);
+ DrawWholeMapView();
+ PlaySE(SE_TRACK_DOOR);
+ DestroyTask(taskId);
+ ScriptContext2_Disable();
+ }
+ break;
+ }
+}
+
+void ExecuteTruckSequence(void)
+{
+ MapGridSetMetatileIdAt(11, 8, 525);
+ MapGridSetMetatileIdAt(11, 9, 533);
+ MapGridSetMetatileIdAt(11, 10, 541);
+ DrawWholeMapView();
+ ScriptContext2_Enable();
+ CpuFastFill(0, gPlttBufferFaded, 0x400);
+ CreateTask(Task_HandleTruckSequence, 0xA);
+}
+
+void EndTruckSequence(void)
+{
+ if (!FuncIsActiveTask(Task_HandleTruckSequence))
+ {
+ sub_805BD90(1, gSaveBlock1.location.mapNum, gSaveBlock1.location.mapGroup, 3, 3);
+ sub_805BD90(2, gSaveBlock1.location.mapNum, gSaveBlock1.location.mapGroup, 0, -3);
+ sub_805BD90(3, gSaveBlock1.location.mapNum, gSaveBlock1.location.mapGroup, -3, 0);
+ }
+}
diff --git a/src/var.c b/src/var.c
index b6639aa5f..08b109e6f 100644
--- a/src/var.c
+++ b/src/var.c
@@ -1,4 +1,5 @@
#include "global.h"
+#include "var.h"
extern u16 *gSpecialVars[];
diff --git a/src/wallclock.c b/src/wallclock.c
index 8ee04c36a..05e30a8cb 100644
--- a/src/wallclock.c
+++ b/src/wallclock.c
@@ -11,11 +11,10 @@
#include "sound.h"
//Functions that need to be put in headers
-void LZ77UnCompVram(const void *src, void *dest);
void remove_some_task(void);
void LoadCompressedObjectPic(void *);
-extern u16 gUnknown_0202E8CC;
+extern u16 gSpecialVar_0x8004;
extern u16 gMiscClockMale_Pal[];
extern u16 gMiscClockFemale_Pal[];
extern u8 gMiscClock_Gfx[];
@@ -119,7 +118,7 @@ static void LoadWallClockGraphics(void)
DmaClear16(3, PLTT, PLTT_SIZE);
LZ77UnCompVram(gMiscClock_Gfx, (void *)VRAM);
- if(gUnknown_0202E8CC == MALE)
+ if(gSpecialVar_0x8004 == MALE)
LoadPalette(gMiscClockMale_Pal, 0, 32);
else
LoadPalette(gMiscClockFemale_Pal, 0, 32);
diff --git a/src/wild_encounter.c b/src/wild_encounter.c
index f4befa466..151088cd6 100644
--- a/src/wild_encounter.c
+++ b/src/wild_encounter.c
@@ -1,21 +1,27 @@
#include "global.h"
+#include "abilities.h"
#include "fieldmap.h"
#include "pokemon.h"
#include "rng.h"
#include "script.h"
+#include "flag.h"
+#include "var.h"
-struct WildPokemon {
+struct WildPokemon
+{
u8 minLevel;
u8 maxLevel;
u16 species;
};
-struct WildPokemonInfo {
+struct WildPokemonInfo
+{
u8 encounterRate;
struct WildPokemon *wildPokemon;
};
-struct WildPokemonHeader {
+struct WildPokemonHeader
+{
u8 mapGroup;
u8 mapNum;
struct WildPokemonInfo *landMonsInfo;
@@ -26,26 +32,21 @@ struct WildPokemonHeader {
extern bool8 sub_805759C(u8);
extern void GetXYCoordsOneStepInFrontOfPlayer(void *, void *);
-extern u32 sub_80C8448(void);
-extern s16 sub_810CAE4(u8, u32);
+extern s16 sub_810CAE4(u8, struct Pokeblock *);
extern bool32 GetSafariZoneFlag(void);
extern u8 TestPlayerAvatarFlags(u8);
extern u8 MetatileBehavior_IsLandWildEncounter(u8);
extern u8 sub_81344CC(void);
extern u8 MetatileBehavior_IsWaterWildEncounter(u8);
-extern void sub_8081A00(void);
+extern void CheckForSafariZoneAndProceed(void);
extern u8 MetatileBehavior_IsBridge(u8);
extern void PlayerGetDestCoords(u16 *x, u16 *y);
extern void sub_80BEA50(u16);
extern void sav12_xor_increment(u8);
-extern u8 FlagGet(u16);
-extern u16 VarGet(u16);
extern int MapGridGetMetatileBehaviorAt(int x, int y);
+extern struct Pokeblock *SafariZoneGetActivePokeblock(void);
-extern u8 gWildEncountersDisabled;
-extern u16 gUnknown_0839DC00[];
-//extern u16 gUnknown_0839DC00[3][3];
-extern u32 gUnknown_0202FF80; //Feebas rng value
+extern u16 gRoute119WaterTileData[];
extern struct WildPokemonHeader gWildMonHeaders[];
extern struct Pokemon gEnemyParty[6];
extern struct Pokemon gPlayerParty[6];
@@ -53,220 +54,199 @@ extern u16 gScriptResult;
extern struct WildPokemon gWildFeebasRoute119Data;
extern u8 Event_RepelWoreOff[];
+EWRAM_DATA static u8 sWildEncountersDisabled = 0;
+EWRAM_DATA static u32 sFeebasRngValue = 0;
+
#define NUM_FEEBAS_SPOTS 6
-u16 sub_8084984(s16 x, s16 y, u8 c);
-bool8 CheckFeebas(void);
-u16 FeebasRandom(void);
-void FeebasSeedRng(u16 seed);
-u8 PickWildMon_Grass(void);
-u8 PickWildMon_Water(void);
-u8 PickWildMon_Fishing(u8 rod);
-u8 RandomInRange(struct WildPokemon *wildPokemon);
-u16 GetCurrentMapWildMonHeader(void);
-u8 PickWildMonNature(void);
-void CreateWildMon(u16 species, u8 b);
-bool8 GenerateWildMon(struct WildPokemonInfo *a, u8 b, u8 c);
-u16 GenerateFishingWildMon(struct WildPokemonInfo *a, u8 rod);
-bool8 SetUpMassOutbreakEncounter(u8 a);
-bool8 DoMassOutbreakEncounterTest(void);
-bool8 DoWildEncounterRateDiceRoll(u16 a);
-bool8 DoWildEncounterTest(u32 a, u8 b);
-bool8 DoGlobalWildEncounterDiceRoll(void);
-bool8 StandardWildEncounter(u16 a, u16 b);
-void RockSmashWildEncounter(void);
-u8 SweetScentWildEncounter(void);
-u8 GetFishingWildMonListHeader(void);
-void FishingWildEncounter(u8 rod);
-u16 GetLocalWildMon(u8 *a1);
-u16 GetMirageIslandMon(void);
-bool8 UpdateRepelCounter(void);
-bool8 RepelCheck(bool8 level);
-void ApplyFluteEncounterRateMod(u32 *a1);
-void ApplyCleanseTagEncounterRateMod(u32 *a1);
-
-
-void DisableWildEncounters(bool8 disable)
-{
- gWildEncountersDisabled = disable;
-}
+static u16 FeebasRandom(void);
+static void FeebasSeedRng(u16 seed);
+
+static bool8 RepelCheck(u8 level);
+static void ApplyFluteEncounterRateMod(u32 *encRate);
+static void ApplyCleanseTagEncounterRateMod(u32 *encRate);
-u16 sub_8084984(s16 x, s16 y, u8 c)
+void DisableWildEncounters(bool8 disabled)
{
- //odd, but needed to match
- u16 *arr = gUnknown_0839DC00;
- u16 *ptr = &arr[c * 3];
- u16 r9 = gUnknown_0839DC00[c * 3 + 1];
- u16 r6 = gUnknown_0839DC00[c * 3 + 2];
- u16 r5 = *ptr;
+ sWildEncountersDisabled = disabled;
+}
- while(r5 <= r9)
+static u16 GetRoute119WaterTileNum(s16 x, s16 y, u8 section)
+{
+ u16 xCur;
+ u16 yCur;
+ u16 yMin = gRoute119WaterTileData[section * 3 + 0];
+ u16 yMax = gRoute119WaterTileData[section * 3 + 1];
+ u16 tileNum = gRoute119WaterTileData[section * 3 + 2];
+
+ for (yCur = yMin; yCur <= yMax; yCur++)
{
- u16 i;
-
- for(i = 0; i < gMapHeader.mapData->width; i++)
+ for (xCur = 0; xCur < gMapHeader.mapData->width; xCur++)
{
- if(sub_805759C(MapGridGetMetatileBehaviorAt(i + 7, r5 + 7)) == TRUE)
+ if (sub_805759C(MapGridGetMetatileBehaviorAt(xCur + 7, yCur + 7)) == TRUE)
{
- r6++;
- if(x == i && y == r5)
- return r6;
+ tileNum++;
+ if (x == xCur && y == yCur)
+ return tileNum;
}
- //_08084A14
}
- r5++;
}
-
- return r6 + 1;
+ return tileNum + 1;
}
-bool8 CheckFeebas(void)
+static bool8 CheckFeebas(void)
{
+ u8 i;
u16 feebasSpots[6];
s16 x;
s16 y;
- u8 r7 = 0;
- u8 i;
- u16 foo;
+ u8 route119section = 0;
+ u16 waterTileNum;
- if(gSaveBlock1.location.mapGroup == 0 && gSaveBlock1.location.mapNum == 0x22)
+ if (gSaveBlock1.location.mapGroup == 0 && gSaveBlock1.location.mapNum == 0x22)
{
GetXYCoordsOneStepInFrontOfPlayer(&x, &y);
x -= 7;
y -= 7;
-
- // *sigh* whatever gets the code to match!
+
+#ifdef NONMATCHING
+ if (y >= gRoute119WaterTileData[3 * 1 + 0] && y <= gRoute119WaterTileData[3 * 1 + 1])
+ route119section = 1;
+ if (y >= gRoute119WaterTileData[3 * 2 + 0] && y <= gRoute119WaterTileData[3 * 2 + 1])
+ route119section = 2;
+#else
{
- register u16 *arr asm("r0");
- if(y >= (arr = gUnknown_0839DC00)[3 * 1 + 0] && y <= arr[3 * 1 + 1])
- r7 = 1;
- if(y >= arr[3 * 2 + 0] && y <= arr[3 * 2 + 1])
- r7 = 2;
+ register u16 *arr asm("r0");
+ if (y >= (arr = gRoute119WaterTileData)[3 * 1 + 0] && y <= arr[3 * 1 + 1])
+ route119section = 1;
+ if (y >= arr[3 * 2 + 0] && y <= arr[3 * 2 + 1])
+ route119section = 2;
}
- //_08084A8E
-
- if(Random() % 100 > 49) //Why not just do (Random() & 1) to get a 50% chance?
+#endif
+
+ if (Random() % 100 > 49) //50% chance of encountering Feebas
return FALSE;
- //_08084AC8
- FeebasSeedRng(gSaveBlock1.feebasLocationSeed);
- for(i = 0; i != NUM_FEEBAS_SPOTS;)
+ FeebasSeedRng(gSaveBlock1.easyChatPairs[0].unk2);
+ for (i = 0; i != NUM_FEEBAS_SPOTS;)
{
feebasSpots[i] = FeebasRandom() % 447;
- if(feebasSpots[i] == 0)
+ if (feebasSpots[i] == 0)
feebasSpots[i] = 447;
- if(feebasSpots[i] < 1 || feebasSpots[i] >= 4)
+ if (feebasSpots[i] < 1 || feebasSpots[i] >= 4)
i++;
}
- foo = sub_8084984(x, y, r7);
- for(i = 0; i < NUM_FEEBAS_SPOTS; i++)
+ waterTileNum = GetRoute119WaterTileNum(x, y, route119section);
+ for (i = 0; i < NUM_FEEBAS_SPOTS; i++)
{
- if(foo == feebasSpots[i])
+ if (waterTileNum == feebasSpots[i])
return TRUE;
}
}
- //_08084B38
return FALSE;
}
-u16 FeebasRandom(void)
+static u16 FeebasRandom(void)
{
- gUnknown_0202FF80 = 12345 + 0x41C64E6D * gUnknown_0202FF80;
- return gUnknown_0202FF80 >> 16;
+ sFeebasRngValue = 12345 + 0x41C64E6D * sFeebasRngValue;
+ return sFeebasRngValue >> 16;
}
-void FeebasSeedRng(u16 seed)
+static void FeebasSeedRng(u16 seed)
{
- gUnknown_0202FF80 = seed;
+ sFeebasRngValue = seed;
}
-u8 PickWildMon_Grass(void)
+static u8 ChooseWildMonIndex_Land(void)
{
- u8 val = Random() % 100;
+ u8 rand = Random() % 100;
- if(val < 20)
+ if (rand < 20) //20% chance
return 0;
- if(val >= 20 && val < 40)
+ if (rand >= 20 && rand < 40) //20% chance
return 1;
- if(val >= 40 && val < 50)
+ if (rand >= 40 && rand < 50) //10% chance
return 2;
- if(val >= 50 && val < 60)
+ if (rand >= 50 && rand < 60) //10% chance
return 3;
- if(val >= 60 && val < 70)
+ if (rand >= 60 && rand < 70) //10% chance
return 4;
- if(val >= 70 && val < 80)
+ if (rand >= 70 && rand < 80) //10% chance
return 5;
- if(val >= 80 && val < 85)
+ if (rand >= 80 && rand < 85) //5% chance
return 6;
- if(val >= 85 && val < 90)
+ if (rand >= 85 && rand < 90) //5% chance
return 7;
- if(val >= 90 && val < 94)
+ if (rand >= 90 && rand < 94) //4% chance
return 8;
- if(val >= 94 && val < 98)
+ if (rand >= 94 && rand < 98) //4% chance
return 9;
- if(val == 98)
+ if (rand == 98) //1% chance
return 10;
- else
+ else //1% chance
return 11;
}
-u8 PickWildMon_Water(void)
+static u8 ChooseWildMonIndex_Water(void)
{
- u8 val = Random() % 100;
+ u8 rand = Random() % 100;
- if(val < 60)
+ if (rand < 60) //60% chance
return 0;
- if(val >= 60 && val < 90)
+ if (rand >= 60 && rand < 90) //30% chance
return 1;
- if(val >= 90 && val < 95)
+ if (rand >= 90 && rand < 95) //5% chance
return 2;
- if(val >= 95 && val < 99)
- return 3;
- else
+ if (rand >= 95 && rand < 99) //4% chance
+ return 3;
+ else //1% chance
return 4;
}
-u8 PickWildMon_Fishing(u8 rod)
+enum
{
- u32 r5 = 0;
- u8 val = Random() % 100;
+ OLD_ROD,
+ GOOD_ROD,
+ SUPER_ROD
+};
- switch(rod)
+static u8 ChooseWildMonIndex_Fishing(u8 rod)
+{
+ u8 wildMonIndex = 0;
+ u8 rand = Random() % 100;
+
+ switch (rod)
{
- case 0: //old rod?
- if(val < 70)
- r5 = 0;
- else
- r5 = 1;
- return r5;
- case 1: //good rod?
- if(val < 60)
- r5 = 2;
- if(val >= 60 && val < 80)
- r5 = 3;
- if(val >= 80 && val < 100)
- r5 = 4;
- return r5;
- case 2: //super rod?
- if(val < 40)
- r5 = 5;
- if(val >= 40 && val < 80)
- r5 = 6;
- if(val >= 80 && val < 95)
- r5 = 7;
- if(val >= 95 && val < 99)
- r5 = 8;
- if(val == 99)
- r5 = 9;
- return r5;
- default:
- return r5;
+ case OLD_ROD:
+ if (rand < 70) //70% chance
+ wildMonIndex = 0;
+ else //30% chance
+ wildMonIndex = 1;
+ break;
+ case GOOD_ROD:
+ if (rand < 60) //60% chance
+ wildMonIndex = 2;
+ if (rand >= 60 && rand < 80) //20% chance
+ wildMonIndex = 3;
+ if (rand >= 80 && rand < 100) //20% chance
+ wildMonIndex = 4;
+ break;
+ case SUPER_ROD:
+ if (rand < 40) //40% chance
+ wildMonIndex = 5;
+ if (rand >= 40 && rand < 80) //40% chance
+ wildMonIndex = 6;
+ if (rand >= 80 && rand < 95) //15% chance
+ wildMonIndex = 7;
+ if (rand >= 95 && rand < 99) //4% chance
+ wildMonIndex = 8;
+ if (rand == 99) //1% chance
+ wildMonIndex = 9;
+ break;
}
-
- return r5;
+ return wildMonIndex;
}
-//Chooses level of wild Pokemon
-u8 RandomInRange(struct WildPokemon *wildPokemon)
+static u8 ChooseWildMonLevel(struct WildPokemon *wildPokemon)
{
u8 min;
u8 max;
@@ -274,7 +254,7 @@ u8 RandomInRange(struct WildPokemon *wildPokemon)
u8 rand;
//Make sure minimum level is less than maximum level
- if(wildPokemon->maxLevel >= wildPokemon->minLevel)
+ if (wildPokemon->maxLevel >= wildPokemon->minLevel)
{
min = wildPokemon->minLevel;
max = wildPokemon->maxLevel;
@@ -289,180 +269,160 @@ u8 RandomInRange(struct WildPokemon *wildPokemon)
return min + rand;
}
-u16 GetCurrentMapWildMonHeader(void)
+static u16 GetCurrentMapWildMonHeader(void)
{
u16 i;
- for(i = 0; gWildMonHeaders[i].mapGroup != 0xFF; i++)
+ for (i = 0; gWildMonHeaders[i].mapGroup != 0xFF; i++)
{
- if(gWildMonHeaders[i].mapGroup == gSaveBlock1.location.mapGroup &&
+ if (gWildMonHeaders[i].mapGroup == gSaveBlock1.location.mapGroup &&
gWildMonHeaders[i].mapNum == gSaveBlock1.location.mapNum)
return i;
}
return -1;
}
-u8 PickWildMonNature(void)
+static u8 PickWildMonNature(void)
{
- u16 foo;
- u32 r7;
- u8 arr[25];
+ u8 i;
+ u8 j;
+ struct Pokeblock *safariPokeblock;
+ u8 natures[25];
- if(GetSafariZoneFlag() == TRUE && Random() % 100 < 80)
+ if (GetSafariZoneFlag() == TRUE && Random() % 100 < 80)
{
- r7 = sub_80C8448();
-
- if(r7)
+ safariPokeblock = SafariZoneGetActivePokeblock();
+ if (safariPokeblock != NULL)
{
- u8 i;
-
- for(i = 0; i < 25; i++)
- arr[i] = i;
- //_08084E04
- for(i = 0; i < 24; i++)
+ for (i = 0; i < 25; i++)
+ natures[i] = i;
+ for (i = 0; i < 24; i++)
{
- u8 j;
-
- for(j = i + 1; j < 25; j++)
+ for (j = i + 1; j < 25; j++)
{
- if(Random() & 1)
+ if (Random() & 1)
{
- u8 temp = arr[i];
+ u8 temp = natures[i];
- arr[i] = arr[j];
- arr[j] = temp;
+ natures[i] = natures[j];
+ natures[j] = temp;
}
}
}
- //_08084E3E
- for(i = 0; i < 25; i++)
+ for (i = 0; i < 25; i++)
{
- if(sub_810CAE4(arr[i], r7) > 0)
- return arr[i];
+ if (sub_810CAE4(natures[i], safariPokeblock) > 0)
+ return natures[i];
}
}
}
- //_08084E5E
return Random() % 25;
}
-void CreateWildMon(u16 species, u8 b)
+static void CreateWildMon(u16 species, u8 b)
{
ZeroEnemyPartyMons();
CreateMonWithNature(&gEnemyParty[0], species, b, 0x20, PickWildMonNature());
}
-bool8 GenerateWildMon(struct WildPokemonInfo *a, u8 b, u8 c)
+static bool8 GenerateWildMon(struct WildPokemonInfo *wildMonInfo, u8 area, bool8 checkRepel)
{
- u8 mon = 0;
+ u8 wildMonIndex = 0;
u8 level;
- switch(b)
+ switch (area)
{
- case 0:
- mon = PickWildMon_Grass();
- break;
- case 1:
- mon = PickWildMon_Water();
- break;
- case 2:
- mon = PickWildMon_Water();
- break;
- default:
- break;
- }
-
- level = RandomInRange(&a->wildPokemon[mon]);
- if(c == 1 && RepelCheck(level) == 0)
- {
- return 0;
+ case 0:
+ wildMonIndex = ChooseWildMonIndex_Land();
+ break;
+ case 1:
+ wildMonIndex = ChooseWildMonIndex_Water();
+ break;
+ case 2:
+ wildMonIndex = ChooseWildMonIndex_Water();
+ break;
}
+ level = ChooseWildMonLevel(&wildMonInfo->wildPokemon[wildMonIndex]);
+ if (checkRepel == TRUE && RepelCheck(level) == FALSE)
+ return FALSE;
else
{
- CreateWildMon(a->wildPokemon[mon].species, level);
- return 1;
+ CreateWildMon(wildMonInfo->wildPokemon[wildMonIndex].species, level);
+ return TRUE;
}
}
-u16 GenerateFishingWildMon(struct WildPokemonInfo *a, u8 rod)
+static u16 GenerateFishingWildMon(struct WildPokemonInfo *wildMonInfo, u8 rod)
{
- u8 mon = PickWildMon_Fishing(rod);
- u8 level = RandomInRange(&a->wildPokemon[mon]);
+ u8 wildMonIndex = ChooseWildMonIndex_Fishing(rod);
+ u8 level = ChooseWildMonLevel(&wildMonInfo->wildPokemon[wildMonIndex]);
- CreateWildMon(a->wildPokemon[mon].species, level);
- return a->wildPokemon[mon].species;
+ CreateWildMon(wildMonInfo->wildPokemon[wildMonIndex].species, level);
+ return wildMonInfo->wildPokemon[wildMonIndex].species;
}
-bool8 SetUpMassOutbreakEncounter(u8 a)
+static bool8 SetUpMassOutbreakEncounter(bool8 checkRepel)
{
u16 i;
- if(a == 1 && RepelCheck(gSaveBlock1.outbreakPokemonLevel) == 0)
- {
- return 0;
- }
- //_08084F78
- CreateWildMon(gSaveBlock1.outbreakPokemonSpecies, gSaveBlock1.outbreakPokemonLevel);
- for(i = 0; i < 4; i++)
+ if (checkRepel == TRUE && RepelCheck(gSaveBlock1.outbreakPokemonLevel) == 0)
+ return FALSE;
+ else
{
- SetMonMoveSlot(&gEnemyParty[0], gSaveBlock1.outbreakPokemonMoves[i], i);
+ CreateWildMon(gSaveBlock1.outbreakPokemonSpecies, gSaveBlock1.outbreakPokemonLevel);
+ for (i = 0; i < 4; i++)
+ SetMonMoveSlot(&gEnemyParty[0], gSaveBlock1.outbreakPokemonMoves[i], i);
+ return TRUE;
}
- return 1;
}
-bool8 DoMassOutbreakEncounterTest(void)
+static bool8 DoMassOutbreakEncounterTest(void)
{
- if(gSaveBlock1.outbreakPokemonSpecies &&
- gSaveBlock1.location.mapNum == gSaveBlock1.outbreakLocationMapNum &&
- gSaveBlock1.location.mapGroup == gSaveBlock1.outbreakLocationMapGroup)
+ if (gSaveBlock1.outbreakPokemonSpecies != 0
+ && gSaveBlock1.location.mapNum == gSaveBlock1.outbreakLocationMapNum
+ && gSaveBlock1.location.mapGroup == gSaveBlock1.outbreakLocationMapGroup)
{
- if(Random() % 100 < gSaveBlock1.outbreakPokemonProbability)
- return 1;
+ if (Random() % 100 < gSaveBlock1.outbreakPokemonProbability)
+ return TRUE;
}
- return 0;
+ return FALSE;
}
-bool8 DoWildEncounterRateDiceRoll(u16 a)
+static bool8 DoWildEncounterRateDiceRoll(u16 encounterRate)
{
- if(Random() % 2880 < a)
+ if (Random() % 2880 < encounterRate)
return TRUE;
else
return FALSE;
}
-bool8 DoWildEncounterTest(u32 encounterRate, u8 b)
+static bool8 DoWildEncounterTest(u32 encounterRate, bool8 ignoreAbility)
{
encounterRate *= 16;
-
- if(TestPlayerAvatarFlags(6))
- {
+ if (TestPlayerAvatarFlags(6))
encounterRate = encounterRate * 80 / 100;
- }
- //_0808507E
ApplyFluteEncounterRateMod(&encounterRate);
ApplyCleanseTagEncounterRateMod(&encounterRate);
-
- if(b == 0)
+ if (!ignoreAbility)
{
// UB: Too few arguments for function 'GetMonData'
- if(!GetMonData(&gPlayerParty[0], MON_DATA_SANITY_BIT3))
+ if (!GetMonData(&gPlayerParty[0], MON_DATA_SANITY_BIT3))
{
u32 ability = GetMonAbility(&gPlayerParty[0]);
- if(ability == 1)
+ if (ability == ABILITY_STENCH)
encounterRate /= 2;
- if(ability == 0x23)
+ if (ability == ABILITY_ILLUMINATE)
encounterRate *= 2;
}
}
- //_080850BA
- if(encounterRate > 2880)
+ if (encounterRate > 2880)
encounterRate = 2880;
return DoWildEncounterRateDiceRoll(encounterRate);
}
-bool8 DoGlobalWildEncounterDiceRoll(void)
+static bool8 DoGlobalWildEncounterDiceRoll(void)
{
- if(Random() % 100 >= 60)
+ if (Random() % 100 >= 60)
return FALSE;
else
return TRUE;
@@ -470,28 +430,29 @@ bool8 DoGlobalWildEncounterDiceRoll(void)
bool8 StandardWildEncounter(u16 a, u16 b)
{
- u16 unk;
+ u16 headerNum;
struct Roamer *roamer;
- if(gWildEncountersDisabled != TRUE)
+ if (sWildEncountersDisabled == TRUE)
+ return 0;
+ else
{
- unk = GetCurrentMapWildMonHeader();
-
- if(unk != 0xFFFF)
+ headerNum = GetCurrentMapWildMonHeader();
+ if (headerNum != 0xFFFF)
{
- if(MetatileBehavior_IsLandWildEncounter(a) == 1)
+ if (MetatileBehavior_IsLandWildEncounter(a) == TRUE)
{
- if(gWildMonHeaders[unk].landMonsInfo)
+ if (gWildMonHeaders[headerNum].landMonsInfo)
{
- if(b != a && !DoGlobalWildEncounterDiceRoll())
+ if (b != a && !DoGlobalWildEncounterDiceRoll())
return 0;
- if(DoWildEncounterTest(gWildMonHeaders[unk].landMonsInfo->encounterRate, 0) == TRUE)
+ if (DoWildEncounterTest(gWildMonHeaders[headerNum].landMonsInfo->encounterRate, 0) == TRUE)
{
- if(sub_81344CC() == TRUE)
+ if (sub_81344CC() == TRUE)
{
roamer = &gSaveBlock1.roamer;
- if(RepelCheck(roamer->level))
+ if (RepelCheck(roamer->level))
{
sub_8081A5C();
return 1;
@@ -499,12 +460,12 @@ bool8 StandardWildEncounter(u16 a, u16 b)
}
else
{
- if(DoMassOutbreakEncounterTest() == TRUE && SetUpMassOutbreakEncounter(1) == TRUE)
+ if (DoMassOutbreakEncounterTest() == TRUE && SetUpMassOutbreakEncounter(1) == TRUE)
{
- sub_8081A00();
+ CheckForSafariZoneAndProceed();
return 1;
}
- if (GenerateWildMon(gWildMonHeaders[unk].landMonsInfo, 0, 1) == 1)
+ if (GenerateWildMon(gWildMonHeaders[headerNum].landMonsInfo, 0, TRUE) == TRUE)
{
goto label;
}
@@ -512,37 +473,34 @@ bool8 StandardWildEncounter(u16 a, u16 b)
}
}
}
- else
+ else if (MetatileBehavior_IsWaterWildEncounter(a) == TRUE
+ || (TestPlayerAvatarFlags(8) && MetatileBehavior_IsBridge(a) == TRUE))
{
- //_080851D8
- if(MetatileBehavior_IsWaterWildEncounter(a) == TRUE || TestPlayerAvatarFlags(8) && MetatileBehavior_IsBridge(a) == TRUE)
+ if (gWildMonHeaders[headerNum].waterMonsInfo)
{
- if(gWildMonHeaders[unk].waterMonsInfo)
- {
- if(b != a && !DoGlobalWildEncounterDiceRoll())
- return 0;
+ if (b != a && !DoGlobalWildEncounterDiceRoll())
+ return 0;
- if(DoWildEncounterTest(gWildMonHeaders[unk].waterMonsInfo->encounterRate, 0) == TRUE)
+ if (DoWildEncounterTest(gWildMonHeaders[headerNum].waterMonsInfo->encounterRate, 0) == TRUE)
+ {
+ if (sub_81344CC() == TRUE)
{
- if(sub_81344CC() == TRUE)
+ roamer = &gSaveBlock1.roamer;
+ if (RepelCheck(roamer->level))
{
- roamer = &gSaveBlock1.roamer;
- if(RepelCheck(roamer->level))
- {
- sub_8081A5C();
- return 1;
- }
+ sub_8081A5C();
+ return 1;
}
- else
+ }
+ else
+ {
+ //_08085268
+ if (GenerateWildMon(gWildMonHeaders[headerNum].waterMonsInfo, 1, TRUE) == TRUE)
{
- //_08085268
- if(GenerateWildMon(gWildMonHeaders[unk].waterMonsInfo, 1, 1) == 1)
- {
- label:
- //_0808527A
- sub_8081A00();
- return 1;
- }
+ label:
+ //_0808527A
+ CheckForSafariZoneAndProceed();
+ return 1;
}
}
}
@@ -557,19 +515,19 @@ void RockSmashWildEncounter(void)
{
u16 headerNum = GetCurrentMapWildMonHeader();
- if(headerNum != 0xFFFF)
+ if (headerNum != 0xFFFF)
{
struct WildPokemonInfo *wildPokemonInfo = gWildMonHeaders[headerNum].rockSmashMonsInfo;
- if(wildPokemonInfo == NULL)
+ if (wildPokemonInfo == NULL)
{
gScriptResult = 0;
return;
}
- else if(DoWildEncounterTest(wildPokemonInfo->encounterRate, 1) == TRUE &&
- GenerateWildMon(wildPokemonInfo, 2, 1) == 1)
+ else if (DoWildEncounterTest(wildPokemonInfo->encounterRate, 1) == TRUE
+ && GenerateWildMon(wildPokemonInfo, 2, TRUE) == TRUE)
{
- sub_8081A00();
+ CheckForSafariZoneAndProceed();
gScriptResult = 1;
return;
}
@@ -578,7 +536,7 @@ void RockSmashWildEncounter(void)
return;
}
-u8 SweetScentWildEncounter(void)
+bool8 SweetScentWildEncounter(void)
{
s16 x;
s16 y;
@@ -586,75 +544,60 @@ u8 SweetScentWildEncounter(void)
struct WildPokemonInfo *wildPokemonInfo;
PlayerGetDestCoords(&x, &y);
- //headerNum = GetCurrentMapWildMonHeader();
- if((headerNum = GetCurrentMapWildMonHeader()) != 0xFFFF)
+ if ((headerNum = GetCurrentMapWildMonHeader()) != 0xFFFF)
{
- if(MetatileBehavior_IsLandWildEncounter(MapGridGetMetatileBehaviorAt(x, y)) == 1)
+ if (MetatileBehavior_IsLandWildEncounter(MapGridGetMetatileBehaviorAt(x, y)) == 1)
{
wildPokemonInfo = gWildMonHeaders[headerNum].landMonsInfo;
-
- if(wildPokemonInfo == NULL)
- return 0;
-
- if(sub_81344CC() == 1)
+ if (wildPokemonInfo == NULL)
+ return FALSE;
+ if (sub_81344CC() == TRUE)
{
- //_080853BC
sub_8081A5C();
- return 1;
+ return TRUE;
}
-
- if(DoMassOutbreakEncounterTest() == 1)
+ if (DoMassOutbreakEncounterTest() == TRUE)
SetUpMassOutbreakEncounter(0);
else
- //_08085374
- GenerateWildMon(wildPokemonInfo, 0, 0);
- //_080853D2
- sub_8081A00();
- return 1;
+ GenerateWildMon(wildPokemonInfo, 0, FALSE);
+ CheckForSafariZoneAndProceed();
+ return TRUE;
}
- //_08085380
- else
+ else if (MetatileBehavior_IsWaterWildEncounter(MapGridGetMetatileBehaviorAt(x, y)) == 1)
{
- if(MetatileBehavior_IsWaterWildEncounter(MapGridGetMetatileBehaviorAt(x, y)) == 1)
+ wildPokemonInfo = gWildMonHeaders[headerNum].waterMonsInfo;
+ if (wildPokemonInfo == NULL)
+ return FALSE;
+ if (sub_81344CC() == TRUE)
{
- wildPokemonInfo = gWildMonHeaders[headerNum].waterMonsInfo;
-
- if(wildPokemonInfo == NULL)
- return 0;
-
- if(sub_81344CC() == 1)
- {
- sub_8081A5C();
- return 1;
- }
- else
- //_080853C8
- GenerateWildMon(wildPokemonInfo, 1, 0);
- sub_8081A00();
- return 1;
+ sub_8081A5C();
+ return TRUE;
}
+ GenerateWildMon(wildPokemonInfo, 1, FALSE);
+ CheckForSafariZoneAndProceed();
+ return TRUE;
}
}
- return 0;
+ return FALSE;
}
-u8 GetFishingWildMonListHeader(void)
+bool8 GetFishingWildMonListHeader(void)
{
u16 headerNum = GetCurrentMapWildMonHeader();
- if(headerNum != 0xFFFF && gWildMonHeaders[headerNum].fishingMonsInfo != NULL)
- return 1;
+ if (headerNum != 0xFFFF && gWildMonHeaders[headerNum].fishingMonsInfo != NULL)
+ return TRUE;
else
- return 0;
+ return FALSE;
}
void FishingWildEncounter(u8 rod)
{
u16 species;
- if(CheckFeebas() == TRUE)
+ if (CheckFeebas() == TRUE)
{
- u8 level = RandomInRange(&gWildFeebasRoute119Data);
+ u8 level = ChooseWildMonLevel(&gWildFeebasRoute119Data);
species = gWildFeebasRoute119Data.species;
CreateWildMon(species, level);
@@ -667,7 +610,7 @@ void FishingWildEncounter(u8 rod)
}
sav12_xor_increment(12);
sub_80BEA50(species);
- sub_8081A00();
+ CheckForSafariZoneAndProceed();
}
u16 GetLocalWildMon(bool8 *isWaterMon)
@@ -678,34 +621,29 @@ u16 GetLocalWildMon(bool8 *isWaterMon)
*isWaterMon = FALSE;
headerNum = GetCurrentMapWildMonHeader();
- if(headerNum == 0xFFFF)
+ if (headerNum == 0xFFFF)
return 0;
-
landMonsInfo = gWildMonHeaders[headerNum].landMonsInfo;
waterMonsInfo = gWildMonHeaders[headerNum].waterMonsInfo;
-
- if (!landMonsInfo && !waterMonsInfo)
+ //Neither
+ if (landMonsInfo == NULL && waterMonsInfo == NULL)
return 0;
-
- if (landMonsInfo && !waterMonsInfo)
- {
- return landMonsInfo->wildPokemon[PickWildMon_Grass()].species;
- }
-
- if (!landMonsInfo && waterMonsInfo)
+ //Land Pokemon
+ if (landMonsInfo != NULL && waterMonsInfo == NULL)
+ return landMonsInfo->wildPokemon[ChooseWildMonIndex_Land()].species;
+ //Water Pokemon
+ if (landMonsInfo == NULL && waterMonsInfo != NULL)
{
*isWaterMon = TRUE;
- return waterMonsInfo->wildPokemon[PickWildMon_Water()].species;
+ return waterMonsInfo->wildPokemon[ChooseWildMonIndex_Water()].species;
}
-
+ //Either land or water Pokemon
if ((Random() % 100) < 80)
- {
- return landMonsInfo->wildPokemon[PickWildMon_Grass()].species;
- }
+ return landMonsInfo->wildPokemon[ChooseWildMonIndex_Land()].species;
else
{
*isWaterMon = TRUE;
- return waterMonsInfo->wildPokemon[PickWildMon_Water()].species;
+ return waterMonsInfo->wildPokemon[ChooseWildMonIndex_Water()].species;
}
}
@@ -713,25 +651,25 @@ u16 GetMirageIslandMon(void)
{
u16 headerNum = GetCurrentMapWildMonHeader();
- if(headerNum != 0xFFFF)
+ if (headerNum != 0xFFFF)
{
struct WildPokemonInfo *waterMonsInfo = gWildMonHeaders[headerNum].waterMonsInfo;
- if(waterMonsInfo)
- return waterMonsInfo->wildPokemon[PickWildMon_Water()].species;
+ if (waterMonsInfo)
+ return waterMonsInfo->wildPokemon[ChooseWildMonIndex_Water()].species;
}
return 0;
}
bool8 UpdateRepelCounter(void)
{
- u16 steps = VarGet(0x4021);
+ u16 steps = VarGet(VAR_REPEL_STEP_COUNT);
- if(steps != 0)
+ if (steps != 0)
{
steps--;
- VarSet(0x4021, steps);
- if(steps == 0)
+ VarSet(VAR_REPEL_STEP_COUNT, steps);
+ if (steps == 0)
{
ScriptContext1_SetupScript(Event_RepelWoreOff);
return TRUE;
@@ -741,20 +679,20 @@ bool8 UpdateRepelCounter(void)
}
//Returns FALSE if Repel prevents wild Pokemon at the specified level from appearing
-bool8 RepelCheck(bool8 level)
+static bool8 RepelCheck(u8 level)
{
u8 i;
- if(!VarGet(0x4021))
+ if (!VarGet(VAR_REPEL_STEP_COUNT))
return TRUE;
else
{
- for(i = 0; i < 6; i++)
+ for (i = 0; i < 6; i++)
{
// UB: Too few arguments for function 'GetMonData'
- if(GetMonData(&gPlayerParty[i], MON_DATA_HP) && !GetMonData(&gPlayerParty[i], MON_DATA_IS_EGG))
+ if (GetMonData(&gPlayerParty[i], MON_DATA_HP) && !GetMonData(&gPlayerParty[i], MON_DATA_IS_EGG))
{
- if(level < (u8)GetMonData(&gPlayerParty[i], MON_DATA_LEVEL))
+ if (level < (u8)GetMonData(&gPlayerParty[i], MON_DATA_LEVEL))
return FALSE;
else
return TRUE;
@@ -764,17 +702,17 @@ bool8 RepelCheck(bool8 level)
}
}
-void ApplyFluteEncounterRateMod(u32 *a1)
+static void ApplyFluteEncounterRateMod(u32 *encRate)
{
- if(FlagGet(0x84D) == 1)
- *a1 = *a1 + *a1 / 2;
- else if(FlagGet(0x84E) == 1)
- *a1 = *a1 / 2;
+ if (FlagGet(SYS_ENC_UP_ITEM) == TRUE)
+ *encRate += *encRate / 2;
+ else if (FlagGet(SYS_ENC_DOWN_ITEM) == TRUE)
+ *encRate = *encRate / 2;
}
-void ApplyCleanseTagEncounterRateMod(u32 *a1)
+static void ApplyCleanseTagEncounterRateMod(u32 *encRate)
{
// UB: Too few arguments for function 'GetMonData'
- if(GetMonData(&gPlayerParty[0], MON_DATA_HELD_ITEM) == 0xBE)
- *a1 = *a1 * 2 / 3;
+ if (GetMonData(&gPlayerParty[0], MON_DATA_HELD_ITEM) == 0xBE)
+ *encRate = *encRate * 2 / 3;
}