diff options
Diffstat (limited to 'src')
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); + } +} @@ -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; } |