diff options
author | golem galvanize <golemgalvanize@github.com> | 2018-04-25 00:28:57 -0400 |
---|---|---|
committer | golem galvanize <golemgalvanize@github.com> | 2018-04-25 00:28:57 -0400 |
commit | 6a401b53867de87165f625510624c4a296dba34b (patch) | |
tree | 1a03aba54ebed695fffe2c11a1eb26f2b975f960 /src | |
parent | 069a7e71fc8bd0886fe2d5c39bb96d8fee0d798b (diff) | |
parent | 867b496f2e5a525043c9fd82ccaaad9349c89fac (diff) |
Merge branch 'master' of https://github.com/pret/pokeemerald into decompile_pokedex
Diffstat (limited to 'src')
-rw-r--r-- | src/battle_anim.c | 22 | ||||
-rw-r--r-- | src/battle_anim_sound_tasks.c | 438 | ||||
-rw-r--r-- | src/bike.c | 3 | ||||
-rw-r--r-- | src/decoration.c | 20 | ||||
-rw-r--r-- | src/dewford_trend.c | 340 | ||||
-rw-r--r-- | src/field_camera.c | 491 | ||||
-rwxr-xr-x | src/item_use.c | 4 | ||||
-rw-r--r-- | src/mail.c | 6 | ||||
-rw-r--r-- | src/map_name_popup.c | 474 | ||||
-rw-r--r-- | src/map_obj_lock.c | 187 | ||||
-rw-r--r-- | src/mon_markings.c | 611 | ||||
-rw-r--r-- | src/naming_screen.c | 124 | ||||
-rw-r--r-- | src/option_menu.c | 19 | ||||
-rw-r--r-- | src/overworld.c | 27 | ||||
-rw-r--r-- | src/pokemon_icon.c | 304 | ||||
-rw-r--r-- | src/pokemon_summary_screen.c | 86 | ||||
-rw-r--r-- | src/rom6.c | 209 | ||||
-rw-r--r-- | src/rotating_gate.c | 1188 | ||||
-rw-r--r-- | src/script_movement.c | 233 | ||||
-rw-r--r-- | src/text_window.c | 40 |
20 files changed, 4595 insertions, 231 deletions
diff --git a/src/battle_anim.c b/src/battle_anim.c index 7a5197740..8071736e6 100644 --- a/src/battle_anim.c +++ b/src/battle_anim.c @@ -123,7 +123,7 @@ EWRAM_DATA static u8 sAnimBackgroundFadeState = 0; EWRAM_DATA static u16 sAnimMoveIndex = 0; // set but unused. EWRAM_DATA u8 gBattleAnimAttacker = 0; EWRAM_DATA u8 gBattleAnimTarget = 0; -EWRAM_DATA u16 gAnimSpeciesByBanks[MAX_BATTLERS_COUNT] = {0}; +EWRAM_DATA u16 gAnimBattlerSpecies[MAX_BATTLERS_COUNT] = {0}; EWRAM_DATA u8 gUnknown_02038440 = 0; // const rom data @@ -228,15 +228,15 @@ void LaunchBattleAnimation(const u8 *const animsTable[], u16 tableId, bool8 isMo for (i = 0; i < MAX_BATTLERS_COUNT; i++) { if (GetBattlerSide(i) != 0) - gAnimSpeciesByBanks[i] = GetMonData(&gEnemyParty[gBattlerPartyIndexes[i]], MON_DATA_SPECIES); + gAnimBattlerSpecies[i] = GetMonData(&gEnemyParty[gBattlerPartyIndexes[i]], MON_DATA_SPECIES); else - gAnimSpeciesByBanks[i] = GetMonData(&gPlayerParty[gBattlerPartyIndexes[i]], MON_DATA_SPECIES); + gAnimBattlerSpecies[i] = GetMonData(&gPlayerParty[gBattlerPartyIndexes[i]], MON_DATA_SPECIES); } } else { for (i = 0; i < 4; i++) - gAnimSpeciesByBanks[i] = gContestResources->field_18->field_0; + gAnimBattlerSpecies[i] = gContestResources->field_18->field_0; } if (!isMoveAnim) @@ -1318,16 +1318,16 @@ s8 BattleAnimAdjustPanning2(s8 pan) return pan; } -s16 sub_80A52EC(s16 a) +s16 KeepPanInRange(s16 panArg) { - s16 var = a; + s16 pan = panArg; - if (var > 63) - var = 63; - else if (var < -64) - var = -64; + if (pan > PAN_SIDE_OPPONENT) + pan = PAN_SIDE_OPPONENT; + else if (pan < PAN_SIDE_PLAYER) + pan = PAN_SIDE_PLAYER; - return var; + return pan; } s16 CalculatePanIncrement(s16 sourcePan, s16 targetPan, s16 incrementPan) diff --git a/src/battle_anim_sound_tasks.c b/src/battle_anim_sound_tasks.c new file mode 100644 index 000000000..e956fd44f --- /dev/null +++ b/src/battle_anim_sound_tasks.c @@ -0,0 +1,438 @@ +#include "global.h" +#include "battle.h" +#include "constants/battle_anim.h" +#include "constants/species.h" +#include "battle_anim.h" +#include "task.h" +#include "sound.h" +#include "contest.h" + +// this file's functions +static void sub_8158B98(u8 taskId); +static void sub_8158C04(u8 taskId); +static void sub_8158D08(u8 taskId); +static void sub_8158FF4(u8 taskId); +static void sub_815913C(u8 taskId); +static void sub_8159308(u8 taskId); + +// task start +void sub_8158B30(u8 taskId) +{ + s8 pan1, pan2, panIncrement; + + gTasks[taskId].data[0] = gBattleAnimArgs[0]; + gTasks[taskId].data[1] = gBattleAnimArgs[1]; + + pan1 = BattleAnimAdjustPanning(PAN_SIDE_PLAYER); + pan2 = BattleAnimAdjustPanning(PAN_SIDE_OPPONENT); + panIncrement = CalculatePanIncrement(pan1, pan2, 2); + + gTasks[taskId].data[2] = pan1; + gTasks[taskId].data[3] = pan2; + gTasks[taskId].data[4] = panIncrement; + gTasks[taskId].data[10] = 10; + + gTasks[taskId].func = sub_8158B98; +} + +static void sub_8158B98(u8 taskId) +{ + s16 pan = gTasks[taskId].data[2]; + s8 panIncrement = gTasks[taskId].data[4]; + if (++gTasks[taskId].data[11] == 111) + { + gTasks[taskId].data[10] = 5; + gTasks[taskId].data[11] = 0; + gTasks[taskId].func = sub_8158C04; + } + else + { + if (++gTasks[taskId].data[10] == 11) + { + gTasks[taskId].data[10] = 0; + PlaySE12WithPanning(gTasks[taskId].data[0], pan); + } + pan += panIncrement; + gTasks[taskId].data[2] = KeepPanInRange(pan); + } +} + +static void sub_8158C04(u8 taskId) +{ + if (++gTasks[taskId].data[10] == 6) + { + s8 pan; + + gTasks[taskId].data[10] = 0; + pan = BattleAnimAdjustPanning(PAN_SIDE_OPPONENT); + PlaySE12WithPanning(gTasks[taskId].data[1], pan); + if (++gTasks[taskId].data[11] == 2) + DestroyAnimSoundTask(taskId); + } +} +// task end + +// task start +void sub_8158C58(u8 taskId) +{ + u16 songId = gBattleAnimArgs[0]; + s8 targetPan = gBattleAnimArgs[2]; + s8 panIncrement = gBattleAnimArgs[3]; + u8 r10 = gBattleAnimArgs[4]; + u8 r7 = gBattleAnimArgs[5]; + u8 r9 = gBattleAnimArgs[6]; + s8 sourcePan = BattleAnimAdjustPanning(gBattleAnimArgs[1]); + + targetPan = BattleAnimAdjustPanning(targetPan); + panIncrement = CalculatePanIncrement(sourcePan, targetPan, panIncrement); + + gTasks[taskId].data[0] = songId; + gTasks[taskId].data[1] = sourcePan; + gTasks[taskId].data[2] = targetPan; + gTasks[taskId].data[3] = panIncrement; + gTasks[taskId].data[4] = r10; + gTasks[taskId].data[5] = r7; + gTasks[taskId].data[6] = r9; + gTasks[taskId].data[10] = 0; + gTasks[taskId].data[11] = sourcePan; + gTasks[taskId].data[12] = r9; + + gTasks[taskId].func = sub_8158D08; + sub_8158D08(taskId); +} + +static void sub_8158D08(u8 taskId) +{ + if (gTasks[taskId].data[12]++ == gTasks[taskId].data[6]) + { + gTasks[taskId].data[12] = 0; + PlaySE12WithPanning(gTasks[taskId].data[0], gTasks[taskId].data[11]); + if (--gTasks[taskId].data[4] == 0) + { + DestroyAnimSoundTask(taskId); + return; + } + } + + if (gTasks[taskId].data[10]++ == gTasks[taskId].data[5]) + { + gTasks[taskId].data[10] = 0; + gTasks[taskId].data[11] += gTasks[taskId].data[3]; + gTasks[taskId].data[11] = KeepPanInRange(gTasks[taskId].data[11]); + } +} +// task end + +// task start +void sub_8158D8C(u8 taskId) +{ + u16 species = 0; + s8 pan = BattleAnimAdjustPanning(PAN_SIDE_PLAYER); + if (IsContest()) + { + if (gBattleAnimArgs[0] == ANIM_ATTACKER) + species = gContestResources->field_18->field_0; + else + DestroyAnimVisualTask(taskId); // UB: function should return upon destroying task + } + else + { + u8 battlerId; + + // get wanted battler + if (gBattleAnimArgs[0] == ANIM_ATTACKER) + battlerId = gBattleAnimAttacker; + else if (gBattleAnimArgs[0] == ANIM_TARGET) + battlerId = gBattleAnimTarget; + else if (gBattleAnimArgs[0] == ANIM_ATK_PARTNER) + battlerId = BATTLE_PARTNER(gBattleAnimAttacker); + else + battlerId = BATTLE_PARTNER(gBattleAnimTarget); + + // check if battler is visible + if ((gBattleAnimArgs[0] == ANIM_TARGET || gBattleAnimArgs[0] == ANIM_DEF_PARTNER) && !IsBattlerSpriteVisible(battlerId)) + { + DestroyAnimVisualTask(taskId); + return; + } + + if (GetBattlerSide(battlerId) != B_SIDE_PLAYER) + species = GetMonData(&gEnemyParty[gBattlerPartyIndexes[battlerId]], MON_DATA_SPECIES); + else + species = GetMonData(&gPlayerParty[gBattlerPartyIndexes[battlerId]], MON_DATA_SPECIES); + } + + if (species != SPECIES_NONE) + PlayCry3(species, pan, 3); + + DestroyAnimVisualTask(taskId); +} +// task end + +// task start +void sub_8158E9C(u8 taskId) +{ + u16 species = 0; + s8 pan = BattleAnimAdjustPanning(PAN_SIDE_PLAYER); + if (IsContest()) + { + if (gBattleAnimArgs[0] == ANIM_ATTACKER) + species = gContestResources->field_18->field_0; + else + DestroyAnimVisualTask(taskId); // UB: function should return upon destroying task + } + else + { + u8 battlerId; + + // get wanted battler + if (gBattleAnimArgs[0] == ANIM_ATTACKER) + battlerId = gBattleAnimAttacker; + else if (gBattleAnimArgs[0] == ANIM_TARGET) + battlerId = gBattleAnimTarget; + else if (gBattleAnimArgs[0] == ANIM_ATK_PARTNER) + battlerId = BATTLE_PARTNER(gBattleAnimAttacker); + else + battlerId = BATTLE_PARTNER(gBattleAnimTarget); + + // check if battler is visible + if ((gBattleAnimArgs[0] == ANIM_TARGET || gBattleAnimArgs[0] == ANIM_DEF_PARTNER) && !IsBattlerSpriteVisible(battlerId)) + { + DestroyAnimVisualTask(taskId); + return; + } + + if (GetBattlerSide(battlerId) != B_SIDE_PLAYER) + species = GetMonData(&gEnemyParty[gBattlerPartyIndexes[battlerId]], MON_DATA_SPECIES); + else + species = GetMonData(&gPlayerParty[gBattlerPartyIndexes[battlerId]], MON_DATA_SPECIES); + } + + gTasks[taskId].data[0] = gBattleAnimArgs[1]; + gTasks[taskId].data[1] = species; + gTasks[taskId].data[2] = pan; + + if (species != SPECIES_NONE) + { + if (gBattleAnimArgs[1] == 0xFF) + PlayCry3(species, pan, 9); + else + PlayCry3(species, pan, 7); + + gTasks[taskId].func = sub_8158FF4; + } + else + { + DestroyAnimVisualTask(taskId); + } +} + +static void sub_8158FF4(u8 taskId) +{ + u16 species = gTasks[taskId].data[1]; + s8 pan = gTasks[taskId].data[2]; + + if (gTasks[taskId].data[9] < 2) + { + gTasks[taskId].data[9]++; + } + else + { + if (gTasks[taskId].data[0] == 0xFF) + { + if (!IsCryPlaying()) + { + PlayCry3(species, pan, 10); + DestroyAnimVisualTask(taskId); + } + } + else + { + if (!IsCryPlaying()) + { + PlayCry3(species, pan, 8); + DestroyAnimVisualTask(taskId); + } + } + } +} +// task end + +void sub_8159078(u8 taskId) +{ + if (gTasks[taskId].data[9] < 2) + { + gTasks[taskId].data[9]++; + } + else + { + if (!IsCryPlaying()) + DestroyAnimVisualTask(taskId); + } +} + +// task start +void sub_81590B8(u8 taskId) +{ + u16 species; + s8 pan; + + gTasks[taskId].data[10] = gBattleAnimArgs[0]; + pan = BattleAnimAdjustPanning(PAN_SIDE_PLAYER); + + if (IsContest()) + species = gContestResources->field_18->field_0; + else + species = gAnimBattlerSpecies[gBattleAnimAttacker]; + + gTasks[taskId].data[1] = species; + gTasks[taskId].data[2] = pan; + + if (species != SPECIES_NONE) + gTasks[taskId].func = sub_815913C; + else + DestroyAnimVisualTask(taskId); +} + +static void sub_815913C(u8 taskId) +{ + u16 species = gTasks[taskId].data[1]; + s8 pan = gTasks[taskId].data[2]; + + switch (gTasks[taskId].data[9]) + { + case 2: + PlayCry6(species, pan, 4); + gTasks[taskId].data[9]++; + break; + case 1: + case 3: + case 4: + gTasks[taskId].data[9]++; + break; + case 5: + if (IsCryPlaying()) + break; + case 0: + StopCryAndClearCrySongs(); + gTasks[taskId].data[9]++; + break; + default: + if (gTasks[taskId].data[10] == 0) + PlayCry6(species, pan, 6); + else + PlayCry3(species, pan, 6); + + DestroyAnimVisualTask(taskId); + break; + } +} +// task end + +void sub_8159210(u8 taskId) +{ + u16 songId = gBattleAnimArgs[0]; + s8 pan = BattleAnimAdjustPanning(gBattleAnimArgs[1]); + + PlaySE1WithPanning(songId, pan); + DestroyAnimVisualTask(taskId); +} + +void sub_8159244(u8 taskId) +{ + u16 songId = gBattleAnimArgs[0]; + s8 pan = BattleAnimAdjustPanning(gBattleAnimArgs[1]); + + PlaySE2WithPanning(songId, pan); + DestroyAnimVisualTask(taskId); +} + +void sub_8159278(u8 taskId) +{ + s8 targetPan = gBattleAnimArgs[1]; + s8 panIncrement = gBattleAnimArgs[2]; + u16 r9 = gBattleAnimArgs[3]; + s8 sourcePan = BattleAnimAdjustPanning(gBattleAnimArgs[0]); + + targetPan = BattleAnimAdjustPanning(targetPan); + panIncrement = CalculatePanIncrement(sourcePan, targetPan, panIncrement); + + gTasks[taskId].data[1] = sourcePan; + gTasks[taskId].data[2] = targetPan; + gTasks[taskId].data[3] = panIncrement; + gTasks[taskId].data[5] = r9; + gTasks[taskId].data[10] = 0; + gTasks[taskId].data[11] = sourcePan; + + gTasks[taskId].func = sub_8159308; + sub_8159308(taskId); +} + +#ifdef NONMATCHING +void sub_8159308(u8 taskId) +{ + s16 panIncrement = gTasks[taskId].data[3]; + + if (gTasks[taskId].data[10]++ == gTasks[taskId].data[5]) + { + gTasks[taskId].data[10] = 0; + + gTasks[taskId].data[11] += panIncrement; + gTasks[taskId].data[11] = KeepPanInRange(gTasks[taskId].data[11]); + } + + gUnknown_02038440 = gTasks[taskId].data[11]; + if (gTasks[taskId].data[11] == gTasks[taskId].data[2]) + DestroyAnimVisualTask(taskId); +} +#else +ASM_DIRECT +void sub_8159308(u8 taskId) +{ + asm_unified(" push {r4,r5,lr}\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + adds r5, r0, 0\n\ + ldr r1, =gTasks\n\ + lsls r0, r5, 2\n\ + adds r0, r5\n\ + lsls r0, 3\n\ + adds r4, r0, r1\n\ + ldrh r2, [r4, 0xE]\n\ + ldrh r0, [r4, 0x1C]\n\ + adds r1, r0, 0x1\n\ + strh r1, [r4, 0x1C]\n\ + lsls r0, 16\n\ + asrs r0, 16\n\ + movs r3, 0x12\n\ + ldrsh r1, [r4, r3]\n\ + cmp r0, r1\n\ + bne _08159342\n\ + movs r0, 0\n\ + strh r0, [r4, 0x1C]\n\ + ldrh r1, [r4, 0x1E]\n\ + adds r0, r2, r1\n\ + strh r0, [r4, 0x1E]\n\ + movs r2, 0x1E\n\ + ldrsh r0, [r4, r2]\n\ + bl KeepPanInRange\n\ + strh r0, [r4, 0x1E]\n\ +_08159342:\n\ + ldr r1, =gUnknown_02038440\n\ + ldrh r0, [r4, 0x1E]\n\ + strb r0, [r1]\n\ + movs r3, 0x1E\n\ + ldrsh r1, [r4, r3]\n\ + movs r2, 0xC\n\ + ldrsh r0, [r4, r2]\n\ + cmp r1, r0\n\ + bne _0815935A\n\ + adds r0, r5, 0\n\ + bl DestroyAnimVisualTask\n\ +_0815935A:\n\ + pop {r4,r5}\n\ + pop {r0}\n\ + bx r0\n\ + .pool"); +} +#endif diff --git a/src/bike.c b/src/bike.c index 64af7c711..782eceb8e 100644 --- a/src/bike.c +++ b/src/bike.c @@ -12,7 +12,6 @@ extern bool8 gBikeCyclingChallenge; extern u8 gBikeCollisions; -extern bool8 gUnknown_02037348; extern u8 sub_8093514(u8 direction); extern u8 sub_808B980(u8 direction); @@ -989,7 +988,7 @@ bool8 player_should_look_direction_be_enforced_upon_movement(void) void GetOnOffBike(u8 transitionFlags) { - gUnknown_02037348 = FALSE; + gUnusedBikeCameraAheadPanback = FALSE; if (gPlayerAvatar.flags & (PLAYER_AVATAR_FLAG_MACH_BIKE | PLAYER_AVATAR_FLAG_ACRO_BIKE)) { diff --git a/src/decoration.c b/src/decoration.c index a0855db69..f376c2115 100644 --- a/src/decoration.c +++ b/src/decoration.c @@ -1305,12 +1305,12 @@ void sub_8128060(u8 taskId) void ConfigureCameraObjectForPlacingDecoration(struct PlaceDecorationGraphicsDataBuffer *data, u8 decor) { - sDecor_CameraSpriteObjectIdx1 = gSprites[gUnknown_03005DD0.unk4].data[0]; - gUnknown_03005DD0.unk4 = gpu_pal_decompress_alloc_tag_and_upload(data, decor); - gSprites[gUnknown_03005DD0.unk4].oam.priority = 1; - gSprites[gUnknown_03005DD0.unk4].callback = sub_81292D0; - gSprites[gUnknown_03005DD0.unk4].pos1.x = gUnknown_085A7250[data->decoration->shape].x; - gSprites[gUnknown_03005DD0.unk4].pos1.y = gUnknown_085A7250[data->decoration->shape].y; + sDecor_CameraSpriteObjectIdx1 = gSprites[gUnknown_03005DD0.spriteId].data[0]; + gUnknown_03005DD0.spriteId = gpu_pal_decompress_alloc_tag_and_upload(data, decor); + gSprites[gUnknown_03005DD0.spriteId].oam.priority = 1; + gSprites[gUnknown_03005DD0.spriteId].callback = sub_81292D0; + gSprites[gUnknown_03005DD0.spriteId].pos1.x = gUnknown_085A7250[data->decoration->shape].x; + gSprites[gUnknown_03005DD0.spriteId].pos1.y = gUnknown_085A7250[data->decoration->shape].y; } void SetUpPlacingDecorationPlayerAvatar(u8 taskId, struct PlaceDecorationGraphicsDataBuffer *data) @@ -1332,7 +1332,7 @@ void SetUpPlacingDecorationPlayerAvatar(u8 taskId, struct PlaceDecorationGraphic } gSprites[sDecor_CameraSpriteObjectIdx2].oam.priority = 1; DestroySprite(&gSprites[sDecor_CameraSpriteObjectIdx1]); - sDecor_CameraSpriteObjectIdx1 = gUnknown_03005DD0.unk4; + sDecor_CameraSpriteObjectIdx1 = gUnknown_03005DD0.spriteId; } void sub_812826C(u8 taskId) @@ -2251,9 +2251,9 @@ bool8 sub_81299AC(u8 taskId) void SetUpPuttingAwayDecorationPlayerAvatar(void) { player_get_direction_lower_nybble(); - sDecor_CameraSpriteObjectIdx1 = gSprites[gUnknown_03005DD0.unk4].data[0]; + sDecor_CameraSpriteObjectIdx1 = gSprites[gUnknown_03005DD0.spriteId].data[0]; sub_812A39C(); - gUnknown_03005DD0.unk4 = CreateSprite(&gUnknown_085A7404, 0x78, 0x50, 0); + gUnknown_03005DD0.spriteId = CreateSprite(&gUnknown_085A7404, 0x78, 0x50, 0); if (gSaveBlock2Ptr->playerGender == MALE) { sDecor_CameraSpriteObjectIdx2 = AddPseudoFieldObject(0xC1, SpriteCallbackDummy, 0x88, 0x48, 0); @@ -2264,7 +2264,7 @@ void SetUpPuttingAwayDecorationPlayerAvatar(void) } gSprites[sDecor_CameraSpriteObjectIdx2].oam.priority = 1; DestroySprite(&gSprites[sDecor_CameraSpriteObjectIdx1]); - sDecor_CameraSpriteObjectIdx1 = gUnknown_03005DD0.unk4; + sDecor_CameraSpriteObjectIdx1 = gUnknown_03005DD0.spriteId; gSprites[sDecor_CameraSpriteObjectIdx1].oam.priority = 1; } diff --git a/src/dewford_trend.c b/src/dewford_trend.c new file mode 100644 index 000000000..3ceec6563 --- /dev/null +++ b/src/dewford_trend.c @@ -0,0 +1,340 @@ +#include "global.h" +#include "dewford_trend.h" +#include "easy_chat.h" +#include "constants/easy_chat.h" +#include "event_data.h" +#include "link.h" +#include "malloc.h" +#include "random.h" +#include "text.h" +#include "tv.h" + +// static functions +static void sub_8122804(struct EasyChatPair *s, u16 b, u8 c); +static bool8 sub_8122A58(struct EasyChatPair *a, struct EasyChatPair *b, u8 c); +static void sub_8122B28(struct EasyChatPair *s); +static bool8 SB1ContainsWords(u16 *a); +static bool8 IsEasyChatPairEqual(u16 *words1, u16 *words2); +static s16 GetEqualEasyChatPairIndex(struct EasyChatPair *s, struct EasyChatPair *a, u16 b); + +// text +void InitDewfordTrend(void) +{ + u16 i; + + for (i = 0; i < 5; i++) + { + gSaveBlock1Ptr->easyChatPairs[i].words[0] = sub_811EE38(EC_GROUP_CONDITIONS); + + if (Random() & 1) + gSaveBlock1Ptr->easyChatPairs[i].words[1] = sub_811EE38(EC_GROUP_LIFESTYLE); + else + gSaveBlock1Ptr->easyChatPairs[i].words[1] = sub_811EE38(EC_GROUP_HOBBIES); + + gSaveBlock1Ptr->easyChatPairs[i].unk1_6 = Random() & 1; + sub_8122B28(&(gSaveBlock1Ptr->easyChatPairs[i])); + } + sub_8122804(gSaveBlock1Ptr->easyChatPairs, 5, 0); +} + +void UpdateDewfordTrendPerDay(u16 a) +{ + u16 i; + + if (a != 0) + { + u32 sp0 = a * 5; + + for (i = 0; i < 5; i++) + { + u32 r4; + u32 r2 = sp0; + struct EasyChatPair *r5 = &(gSaveBlock1Ptr->easyChatPairs[i]); + + if (r5->unk1_6 == 0) + { + if (r5->unk0_0 >= (u16)r2) + { + r5->unk0_0 -= r2; + if (r5->unk0_0 == 0) + r5->unk1_6 = 1; + continue; + } + r2 -= r5->unk0_0; + r5->unk0_0 = 0; + r5->unk1_6 = 1; + } + r4 = r5->unk0_0 + r2; + if ((u16)r4 > r5->unk0_7) + { + u32 sp4 = r4 % r5->unk0_7; + r4 = r4 / r5->unk0_7; + + r5->unk1_6 = r4 ^ 1; + if (r5->unk1_6) + r5->unk0_0 = sp4; + else + r5->unk0_0 = r5->unk0_7 - sp4; + } + else + { + r5->unk0_0 = r4; + + if (r5->unk0_0 == r5->unk0_7) + r5->unk1_6 = 0; + } + } + sub_8122804(gSaveBlock1Ptr->easyChatPairs, 5, 0); + } +} + + +bool8 sub_81226D8(u16 *a) +{ + struct EasyChatPair s = {0}; + u16 i; + + if (!SB1ContainsWords(a)) + { + if (!FlagGet(FLAG_SYS_POPWORD_INPUT)) + { + FlagSet(FLAG_SYS_POPWORD_INPUT); + if (!FlagGet(FLAG_SYS_MIX_RECORD)) + { + gSaveBlock1Ptr->easyChatPairs[0].words[0] = a[0]; + gSaveBlock1Ptr->easyChatPairs[0].words[1] = a[1]; + return TRUE; + } + } + + s.words[0] = a[0]; + s.words[1] = a[1]; + s.unk1_6 = 1; + sub_8122B28(&s); + + for (i = 0; i < 5; i++) + { + if (sub_8122A58(&s, &(gSaveBlock1Ptr->easyChatPairs[i]), 0)) + { + u16 r3 = 4; + + while (r3 > i) + { + gSaveBlock1Ptr->easyChatPairs[r3] = gSaveBlock1Ptr->easyChatPairs[r3 - 1]; + r3--; + } + gSaveBlock1Ptr->easyChatPairs[i] = s; + if(i == 4) + sub_80EDC60(a); + return (i == 0); + } + } + gSaveBlock1Ptr->easyChatPairs[4] = s; + sub_80EDC60(a); + } + return FALSE; +} + + +static void sub_8122804(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_8122A58(&s[i], &s[h], c)) + { + struct EasyChatPair temp; + + temp = s[i]; + s[i] = s[h]; + s[h] = temp; + } + } + } +} + +void sub_812287C(void *a, u32 b, u8 unused) +{ + u16 i, j, r3, players; + struct EasyChatPair *buffer1, *buffer2, *src, *dst, *foo_of_buffer2; + + buffer1 = Alloc(0x100); + if(buffer1 != NULL) + { + buffer2 = Alloc(0x100); + if(buffer2 == NULL) + { + Free(buffer1); + } + else + { + players = GetLinkPlayerCount(); + for (i = 0; i < players; i++) + memcpy(&(buffer1[i * 5]), (u8 *)a + i * b, 40); + src = buffer1; + dst = buffer2; + r3 = 0; + for (i = 0; i < players; i++) + { + for (j = 0; j < 5; j++) + { + s16 foo = GetEqualEasyChatPairIndex(buffer2, src, r3); + if (foo < 0) + { + *(dst++) = *src; + r3++; + } + else + { + foo_of_buffer2 = (struct EasyChatPair *)((u32)buffer2 + (foo * 8)); //required to do this to reverse the order of register operands in add ASM statement + if (foo_of_buffer2->unk0_0 < src->unk0_0) + { + *foo_of_buffer2 = *src; + } + } + src++; + } + } + sub_8122804(buffer2, r3, 2); + src = buffer2; + dst = gSaveBlock1Ptr->easyChatPairs; + for (i = 0; i < 5; i++) + *(dst++) = *(src++); + Free(buffer1); + Free(buffer2); + } + } +} + +void BufferTrendyPhraseString(void) +{ + struct EasyChatPair *s = &gSaveBlock1Ptr->easyChatPairs[gSpecialVar_0x8004]; + + ConvertEasyChatWordsToString(gStringVar1, s->words, 2, 1); +} + +void TrendyPhraseIsOld(void) +{ + u16 result = 0; + + if (gSaveBlock1Ptr->easyChatPairs[0].unk0_0 - gSaveBlock1Ptr->easyChatPairs[1].unk0_0 < 2) + { + asm("":::"r2"); //Force the compiler to store address of gSaveBlock1 in r3 instead of r2 + if (!gSaveBlock1Ptr->easyChatPairs[0].unk1_6 && gSaveBlock1Ptr->easyChatPairs[1].unk1_6) + result = 1; + } + gSpecialVar_Result = result; +} + +void GetDewfordHallPaintingNameIndex(void) +{ + gSpecialVar_Result = (gSaveBlock1Ptr->easyChatPairs[0].words[0] + gSaveBlock1Ptr->easyChatPairs[0].words[1]) & 7; +} + +static bool8 sub_8122A58(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; +} + +static void sub_8122B28(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(); +} + +static bool8 SB1ContainsWords(u16 *a) +{ + u16 i; + + for (i = 0; i < 5; i++) + { + if (IsEasyChatPairEqual(a, gSaveBlock1Ptr->easyChatPairs[i].words) != 0) + return TRUE; + } + return FALSE; +} + +static bool8 IsEasyChatPairEqual(u16 *words1, u16 *words2) +{ + u16 i; + + for (i = 0; i < 2; i++) + { + if (*(words1++) != *(words2++)) + return FALSE; + } + return TRUE; +} + +static s16 GetEqualEasyChatPairIndex(struct EasyChatPair*s, struct EasyChatPair *a, u16 b) +{ + s16 i; + + for (i = 0; i < b; i++) + { + if (IsEasyChatPairEqual(a->words, s->words)) + return i; + s++; + } + return -1; +} diff --git a/src/field_camera.c b/src/field_camera.c index 17ced6aa5..f653e0bf1 100644 --- a/src/field_camera.c +++ b/src/field_camera.c @@ -1,9 +1,18 @@ - -// Includes #include "global.h" +#include "berry.h" +#include "bike.h" +#include "field_camera.h" +#include "field_player_avatar.h" +#include "fieldmap.h" +#include "field_map_obj.h" +#include "gpu_regs.h" +#include "menu.h" +#include "overworld.h" +#include "rotating_gate.h" +#include "sprite.h" +#include "text.h" // Static type declarations - struct FieldCameraUnknownStruct { u8 unk0; @@ -13,16 +22,474 @@ struct FieldCameraUnknownStruct bool8 unk4; }; -// Static RAM declarations +// static functions +static void RedrawMapSliceNorth(struct FieldCameraUnknownStruct *a, const struct MapData *mapData); +static void RedrawMapSliceSouth(struct FieldCameraUnknownStruct *a, const struct MapData *mapData); +static void RedrawMapSliceEast(struct FieldCameraUnknownStruct *a, const struct MapData *mapData); +static void RedrawMapSliceWest(struct FieldCameraUnknownStruct *a, const struct MapData *mapData); +static s32 MapPosToBgTilemapOffset(struct FieldCameraUnknownStruct *a, s32 x, s32 y); +static void DrawWholeMapViewInternal(int x, int y, const struct MapData *mapData); +static void DrawMetatileAt(const struct MapData *mapData, u16, int, int); +static void DrawMetatile(s32 a, u16 *b, u16 c); +static void CameraPanningCB_PanAhead(void); + +// IWRAM bss vars +static IWRAM_DATA struct FieldCameraUnknownStruct gUnknown_03000E20; +static IWRAM_DATA s16 gUnknown_03000E28; +static IWRAM_DATA s16 gUnknown_03000E2A; +static IWRAM_DATA u8 gUnknown_03000E2C; +static IWRAM_DATA void (*gUnknown_03000E30)(void); + +// text +static void move_tilemap_camera_to_upper_left_corner_(struct FieldCameraUnknownStruct *a) +{ + a->unk2 = 0; + a->unk3 = 0; + a->unk0 = 0; + a->unk1 = 0; + a->unk4 = TRUE; +} + +static void tilemap_move_something(struct FieldCameraUnknownStruct *a, u32 b, u32 c) +{ + a->unk2 += b; + a->unk2 %= 32; + a->unk3 += c; + a->unk3 %= 32; +} + +static void coords8_add(struct FieldCameraUnknownStruct *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_03000E20); +} + +void FieldUpdateBgTilemapScroll(void) +{ + u32 r4, r5; + r5 = gUnknown_03000E20.unk0 + gUnknown_03000E28; + r4 = gUnknown_03000E2A + gUnknown_03000E20.unk1 + 8; + + SetGpuReg(REG_OFFSET_BG1HOFS, r5); + SetGpuReg(REG_OFFSET_BG1VOFS, r4); + SetGpuReg(REG_OFFSET_BG2HOFS, r5); + SetGpuReg(REG_OFFSET_BG2VOFS, r4); + SetGpuReg(REG_OFFSET_BG3HOFS, r5); + SetGpuReg(REG_OFFSET_BG3VOFS, r4); +} + +void sub_8089C08(s16 *a, s16 *b) +{ + *a = gUnknown_03000E20.unk0 + gUnknown_03000E28; + *b = gUnknown_03000E20.unk1 + gUnknown_03000E2A + 8; +} + +void DrawWholeMapView(void) +{ + DrawWholeMapViewInternal(gSaveBlock1Ptr->pos.x, gSaveBlock1Ptr->pos.y, gMapHeader.mapData); + gUnknown_03000E20.unk4 = TRUE; +} + +static void DrawWholeMapViewInternal(int x, int y, const struct MapData *mapData) +{ + u8 i; + u8 j; + u32 r6; + u8 temp; + + for (i = 0; i < 32; i += 2) + { + temp = gUnknown_03000E20.unk3 + i; + if (temp >= 32) + temp -= 32; + r6 = temp * 32; + for (j = 0; j < 32; j += 2) + { + temp = gUnknown_03000E20.unk2 + j; + if (temp >= 32) + temp -= 32; + DrawMetatileAt(mapData, r6 + temp, x + j / 2, y + i / 2); + } + } +} + +static void RedrawMapSlicesForCameraUpdate(struct FieldCameraUnknownStruct *a, int x, int y) +{ + const 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 FieldCameraUnknownStruct *a, const 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, gSaveBlock1Ptr->pos.x + i / 2, gSaveBlock1Ptr->pos.y + 14); + } +} + +static void RedrawMapSliceSouth(struct FieldCameraUnknownStruct *a, const 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, gSaveBlock1Ptr->pos.x + i / 2, gSaveBlock1Ptr->pos.y); + } +} + +static void RedrawMapSliceEast(struct FieldCameraUnknownStruct *a, const 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, gSaveBlock1Ptr->pos.x, gSaveBlock1Ptr->pos.y + i / 2); + } +} + +static void RedrawMapSliceWest(struct FieldCameraUnknownStruct *a, const 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, gSaveBlock1Ptr->pos.x + 14, gSaveBlock1Ptr->pos.y + i / 2); + } +} + +void CurrentMapDrawMetatileAt(int a, int b) +{ + int offset = MapPosToBgTilemapOffset(&gUnknown_03000E20, a, b); + + if (offset >= 0) + { + DrawMetatileAt(gMapHeader.mapData, offset, a, b); + gUnknown_03000E20.unk4 = TRUE; + } +} + +void DrawDoorMetatileAt(int x, int y, u16 *arr) +{ + int offset = MapPosToBgTilemapOffset(&gUnknown_03000E20, x, y); + + if (offset >= 0) + { + DrawMetatile(1, arr, offset); + gUnknown_03000E20.unk4 = TRUE; + } +} + +static void DrawMetatileAt(const 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: + gBGTilemapBuffers3[c] = b[0]; + gBGTilemapBuffers3[c + 1] = b[1]; + gBGTilemapBuffers3[c + 0x20] = b[2]; + gBGTilemapBuffers3[c + 0x21] = b[3]; + + gBGTilemapBuffers1[c] = 0; + gBGTilemapBuffers1[c + 1] = 0; + gBGTilemapBuffers1[c + 0x20] = 0; + gBGTilemapBuffers1[c + 0x21] = 0; + + gBGTilemapBuffers2[c] = b[4]; + gBGTilemapBuffers2[c + 1] = b[5]; + gBGTilemapBuffers2[c + 0x20] = b[6]; + gBGTilemapBuffers2[c + 0x21] = b[7]; + break; + case 1: + gBGTilemapBuffers3[c] = b[0]; + gBGTilemapBuffers3[c + 1] = b[1]; + gBGTilemapBuffers3[c + 0x20] = b[2]; + gBGTilemapBuffers3[c + 0x21] = b[3]; + + gBGTilemapBuffers1[c] = b[4]; + gBGTilemapBuffers1[c + 1] = b[5]; + gBGTilemapBuffers1[c + 0x20] = b[6]; + gBGTilemapBuffers1[c + 0x21] = b[7]; + + gBGTilemapBuffers2[c] = 0; + gBGTilemapBuffers2[c + 1] = 0; + gBGTilemapBuffers2[c + 0x20] = 0; + gBGTilemapBuffers2[c + 0x21] = 0; + break; + case 0: + gBGTilemapBuffers3[c] = 0x3014; + gBGTilemapBuffers3[c + 1] = 0x3014; + gBGTilemapBuffers3[c + 0x20] = 0x3014; + gBGTilemapBuffers3[c + 0x21] = 0x3014; + + gBGTilemapBuffers1[c] = b[0]; + gBGTilemapBuffers1[c + 1] = b[1]; + gBGTilemapBuffers1[c + 0x20] = b[2]; + gBGTilemapBuffers1[c + 0x21] = b[3]; -IWRAM_DATA struct FieldCameraUnknownStruct gUnknown_03000E20; -IWRAM_DATA s16 gUnknown_03000E28; -IWRAM_DATA s16 gUnknown_03000E2A; -IWRAM_DATA u8 gUnknown_03000E2C; -IWRAM_DATA void (*gUnknown_03000E30)(void); + gBGTilemapBuffers2[c] = b[4]; + gBGTilemapBuffers2[c + 1] = b[5]; + gBGTilemapBuffers2[c + 0x20] = b[6]; + gBGTilemapBuffers2[c + 0x21] = b[7]; + break; + } + schedule_bg_copy_tilemap_to_vram(1); + schedule_bg_copy_tilemap_to_vram(2); + schedule_bg_copy_tilemap_to_vram(3); +} + +static s32 MapPosToBgTilemapOffset(struct FieldCameraUnknownStruct *a, s32 x, s32 y) +{ + x -= gSaveBlock1Ptr->pos.x; + x *= 2; + if (x >= 32 || x < 0) + return -1; + x = x + a->unk2; + if (x >= 32) + x -= 32; + + y = (y - gSaveBlock1Ptr->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 CameraObject *a) +{ + if (a->spriteId != 0) + { + a->unk8 = gSprites[a->spriteId].data[2]; + a->unkC = gSprites[a->spriteId].data[3]; + } +} + +void ResetCameraUpdateInfo(void) +{ + gUnknown_03005DD0.unk8 = 0; + gUnknown_03005DD0.unkC = 0; + gUnknown_03005DD0.x = 0; + gUnknown_03005DD0.y = 0; + gUnknown_03005DD0.spriteId = 0; + gUnknown_03005DD0.callback = NULL; +} + +u32 InitCameraUpdateCallback(u8 a) +{ + if (gUnknown_03005DD0.spriteId != 0) + DestroySprite(&gSprites[gUnknown_03005DD0.spriteId]); + gUnknown_03005DD0.spriteId = AddCameraObject(a); + gUnknown_03005DD0.callback = CameraUpdateCallback; + return 0; +} + +void CameraUpdate(void) +{ + int deltaX; + int deltaY; + int r0; + int r1; + int r7; + int r8; + + if (gUnknown_03005DD0.callback != NULL) + gUnknown_03005DD0.callback(&gUnknown_03005DD0); + r7 = gUnknown_03005DD0.unk8; + r8 = gUnknown_03005DD0.unkC; + deltaX = 0; + deltaY = 0; + r1 = gUnknown_03005DD0.x; + r0 = gUnknown_03005DD0.y; + + + 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_03005DD0.x += r7; + gUnknown_03005DD0.x = gUnknown_03005DD0.x - 16 * (gUnknown_03005DD0.x / 16); + gUnknown_03005DD0.y += r8; + gUnknown_03005DD0.y = gUnknown_03005DD0.y - 16 * (gUnknown_03005DD0.y / 16); + + if (deltaX != 0 || deltaY != 0) + { + CameraMove(deltaX, deltaY); + UpdateFieldObjectsForCameraUpdate(deltaX, deltaY); + RotatingGatePuzzleCameraUpdate(deltaX, deltaY); + ResetBerryTreeSparkleFlags(); + tilemap_move_something(&gUnknown_03000E20, deltaX * 2, deltaY * 2); + RedrawMapSlicesForCameraUpdate(&gUnknown_03000E20, deltaX * 2, deltaY * 2); + } + + coords8_add(&gUnknown_03000E20, r7, r8); + gUnknown_03005DEC -= r7; + gUnknown_03005DE8 -= r8; +} + +void camera_move_and_redraw(int a, int b) //unused +{ + CameraMove(a, b); + UpdateFieldObjectsForCameraUpdate(a, b); + DrawWholeMapView(); + gUnknown_03005DEC -= a * 16; + gUnknown_03005DE8 -= b * 16; +} + +void SetCameraPanningCallback(void (*a)(void)) +{ + gUnknown_03000E30 = a; +} + +void SetCameraPanning(s16 a, s16 b) +{ + gUnknown_03000E28 = a; + gUnknown_03000E2A = b + 32; +} + +void InstallCameraPanAheadCallback(void) +{ + gUnknown_03000E30 = CameraPanningCB_PanAhead; + gUnknown_03000E2C = 0; + gUnknown_03000E28 = 0; + gUnknown_03000E2A = 32; +} + +void UpdateCameraPanning(void) +{ + if (gUnknown_03000E30 != NULL) + gUnknown_03000E30(); + //Update sprite offset of overworld objects + gSpriteCoordOffsetX = gUnknown_03005DEC - gUnknown_03000E28; + gSpriteCoordOffsetY = gUnknown_03005DE8 - gUnknown_03000E2A - 8; +} + +static void CameraPanningCB_PanAhead(void) +{ + u8 var; -// Static ROM declarations + if (gUnusedBikeCameraAheadPanback == FALSE) + { + InstallCameraPanAheadCallback(); + } + else + { + // this code is never reached. + if (gPlayerAvatar.tileTransitionState == T_TILE_TRANSITION) + { + gUnknown_03000E2C ^= 1; + if (gUnknown_03000E2C == 0) + return; + } + else + { + gUnknown_03000E2C = 0; + } -// .rodata + var = player_get_direction_upper_nybble(); + if (var == 2) + { + if (gUnknown_03000E2A > -8) + gUnknown_03000E2A -= 2; + } + else if (var == 1) + { + if (gUnknown_03000E2A < 72) + gUnknown_03000E2A += 2; + } + else if (gUnknown_03000E2A < 32) + { + gUnknown_03000E2A += 2; + } + else if (gUnknown_03000E2A > 32) + { + gUnknown_03000E2A -= 2; + } + } +} -// .text diff --git a/src/item_use.c b/src/item_use.c index 3b6b286b7..80b33220e 100755 --- a/src/item_use.c +++ b/src/item_use.c @@ -912,7 +912,7 @@ void re_escape_rope(u8 taskId) DisplayItemMessageOnField(taskId, gStringVar4, task08_080A1C44); } -bool8 sub_80FE314(void) +bool8 CanUseEscapeRopeOnCurrMap(void) { if (gMapHeader.flags & 2) return TRUE; @@ -922,7 +922,7 @@ bool8 sub_80FE314(void) void ItemUseOutOfBattle_EscapeRope(u8 taskId) { - if (sub_80FE314() == TRUE) + if (CanUseEscapeRopeOnCurrMap() == TRUE) { gUnknown_0203A0F4 = re_escape_rope; SetUpItemUseOnFieldCallback(taskId); diff --git a/src/mail.c b/src/mail.c index ac263ac67..85ba86974 100644 --- a/src/mail.c +++ b/src/mail.c @@ -403,11 +403,11 @@ static bool8 MailReadBuildGraphics(void) switch (sMailRead->animsActive) { case 1: - sub_80D2F68(icon); + LoadMonIconPalette(icon); sMailRead->monIconSprite = sub_80D2D78(icon, SpriteCallbackDummy, 0x60, 0x80, 0, 0); break; case 2: - sub_80D2F68(icon); + LoadMonIconPalette(icon); sMailRead->monIconSprite = sub_80D2D78(icon, SpriteCallbackDummy, 0x28, 0x80, 0, 0); break; } @@ -540,7 +540,7 @@ static void CB2_ExitMailReadFreeVars(void) { case 1: case 2: - sub_80D2FF0(sub_80D2E84(sMailRead->mail->species)); + FreeMonIconPalette(sub_80D2E84(sMailRead->mail->species)); sub_80D2EF8(&gSprites[sMailRead->monIconSprite]); } memset(sMailRead, 0, sizeof(*sMailRead)); diff --git a/src/map_name_popup.c b/src/map_name_popup.c new file mode 100644 index 000000000..59b1622eb --- /dev/null +++ b/src/map_name_popup.c @@ -0,0 +1,474 @@ +#include "global.h" +#include "constants/region_map_sections.h" +#include "constants/weather.h" +#include "bg.h" +#include "event_data.h" +#include "gpu_regs.h" +#include "international_string_util.h" +#include "menu.h" +#include "map_name_popup.h" +#include "palette.h" +#include "region_map.h" +#include "rom_818CFC8.h" +#include "start_menu.h" +#include "string_util.h" +#include "task.h" +#include "text.h" + + +// enums +enum MapPopUp_Themes +{ + MAPPOPUP_THEME_WOOD, + MAPPOPUP_THEME_MARBLE, + MAPPOPUP_THEME_STONE, + MAPPOPUP_THEME_BRICK, + MAPPOPUP_THEME_UNDERWATER, + MAPPOPUP_THEME_STONE2, +}; + +// static functions +static void Task_MapNamePopUpWindow(u8 taskId); +static void ShowMapNamePopUpWindow(void); +static void LoadMapNamePopUpWindowBg(void); + +// EWRAM +static EWRAM_DATA u8 mapNamePopupTaskId = 0; + +// .rodata +static const u8 gMapPopUp_Table[][960] = +{ + INCBIN_U8("graphics/interface/map_popup/wood.4bpp"), + INCBIN_U8("graphics/interface/map_popup/marble.4bpp"), + INCBIN_U8("graphics/interface/map_popup/stone.4bpp"), + INCBIN_U8("graphics/interface/map_popup/brick.4bpp"), + INCBIN_U8("graphics/interface/map_popup/underwater.4bpp"), + INCBIN_U8("graphics/interface/map_popup/stone2.4bpp"), +}; + +static const u8 gMapPopUp_Outline_Table[][960] = +{ + INCBIN_U8("graphics/interface/map_popup/wood_outline.4bpp"), + INCBIN_U8("graphics/interface/map_popup/marble_outline.4bpp"), + INCBIN_U8("graphics/interface/map_popup/stone_outline.4bpp"), + INCBIN_U8("graphics/interface/map_popup/brick_outline.4bpp"), + INCBIN_U8("graphics/interface/map_popup/underwater_outline.4bpp"), + INCBIN_U8("graphics/interface/map_popup/stone2_outline.4bpp"), +}; + +static const u16 gMapPopUp_Palette_Table[][16] = +{ + INCBIN_U16("graphics/interface/map_popup/wood.gbapal"), + INCBIN_U16("graphics/interface/map_popup/marble_outline.gbapal"), + INCBIN_U16("graphics/interface/map_popup/stone_outline.gbapal"), + INCBIN_U16("graphics/interface/map_popup/brick_outline.gbapal"), + INCBIN_U16("graphics/interface/map_popup/underwater_outline.gbapal"), + INCBIN_U16("graphics/interface/map_popup/stone2_outline.gbapal"), +}; + +static const u16 gUnknown_0857F444[16] = INCBIN_U16("graphics/interface/map_popup/857F444.gbapal"); + +static const u8 gRegionMapSectionId_To_PopUpThemeIdMapping[] = +{ + MAPPOPUP_THEME_WOOD, MAPPOPUP_THEME_WOOD, MAPPOPUP_THEME_WOOD, MAPPOPUP_THEME_WOOD, + MAPPOPUP_THEME_WOOD, MAPPOPUP_THEME_WOOD, MAPPOPUP_THEME_WOOD, MAPPOPUP_THEME_BRICK, + MAPPOPUP_THEME_MARBLE, MAPPOPUP_THEME_MARBLE, MAPPOPUP_THEME_MARBLE, MAPPOPUP_THEME_BRICK, + MAPPOPUP_THEME_MARBLE, MAPPOPUP_THEME_BRICK, MAPPOPUP_THEME_MARBLE, MAPPOPUP_THEME_BRICK, + MAPPOPUP_THEME_WOOD, MAPPOPUP_THEME_WOOD, MAPPOPUP_THEME_WOOD, MAPPOPUP_THEME_WOOD, + MAPPOPUP_THEME_UNDERWATER, MAPPOPUP_THEME_UNDERWATER, MAPPOPUP_THEME_UNDERWATER, MAPPOPUP_THEME_UNDERWATER, + MAPPOPUP_THEME_UNDERWATER, MAPPOPUP_THEME_WOOD, MAPPOPUP_THEME_WOOD, MAPPOPUP_THEME_WOOD, + MAPPOPUP_THEME_WOOD, MAPPOPUP_THEME_WOOD, MAPPOPUP_THEME_WOOD, MAPPOPUP_THEME_WOOD, + MAPPOPUP_THEME_WOOD, MAPPOPUP_THEME_WOOD, MAPPOPUP_THEME_WOOD, MAPPOPUP_THEME_WOOD, + MAPPOPUP_THEME_WOOD, MAPPOPUP_THEME_UNDERWATER, MAPPOPUP_THEME_WOOD, MAPPOPUP_THEME_UNDERWATER, + MAPPOPUP_THEME_UNDERWATER, MAPPOPUP_THEME_UNDERWATER, MAPPOPUP_THEME_UNDERWATER, MAPPOPUP_THEME_UNDERWATER, + MAPPOPUP_THEME_UNDERWATER, MAPPOPUP_THEME_UNDERWATER, MAPPOPUP_THEME_UNDERWATER, MAPPOPUP_THEME_UNDERWATER, + MAPPOPUP_THEME_UNDERWATER, MAPPOPUP_THEME_UNDERWATER, MAPPOPUP_THEME_STONE2, MAPPOPUP_THEME_STONE2, + MAPPOPUP_THEME_STONE2, MAPPOPUP_THEME_STONE2, MAPPOPUP_THEME_STONE2, MAPPOPUP_THEME_STONE, + MAPPOPUP_THEME_STONE, MAPPOPUP_THEME_WOOD, MAPPOPUP_THEME_MARBLE, MAPPOPUP_THEME_WOOD, + MAPPOPUP_THEME_STONE, MAPPOPUP_THEME_WOOD, MAPPOPUP_THEME_MARBLE, MAPPOPUP_THEME_STONE, + MAPPOPUP_THEME_STONE, MAPPOPUP_THEME_STONE, MAPPOPUP_THEME_STONE, MAPPOPUP_THEME_STONE, + MAPPOPUP_THEME_STONE, MAPPOPUP_THEME_STONE2, MAPPOPUP_THEME_STONE, MAPPOPUP_THEME_WOOD, + MAPPOPUP_THEME_STONE, MAPPOPUP_THEME_WOOD, MAPPOPUP_THEME_STONE, MAPPOPUP_THEME_STONE, + MAPPOPUP_THEME_WOOD, MAPPOPUP_THEME_WOOD, MAPPOPUP_THEME_STONE, MAPPOPUP_THEME_STONE2, + MAPPOPUP_THEME_STONE, MAPPOPUP_THEME_STONE, MAPPOPUP_THEME_STONE, MAPPOPUP_THEME_STONE, + MAPPOPUP_THEME_WOOD, MAPPOPUP_THEME_STONE, MAPPOPUP_THEME_STONE, MAPPOPUP_THEME_MARBLE, + MAPPOPUP_THEME_STONE, MAPPOPUP_THEME_STONE, MAPPOPUP_THEME_STONE, MAPPOPUP_THEME_WOOD, + MAPPOPUP_THEME_WOOD, MAPPOPUP_THEME_STONE, MAPPOPUP_THEME_STONE, MAPPOPUP_THEME_STONE2, + MAPPOPUP_THEME_STONE, MAPPOPUP_THEME_STONE2, MAPPOPUP_THEME_STONE2, MAPPOPUP_THEME_STONE2, + MAPPOPUP_THEME_STONE, MAPPOPUP_THEME_STONE, MAPPOPUP_THEME_STONE, MAPPOPUP_THEME_MARBLE +}; + +static const u8 gText_PyramidFloor1[] = _("PYRAMID FLOOR 1"); +static const u8 gText_PyramidFloor2[] = _("PYRAMID FLOOR 2"); +static const u8 gText_PyramidFloor3[] = _("PYRAMID FLOOR 3"); +static const u8 gText_PyramidFloor4[] = _("PYRAMID FLOOR 4"); +static const u8 gText_PyramidFloor5[] = _("PYRAMID FLOOR 5"); +static const u8 gText_PyramidFloor6[] = _("PYRAMID FLOOR 6"); +static const u8 gText_PyramidFloor7[] = _("PYRAMID FLOOR 7"); +static const u8 gText_Pyramid[] = _("PYRAMID"); + +static const u8 * const gBattlePyramid_MapHeaderStrings[] = +{ + gText_PyramidFloor1, + gText_PyramidFloor2, + gText_PyramidFloor3, + gText_PyramidFloor4, + gText_PyramidFloor5, + gText_PyramidFloor6, + gText_PyramidFloor7, + gText_Pyramid, +}; + +// text +bool8 sub_80D47D4(void) +{ + HideStartMenu(); + ShowMapNamePopup(); + return 1; +} + +void ShowMapNamePopup(void) +{ + if (FlagGet(FLAG_SPECIAL_FLAG_0x4000) != TRUE) + { + if (!FuncIsActiveTask(Task_MapNamePopUpWindow)) + { + mapNamePopupTaskId = CreateTask(Task_MapNamePopUpWindow, 90); + SetGpuReg(REG_OFFSET_BG0VOFS, 40); + gTasks[mapNamePopupTaskId].data[0] = 6; + gTasks[mapNamePopupTaskId].data[2] = 40; + } + else + { + if (gTasks[mapNamePopupTaskId].data[0] != 2) + gTasks[mapNamePopupTaskId].data[0] = 2; + gTasks[mapNamePopupTaskId].data[3] = 1; + } + } +} + +static void Task_MapNamePopUpWindow(u8 taskId) +{ + struct Task *task = &gTasks[taskId]; + + switch (task->data[0]) + { + case 6: + task->data[4]++; + if (task->data[4] > 30) + { + task->data[0] = 0; + task->data[4] = 0; + ShowMapNamePopUpWindow(); + } + break; + case 0: + task->data[2] -= 2; + if (task->data[2] <= 0 ) + { + task->data[2] = 0; + task->data[0] = 1; + gTasks[mapNamePopupTaskId].data[1] = 0; + } + break; + case 1: + task->data[1]++; + if (task->data[1] > 120 ) + { + task->data[1] = 0; + task->data[0] = 2; + } + break; + case 2: + task->data[2] += 2; + if (task->data[2] > 39) + { + task->data[2] = 40; + if (task->data[3]) + { + task->data[0] = 6; + task->data[4] = 0; + task->data[3] = 0; + } + else + { + task->data[0] = 4; + return; + } + } + break; + case 4: + sub_819746C(GetMapNamePopUpWindowId(), TRUE); + task->data[0] = 5; + break; + case 5: + HideMapNamePopUpWindow(); + return; + } + SetGpuReg(REG_OFFSET_BG0VOFS, task->data[2]); +} + +void HideMapNamePopUpWindow(void) +{ + if (FuncIsActiveTask(Task_MapNamePopUpWindow)) + { + sub_819746C(GetMapNamePopUpWindowId(), TRUE); + RemoveMapNamePopUpWindow(); + SetGpuReg_ForcedBlank(REG_OFFSET_BG0VOFS, 0); + DestroyTask(mapNamePopupTaskId); + } +} + +static void ShowMapNamePopUpWindow(void) +{ + u8 mapDisplayHeader[24]; + u8 *withoutPrefixPtr; + u8 x; + const u8* mapDisplayHeaderSource; + + if(InBattlePyramid()) + { + if(gMapHeader.mapDataId == 0x17A) + { + withoutPrefixPtr = &(mapDisplayHeader[3]); + mapDisplayHeaderSource = gBattlePyramid_MapHeaderStrings[7]; + } + else + { + withoutPrefixPtr = &(mapDisplayHeader[3]); + mapDisplayHeaderSource = gBattlePyramid_MapHeaderStrings[gSaveBlock2Ptr->battlePyramidWildHeaderId]; + } + StringCopy(withoutPrefixPtr, mapDisplayHeaderSource); + } + else + { + withoutPrefixPtr = &(mapDisplayHeader[3]); + GetMapName(withoutPrefixPtr, gMapHeader.regionMapSectionId, 0); + } + AddMapNamePopUpWindow(); + LoadMapNamePopUpWindowBg(); + x = GetStringCenterAlignXOffset(7, withoutPrefixPtr, 80); + mapDisplayHeader[0] = EXT_CTRL_CODE_BEGIN; + mapDisplayHeader[1] = EXT_CTRL_CODE_HIGHLIGHT; + mapDisplayHeader[2] = TEXT_COLOR_TRANSPARENT; + PrintTextOnWindow(GetMapNamePopUpWindowId(), 7, mapDisplayHeader, x, 3, 0xFF, NULL); + CopyWindowToVram(GetMapNamePopUpWindowId(), 3); +} + +#ifdef NONMATCHING +static void sub_80D4A78(u8 bg, u8 x, u8 y, u8 deltaX, u8 deltaY, u8 unused) +{ + s32 i; + + for(i=0; i<=11; i++) + { + FillBgTilemapBufferRect(bg, 0x21D + i, x + i - 1, y - 1, 1, 1, 0xE); + } + FillBgTilemapBufferRect(bg, 0x229 + i, x - 1, y, 1, 1, 0xE); + FillBgTilemapBufferRect(bg, 0x22A + i, deltaX + x, y, 1, 1, 0xE); + FillBgTilemapBufferRect(bg, 0x22B + i, x - 1, y + 1 , 1, 1, 0xE); + FillBgTilemapBufferRect(bg, 0x22C + i, deltaX + x, y + 1, 1, 1, 0xE); + FillBgTilemapBufferRect(bg, 0x22D + i, x - 1, y + 2, 1, 1, 0xE); + FillBgTilemapBufferRect(bg, 0x22E + i, deltaX + x, y + 2, 1, 1, 0xE); + for(i=0; i<=11; i++) + { + FillBgTilemapBufferRect(bg, 0x22F + i, x + i - 1, y + deltaY, 1, 1, 0xE); + } +} +#else +ASM_DIRECT +static void sub_80D4A78(u8 bg, u8 x, u8 y, u8 deltaX, u8 deltaY, u8 unused) +{ + asm("\n\ + .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, 0x1C\n\ + ldr r4, [sp, 0x3C]\n\ + lsls r0, 24\n\ + lsrs r7, r0, 24\n\ + lsls r1, 24\n\ + lsrs r1, 24\n\ + mov r10, r1\n\ + lsls r2, 24\n\ + lsls r3, 24\n\ + lsrs r3, 24\n\ + str r3, [sp, 0x10]\n\ + lsls r4, 24\n\ + lsrs r4, 24\n\ + str r4, [sp, 0x14]\n\ + movs r5, 0\n\ + lsls r0, r1, 24\n\ + asrs r1, r0, 24\n\ + lsrs r3, r2, 24\n\ + str r3, [sp, 0xC]\n\ + movs r6, 0xFF\n\ + lsls r6, 24\n\ + adds r6, r2\n\ + mov r8, r6\n\ + str r0, [sp, 0x18]\n\ + subs r4, r1, 0x1\n\ + _080D4AB4:\n\ + ldr r0, =0x0000021d\n\ + adds r1, r5, r0\n\ + lsls r1, 16\n\ + lsrs r1, 16\n\ + lsls r2, r4, 24\n\ + lsrs r2, 24\n\ + movs r3, 0x1\n\ + str r3, [sp]\n\ + str r3, [sp, 0x4]\n\ + movs r6, 0xE\n\ + mov r9, r6\n\ + str r6, [sp, 0x8]\n\ + adds r0, r7, 0\n\ + mov r6, r8\n\ + lsrs r3, r6, 24\n\ + bl FillBgTilemapBufferRect\n\ + adds r4, 0x1\n\ + adds r5, 0x1\n\ + cmp r5, 0xB\n\ + ble _080D4AB4\n\ + ldr r1, =0x00000229\n\ + movs r0, 0x1\n\ + negs r0, r0\n\ + add r0, r10\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + mov r8, r0\n\ + movs r5, 0x1\n\ + str r5, [sp]\n\ + str r5, [sp, 0x4]\n\ + mov r2, r9\n\ + str r2, [sp, 0x8]\n\ + adds r0, r7, 0\n\ + mov r2, r8\n\ + ldr r3, [sp, 0xC]\n\ + bl FillBgTilemapBufferRect\n\ + ldr r1, =0x0000022a\n\ + ldr r6, [sp, 0x10]\n\ + add r6, r10\n\ + lsls r6, 24\n\ + lsrs r6, 24\n\ + str r5, [sp]\n\ + str r5, [sp, 0x4]\n\ + mov r3, r9\n\ + str r3, [sp, 0x8]\n\ + adds r0, r7, 0\n\ + adds r2, r6, 0\n\ + ldr r3, [sp, 0xC]\n\ + bl FillBgTilemapBufferRect\n\ + ldr r1, =0x0000022b\n\ + ldr r4, [sp, 0xC]\n\ + adds r4, 0x1\n\ + lsls r4, 24\n\ + lsrs r4, 24\n\ + str r5, [sp]\n\ + str r5, [sp, 0x4]\n\ + mov r0, r9\n\ + str r0, [sp, 0x8]\n\ + adds r0, r7, 0\n\ + mov r2, r8\n\ + adds r3, r4, 0\n\ + bl FillBgTilemapBufferRect\n\ + movs r1, 0x8B\n\ + lsls r1, 2\n\ + str r5, [sp]\n\ + str r5, [sp, 0x4]\n\ + mov r2, r9\n\ + str r2, [sp, 0x8]\n\ + adds r0, r7, 0\n\ + adds r2, r6, 0\n\ + adds r3, r4, 0\n\ + bl FillBgTilemapBufferRect\n\ + ldr r1, =0x0000022d\n\ + ldr r4, [sp, 0xC]\n\ + adds r4, 0x2\n\ + lsls r4, 24\n\ + lsrs r4, 24\n\ + str r5, [sp]\n\ + str r5, [sp, 0x4]\n\ + mov r3, r9\n\ + str r3, [sp, 0x8]\n\ + adds r0, r7, 0\n\ + mov r2, r8\n\ + adds r3, r4, 0\n\ + bl FillBgTilemapBufferRect\n\ + ldr r1, =0x0000022e\n\ + str r5, [sp]\n\ + str r5, [sp, 0x4]\n\ + mov r0, r9\n\ + str r0, [sp, 0x8]\n\ + adds r0, r7, 0\n\ + adds r2, r6, 0\n\ + adds r3, r4, 0\n\ + bl FillBgTilemapBufferRect\n\ + movs r5, 0\n\ + ldr r1, [sp, 0xC]\n\ + ldr r2, [sp, 0x14]\n\ + adds r0, r1, r2\n\ + lsls r4, r0, 24\n\ + movs r6, 0x1\n\ + _080D4B8A:\n\ + ldr r3, =0x0000022f\n\ + adds r1, r5, r3\n\ + lsls r1, 16\n\ + lsrs r1, 16\n\ + subs r0, r5, 0x1\n\ + ldr r3, [sp, 0x18]\n\ + asrs r2, r3, 24\n\ + adds r2, r0\n\ + lsls r2, 24\n\ + lsrs r2, 24\n\ + str r6, [sp]\n\ + str r6, [sp, 0x4]\n\ + movs r0, 0xE\n\ + str r0, [sp, 0x8]\n\ + adds r0, r7, 0\n\ + lsrs r3, r4, 24\n\ + bl FillBgTilemapBufferRect\n\ + adds r5, 0x1\n\ + cmp r5, 0xB\n\ + ble _080D4B8A\n\ + add sp, 0x1C\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\ + .pool\n\ + .syntax divided"); +} +#endif // NONMATCHING + +static void LoadMapNamePopUpWindowBg(void) +{ + u8 popupWindowId; + u16 regionMapSectionId; + u8 popUpThemeId; + + popupWindowId = GetMapNamePopUpWindowId(); + regionMapSectionId = gMapHeader.regionMapSectionId; + if(regionMapSectionId > MAPSEC_DYNAMIC) + { + if(regionMapSectionId > MAPSEC_SPECIAL_AREA) + regionMapSectionId -= (MAPSEC_SPECIAL_AREA - MAPSEC_DYNAMIC); + else + regionMapSectionId = 0; //discard kanto region sections + } + popUpThemeId = gRegionMapSectionId_To_PopUpThemeIdMapping[regionMapSectionId]; + + LoadBgTiles(GetWindowAttribute(popupWindowId, 0), &(gMapPopUp_Outline_Table[popUpThemeId][0]), 0x400, 0x21D); + CallWindowFunction(popupWindowId, sub_80D4A78); + PutWindowTilemap(popupWindowId); + if(gMapHeader.weather == WEATHER_BUBBLES) + LoadPalette(&gUnknown_0857F444, 0xE0, 0x20); + else + LoadPalette(&(gMapPopUp_Palette_Table[popUpThemeId][0]), 0xE0, 0x20); + BlitBitmapToWindow(popupWindowId, &(gMapPopUp_Table[popUpThemeId][0]), 0, 0, 80, 24); +} diff --git a/src/map_obj_lock.c b/src/map_obj_lock.c new file mode 100644 index 000000000..688d0594d --- /dev/null +++ b/src/map_obj_lock.c @@ -0,0 +1,187 @@ +#include "global.h" +#include "event_data.h" +#include "field_map_obj.h" +#include "field_map_obj_helpers.h" +#include "field_player_avatar.h" +#include "map_obj_lock.h" +#include "script_movement.h" +#include "task.h" +#include "trainer_see.h" + +bool8 walkrun_is_standing_still(void) +{ + if (gPlayerAvatar.tileTransitionState == T_TILE_TRANSITION) + return FALSE; + else + return TRUE; +} + +static void sub_80983A4(u8 taskId) +{ + if (walkrun_is_standing_still()) + { + sub_808B864(); + DestroyTask(taskId); + } +} + +bool8 sub_80983C4(void) +{ + if (FuncIsActiveTask(sub_80983A4)) + { + return FALSE; + } + else + { + sub_808BCF4(); + return TRUE; + } +} + + +void ScriptFreezeMapObjects(void) +{ + FreezeMapObjects(); + CreateTask(sub_80983A4, 80); +} + +static void sub_8098400(u8 taskId) +{ + struct Task *task = &gTasks[taskId]; + + if (!task->data[0] && walkrun_is_standing_still() == TRUE) + { + sub_808B864(); + task->data[0] = 1; + } + if (!task->data[1] && !gMapObjects[gSelectedMapObject].mapobj_bit_1) + { + FreezeMapObject(&gMapObjects[gSelectedMapObject]); + task->data[1] = 1; + } + if (task->data[0] && task->data[1]) + DestroyTask(taskId); +} + +bool8 sub_809847C(void) +{ + if (FuncIsActiveTask(sub_8098400)) + { + return FALSE; + } + else + { + sub_808BCF4(); + return TRUE; + } +} + +void LockSelectedMapObject(void) +{ + u8 taskId; + FreezeMapObjectsExceptOne(gSelectedMapObject); + taskId = CreateTask(sub_8098400, 80); + if (!gMapObjects[gSelectedMapObject].mapobj_bit_1) + { + FreezeMapObject(&gMapObjects[gSelectedMapObject]); + gTasks[taskId].data[1] = 1; + } +} + +void sub_80984F4(void) +{ + u8 objectId = GetFieldObjectIdByLocalIdAndMap(0xFF, 0, 0); + FieldObjectClearAnimIfSpecialAnimFinished(&gMapObjects[objectId]); + sub_80D338C(); + UnfreezeMapObjects(); +} + +void sub_8098524(void) +{ + u8 objectId; + + if (gMapObjects[gSelectedMapObject].active) + FieldObjectClearAnimIfSpecialAnimFinished(&gMapObjects[gSelectedMapObject]); + objectId = GetFieldObjectIdByLocalIdAndMap(0xFF, 0, 0); + FieldObjectClearAnimIfSpecialAnimFinished(&gMapObjects[objectId]); + sub_80D338C(); + UnfreezeMapObjects(); +} + +void sub_8098574(void) +{ + FieldObjectFaceOppositeDirection(&gMapObjects[gSelectedMapObject], gSpecialVar_Facing); +} + +void sub_809859C(void) +{ + FieldObjectClearAnimIfSpecialAnimActive(&gMapObjects[gSelectedMapObject]); +} + +static void sub_80985BC(u8 taskId) +{ + struct Task *task = &gTasks[taskId]; + u8 mapObjectId = task->data[2]; + + if (!task->data[0] && walkrun_is_standing_still() == TRUE) + { + sub_808B864(); + task->data[0] = 1; + } + if (!task->data[1] && !gMapObjects[mapObjectId].mapobj_bit_1) + { + FreezeMapObject(&gMapObjects[mapObjectId]); + task->data[1] = 1; + } + if (task->data[0] && task->data[1]) + DestroyTask(taskId); +} + +void sub_8098630(void) +{ + u8 trainerObjectId1, trainerObjectId2, taskId; + trainerObjectId1 = GetChosenApproachingTrainerMapObjectId(0); + if(gNoOfApproachingTrainers == 2) + { + trainerObjectId2 = GetChosenApproachingTrainerMapObjectId(1); + sub_8098074(trainerObjectId1, trainerObjectId2); + taskId = CreateTask(sub_80985BC, 80); + gTasks[taskId].data[2] = trainerObjectId1; + if(!gMapObjects[trainerObjectId1].mapobj_bit_1) + { + FreezeMapObject(&gMapObjects[trainerObjectId1]); + gTasks[taskId].data[1] = 1; + } + taskId = CreateTask(sub_80985BC, 81); + gTasks[taskId].data[2] = trainerObjectId2; + if(!gMapObjects[trainerObjectId2].mapobj_bit_1) + { + FreezeMapObject(&gMapObjects[trainerObjectId2]); + gTasks[taskId].data[1] = 1; + } + } + else + { + FreezeMapObjectsExceptOne(trainerObjectId1); + taskId = CreateTask(sub_80985BC, 80); + gTasks[taskId].data[2] = trainerObjectId1; + if(!gMapObjects[trainerObjectId1].mapobj_bit_1) + { + FreezeMapObject(&gMapObjects[trainerObjectId1]); + gTasks[taskId].data[1] = 1; + } + } +} + +bool8 sub_8098734(void) +{ + if (FuncIsActiveTask(sub_80985BC)) + { + return FALSE; + } + else + { + sub_808BCF4(); + return TRUE; + } +} diff --git a/src/mon_markings.c b/src/mon_markings.c new file mode 100644 index 000000000..147872ab6 --- /dev/null +++ b/src/mon_markings.c @@ -0,0 +1,611 @@ +#include "global.h" +#include "dma3.h" +#include "graphics.h" +#include "main.h" +#include "menu_indicators.h" +#include "mon_markings.h" +#include "constants/songs.h" +#include "sound.h" +#include "sprite.h" +#include "text_window.h" + +#define MENU_TEXT_SPRITE_X_OFFSET 32 + +// static functions +static void sub_811FC80(s16, s16, u16, u16); +static void TaskDummy7(struct Sprite *); +static void sub_811FF40(struct Sprite *); +static void sub_811FF7C(struct Sprite *); +static struct Sprite *sub_811FFD4(u16, u16, const u16 *, u16); + +// .rodata +static const u16 gUnknown_0859E65C[] = INCBIN_U16("graphics/misc/mon_markings.gbapal"); +static const u8 gUnknown_0859E67C[] = INCBIN_U8("graphics/misc/mon_markings.4bpp"); + +static const struct OamData gUnknown_0859EE7C = +{ + .y = 0, + .affineMode = 0, + .objMode = 0, + .mosaic = 0, + .bpp = 0, + .shape = 0, + .x = 0, + .matrixNum = 0, + .size = 3, + .tileNum = 0, + .priority = 0, + .paletteNum = 0, + .affineParam = 0, +}; + +static const struct OamData gUnknown_0859EE84 = +{ + .y = 0, + .affineMode = 0, + .objMode = 0, + .mosaic = 0, + .bpp = 0, + .shape = 0, + .x = 0, + .matrixNum = 0, + .size = 0, + .tileNum = 0, + .priority = 0, + .paletteNum = 0, + .affineParam = 0, +}; + +static const union AnimCmd gUnknown_0859EE8C[] = +{ + ANIMCMD_FRAME(0, 5), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_0859EE94[] = +{ + ANIMCMD_FRAME(1, 5), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_0859EE9C[] = +{ + ANIMCMD_FRAME(2, 5), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_0859EEA4[] = +{ + ANIMCMD_FRAME(3, 5), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_0859EEAC[] = +{ + ANIMCMD_FRAME(4, 5), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_0859EEB4[] = +{ + ANIMCMD_FRAME(5, 5), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_0859EEBC[] = +{ + ANIMCMD_FRAME(6, 5), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_0859EEC4[] = +{ + ANIMCMD_FRAME(7, 5), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_0859EECC[] = +{ + ANIMCMD_FRAME(8, 5), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_0859EED4[] = +{ + ANIMCMD_FRAME(9, 5), + ANIMCMD_END, +}; + +static const union AnimCmd *const gUnknown_0859EEDC[] = +{ + gUnknown_0859EE8C, + gUnknown_0859EE94, + gUnknown_0859EE9C, + gUnknown_0859EEA4, + gUnknown_0859EEAC, + gUnknown_0859EEB4, + gUnknown_0859EEBC, + gUnknown_0859EEC4, + gUnknown_0859EECC, + gUnknown_0859EED4, +}; + +static const union AnimCmd gUnknown_0859EF04[] = +{ + ANIMCMD_FRAME(0, 5), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_0859EF0C[] = +{ + ANIMCMD_FRAME(64, 5), + ANIMCMD_END, +}; + +static const union AnimCmd *const gUnknown_0859EF14[] = +{ + gUnknown_0859EF04, + gUnknown_0859EF0C, +}; + +static const struct OamData gUnknown_0859EF1C = +{ + .y = 0, + .affineMode = 0, + .objMode = 0, + .mosaic = 0, + .bpp = 0, + .shape = 1, + .x = 0, + .matrixNum = 0, + .size = 1, + .tileNum = 0, + .priority = 0, + .paletteNum = 0, + .affineParam = 0, +}; + +static const union AnimCmd gUnknown_0859EF24[] = +{ + ANIMCMD_FRAME(0, 5), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_0859EF2C[] = +{ + ANIMCMD_FRAME(4, 5), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_0859EF34[] = +{ + ANIMCMD_FRAME(8, 5), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_0859EF3C[] = +{ + ANIMCMD_FRAME(12, 5), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_0859EF44[] = +{ + ANIMCMD_FRAME(16, 5), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_0859EF4C[] = +{ + ANIMCMD_FRAME(20, 5), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_0859EF54[] = +{ + ANIMCMD_FRAME(24, 5), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_0859EF5C[] = +{ + ANIMCMD_FRAME(28, 5), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_0859EF64[] = +{ + ANIMCMD_FRAME(32, 5), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_0859EF6C[] = +{ + ANIMCMD_FRAME(36, 5), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_0859EF74[] = +{ + ANIMCMD_FRAME(40, 5), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_0859EF7C[] = +{ + ANIMCMD_FRAME(44, 5), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_0859EF84[] = +{ + ANIMCMD_FRAME(48, 5), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_0859EF8C[] = +{ + ANIMCMD_FRAME(52, 5), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_0859EF94[] = +{ + ANIMCMD_FRAME(56, 5), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_0859EF9C[] = +{ + ANIMCMD_FRAME(60, 5), + ANIMCMD_END, +}; + +static const union AnimCmd *const gUnknown_0859EFA4[] = +{ + gUnknown_0859EF24, + gUnknown_0859EF2C, + gUnknown_0859EF34, + gUnknown_0859EF3C, + gUnknown_0859EF44, + gUnknown_0859EF4C, + gUnknown_0859EF54, + gUnknown_0859EF5C, + gUnknown_0859EF64, + gUnknown_0859EF6C, + gUnknown_0859EF74, + gUnknown_0859EF7C, + gUnknown_0859EF84, + gUnknown_0859EF8C, + gUnknown_0859EF94, + gUnknown_0859EF9C, +}; + +static EWRAM_DATA struct PokemonMarkMenu *sMenu = NULL; + +void sub_811F90C(struct PokemonMarkMenu *ptr) +{ + sMenu = ptr; +} + +void sub_811F918(void) +{ + const struct TilesPal *frame = GetWindowFrameTilesPal(gSaveBlock2Ptr->optionsWindowFrameType); + sMenu->frameTiles = frame->tiles; + sMenu->framePalette = frame->pal; + sMenu->tileLoadState = 0; + CpuFill16(0, sMenu->menuWindowSpriteTiles, sizeof(sMenu->menuWindowSpriteTiles)); +} + +bool8 sub_811F960(void) +{ + u16 i; + u8 *dest = sMenu->menuWindowSpriteTiles + sMenu->tileLoadState * 0x100; + + switch (sMenu->tileLoadState) + { + case 0: + CpuFastCopy(sMenu->frameTiles, dest, TILE_SIZE_4BPP); + for (i = 0; i < 6; i++) + { + CpuFastCopy(sMenu->frameTiles + TILE_SIZE_4BPP, dest + TILE_SIZE_4BPP * (i + 1), TILE_SIZE_4BPP); + } + CpuFastCopy(sMenu->frameTiles + TILE_SIZE_4BPP * 2, dest + TILE_SIZE_4BPP * 7, TILE_SIZE_4BPP); + sMenu->tileLoadState++; + break; + default: + CpuFastCopy(sMenu->frameTiles + TILE_SIZE_4BPP * 3, dest, TILE_SIZE_4BPP); + for (i = 0; i < 6; i++) + { + CpuFastCopy(sMenu->frameTiles + TILE_SIZE_4BPP * 4, dest + TILE_SIZE_4BPP * (i + 1), TILE_SIZE_4BPP); + } + CpuFastCopy(sMenu->frameTiles + TILE_SIZE_4BPP * 5, dest + TILE_SIZE_4BPP * 7, TILE_SIZE_4BPP); + sMenu->tileLoadState++; + break; + case 13: + CpuFastCopy(sMenu->frameTiles + TILE_SIZE_4BPP * 6, dest, TILE_SIZE_4BPP); + for (i = 0; i < 6; i++) + { + CpuFastCopy(sMenu->frameTiles + TILE_SIZE_4BPP * 7, dest + TILE_SIZE_4BPP * (i + 1), TILE_SIZE_4BPP); + } + CpuFastCopy(sMenu->frameTiles + TILE_SIZE_4BPP * 8, dest + TILE_SIZE_4BPP * 7, TILE_SIZE_4BPP); + sMenu->tileLoadState++; + return FALSE; + case 14: + return FALSE; + } + + return TRUE; +} + +void sub_811FA90(void) +{ + sub_811F918(); + while (sub_811F960()); +} + +void sub_811FAA4(u8 markings, s16 x, s16 y) +{ + u16 i; + sMenu->cursorPos = 0; + sMenu->markings = markings; + for (i = 0; i < 4; i++) + sMenu->markingsArray[i] = (sMenu->markings >> i) & 1; + sub_811FC80(x, y, sMenu->baseTileTag, sMenu->basePaletteTag); +} + +void sub_811FAF8(void) +{ + u16 i; + + for (i = 0; i < 2; i++) + { + FreeSpriteTilesByTag(sMenu->baseTileTag + i); + FreeSpritePaletteByTag(sMenu->basePaletteTag + i); + } + for (i = 0; i < 2; i++) + { + if (!sMenu->menuWindowSprites[i]) + return; + DestroySprite(sMenu->menuWindowSprites[i]); + sMenu->menuWindowSprites[i] = NULL; + } + for (i = 0; i < 4; i++) + { + if (!sMenu->menuMarkingSprites[i]) + return; + DestroySprite(sMenu->menuMarkingSprites[i]); + sMenu->menuMarkingSprites[i] = NULL; + } + if (sMenu->unkSprite) + { + DestroySprite(sMenu->unkSprite); + sMenu->unkSprite = NULL; + } + if (sMenu->menuTextSprite) + { + DestroySprite(sMenu->menuTextSprite); + sMenu->menuTextSprite = NULL; + } +} + + +bool8 sub_811FBA4(void) +{ + u16 i; + + if (gMain.newKeys & DPAD_UP) + { + s8 pos; + PlaySE(SE_SELECT); + pos = --sMenu->cursorPos; + if (pos < 0) + sMenu->cursorPos = 5; + return TRUE; + } + + if (gMain.newKeys & DPAD_DOWN) + { + s8 pos; + PlaySE(SE_SELECT); + pos = ++sMenu->cursorPos; + if (pos > 5) + sMenu->cursorPos = 0; + return TRUE; + } + + if (gMain.newKeys & A_BUTTON) + { + PlaySE(SE_SELECT); + + switch (sMenu->cursorPos) + { + case 4: + sMenu->markings = 0; + for (i = 0; i < 4; i++) + sMenu->markings |= sMenu->markingsArray[i] << i; + return FALSE; + case 5: + return FALSE; + } + + sMenu->markingsArray[sMenu->cursorPos] = !sMenu->markingsArray[sMenu->cursorPos]; + return TRUE; + } + + if (gMain.newKeys & B_BUTTON) + { + PlaySE(SE_SELECT); + return FALSE; + } + + return TRUE; +} + +static void sub_811FC80(s16 x, s16 y, u16 baseTileTag, u16 basePaletteTag) +{ + u16 i; + u8 spriteId; + + struct SpriteSheet sheets[] = + { + { sMenu->menuWindowSpriteTiles, 0x1000, baseTileTag }, + { gPokenavConditionMarker_Gfx, 0x320, baseTileTag + 1 }, + { NULL, 0 } + }; + + struct SpritePalette palettes[] = + { + { sMenu->framePalette, basePaletteTag }, + { gPokenavConditionMarker_Pal, basePaletteTag + 1}, + { NULL, 0 } + }; + + struct SpriteTemplate sprTemplate = + { + baseTileTag, + basePaletteTag, + &gUnknown_0859EE7C, + gUnknown_0859EF14, + NULL, + gDummySpriteAffineAnimTable, + TaskDummy7, + }; + + LoadSpriteSheets(sheets); + LoadSpritePalettes(palettes); + + for (i = 0; i < 2; i++) + { + spriteId = CreateSprite(&sprTemplate, x + 32, y + 32, 1); + if (spriteId != 64) + { + sMenu->menuWindowSprites[i] = &gSprites[spriteId]; + StartSpriteAnim(&gSprites[spriteId], i); + } + else + { + sMenu->menuWindowSprites[i] = NULL; + return; + } + } + + sMenu->menuWindowSprites[1]->pos1.y = y + 96; + + sprTemplate.tileTag++; + sprTemplate.paletteTag++; + sprTemplate.anims = gUnknown_0859EEDC; + sprTemplate.callback = sub_811FF40; + sprTemplate.oam = &gUnknown_0859EE84; + + for (i = 0; i < 4; i++) + { + spriteId = CreateSprite(&sprTemplate, x + 32, y + 16 + 16 * i, 0); + if (spriteId != 64) + { + sMenu->menuMarkingSprites[i] = &gSprites[spriteId]; + gSprites[spriteId].data[0] = i; + } + else + { + sMenu->menuMarkingSprites[i] = NULL; + return; + } + } + + sprTemplate.callback = SpriteCallbackDummy; + + spriteId = CreateSprite(&sprTemplate, 0, 0, 0); + + if (spriteId != 64) + { + sMenu->menuTextSprite = &gSprites[spriteId]; + sMenu->menuTextSprite->oam.shape = ST_OAM_SQUARE; + sMenu->menuTextSprite->oam.size = 2; + StartSpriteAnim(sMenu->menuTextSprite, 9); + sMenu->menuTextSprite->pos1.x = x + MENU_TEXT_SPRITE_X_OFFSET; + sMenu->menuTextSprite->pos1.y = y + 80; + CalcCenterToCornerVec(sMenu->menuTextSprite, 1, 2, 0); + } + else + { + sMenu->menuTextSprite = NULL; + } + + sprTemplate.callback = sub_811FF7C; + spriteId = CreateSprite(&sprTemplate, x + 12, 0, 0); + if(spriteId != 64) + { + sMenu->unkSprite = &gSprites[spriteId]; + sMenu->unkSprite->data[0] = y + 16; + StartSpriteAnim(sMenu->unkSprite, 8); + } + else + { + sMenu->unkSprite = NULL; + } + +} + +static void TaskDummy7(struct Sprite *sprite) +{ +} + +static void sub_811FF40(struct Sprite *sprite) +{ + if (sMenu->markingsArray[sprite->data[0]]) + StartSpriteAnim(sprite, 2 * sprite->data[0] + 1); + else + StartSpriteAnim(sprite, 2 * sprite->data[0]); +} + +static void sub_811FF7C(struct Sprite *sprite) +{ + sprite->pos1.y = (16 * sMenu->cursorPos) + sprite->data[0]; +} + +struct Sprite *sub_811FF94(u16 tileTag, u16 paletteTag, const u16 *palette) +{ + if (!palette) + palette = gUnknown_0859E65C; + return sub_811FFD4(tileTag, paletteTag, palette, 16); +} + +struct Sprite *sub_811FFB4(u16 tileTag, u16 paletteTag, const u16 *palette) +{ + if (!palette) + palette = gUnknown_0859E65C; + return sub_811FFD4(tileTag, paletteTag, palette, 1); +} + +static struct Sprite *sub_811FFD4(u16 tileTag, u16 paletteTag, const u16 *palette, u16 size) +{ + u8 spriteId; + struct SpriteTemplate sprTemplate; + struct SpriteSheet sheet = { gUnknown_0859E67C, 0x80, tileTag }; + struct SpritePalette sprPalette = { palette, paletteTag }; + + sprTemplate.tileTag = tileTag; + sprTemplate.paletteTag = paletteTag; + sprTemplate.oam = &gUnknown_0859EF1C; + sprTemplate.anims = gUnknown_0859EFA4; + sprTemplate.images = NULL; + sprTemplate.affineAnims = gDummySpriteAffineAnimTable; + sprTemplate.callback = TaskDummy7; + + sheet.size = size * 0x80; + + LoadSpriteSheet(&sheet); + LoadSpritePalette(&sprPalette); + + spriteId = CreateSprite(&sprTemplate, 0, 0, 0); + if (spriteId != 64) + return &gSprites[spriteId]; + else + return NULL; +} + +void sub_8120084(u8 markings, void *dest) +{ + RequestDma3Copy(gUnknown_0859E67C + markings * 0x80, dest, 0x80, 0x10); +} diff --git a/src/naming_screen.c b/src/naming_screen.c index be306c765..0e350aa35 100644 --- a/src/naming_screen.c +++ b/src/naming_screen.c @@ -75,7 +75,7 @@ static const u8 gSpriteImage_858BCB8[] = INCBIN_U8("graphics/naming_screen/pc_ic static const u16 gUnknown_0858BD78[] = INCBIN_U16("graphics/naming_screen/0.gbapal"); static const u16 gUnknown_0858BD98[] = INCBIN_U16("graphics/naming_screen/1.gbapal"); -static const u8 *const gUnknown_0858BDB8[] = +static const u8 *const gUnknown_0858BDB8[] = { gText_PkmnTransferredSomeonesPC, gText_PkmnTransferredLanettesPC, @@ -85,7 +85,7 @@ static const u8 *const gUnknown_0858BDB8[] = static const u8 gUnknown_0858BDC8[] = _("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz!"); -static const struct BgTemplate gUnknown_0858BE00[] = +static const struct BgTemplate gUnknown_0858BE00[] = { { .bg = 0, @@ -226,10 +226,10 @@ void DoNamingScreen(u8 templateNum, u8 *destBuffer, u16 monSpecies, u16 monGende gNamingScreenData->monPersonality = monPersonality; gNamingScreenData->destBuffer = destBuffer; gNamingScreenData->returnCallback = returnCallback; - + if (templateNum == 0) StartTimer1(); - + SetMainCallback2(C2_NamingScreen); } } @@ -316,15 +316,15 @@ static void sub_80E2FA4(void) static void NamingScreen_InitBGs(void) { u8 i; - + DmaClearLarge16(3, (void *)VRAM, VRAM_SIZE, 0x1000); DmaClear32(3, (void *)OAM, OAM_SIZE); DmaClear16(3, (void *)PLTT, PLTT_SIZE); - + SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_MODE_0); ResetBgsAndClearDma3BusyFlags(0); InitBgsFromTemplates(0, gUnknown_0858BE00, 4); - + ChangeBgX(0, 0, 0); ChangeBgY(0, 0, 0); ChangeBgX(1, 0, 0); @@ -333,21 +333,21 @@ static void NamingScreen_InitBGs(void) ChangeBgY(2, 0, 0); ChangeBgX(3, 0, 0); ChangeBgY(3, 0, 0); - + sub_81971D0(); sub_8197200(); - + for (i = 0; i < 5; i++) gNamingScreenData->windows[i] = AddWindow(&gUnknown_0858BE10[i]); - + SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_OBJ_1D_MAP | DISPCNT_OBJ_ON); SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_EFFECT_BLEND | BLDCNT_TGT2_BG1 | BLDCNT_TGT2_BG2); SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(0xC, 0x8)); - + SetBgTilemapBuffer(1, gNamingScreenData->tilemapBuffer1); SetBgTilemapBuffer(2, gNamingScreenData->tilemapBuffer2); SetBgTilemapBuffer(3, gNamingScreenData->tilemapBuffer3); - + FillBgTilemapBufferRect_Palette0(1, 0, 0, 0, 0x20, 0x20); FillBgTilemapBufferRect_Palette0(2, 0, 0, 0, 0x20, 0x20); FillBgTilemapBufferRect_Palette0(3, 0, 0, 0, 0x20, 0x20); @@ -511,7 +511,7 @@ static bool8 MainState_WaitFadeOutAndExit(void) static void DisplaySentToPCMessage(void) { u8 stringToDisplay = 0; - + if (!sub_813B260()) { StringCopy(gStringVar1, GetBoxNamePtr(VarGet(VAR_STORAGE_UNKNOWN))); @@ -524,10 +524,10 @@ static void DisplaySentToPCMessage(void) StringCopy(gStringVar3, GetBoxNamePtr(get_unknown_box_id())); stringToDisplay = 2; } - + if (FlagGet(FLAG_SYS_PC_LANETTE)) stringToDisplay++; - + StringExpandPlaceholders(gStringVar4, gUnknown_0858BDB8[stringToDisplay]); NewMenuHelpers_DrawDialogueFrame(0, 0); gTextFlags.flag_0 = TRUE; @@ -538,10 +538,10 @@ static void DisplaySentToPCMessage(void) static bool8 sub_80E3604(void) { RunTextPrinters(); - + if (!IsTextPrinterActive(0) && (gMain.newKeys & A_BUTTON)) gNamingScreenData->state = MAIN_STATE_BEGIN_FADE_OUT; - + return FALSE; } @@ -562,17 +562,17 @@ static bool8 MainState_WaitPageSwap(void) s16 cursorX; s16 cursorY; bool32 var3; - + if (IsPageSwapAnimNotInProgress()) { - + GetCursorPos(&cursorX, &cursorY); var3 = (cursorX == GetCurrentPageColumnCount()); - + gNamingScreenData->state = MAIN_STATE_HANDLE_INPUT; gNamingScreenData->currentPage++; gNamingScreenData->currentPage %= 3; - + if (var3) { cursorX = GetCurrentPageColumnCount(); @@ -582,7 +582,7 @@ static bool8 MainState_WaitPageSwap(void) if (cursorX >= GetCurrentPageColumnCount()) cursorX = GetCurrentPageColumnCount() - 1; } - + SetCursorPos(cursorX, cursorY); sub_80E4E5C(); SetInputState(INPUT_STATE_ENABLED); @@ -603,7 +603,7 @@ static bool8 PageSwapAnimState_1(struct Task *); static bool8 PageSwapAnimState_2(struct Task *); static bool8 PageSwapAnimState_Done(struct Task *); -static bool8 (*const sPageSwapAnimStateFuncs[])(struct Task *) = +static bool8 (*const sPageSwapAnimStateFuncs[])(struct Task *) = { PageSwapAnimState_Init, PageSwapAnimState_1, @@ -754,7 +754,7 @@ static void Task_80E39BC(u8 taskId) task->data[3] += task->data[4]; task->data[6] += task->data[4]; } - + if (task->data[3] == 16 && task->data[6] == 22) { task->data[4] = -4; @@ -893,7 +893,7 @@ static void CursorInit(void) static void SetCursorPos(s16 x, s16 y) { struct Sprite *cursorSprite = &gSprites[gNamingScreenData->cursorSpriteId]; - + if (x < gUnknown_0858BEA0[sub_80E3274()]) cursorSprite->pos1.x = gUnknown_0858BEA3[x + sub_80E3274() * 8] + 38; else @@ -909,7 +909,7 @@ static void SetCursorPos(s16 x, s16 y) static void GetCursorPos(s16 *x, s16 *y) { struct Sprite *cursorSprite = &gSprites[gNamingScreenData->cursorSpriteId]; - + *x = cursorSprite->data[0]; *y = cursorSprite->data[1]; } @@ -1133,7 +1133,7 @@ static void CreateInputTargetIcon(void) static void TaskDummy2(void) { - + } static void NamingScreen_CreatePlayerIcon(void) @@ -1160,7 +1160,7 @@ static void NamingScreen_CreateMonIcon(void) { u8 spriteId; - sub_80D2F04(); + LoadMonIconPalettes(); spriteId = CreateMonIcon(gNamingScreenData->monSpecies, SpriteCallbackDummy, 0x38, 0x28, 0, gNamingScreenData->monPersonality, 1); gSprites[spriteId].oam.priority = 3; } @@ -1331,7 +1331,7 @@ static void InputState_Disabled(struct Task *task) static void InputState_Enabled(struct Task *task) { task->tKeyboardEvent = 0; - + if (gMain.newKeys & A_BUTTON) task->tKeyboardEvent = KBEVENT_PRESSED_A; else if (gMain.newKeys & B_BUTTON) @@ -1454,7 +1454,7 @@ static void sub_80E4894(void) static void sub_80E48E8(void) { u8 buffer[0x20]; - + StringCopy(buffer, gSpeciesNames[gNamingScreenData->monSpecies]); StringAppendN(buffer, gNamingScreenData->template->title, 15); FillWindowPixelBuffer(gNamingScreenData->windows[3], 0x11); @@ -1492,10 +1492,10 @@ static void sub_80E498C(void) static void TaskDummy3(void) { - + } -static const u8 sGenderColors[2][3] = +static const u8 sGenderColors[2][3] = { {0, 9, 8}, {0, 5, 4} @@ -1505,7 +1505,7 @@ static void sub_80E49BC(void) { u8 genderSymbol[2]; bool8 isFemale = FALSE; - + StringCopy(genderSymbol, gText_MaleSymbol); if (gNamingScreenData->monGender != MON_GENDERLESS) @@ -1575,7 +1575,7 @@ static bool8 sub_80E4B54(void) sub_80E4D10(); CopyBgTilemapBufferToVram(3); PlaySE(SE_SELECT); - + if (GetPreviousTextCaretPosition() != gNamingScreenData->template->maxChars - 1) return FALSE; else @@ -1633,7 +1633,7 @@ static void sub_80E4CF8(u8 bg, const void *src) static void nullsub_10(u8 a1, u8 a2) { - + } static void sub_80E4D10(void) @@ -1643,18 +1643,18 @@ static void sub_80E4D10(void) u16 unk2; u8 maxChars = gNamingScreenData->template->maxChars; u16 unk = gNamingScreenData->inputCharBaseXPos - 0x40; - + FillWindowPixelBuffer(gNamingScreenData->windows[2], 0x11); - + for (i = 0; i < maxChars; i++) { temp[0] = gNamingScreenData->textBuffer[i]; temp[1] = gExpandedPlaceholder_Empty[0]; unk2 = (sub_80E503C(temp[0]) == 1) ? 2 : 0; - + PrintTextOnWindow(gNamingScreenData->windows[2], 1, temp, i * 8 + unk + unk2, 1, 0xFF, NULL); } - + sub_80E498C(); CopyWindowToVram(gNamingScreenData->windows[2], 2); PutWindowTilemap(gNamingScreenData->windows[2]); @@ -1674,12 +1674,12 @@ static const struct TextColorThing sUnkColorStruct = } }; -static const u8 sFillValues[3] = +static const u8 sFillValues[3] = { 0xEE, 0xDD, 0xFF }; -static const u8 *const sUnkColors[3] = +static const u8 *const sUnkColors[3] = { sUnkColorStruct.colors[1], sUnkColorStruct.colors[0], @@ -1689,18 +1689,18 @@ static const u8 *const sUnkColors[3] = static void sub_80E4DE4(u8 window, u8 a1) { u8 i; - + FillWindowPixelBuffer(window, sFillValues[a1]); - + for (i = 0; i < 4; i++) { box_print(window, 1, 0, i * 16 + 1, sUnkColors[a1], 0, gUnknown_0858C198[a1][i]); } - + PutWindowTilemap(window); } -static const u8 *const gUnknown_0858BF98[] = +static const u8 *const gUnknown_0858BF98[] = { gUnknown_08DD4620, gUnknown_08DD46E0, @@ -1714,7 +1714,7 @@ static void sub_80E4E5C(void) u8 unk3; u8 bg1Priority = GetGpuReg(REG_OFFSET_BG1CNT) & 3; u8 bg2Priority = GetGpuReg(REG_OFFSET_BG2CNT) & 3; - + if (bg1Priority > bg2Priority) { unk1 = 1; @@ -1727,7 +1727,7 @@ static void sub_80E4E5C(void) unk2 = 2; unk3 = gNamingScreenData->windows[1]; } - + sub_80E4CF8(unk1, gUnknown_0858BF98[gNamingScreenData->currentPage]); sub_80E4DE4(unk3, sub_80E3254()); nullsub_10(unk1, sub_80E3254()); @@ -1737,7 +1737,7 @@ static void sub_80E4E5C(void) static void sub_80E4EF0(void) { const u8 color[3] = { 15, 1, 2 }; - + FillWindowPixelBuffer(gNamingScreenData->windows[4], 0xFF); box_print(gNamingScreenData->windows[4], 0, 2, 1, color, 0, gText_MoveOkBack); PutWindowTilemap(gNamingScreenData->windows[4]); @@ -1787,7 +1787,7 @@ static void sub_80E501C(void) static bool8 sub_80E503C(u8 character) { u8 i; - + for (i = 0; gUnknown_0858BDC8[i] != EOS; i++) { if (character == gUnknown_0858BDC8[i]) @@ -1987,20 +1987,20 @@ static const struct SpriteFrameImage gUnknown_0858C080[] = {gSpriteImage_858BCB8, sizeof(gSpriteImage_858BCB8)}, }; -static const union AnimCmd gSpriteAnim_858C090[] = +static const union AnimCmd gSpriteAnim_858C090[] = { ANIMCMD_FRAME(0, 1), ANIMCMD_JUMP(0) }; -static const union AnimCmd gSpriteAnim_858C098[] = +static const union AnimCmd gSpriteAnim_858C098[] = { ANIMCMD_FRAME(4, 8), ANIMCMD_FRAME(8, 8), ANIMCMD_END }; -static const union AnimCmd gSpriteAnim_858C0A4[] = +static const union AnimCmd gSpriteAnim_858C0A4[] = { ANIMCMD_FRAME(0, 2), ANIMCMD_FRAME(1, 2), @@ -2023,7 +2023,7 @@ static const union AnimCmd *const gSpriteAnimTable_858C0BC[] = gSpriteAnim_858C0A4 }; -static const struct SpriteTemplate gUnknown_0858C0C0 = +static const struct SpriteTemplate gUnknown_0858C0C0 = { .tileTag = 0x0002, .paletteTag = 0x0004, @@ -2034,7 +2034,7 @@ static const struct SpriteTemplate gUnknown_0858C0C0 = .callback = sub_80E4084 }; -static const struct SpriteTemplate gUnknown_0858C0D8 = +static const struct SpriteTemplate gUnknown_0858C0D8 = { .tileTag = 0x0003, .paletteTag = 0x0001, @@ -2045,7 +2045,7 @@ static const struct SpriteTemplate gUnknown_0858C0D8 = .callback = SpriteCallbackDummy }; -static const struct SpriteTemplate gUnknown_0858C0F0 = +static const struct SpriteTemplate gUnknown_0858C0F0 = { .tileTag = 0x0004, .paletteTag = 0x0004, @@ -2056,7 +2056,7 @@ static const struct SpriteTemplate gUnknown_0858C0F0 = .callback = SpriteCallbackDummy }; -static const struct SpriteTemplate gUnknown_0858C108 = +static const struct SpriteTemplate gUnknown_0858C108 = { .tileTag = 0x0000, .paletteTag = 0x0006, @@ -2067,7 +2067,7 @@ static const struct SpriteTemplate gUnknown_0858C108 = .callback = SpriteCallbackDummy }; -static const struct SpriteTemplate gUnknown_0858C120 = +static const struct SpriteTemplate gUnknown_0858C120 = { .tileTag = 0x0001, .paletteTag = 0x0007, @@ -2078,7 +2078,7 @@ static const struct SpriteTemplate gUnknown_0858C120 = .callback = SpriteCallbackDummy }; -static const struct SpriteTemplate gUnknown_0858C138 = +static const struct SpriteTemplate gUnknown_0858C138 = { .tileTag = 0x0007, .paletteTag = 0x0005, @@ -2089,7 +2089,7 @@ static const struct SpriteTemplate gUnknown_0858C138 = .callback = sub_80E3B30 }; -static const struct SpriteTemplate sSpriteTemplate_InputArrow = +static const struct SpriteTemplate sSpriteTemplate_InputArrow = { .tileTag = 0x000A, .paletteTag = 0x0003, @@ -2100,7 +2100,7 @@ static const struct SpriteTemplate sSpriteTemplate_InputArrow = .callback = sub_80E3C20 }; -static const struct SpriteTemplate sSpriteTemplate_Underscore = +static const struct SpriteTemplate sSpriteTemplate_Underscore = { .tileTag = 0x000B, .paletteTag = 0x0003, @@ -2111,7 +2111,7 @@ static const struct SpriteTemplate sSpriteTemplate_Underscore = .callback = sub_80E3C6C }; -static const struct SpriteTemplate gUnknown_0858C180 = +static const struct SpriteTemplate gUnknown_0858C180 = { .tileTag = 0xFFFF, .paletteTag = 0x0000, @@ -2122,7 +2122,7 @@ static const struct SpriteTemplate gUnknown_0858C180 = .callback = SpriteCallbackDummy }; -static const u8* const gUnknown_0858C198[][4] = +static const u8* const gUnknown_0858C198[][4] = { { gUnknown_0862B88D, diff --git a/src/option_menu.c b/src/option_menu.c index cbbe14b77..de9a216a6 100644 --- a/src/option_menu.c +++ b/src/option_menu.c @@ -146,23 +146,7 @@ void CB2_InitOptionMenu(void) gMain.state++; break; case 1: - { - u8 *addr; - u32 size; - - addr = (u8 *)VRAM; - size = 0x18000; - while (1) - { - DmaFill16(3, 0, addr, 0x1000); - addr += 0x1000; - size -= 0x1000; - if (size <= 0x1000) - { - DmaFill16(3, 0, addr, size); - break; - } - } + DmaClearLarge16(3, (void*)(VRAM), VRAM_SIZE, 0x1000); DmaClear32(3, OAM, OAM_SIZE); DmaClear16(3, PLTT, PLTT_SIZE); SetGpuReg(REG_OFFSET_DISPCNT, 0); @@ -189,7 +173,6 @@ void CB2_InitOptionMenu(void) ShowBg(0); ShowBg(1); gMain.state++; - } break; case 2: ResetPaletteFade(); diff --git a/src/overworld.c b/src/overworld.c index 920f6f8f1..532615f27 100644 --- a/src/overworld.c +++ b/src/overworld.c @@ -89,9 +89,6 @@ extern const u16 gUnknown_82EC7C4[]; extern u16 gSaveFileStatus; extern u16 gUnknown_03005DA8; -extern u8 *gUnknown_03005DA0; -extern u8 *gUnknown_03005D9C; -extern u8 *gUnknown_03005DA4; extern bool8 (*gUnknown_03005DB0)(void); extern u8 gUnknown_03005DB4; extern u8 gFieldLinkPlayerCount; @@ -1422,12 +1419,12 @@ static void overworld_bg_setup(void) SetBgAttribute(1, BG_CTRL_ATTR_PALETTEMODE, 1); SetBgAttribute(2, BG_CTRL_ATTR_PALETTEMODE, 1); SetBgAttribute(3, BG_CTRL_ATTR_PALETTEMODE, 1); - gUnknown_03005DA0 = AllocZeroed(0x800); - gUnknown_03005D9C = AllocZeroed(0x800); - gUnknown_03005DA4 = AllocZeroed(0x800); - SetBgTilemapBuffer(1, gUnknown_03005DA0); - SetBgTilemapBuffer(2, gUnknown_03005D9C); - SetBgTilemapBuffer(3, gUnknown_03005DA4); + gBGTilemapBuffers2 = AllocZeroed(0x800); + gBGTilemapBuffers1 = AllocZeroed(0x800); + gBGTilemapBuffers3 = AllocZeroed(0x800); + SetBgTilemapBuffer(1, gBGTilemapBuffers2); + SetBgTilemapBuffer(2, gBGTilemapBuffers1); + SetBgTilemapBuffer(3, gBGTilemapBuffers3); sub_81971D0(); } @@ -1435,12 +1432,12 @@ void overworld_free_bg_tilemaps(void) { sub_81BE72C(); sub_81971F4(); - if (gUnknown_03005DA4 != NULL) - FREE_AND_SET_NULL(gUnknown_03005DA4); - if (gUnknown_03005D9C != NULL) - FREE_AND_SET_NULL(gUnknown_03005D9C); - if (gUnknown_03005DA0 != NULL) - FREE_AND_SET_NULL(gUnknown_03005DA0); + if (gBGTilemapBuffers3 != NULL) + FREE_AND_SET_NULL(gBGTilemapBuffers3); + if (gBGTilemapBuffers1 != NULL) + FREE_AND_SET_NULL(gBGTilemapBuffers1); + if (gBGTilemapBuffers2 != NULL) + FREE_AND_SET_NULL(gBGTilemapBuffers2); } static void ResetSafariZoneFlag_(void) diff --git a/src/pokemon_icon.c b/src/pokemon_icon.c index 4d1cc51c5..253ab2cb4 100644 --- a/src/pokemon_icon.c +++ b/src/pokemon_icon.c @@ -1,9 +1,28 @@ #include "global.h" #include "sprite.h" +#include "mail.h" #include "graphics.h" +#include "constants/species.h" +#include "palette.h" +#include "pokemon_icon.h" #define POKE_ICON_BASE_PAL_TAG 56000 +struct MonIconSpriteTemplate +{ + const struct OamData *oam; + const u8 *image; + const union AnimCmd *const *anims; + const union AffineAnimCmd *const *affineAnims; + void (*callback)(struct Sprite *); + u16 paletteTag; +}; + +// static functions +static u8 CreateMonIconSprite(struct MonIconSpriteTemplate *, s16, s16, u8); + +// .rodata + const u8 * const gMonIconTable[] = { gMonIcon_Bulbasaur, @@ -1012,3 +1031,288 @@ const u16 sSpriteImageSizes[3][4] = 0x400, // 4×8 }, }; + +u8 CreateMonIcon(u16 species, void (*callback)(struct Sprite *), s16 x, s16 y, u8 subpriority, u32 personality, bool32 extra) +{ + u8 spriteId; + struct MonIconSpriteTemplate iconTemplate = + { + .oam = &sMonIconOamData, + .image = GetMonIconPtr(species, personality, extra), + .anims = sMonIconAnims, + .affineAnims = sMonIconAffineAnims, + .callback = callback, + .paletteTag = POKE_ICON_BASE_PAL_TAG + gMonIconPaletteIndices[species], + }; + + if (species > SPECIES_EGG) + iconTemplate.paletteTag = POKE_ICON_BASE_PAL_TAG; + + spriteId = CreateMonIconSprite(&iconTemplate, x, y, subpriority); + + UpdateMonIconFrame(&gSprites[spriteId]); + + return spriteId; +} + +u8 sub_80D2D78(u16 species, void (*callback)(struct Sprite *), s16 x, s16 y, u8 subpriority, bool32 extra) +{ + u8 spriteId; + struct MonIconSpriteTemplate iconTemplate = + { + .oam = &sMonIconOamData, + .image = NULL, + .anims = sMonIconAnims, + .affineAnims = sMonIconAffineAnims, + .callback = callback, + .paletteTag = POKE_ICON_BASE_PAL_TAG + gMonIconPaletteIndices[species], + }; + + iconTemplate.image = GetMonIconTiles(species, extra); + spriteId = CreateMonIconSprite(&iconTemplate, x, y, subpriority); + + UpdateMonIconFrame(&gSprites[spriteId]); + + return spriteId; +} + +u16 mon_icon_convert_unown_species_id(u16 species, u32 personality) +{ + u16 result; + + if (species == SPECIES_UNOWN) + { + u16 letter = GetUnownLetterByPersonality(personality); + if (letter == 0) + letter = SPECIES_UNOWN; + else + letter += (SPECIES_UNOWN_B - 1); + result = letter; + } + else + { + if (species > SPECIES_EGG) + result = 260; + else + result = species; + } + + return result; +} + +u16 GetUnownLetterByPersonality(u32 personality) +{ + if (!personality) + return 0; + return (((personality & 0x3000000) >> 18) | ((personality & 0x30000) >> 12) | ((personality & 0x300) >> 6) | (personality & 0x3)) % 0x1C; +} + +u16 sub_80D2E84(u16 species) +{ + u16 value; + + if (MailSpeciesToSpecies(species, &value) == SPECIES_UNOWN) + { + if (value == 0) + value += SPECIES_UNOWN; + else + value += (SPECIES_UNOWN_B - 1); + return value; + } + else + { + if(species > (SPECIES_UNOWN_B - 1)) + species = 260; + return mon_icon_convert_unown_species_id(species, 0); + } +} + +const u8 *GetMonIconPtr(u16 species, u32 personality, bool32 extra) +{ + return GetMonIconTiles(mon_icon_convert_unown_species_id(species, personality), extra); +} + + + +void sub_80D2EF8(struct Sprite *sprite) +{ + sub_80D328C(sprite); +} + +void LoadMonIconPalettes(void) +{ + u8 i; + for (i = 0; i < 6; i++) + LoadSpritePalette(&gMonIconPaletteTable[i]); +} + +// unused +void SafeLoadMonIconPalette(u16 species) +{ + u8 palIndex; + if (species > SPECIES_EGG) + species = 260; + palIndex = gMonIconPaletteIndices[species]; + if (IndexOfSpritePaletteTag(gMonIconPaletteTable[palIndex].tag) == 0xFF) + LoadSpritePalette(&gMonIconPaletteTable[palIndex]); +} + +void LoadMonIconPalette(u16 species) +{ + u8 palIndex = gMonIconPaletteIndices[species]; + if (IndexOfSpritePaletteTag(gMonIconPaletteTable[palIndex].tag) == 0xFF) + LoadSpritePalette(&gMonIconPaletteTable[palIndex]); +} + +void FreeMonIconPalettes(void) +{ + u8 i; + for (i = 0; i < 6; i++) + FreeSpritePaletteByTag(gMonIconPaletteTable[i].tag); +} + +// unused +void SafeFreeMonIconPalette(u16 species) +{ + u8 palIndex; + if (species > SPECIES_EGG) + species = 260; + palIndex = gMonIconPaletteIndices[species]; + FreeSpritePaletteByTag(gMonIconPaletteTable[palIndex].tag); +} + +void FreeMonIconPalette(u16 species) +{ + u8 palIndex; + palIndex = gMonIconPaletteIndices[species]; + FreeSpritePaletteByTag(gMonIconPaletteTable[palIndex].tag); +} + +void sub_80D3014(struct Sprite *sprite) +{ + UpdateMonIconFrame(sprite); +} + +const u8* GetMonIconTiles(u16 species, bool32 extra) +{ + const u8* iconSprite = gMonIconTable[species]; + if(species == SPECIES_DEOXYS && extra == TRUE) + { + iconSprite = (const u8*)(0x400 + (u32)iconSprite); //WTF? + } + return iconSprite; +} + +void sub_80D304C(u16 offset) +{ + s32 i; + const struct SpritePalette* monIconPalettePtr; + + if(offset <= 0xA0) + { + monIconPalettePtr = gMonIconPaletteTable; + for(i = 5; i >= 0 ; i--) + { + LoadPalette(monIconPalettePtr->data, offset, 0x20); + offset += 0x10; + monIconPalettePtr++; + } + } +} + +u8 sub_80D3080(u16 species) +{ + if (species > SPECIES_EGG) + species = 260; + return gMonIconPaletteIndices[species]; +} + +u8 sub_80D30A0(u16 species) +{ + return gMonIconPaletteIndices[species]; +} + +const u16* GetValidMonIconPalettePtr(u16 species) +{ + if (species > SPECIES_EGG) + species = 260; + return gMonIconPaletteTable[gMonIconPaletteIndices[species]].data; +} + +// TODO: try to find a way to avoid using asm statement +u8 UpdateMonIconFrame(struct Sprite *sprite) +{ + u8 result = 0; + + if (sprite->animDelayCounter == 0) + { + s16 frame = sprite->anims[sprite->animNum][sprite->animCmdIndex].frame.imageValue; + + switch (frame) + { + case -1: + break; + case -2: + sprite->animCmdIndex = 0; + break; + default: + RequestSpriteCopy( + // pointer arithmetic is needed to get the correct pointer to perform the sprite copy on. + // because sprite->images is a struct def, it has to be casted to (u8 *) before any + // arithmetic can be performed. + (u8 *)sprite->images + (sSpriteImageSizes[sprite->oam.shape][sprite->oam.size] * frame), + (u8 *)(OBJ_VRAM0 + sprite->oam.tileNum * TILE_SIZE_4BPP), + sSpriteImageSizes[sprite->oam.shape][sprite->oam.size]); + { + register u8 duration asm("r0") = sprite->anims[sprite->animNum][sprite->animCmdIndex].frame.duration; + sprite->animDelayCounter = duration; + } + sprite->animCmdIndex++; + result = sprite->animCmdIndex; + break; + } + } + else + { + sprite->animDelayCounter--; + } + return result; +} + +static u8 CreateMonIconSprite(struct MonIconSpriteTemplate *iconTemplate, s16 x, s16 y, u8 subpriority) +{ + u8 spriteId; + + struct SpriteFrameImage image = { NULL, sSpriteImageSizes[iconTemplate->oam->shape][iconTemplate->oam->size] }; + + struct SpriteTemplate spriteTemplate = + { + .tileTag = 0xFFFF, + .paletteTag = iconTemplate->paletteTag, + .oam = iconTemplate->oam, + .anims = iconTemplate->anims, + .images = &image, + .affineAnims = iconTemplate->affineAnims, + .callback = iconTemplate->callback, + }; + + spriteId = CreateSprite(&spriteTemplate, x, y, subpriority); + gSprites[spriteId].animPaused = TRUE; + gSprites[spriteId].animBeginning = FALSE; + gSprites[spriteId].images = (const struct SpriteFrameImage *)iconTemplate->image; + return spriteId; +} + +void sub_80D328C(struct Sprite *sprite) +{ + struct SpriteFrameImage image = { NULL, sSpriteImageSizes[sprite->oam.shape][sprite->oam.size] }; + sprite->images = ℑ + DestroySprite(sprite); +} + +void sub_80D32C8(struct Sprite *sprite, u8 animNum) +{ + sprite->animNum = animNum; + sprite->animDelayCounter = 0; + sprite->animCmdIndex = 0; +} diff --git a/src/pokemon_summary_screen.c b/src/pokemon_summary_screen.c index 834ca6f7d..e7fcce629 100644 --- a/src/pokemon_summary_screen.c +++ b/src/pokemon_summary_screen.c @@ -2776,93 +2776,27 @@ void sub_81C2C38(u8 a) schedule_bg_copy_tilemap_to_vram(0); } - - -#ifdef NONMATCHING u8 sub_81C2D2C(struct WindowTemplate *template, u8 a) { - u8 *r4 = gUnknown_0203CF1C->unk40CB; - if (r4[a] == 0xFF) + u8 *windowIdPtr = &(gUnknown_0203CF1C->unk40CB[a]); + if (*windowIdPtr == 0xFF) { - r4[a] = AddWindow(&template[a]); - FillWindowPixelBuffer(r4[a], 0); + *windowIdPtr = AddWindow(&template[a]); + FillWindowPixelBuffer(*windowIdPtr, 0); } - return r4[a]; -} -#else -ASM_DIRECT -u8 sub_81C2D2C(struct WindowTemplate *template, u8 a) -{ - asm(".syntax unified\n\ - push {r4,lr}\n\ - adds r3, r0, 0\n\ - lsls r1, 24\n\ - lsrs r2, r1, 24\n\ - ldr r0, =gUnknown_0203CF1C\n\ - ldr r4, =0x000040cb\n\ - adds r1, r2, r4\n\ - ldr r0, [r0]\n\ - adds r4, r0, r1\n\ - ldrb r0, [r4]\n\ - cmp r0, 0xFF\n\ - bne _081C2D56\n\ - lsls r0, r2, 3\n\ - adds r0, r3, r0\n\ - bl AddWindow\n\ - strb r0, [r4]\n\ - ldrb r0, [r4]\n\ - movs r1, 0\n\ - bl FillWindowPixelBuffer\n\ -_081C2D56:\n\ - ldrb r0, [r4]\n\ - pop {r4}\n\ - pop {r1}\n\ - bx r1\n\ - .pool\n\ - .syntax divided\n"); + return *windowIdPtr; } -#endif -#ifdef NONMATCHING void sub_81C2D68(u8 a) { - u8 *r4 = gUnknown_0203CF1C->unk40CB; - if (r4[a] != 0xFF) + u8 *windowIdPtr = &(gUnknown_0203CF1C->unk40CB[a]); + if (*windowIdPtr != 0xFF) { - ClearWindowTilemap(r4[a]); - RemoveWindow(r4[a]); - r4[a] = 0xFF; + ClearWindowTilemap(*windowIdPtr); + RemoveWindow(*windowIdPtr); + *windowIdPtr = 0xFF; } } -#else -ASM_DIRECT -void sub_81C2D68(u8 a) -{ - asm(".syntax unified\n\ - push {r4,lr}\n\ - lsls r0, 24\n\ - lsrs r0, 24\n\ - ldr r1, =gUnknown_0203CF1C\n\ - ldr r2, =0x000040cb\n\ - adds r0, r2\n\ - ldr r1, [r1]\n\ - adds r4, r1, r0\n\ - ldrb r0, [r4]\n\ - cmp r0, 0xFF\n\ - beq _081C2D8C\n\ - bl ClearWindowTilemap\n\ - ldrb r0, [r4]\n\ - bl RemoveWindow\n\ - movs r0, 0xFF\n\ - strb r0, [r4]\n\ -_081C2D8C:\n\ - pop {r4}\n\ - pop {r0}\n\ - bx r0\n\ - .pool\n\ - .syntax divided\n"); -} -#endif void sub_81C2D9C(u8 a) { diff --git a/src/rom6.c b/src/rom6.c new file mode 100644 index 000000000..4a5c506b6 --- /dev/null +++ b/src/rom6.c @@ -0,0 +1,209 @@ +#include "global.h" +#include "constants/map_objects.h" +#include "constants/songs.h" +#include "rom6.h" +#include "braille_puzzles.h" +#include "event_data.h" +#include "event_scripts.h" +#include "field_effect.h" +#include "field_map_obj.h" +#include "field_player_avatar.h" +#include "item_use.h" +#include "party_menu.h" +#include "overworld.h" +#include "script.h" +#include "sound.h" +#include "sprite.h" +#include "task.h" + +// static functions +static void task08_080C9820(u8 taskId); +static void sub_8135578(u8 taskId); +static void sub_813552C(u8 taskId); +static void sub_813561C(u8 taskId); +static void sub_81356C4(void); +static void sub_8135714(void); +static void hm2_dig(void); +static void sub_8135780(void); + +// extern RAM loc +extern struct MapPosition gUnknown_0203AB40; + +// text +bool8 npc_before_player_of_type(u8 a) +{ + u8 mapObjId; + + GetXYCoordsOneStepInFrontOfPlayer(&gUnknown_0203AB40.x, &gUnknown_0203AB40.y); + gUnknown_0203AB40.height = PlayerGetZCoord(); + mapObjId = GetFieldObjectIdByXYZ(gUnknown_0203AB40.x, gUnknown_0203AB40.y, gUnknown_0203AB40.height); + if (gMapObjects[mapObjId].graphicsId != a) + { + return FALSE; + } + else + { + gSpecialVar_LastTalked = gMapObjects[mapObjId].localId; + return TRUE; + } +} + +u8 oei_task_add(void) +{ + GetXYCoordsOneStepInFrontOfPlayer(&gUnknown_0203AB40.x, &gUnknown_0203AB40.y); + return CreateTask(task08_080C9820, 8); +} + +static void task08_080C9820(u8 taskId) +{ + u8 mapObjId; + + ScriptContext2_Enable(); + gPlayerAvatar.preventStep = TRUE; + mapObjId = gPlayerAvatar.mapObjectId; + if (!FieldObjectIsSpecialAnimOrDirectionSequenceAnimActive(&gMapObjects[mapObjId]) + || FieldObjectClearAnimIfSpecialAnimFinished(&gMapObjects[mapObjId])) + { + if (gMapHeader.mapType == MAP_TYPE_UNDERWATER) + { + FieldEffectStart(FLDEFF_FIELD_MOVE_SHOW_MON_INIT); + gTasks[taskId].func = sub_8135578; + } + else + { + sub_808C114(); + FieldObjectSetSpecialAnim(&gMapObjects[mapObjId], 0x39); + gTasks[taskId].func = sub_813552C; + } + } +} + +static void sub_813552C(u8 taskId) +{ + if (FieldObjectCheckIfSpecialAnimFinishedOrInactive(&gMapObjects[gPlayerAvatar.mapObjectId]) == TRUE) + { + FieldEffectStart(FLDEFF_FIELD_MOVE_SHOW_MON_INIT); + gTasks[taskId].func = sub_8135578; + } +} + +static void sub_8135578(u8 taskId) +{ + if (!FieldEffectActiveListContains(6)) + { + gFieldEffectArguments[1] = player_get_direction_lower_nybble(); + if (gFieldEffectArguments[1] == 1) + gFieldEffectArguments[2] = 0; + if (gFieldEffectArguments[1] == 2) + gFieldEffectArguments[2] = 1; + if (gFieldEffectArguments[1] == 3) + gFieldEffectArguments[2] = 2; + if (gFieldEffectArguments[1] == 4) + gFieldEffectArguments[2] = 3; + FieldObjectSetGraphicsId(&gMapObjects[gPlayerAvatar.mapObjectId], GetPlayerAvatarGraphicsIdByCurrentState()); + StartSpriteAnim(&gSprites[gPlayerAvatar.spriteId], gFieldEffectArguments[2]); + FieldEffectActiveListRemove(6); + gTasks[taskId].func = sub_813561C; + } +} + +static void sub_813561C(u8 taskId) +{ + void (*func)(void) = (void (*)(void))(((u16)gTasks[taskId].data[8] << 16) | (u16)gTasks[taskId].data[9]); + + func(); + gPlayerAvatar.preventStep = FALSE; + DestroyTask(taskId); +} + +bool8 SetUpFieldMove_RockSmash(void) +{ + if(ShouldDoBrailleStrengthEffect()) + { + gSpecialVar_Result = GetCursorSelectionMonId(); + gUnknown_03005DB0 = FieldCallback_Teleport; + gUnknown_0203CEEC = sub_8179834; + return TRUE; + } + else if (npc_before_player_of_type(0x56) == TRUE) + { + gUnknown_03005DB0 = FieldCallback_Teleport; + gUnknown_0203CEEC = sub_81356C4; + return TRUE; + } + else + { + return FALSE; + } +} + +static void sub_81356C4(void) +{ + gFieldEffectArguments[0] = GetCursorSelectionMonId(); + ScriptContext1_SetupScript(Route111_EventScript_2907F0); +} + +bool8 FldEff_UseRockSmash(void) +{ + u8 taskId = oei_task_add(); + + gTasks[taskId].data[8] = (u32)sub_8135714 >> 16; + gTasks[taskId].data[9] = (u32)sub_8135714; + IncrementGameStat(GAME_STAT_USED_ROCK_SMASH); + return FALSE; +} + +static void sub_8135714(void) +{ + PlaySE(SE_W088); + FieldEffectActiveListRemove(FLDEFF_USE_ROCK_SMASH); + EnableBothScriptContexts(); +} + +bool8 SetUpFieldMove_Dig(void) +{ + if (CanUseEscapeRopeOnCurrMap() == TRUE) + { + gUnknown_03005DB0 = FieldCallback_Teleport; + gUnknown_0203CEEC = hm2_dig; + return TRUE; + } + else + { + return FALSE; + } +} + +static void hm2_dig(void) +{ + Overworld_ResetStateAfterDigEscRope(); + FieldEffectStart(FLDEFF_USE_DIG); + gFieldEffectArguments[0] = GetCursorSelectionMonId(); +} + +bool8 FldEff_UseDig(void) +{ + u8 taskId = oei_task_add(); + + gTasks[taskId].data[8] = (u32)sub_8135780 >> 16; + gTasks[taskId].data[9] = (u32)sub_8135780; + if (!ShouldDoBrailleDigEffect()) + SetPlayerAvatarTransitionFlags(1); + return FALSE; +} + +static void sub_8135780(void) +{ + u8 taskId; + + FieldEffectActiveListRemove(FLDEFF_USE_DIG); + if (ShouldDoBrailleDigEffect()) + { + DoBrailleDigEffect(); + } + else + { + taskId = CreateTask(task08_080A1C44, 8); + gTasks[taskId].data[0] = 0; + } +} diff --git a/src/rotating_gate.c b/src/rotating_gate.c new file mode 100644 index 000000000..db5935fc3 --- /dev/null +++ b/src/rotating_gate.c @@ -0,0 +1,1188 @@ +#include "global.h" +#include "bike.h" +#include "event_data.h" +#include "field_map_obj.h" +#include "constants/maps.h" +#include "constants/songs.h" +#include "sound.h" +#include "sprite.h" + +#define ROTATING_GATE_TILE_TAG 0x1300 +#define ROTATING_GATE_PUZZLE_MAX 12 +#define GATE_ARM_MAX_LENGTH 2 + +#define GATE_ROT(rotationDirection, arm, longArm) \ + ((rotationDirection & 15) << 4) | ((arm & 7) << 1) | (longArm & 1) +#define GATE_ROT_CW(arm, longArm) GATE_ROT(ROTATE_CLOCKWISE, arm, longArm) +#define GATE_ROT_ACW(arm, longArm) GATE_ROT(ROTATE_ANTICLOCKWISE, arm, longArm) +#define GATE_ROT_NONE 255 + +// static functions +static void SpriteCallback_RotatingGate(struct Sprite *sprite); +static u8 RotatingGate_CreateGate(u8 gateId, s16 deltaX, s16 deltaY); +static void RotatingGate_HideGatesOutsideViewport(struct Sprite *sprite); + +// enums +enum +{ + /* + * | + * +-- + */ + GATE_SHAPE_L1, + + /* + * | + * | + * +-- + */ + GATE_SHAPE_L2, + + /* + * | + * +---- + */ + GATE_SHAPE_L3, + + /* + * | + * | + * +---- + */ + GATE_SHAPE_L4, + + /* + * | + * +-- + * | + */ + GATE_SHAPE_T1, + + /* + * | + * | + * +-- + * | + */ + GATE_SHAPE_T2, + + /* + * | + * +---- + * | + */ + GATE_SHAPE_T3, + + /* + * An unused T-shape gate + * | + * +-- + * | + * | + */ + GATE_SHAPE_T4, + + /* + * An unused T-shape gate + * | + * | + * +---- + * | + */ + GATE_SHAPE_UNUSED_T1, + + /* + * An unused T-shape gate + * | + * | + * +-- + * | + * | + */ + GATE_SHAPE_UNUSED_T2, + + /* + * An unused T-shape gate + * | + * +---- + * | + * | + */ + GATE_SHAPE_UNUSED_T3, + + /* + * An unused T-shape gate + * | + * | + * +---- + * | + * | + */ + GATE_SHAPE_UNUSED_T4, +}; + +enum +{ + /* + * 0 degrees (clockwise) + * | + * +-- + * | + */ + GATE_ORIENTATION_0, + + /* + * 90 degress (clockwise) + * --+-- + * | + */ + GATE_ORIENTATION_90, + + /* + * 180 degrees (clockwise) + * | + * --+ + * | + */ + GATE_ORIENTATION_180, + + /* + * 270 degrees (clockwise) + * | + * --+-- + */ + GATE_ORIENTATION_270, + + GATE_ORIENTATION_MAX, +}; + +// Describes the location of the gates "arms" when the gate has not +// been rotated (i.e. rotated 0 degrees) +enum +{ + GATE_ARM_NORTH, + GATE_ARM_EAST, + GATE_ARM_SOUTH, + GATE_ARM_WEST, +}; + +enum +{ + ROTATE_NONE, + ROTATE_ANTICLOCKWISE, + ROTATE_CLOCKWISE, +}; + +enum +{ + PUZZLE_NONE, + PUZZLE_FORTREE_CITY_GYM, + PUZZLE_ROUTE110_TRICK_HOUSE_PUZZLE6, +}; + +// structure +struct RotatingGatePuzzle +{ + s16 x; + s16 y; + u8 shape; + u8 orientation; +}; + +struct Coords8 +{ + s8 deltaX; + s8 deltaY; +}; + +// .rodata +// Fortree +static const struct RotatingGatePuzzle sRotatingGate_FortreePuzzleConfig[] = +{ + { 6, 7, GATE_SHAPE_T2, GATE_ORIENTATION_90}, + { 9, 15, GATE_SHAPE_T2, GATE_ORIENTATION_180}, + { 3, 19, GATE_SHAPE_T2, GATE_ORIENTATION_90}, + { 2, 6, GATE_SHAPE_T1, GATE_ORIENTATION_90}, + { 9, 12, GATE_SHAPE_T1, GATE_ORIENTATION_0}, + { 6, 23, GATE_SHAPE_T1, GATE_ORIENTATION_0}, + {12, 22, GATE_SHAPE_T1, GATE_ORIENTATION_0}, + { 6, 3, GATE_SHAPE_L4, GATE_ORIENTATION_180}, +}; + +// Trickhouse +static const struct RotatingGatePuzzle sRotatingGate_TrickHousePuzzleConfig[] = +{ + {14, 5, GATE_SHAPE_T1, GATE_ORIENTATION_90}, + {10, 6, GATE_SHAPE_L2, GATE_ORIENTATION_180}, + { 6, 6, GATE_SHAPE_L4, GATE_ORIENTATION_90}, + {14, 8, GATE_SHAPE_T1, GATE_ORIENTATION_90}, + { 3, 10, GATE_SHAPE_L3, GATE_ORIENTATION_270}, + { 9, 14, GATE_SHAPE_L1, GATE_ORIENTATION_90}, + { 3, 15, GATE_SHAPE_T3, GATE_ORIENTATION_0}, + { 2, 17, GATE_SHAPE_L2, GATE_ORIENTATION_180}, + {12, 18, GATE_SHAPE_T3, GATE_ORIENTATION_270}, + { 5, 18, GATE_SHAPE_L4, GATE_ORIENTATION_90}, + {10, 19, GATE_SHAPE_L3, GATE_ORIENTATION_180}, +}; + +static const u8 sRotatingGateTiles_1[] = INCBIN_U8("graphics/misc/rotating_gate_1.4bpp"); +static const u8 sRotatingGateTiles_2[] = INCBIN_U8("graphics/misc/rotating_gate_2.4bpp"); +static const u8 sRotatingGateTiles_3[] = INCBIN_U8("graphics/misc/rotating_gate_3.4bpp"); +static const u8 sRotatingGateTiles_4[] = INCBIN_U8("graphics/misc/rotating_gate_4.4bpp"); +static const u8 sRotatingGateTiles_5[] = INCBIN_U8("graphics/misc/rotating_gate_5.4bpp"); +static const u8 sRotatingGateTiles_6[] = INCBIN_U8("graphics/misc/rotating_gate_6.4bpp"); +static const u8 sRotatingGateTiles_7[] = INCBIN_U8("graphics/misc/rotating_gate_7.4bpp"); +static const u8 sRotatingGateTiles_8[] = INCBIN_U8("graphics/misc/rotating_gate_8.4bpp"); + +static const struct OamData sOamData_RotatingGateLarge = +{ + .y = 0, + .affineMode = ST_OAM_AFFINE_NORMAL, + .objMode = 0, + .mosaic = 0, + .bpp = ST_OAM_4BPP, + .shape = ST_OAM_SQUARE, + .x = 0, + .matrixNum = 0, + .size = 3, + .tileNum = 0, + .priority = 2, + .paletteNum = 2, + .affineParam = 0, +}; + +static const struct OamData sOamData_RotatingGateRegular = +{ + .y = 0, + .affineMode = ST_OAM_AFFINE_NORMAL, + .objMode = 0, + .mosaic = 0, + .bpp = ST_OAM_4BPP, + .shape = ST_OAM_SQUARE, + .x = 0, + .matrixNum = 0, + .size = 2, + .tileNum = 0, + .priority = 2, + .paletteNum = 2, + .affineParam = 0, +}; + +static const struct SpriteSheet sRotatingGatesGraphicsTable[] = +{ + {sRotatingGateTiles_1, 0x200, ROTATING_GATE_TILE_TAG + GATE_SHAPE_L1}, + {sRotatingGateTiles_2, 0x800, ROTATING_GATE_TILE_TAG + GATE_SHAPE_L2}, + {sRotatingGateTiles_3, 0x800, ROTATING_GATE_TILE_TAG + GATE_SHAPE_L3}, + {sRotatingGateTiles_4, 0x800, ROTATING_GATE_TILE_TAG + GATE_SHAPE_L4}, + {sRotatingGateTiles_5, 0x200, ROTATING_GATE_TILE_TAG + GATE_SHAPE_T1}, + {sRotatingGateTiles_6, 0x800, ROTATING_GATE_TILE_TAG + GATE_SHAPE_T2}, + {sRotatingGateTiles_7, 0x800, ROTATING_GATE_TILE_TAG + GATE_SHAPE_T3}, + {sRotatingGateTiles_8, 0x800, ROTATING_GATE_TILE_TAG + GATE_SHAPE_T4}, + {NULL}, +}; + +static const union AnimCmd sSpriteAnim_RotatingGateLarge[] = +{ + ANIMCMD_FRAME(0, 0), + ANIMCMD_END, +}; + +static const union AnimCmd sSpriteAnim_RotatingGateRegular[] = +{ + ANIMCMD_FRAME(0, 0), ANIMCMD_END, +}; + +static const union AnimCmd *const sSpriteAnimTable_RotatingGateLarge[] = +{ + sSpriteAnim_RotatingGateLarge, +}; + +static const union AnimCmd *const sSpriteAnimTable_RotatingGateRegular[] = +{ + sSpriteAnim_RotatingGateRegular, +}; + +static const union AffineAnimCmd sSpriteAffineAnim_Rotated0[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, 0, 0), + AFFINEANIMCMD_JUMP(0), +}; + +static const union AffineAnimCmd sSpriteAffineAnim_Rotated90[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, -64, 0), + AFFINEANIMCMD_JUMP(0), +}; + +static const union AffineAnimCmd sSpriteAffineAnim_Rotated180[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, -128, 0), + AFFINEANIMCMD_JUMP(0), +}; + +static const union AffineAnimCmd sSpriteAffineAnim_Rotated270[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, 64, 0), + AFFINEANIMCMD_JUMP(0), +}; + +static const union AffineAnimCmd sSpriteAffineAnim_RotatingClockwise0to90[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, 0, 0), + AFFINEANIMCMD_FRAME(0x0, 0x0, -4, 16), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sSpriteAffineAnim_RotatingClockwise90to180[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, -64, 0), + AFFINEANIMCMD_FRAME(0x0, 0x0, -4, 16), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sSpriteAffineAnim_RotatingClockwise180to270[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, -128, 0), + AFFINEANIMCMD_FRAME(0x0, 0x0, -4, 16), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sSpriteAffineAnim_RotatingClockwise270to360[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, 64, 0), + AFFINEANIMCMD_FRAME(0x0, 0x0, -4, 16), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sSpriteAffineAnim_RotatingAnticlockwise360to270[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, 0, 0), + AFFINEANIMCMD_FRAME(0x0, 0x0, 4, 16), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sSpriteAffineAnim_RotatingAnticlockwise270to180[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, 64, 0), + AFFINEANIMCMD_FRAME(0x0, 0x0, 4, 16), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sSpriteAffineAnim_RotatingAnticlockwise180to90[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, -128, 0), + AFFINEANIMCMD_FRAME(0x0, 0x0, 4, 16), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sSpriteAffineAnim_RotatingAnticlockwise90to0[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, -64, 0), + AFFINEANIMCMD_FRAME(0x0, 0x0, 4, 16), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sSpriteAffineAnim_RotatingClockwise0to90Faster[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, 0, 0), + AFFINEANIMCMD_FRAME(0x0, 0x0, -8, 8), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sSpriteAffineAnim_RotatingClockwise90to180Faster[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, -64, 0), + AFFINEANIMCMD_FRAME(0x0, 0x0, -8, 8), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sSpriteAffineAnim_RotatingClockwise180to270Faster[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, -128, 0), + AFFINEANIMCMD_FRAME(0x0, 0x0, -8, 8), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sSpriteAffineAnim_RotatingClockwise270to360Faster[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, 64, 0), + AFFINEANIMCMD_FRAME(0x0, 0x0, -8, 8), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sSpriteAffineAnim_RotatingAnticlockwise360to270Faster[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, 0, 0), + AFFINEANIMCMD_FRAME(0x0, 0x0, 8, 8), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sSpriteAffineAnim_RotatingAnticlockwise270to180Faster[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, 64, 0), + AFFINEANIMCMD_FRAME(0x0, 0x0, 8, 8), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sSpriteAffineAnim_RotatingAnticlockwise180to90Faster[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, -128, 0), + AFFINEANIMCMD_FRAME(0x0, 0x0, 8, 8), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sSpriteAffineAnim_RotatingAnticlockwise90to0Faster[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, -64, 0), + AFFINEANIMCMD_FRAME(0x0, 0x0, 8, 8), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd *const sSpriteAffineAnimTable_RotatingGate[] = +{ + sSpriteAffineAnim_Rotated0, + sSpriteAffineAnim_Rotated90, + sSpriteAffineAnim_Rotated180, + sSpriteAffineAnim_Rotated270, + sSpriteAffineAnim_RotatingAnticlockwise360to270, + sSpriteAffineAnim_RotatingAnticlockwise90to0, + sSpriteAffineAnim_RotatingAnticlockwise180to90, + sSpriteAffineAnim_RotatingAnticlockwise270to180, + sSpriteAffineAnim_RotatingClockwise0to90, + sSpriteAffineAnim_RotatingClockwise90to180, + sSpriteAffineAnim_RotatingClockwise180to270, + sSpriteAffineAnim_RotatingClockwise270to360, + sSpriteAffineAnim_RotatingAnticlockwise360to270Faster, + sSpriteAffineAnim_RotatingAnticlockwise90to0Faster, + sSpriteAffineAnim_RotatingAnticlockwise180to90Faster, + sSpriteAffineAnim_RotatingAnticlockwise270to180Faster, + sSpriteAffineAnim_RotatingClockwise0to90Faster, + sSpriteAffineAnim_RotatingClockwise90to180Faster, + sSpriteAffineAnim_RotatingClockwise180to270Faster, + sSpriteAffineAnim_RotatingClockwise270to360Faster, +}; + + +static const struct SpriteTemplate sSpriteTemplate_RotatingGateLarge = +{ + .tileTag = ROTATING_GATE_TILE_TAG, + .paletteTag = 0xFFFF, + .oam = &sOamData_RotatingGateLarge, + .anims = sSpriteAnimTable_RotatingGateLarge, + .images = NULL, + .affineAnims = sSpriteAffineAnimTable_RotatingGate, + .callback = SpriteCallback_RotatingGate, +}; + +static const struct SpriteTemplate sSpriteTemplate_RotatingGateRegular = +{ + .tileTag = ROTATING_GATE_TILE_TAG, + .paletteTag = 0xFFFF, + .oam = &sOamData_RotatingGateRegular, + .anims = sSpriteAnimTable_RotatingGateRegular, + .images = NULL, + .affineAnims = sSpriteAffineAnimTable_RotatingGate, + .callback = SpriteCallback_RotatingGate, +}; + +// These structures describe what happens to the gate if you hit it at +// a given coordinate in a 4x4 grid when walking in the specified +// direction. Either the gate does not rotate, or it rotates in the +// given direction. This information is compared against the gate +// "arm" layout to see if there is an arm at the position in order to +// produce the final rotation. +static const u8 sRotatingGate_RotationInfoNorth[4 * 4] = +{ + GATE_ROT_NONE, GATE_ROT_NONE, GATE_ROT_NONE, GATE_ROT_NONE, + GATE_ROT_CW(GATE_ARM_WEST, 1), GATE_ROT_CW(GATE_ARM_WEST, 0), GATE_ROT_ACW(GATE_ARM_EAST, 0), GATE_ROT_ACW(GATE_ARM_EAST, 1), + GATE_ROT_NONE, GATE_ROT_NONE, GATE_ROT_NONE, GATE_ROT_NONE, + GATE_ROT_NONE, GATE_ROT_NONE, GATE_ROT_NONE, GATE_ROT_NONE, +}; + +static const u8 sRotatingGate_RotationInfoSouth[4 * 4] = +{ + GATE_ROT_NONE, GATE_ROT_NONE, GATE_ROT_NONE, GATE_ROT_NONE, + GATE_ROT_NONE, GATE_ROT_NONE, GATE_ROT_NONE, GATE_ROT_NONE, + GATE_ROT_ACW(GATE_ARM_WEST, 1), GATE_ROT_ACW(GATE_ARM_WEST, 0), GATE_ROT_CW(GATE_ARM_EAST, 0), GATE_ROT_CW(GATE_ARM_EAST, 1), + GATE_ROT_NONE, GATE_ROT_NONE, GATE_ROT_NONE, GATE_ROT_NONE, +}; + +static const u8 sRotatingGate_RotationInfoWest[4 * 4] = +{ + GATE_ROT_NONE, GATE_ROT_ACW(GATE_ARM_NORTH, 1), GATE_ROT_NONE, GATE_ROT_NONE, + GATE_ROT_NONE, GATE_ROT_ACW(GATE_ARM_NORTH, 0), GATE_ROT_NONE, GATE_ROT_NONE, + GATE_ROT_NONE, GATE_ROT_CW(GATE_ARM_SOUTH, 0), GATE_ROT_NONE, GATE_ROT_NONE, + GATE_ROT_NONE, GATE_ROT_CW(GATE_ARM_SOUTH, 1), GATE_ROT_NONE, GATE_ROT_NONE, +}; + +static const u8 sRotatingGate_RotationInfoEast[4 * 4] = +{ + GATE_ROT_NONE, GATE_ROT_NONE, GATE_ROT_CW(GATE_ARM_NORTH, 1), GATE_ROT_NONE, + GATE_ROT_NONE, GATE_ROT_NONE, GATE_ROT_CW(GATE_ARM_NORTH, 0), GATE_ROT_NONE, + GATE_ROT_NONE, GATE_ROT_NONE, GATE_ROT_ACW(GATE_ARM_SOUTH, 0), GATE_ROT_NONE, + GATE_ROT_NONE, GATE_ROT_NONE, GATE_ROT_ACW(GATE_ARM_SOUTH, 1), GATE_ROT_NONE, +}; + +// These tables describe the relative coordinate positions the arms +// must move through in order to be rotated. +static const struct Coords8 sRotatingGate_ArmPositionsClockwiseRotation[] = { + { 0, -1 }, { 1, -2 }, { 0, 0 }, { 1, 0 }, { -1, 0 }, { -1, 1 }, { -1, -1 }, { -2, -1 }, +}; + +static const struct Coords8 sRotatingGate_ArmPositionsAntiClockwiseRotation[] = { + { -1, -1 }, { -1, -2 }, { 0, -1 }, { 1, -1 }, { 0, 0 }, { 0, 1 }, { -1, 0 }, { -2, 0 }, +}; + +// Describes where the gates "arms" are in the order north, east, south, west. +// These are adjusted using the current orientation to perform collision checking +static const u8 sRotatingGate_ArmLayout[][4 * 2] = +{ + // L-shape gates + { + 1, 0, + 1, 0, + 0, 0, + 0, 0, + }, + { + 1, 1, + 1, 0, + 0, 0, + 0, 0, + }, + { + 1, 0, + 1, 1, + 0, 0, + 0, 0, + }, + { + 1, 1, + 1, 1, + 0, 0, + 0, 0, + }, + + // T-shape gates + { + 1, 0, + 1, 0, + 1, 0, + 0, 0, + }, + { + 1, 1, + 1, 0, + 1, 0, + 0, 0, + }, + { + 1, 0, + 1, 1, + 1, 0, + 0, 0, + }, + { + 1, 0, + 1, 0, + 1, 1, + 0, 0, + }, + + // Unused T-shape gates + // These have 2-3 long arms and cannot actually be used anywhere + // since configuration for them is missing from the other tables. + { + 1, 1, + 1, 1, + 1, 0, + 0, 0, + }, + { + 1, 1, + 1, 0, + 1, 1, + 0, 0, + }, + { + 1, 0, + 1, 1, + 1, 1, + 0, 0, + }, + { + 1, 1, + 1, 1, + 1, 1, + 0, 0, + }, +}; + +// ewram +static EWRAM_DATA u8 gRotatingGate_GateSpriteIds[ROTATING_GATE_PUZZLE_MAX] = {0}; +static EWRAM_DATA const struct RotatingGatePuzzle *gRotatingGate_PuzzleConfig = NULL; +static EWRAM_DATA u8 gRotatingGate_PuzzleCount = 0; + +// text +static s32 GetCurrentMapRotatingGatePuzzleType(void) +{ + if (gSaveBlock1Ptr->location.mapGroup == MAP_GROUP(FORTREE_CITY_GYM) && + gSaveBlock1Ptr->location.mapNum == MAP_NUM(FORTREE_CITY_GYM)) + { + return PUZZLE_FORTREE_CITY_GYM; + } + + if (gSaveBlock1Ptr->location.mapGroup == MAP_GROUP(ROUTE110_TRICK_HOUSE_PUZZLE6) && + gSaveBlock1Ptr->location.mapNum == MAP_NUM(ROUTE110_TRICK_HOUSE_PUZZLE6)) + { + return PUZZLE_ROUTE110_TRICK_HOUSE_PUZZLE6; + } + + return PUZZLE_NONE; +} + +static void RotatingGate_ResetAllGateOrientations(void) +{ + s32 i; + u8 *ptr; + + ptr = (u8 *)GetVarPointer(VAR_0x4000); + + for (i = 0; i < gRotatingGate_PuzzleCount; i++) + { + ptr[i] = gRotatingGate_PuzzleConfig[i].orientation; + } +} + +static s32 RotatingGate_GetGateOrientation(u8 gateId) +{ + return ((u8 *)GetVarPointer(VAR_0x4000))[gateId]; +} + +static void RotatingGate_SetGateOrientation(u8 gateId, u8 orientation) +{ + ((u8 *)GetVarPointer(VAR_0x4000))[gateId] = orientation; +} + +static void RotatingGate_RotateInDirection(u8 gateId, u32 rotationDirection) +{ + u8 orientation = RotatingGate_GetGateOrientation(gateId); + + if (rotationDirection == ROTATE_ANTICLOCKWISE) + { + if (orientation) + orientation--; + else + orientation = GATE_ORIENTATION_270; + } + else + { + orientation = ++orientation % GATE_ORIENTATION_MAX; + } + RotatingGate_SetGateOrientation(gateId, orientation); +} + +static void RotatingGate_LoadPuzzleConfig(void) +{ + s32 puzzleType = GetCurrentMapRotatingGatePuzzleType(); + u32 i; + + switch (puzzleType) + { + case PUZZLE_FORTREE_CITY_GYM: + gRotatingGate_PuzzleConfig = sRotatingGate_FortreePuzzleConfig; + gRotatingGate_PuzzleCount = + sizeof(sRotatingGate_FortreePuzzleConfig) / sizeof(struct RotatingGatePuzzle); + break; + case PUZZLE_ROUTE110_TRICK_HOUSE_PUZZLE6: + gRotatingGate_PuzzleConfig = sRotatingGate_TrickHousePuzzleConfig; + gRotatingGate_PuzzleCount = + sizeof(sRotatingGate_TrickHousePuzzleConfig) / sizeof(struct RotatingGatePuzzle); + break; + case PUZZLE_NONE: + default: + return; + } + + for (i = 0; i < ROTATING_GATE_PUZZLE_MAX - 1; i++) + { + gRotatingGate_GateSpriteIds[i] = MAX_SPRITES; + } +} + +static void RotatingGate_CreateGatesWithinViewport(s16 deltaX, s16 deltaY) +{ + u8 i; + + // Calculate the bounding box of the camera + // Same as RotatingGate_DestroyGatesOutsideViewport + s16 x = gSaveBlock1Ptr->pos.x - 2; + s16 x2 = gSaveBlock1Ptr->pos.x + 0x11; + s16 y = gSaveBlock1Ptr->pos.y - 2; + s16 y2 = gSaveBlock1Ptr->pos.y + 0xe; + + s16 x3, y3; + + for (i = 0; i < gRotatingGate_PuzzleCount; i++) + { + x3 = gRotatingGate_PuzzleConfig[i].x + 7; + y3 = gRotatingGate_PuzzleConfig[i].y + 7; + + if (y <= y3 && y2 >= y3 && x <= x3 && x2 >= x3 && + gRotatingGate_GateSpriteIds[i] == MAX_SPRITES) + { + gRotatingGate_GateSpriteIds[i] = RotatingGate_CreateGate(i, deltaX, deltaY); + } + } +} + +static u8 RotatingGate_CreateGate(u8 gateId, s16 deltaX, s16 deltaY) +{ + struct Sprite *sprite; + struct SpriteTemplate template; + const struct RotatingGatePuzzle *gate; + u8 spriteId; + s16 x, y; + + gate = &gRotatingGate_PuzzleConfig[gateId]; + + if (gate->shape == GATE_SHAPE_L1 || gate->shape == GATE_SHAPE_T1) + template = sSpriteTemplate_RotatingGateRegular; + else + template = sSpriteTemplate_RotatingGateLarge; + + template.tileTag = gate->shape + ROTATING_GATE_TILE_TAG; + + spriteId = CreateSprite(&template, 0, 0, 0x94); + if (spriteId == MAX_SPRITES) + return MAX_SPRITES; + + x = gate->x + 7; + y = gate->y + 7; + + sprite = &gSprites[spriteId]; + sprite->data[0] = gateId; + sprite->coordOffsetEnabled = 1; + + sub_8092FF0(x + deltaX, y + deltaY, &sprite->pos1.x, &sprite->pos1.y); + RotatingGate_HideGatesOutsideViewport(sprite); + StartSpriteAffineAnim(sprite, RotatingGate_GetGateOrientation(gateId)); + + return spriteId; +} + +static void SpriteCallback_RotatingGate(struct Sprite *sprite) +{ + u8 rotationDirection; + u8 orientation; + u8 affineAnimation; + + rotationDirection = sprite->data[1]; + orientation = sprite->data[2]; + + RotatingGate_HideGatesOutsideViewport(sprite); + + if (rotationDirection == ROTATE_ANTICLOCKWISE) + { + affineAnimation = orientation + 4; + + if (GetPlayerSpeed() != 1) + affineAnimation += 8; + + PlaySE(SE_HI_TURUN); + StartSpriteAffineAnim(sprite, affineAnimation); + } + else if (rotationDirection == ROTATE_CLOCKWISE) + { + affineAnimation = orientation + 8; + + if (GetPlayerSpeed() != 1) + affineAnimation += 8; + + PlaySE(SE_HI_TURUN); + StartSpriteAffineAnim(sprite, affineAnimation); + } + + sprite->data[1] = ROTATE_NONE; +} + +static void RotatingGate_HideGatesOutsideViewport(struct Sprite *sprite) +{ + u16 x; + s16 x2; + u16 y; + s16 y2; + + sprite->invisible = FALSE; + x = sprite->pos1.x + sprite->pos2.x + sprite->centerToCornerVecX + gSpriteCoordOffsetX; + y = sprite->pos1.y + sprite->pos2.y + sprite->centerToCornerVecY + gSpriteCoordOffsetY; + + x2 = x + 0x40; // Dimensions of the rotating gate + y2 = y + 0x40; + + if ((s16)x > DISPLAY_WIDTH + 0x10 - 1 || x2 < -0x10) + { + sprite->invisible = TRUE; + } + + if ((s16)y > DISPLAY_HEIGHT + 0x10 - 1 || y2 < -0x10) + { + sprite->invisible = TRUE; + } +} + +static void LoadRotatingGatePics(void) +{ + LoadSpriteSheets(sRotatingGatesGraphicsTable); +} + +/* +static*/ void RotatingGate_DestroyGatesOutsideViewport(void) +{ + s16 x; + s16 x2; + s16 y; + s16 y2; + s16 xGate; + s16 yGate; + s32 i; + struct Sprite *sprite; + + // Same as RotatingGate_CreateGatesWithinViewport + x = gSaveBlock1Ptr->pos.x - 2; + x2 = gSaveBlock1Ptr->pos.x + 0x11; + y = gSaveBlock1Ptr->pos.y - 2; + y2 = gSaveBlock1Ptr->pos.y + 0xe; + + for (i = 0; i < gRotatingGate_PuzzleCount; i++) + { + xGate = gRotatingGate_PuzzleConfig[i].x + 7; + yGate = gRotatingGate_PuzzleConfig[i].y + 7; + + if (gRotatingGate_GateSpriteIds[i] == MAX_SPRITES) + continue; + + if (xGate < x || xGate > x2 || yGate < y || yGate > y2) + { + sprite = &gSprites[gRotatingGate_GateSpriteIds[i]]; + FreeSpriteOamMatrix(sprite); + DestroySprite(sprite); + gRotatingGate_GateSpriteIds[i] = MAX_SPRITES; + } + } +} + + +#ifdef NONMATCHING +bool8 MapGridIsImpassableAt(s32, s32); //fool the compiler + +static s32 RotatingGate_CanRotate(u8 gateId, s16 rotationDirection) +{ + const struct Coords8 *armPos; + u8 orientation; + s16 x; + s16 y; + u8 shape; + u32 shape8; + s32 i; + s32 j; + s32 armOrientation; + const u8 *gateArmCollisionData; + u8 armIndex; + + if (rotationDirection == ROTATE_ANTICLOCKWISE) + armPos = sRotatingGate_ArmPositionsAntiClockwiseRotation; + else if (rotationDirection == ROTATE_CLOCKWISE) + armPos = sRotatingGate_ArmPositionsClockwiseRotation; + else + return FALSE; + + orientation = RotatingGate_GetGateOrientation(gateId); + + shape = gRotatingGate_PuzzleConfig[gateId].shape; + x = gRotatingGate_PuzzleConfig[gateId].x + 7; + y = gRotatingGate_PuzzleConfig[gateId].y + 7; + + + // Loop through the gate's "arms" clockwise (north, south, east, west) + for (i = GATE_ARM_NORTH, shape8 = shape* 4*2 ; i <= GATE_ARM_WEST; i++) + { + // Ensure that no part of the arm collides with the map + for (j = 0, armOrientation = orientation + i, gateArmCollisionData = (u8 *)((u32)sRotatingGate_ArmLayout + shape8 + 2*i); j < GATE_ARM_MAX_LENGTH; j++) + { + armIndex = 2 * (armOrientation % 4) + j; + + if (*gateArmCollisionData) + { + if (MapGridIsImpassableAt(x + armPos[armIndex].deltaX, y + armPos[armIndex].deltaY) == TRUE) + return FALSE; + } + gateArmCollisionData++; + } + } + + return TRUE; +} + +#else +ASM_DIRECT +static s32 RotatingGate_CanRotate(u8 a, s16 rotationDirection) +{ + 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, 0xC\n\ + lsls r0, 24\n\ + lsrs r4, r0, 24\n\ + cmp r1, 0x1\n\ + bne _080FBCFC\n\ + ldr r0, =sRotatingGate_ArmPositionsAntiClockwiseRotation\n\ + mov r10, r0\n\ + b _080FBD08\n\ + .pool\n\ +_080FBCFC:\n\ + cmp r1, 0x2\n\ + beq _080FBD04\n\ +_080FBD00:\n\ + movs r0, 0\n\ + b _080FBD98\n\ +_080FBD04:\n\ + ldr r1, =sRotatingGate_ArmPositionsClockwiseRotation\n\ + mov r10, r1\n\ +_080FBD08:\n\ + adds r0, r4, 0\n\ + bl RotatingGate_GetGateOrientation\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + str r0, [sp]\n\ + ldr r0, =gRotatingGate_PuzzleConfig\n\ + ldr r1, [r0]\n\ + lsls r0, r4, 3\n\ + adds r0, r1\n\ + ldrb r2, [r0, 0x4]\n\ + ldrh r1, [r0]\n\ + adds r1, 0x7\n\ + ldrh r0, [r0, 0x2]\n\ + adds r0, 0x7\n\ + movs r3, 0\n\ + lsls r2, 3\n\ + str r2, [sp, 0x4]\n\ + lsls r1, 16\n\ + asrs r1, 16\n\ + mov r9, r1\n\ + lsls r0, 16\n\ + asrs r0, 16\n\ + mov r8, r0\n\ +_080FBD38:\n\ + movs r6, 0\n\ + ldr r2, [sp]\n\ + adds r7, r2, r3\n\ + lsls r0, r3, 1\n\ + adds r5, r7, 0\n\ + ldr r1, [sp, 0x4]\n\ + adds r0, r1\n\ + ldr r2, =sRotatingGate_ArmLayout\n\ + adds r4, r0, r2\n\ +_080FBD4A:\n\ + adds r0, r5, 0\n\ + cmp r5, 0\n\ + bge _080FBD52\n\ + adds r0, r7, 0x3\n\ +_080FBD52:\n\ + asrs r0, 2\n\ + lsls r0, 2\n\ + subs r0, r5, r0\n\ + lsls r0, 1\n\ + adds r0, r6\n\ + lsls r0, 24\n\ + lsrs r1, r0, 24\n\ + ldrb r0, [r4]\n\ + cmp r0, 0\n\ + beq _080FBD88\n\ + lsls r1, 2\n\ + add r1, r10\n\ + movs r0, 0\n\ + ldrsb r0, [r1, r0]\n\ + add r0, r9\n\ + ldrb r1, [r1, 0x1]\n\ + lsls r1, 24\n\ + asrs r1, 24\n\ + add r1, r8\n\ + str r3, [sp, 0x8]\n\ + bl MapGridIsImpassableAt\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + ldr r3, [sp, 0x8]\n\ + cmp r0, 0x1\n\ + beq _080FBD00\n\ +_080FBD88:\n\ + adds r4, 0x1\n\ + adds r6, 0x1\n\ + cmp r6, 0x1\n\ + ble _080FBD4A\n\ + adds r3, 0x1\n\ + cmp r3, 0x3\n\ + ble _080FBD38\n\ + movs r0, 0x1\n\ +_080FBD98:\n\ + add sp, 0xC\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\ + .pool\n\ +.syntax divided\n"); +} +#endif + +static s32 RotatingGate_HasArm(u8 gateId, u8 armInfo) +{ + s32 isLongArm; + s8 armOrientation; + s32 arm; + s32 shape; + + arm = armInfo >> 1; + isLongArm = armInfo & 1; + + armOrientation = (arm - RotatingGate_GetGateOrientation(gateId) + 4) % 4; + shape = gRotatingGate_PuzzleConfig[gateId].shape; + return sRotatingGate_ArmLayout[shape][armOrientation * 2 + isLongArm]; +} + +static void RotatingGate_TriggerRotationAnimation(u8 gateId, s32 rotationDirection) +{ + struct Sprite *sprite; + + if (gRotatingGate_GateSpriteIds[gateId] != MAX_SPRITES) + { + sprite = &gSprites[gRotatingGate_GateSpriteIds[gateId]]; + sprite->data[1] = rotationDirection; + sprite->data[2] = RotatingGate_GetGateOrientation(gateId); + } +} + +static u8 RotatingGate_GetRotationInfo(u8 direction, s16 x, s16 y) +{ + register const u8 *ptr; + + if (direction == DIR_NORTH) + ptr = sRotatingGate_RotationInfoNorth; + else if (direction == DIR_SOUTH) + ptr = sRotatingGate_RotationInfoSouth; + else if (direction == DIR_WEST) + ptr = sRotatingGate_RotationInfoWest; + else if (direction == DIR_EAST) + ptr = sRotatingGate_RotationInfoEast; + else + return GATE_ROT_NONE; + + return ptr[y * 4 + x]; +} + +void RotatingGate_InitPuzzle(void) +{ + if (GetCurrentMapRotatingGatePuzzleType()) + { + RotatingGate_LoadPuzzleConfig(); + RotatingGate_ResetAllGateOrientations(); + } +} + +void RotatingGatePuzzleCameraUpdate(u16 deltaX, u16 deltaY) +{ + if (GetCurrentMapRotatingGatePuzzleType()) + { + RotatingGate_CreateGatesWithinViewport(deltaX, deltaY); + RotatingGate_DestroyGatesOutsideViewport(); + } +} + +void RotatingGate_InitPuzzleAndGraphics(void) +{ + if (GetCurrentMapRotatingGatePuzzleType()) + { + LoadRotatingGatePics(); + RotatingGate_LoadPuzzleConfig(); + RotatingGate_CreateGatesWithinViewport(0, 0); + } +} + +bool8 CheckForRotatingGatePuzzleCollision(u8 direction, s16 x, s16 y) +{ + s32 i; + + if (!GetCurrentMapRotatingGatePuzzleType()) + return FALSE; + for (i = 0; i < gRotatingGate_PuzzleCount; i++) + { + s16 gateX = gRotatingGate_PuzzleConfig[i].x + 7; + s16 gateY = gRotatingGate_PuzzleConfig[i].y + 7; + + if (gateX - 2 <= x && x <= gateX + 1 && gateY - 2 <= y && y <= gateY + 1) + { + s16 centerX = x - gateX + 2; + s16 centerY = y - gateY + 2; + u8 rotationInfo = RotatingGate_GetRotationInfo(direction, centerX, centerY); + + if (rotationInfo != GATE_ROT_NONE) + { + u8 rotationDirection = ((rotationInfo & 0xF0) >> 4); + u8 armInfo = rotationInfo & 0xF; + + if (RotatingGate_HasArm(i, armInfo)) + { + if (RotatingGate_CanRotate(i, rotationDirection)) + { + RotatingGate_TriggerRotationAnimation(i, rotationDirection); + RotatingGate_RotateInDirection(i, rotationDirection); + return FALSE; + } + return TRUE; + } + } + } + } + return FALSE; +} + +bool8 CheckForRotatingGatePuzzleCollisionWithoutAnimation(u8 direction, s16 x, s16 y) +{ + s32 i; + + if (!GetCurrentMapRotatingGatePuzzleType()) + return FALSE; + for (i = 0; i < gRotatingGate_PuzzleCount; i++) + { + s16 gateX = gRotatingGate_PuzzleConfig[i].x + 7; + s16 gateY = gRotatingGate_PuzzleConfig[i].y + 7; + + if (gateX - 2 <= x && x <= gateX + 1 && gateY - 2 <= y && y <= gateY + 1) + { + s16 centerX = x - gateX + 2; + s16 centerY = y - gateY + 2; + u8 rotationInfo = RotatingGate_GetRotationInfo(direction, centerX, centerY); + + if (rotationInfo != GATE_ROT_NONE) + { + u8 rotationDirection = ((rotationInfo & 0xF0) >> 4); + u8 armInfo = rotationInfo & 0xF; + + if (RotatingGate_HasArm(i, armInfo)) + { + if (!RotatingGate_CanRotate(i, rotationDirection)) + { + return TRUE; + } + } + } + } + } + return FALSE; +} diff --git a/src/script_movement.c b/src/script_movement.c new file mode 100644 index 000000000..bbeb0eedc --- /dev/null +++ b/src/script_movement.c @@ -0,0 +1,233 @@ +#include "global.h" +#include "script_movement.h" +#include "field_map_obj.h" +#include "field_map_obj_helpers.h" +#include "task.h" +#include "util.h" + +// static functions +static void sub_80D33AC(u8); +static u8 sub_80D33F4(void); +static bool8 sub_80D3408(u8, u8, const u8 *); +static u8 sub_80D3474(u8, u8); +static bool8 sub_80D3584(u8, u8); +static void sub_80D35DC(u8, u8, u8, const u8 *); +static void UnfreezeObjects(u8); +static void sub_80D3660(u8); +static void sub_80A2490(u8, u8, u8, const u8 *); + +// EWRAM_DATA +static EWRAM_DATA const u8 *gUnknown_02039D90[16] = {0}; + +// text +bool8 ScriptMovement_StartObjectMovementScript(u8 localId, u8 mapNum, u8 mapGroup, const u8 *movementScript) +{ + u8 mapObjId; + + if (TryGetFieldObjectIdByLocalIdAndMap(localId, mapNum, mapGroup, &mapObjId)) + return TRUE; + if (!FuncIsActiveTask(sub_80D3660)) + sub_80D33AC(50); + return sub_80D3408(sub_80D33F4(), mapObjId, movementScript); +} + +bool8 ScriptMovement_IsObjectMovementFinished(u8 localId, u8 mapNum, u8 mapBank) +{ + u8 mapObjId; + u8 r4; + u8 r1; + + if (TryGetFieldObjectIdByLocalIdAndMap(localId, mapNum, mapBank, &mapObjId)) + return TRUE; + r4 = sub_80D33F4(); + r1 = sub_80D3474(r4, mapObjId); + if (r1 == 16) + return TRUE; + return sub_80D3584(r4, r1); +} + +void sub_80D338C(void) +{ + u8 taskId; + + taskId = sub_80D33F4(); + if (taskId != 0xFF) + { + UnfreezeObjects(taskId); + DestroyTask(taskId); + } +} + + +static void sub_80D33AC(u8 priority) +{ + u8 taskId; + u8 i; + + taskId = CreateTask(sub_80D3660, priority); + for (i = 1; i < 16; i++) + gTasks[taskId].data[i] = 0xFFFF; +} + +static u8 sub_80D33F4(void) +{ + return FindTaskIdByFunc(sub_80D3660); +} + +static bool8 sub_80D3408(u8 taskId, u8 mapObjId, const u8 *movementScript) +{ + u8 r4; + + r4 = sub_80D3474(taskId, mapObjId); + if (r4 != 16) + { + if (sub_80D3584(taskId, r4) == 0) + { + return TRUE; + } + else + { + sub_80D35DC(taskId, r4, mapObjId, movementScript); + return FALSE; + } + } + r4 = sub_80D3474(taskId, 0xFF); + if (r4 == 16) + { + return TRUE; + } + else + { + sub_80D35DC(taskId, r4, mapObjId, movementScript); + return FALSE; + } +} + +static u8 sub_80D3474(u8 taskId, u8 b) +{ + u8 *ptr; + u8 i; + + ptr = (u8 *)&gTasks[taskId].data[1]; + for (i = 0; i < 16; i++, ptr++) + { + if (*ptr == b) + return i; + } + return 16; +} + +static void sub_80D34B0(u8 taskId, u8 b, u8 **c) +{ + u8 i; + + *c = (u8 *)&gTasks[taskId].data[1]; + for (i = 0; i < b; i++, (*c)++) + ; +} + +static void sub_80D34E4(u8 taskId, u8 b, u8 c) +{ + u8 *ptr; + + sub_80D34B0(taskId, b, &ptr); + *ptr = c; //what is this supposed to do? +} + +static void sub_80D3508(u8 taskId, u8 b, u8 *c) +{ + u8 *ptr; + + sub_80D34B0(taskId, b, &ptr); + *c = *ptr; +} + +static void sub_80D352C(u8 a, u8 b) +{ + u16 var = ~gBitTable[b]; + + gTasks[a].data[0] &= var; +} + +static void sub_80D355C(u8 taskId, u8 b) +{ + gTasks[taskId].data[0] |= gBitTable[b]; +} + +static bool8 sub_80D3584(u8 taskId, u8 b) +{ + u16 var = (u16)gTasks[taskId].data[0] & gBitTable[b]; + + if (var != 0) + return TRUE; + else + return FALSE; +} + +static void npc_obj_offscreen_culling_and_flag_update(u8 a, const u8 *movementScript) +{ + gUnknown_02039D90[a] = movementScript; +} + +static const u8 *sub_80D35CC(u8 a) +{ + return gUnknown_02039D90[a]; +} + +static void sub_80D35DC(u8 taskId, u8 b, u8 mapObjId, const u8 *movementScript) +{ + sub_80D352C(taskId, b); + npc_obj_offscreen_culling_and_flag_update(b, movementScript); + sub_80D34E4(taskId, b, mapObjId); +} + +static void UnfreezeObjects(u8 taskId) +{ + u8 *pMapObjId; + u8 i; + + pMapObjId = (u8 *)&gTasks[taskId].data[1]; + for (i = 0; i < 16; i++, pMapObjId++) + { + if (*pMapObjId != 0xFF) + npc_sync_anim_pause_bits(&gMapObjects[*pMapObjId]); + } +} + +static void sub_80D3660(u8 taskId) +{ + u8 i; + u8 var; + + for (i = 0; i < 16; i++) + { + sub_80D3508(taskId, i, &var); + if (var != 0xFF) + sub_80A2490(taskId, i, var, sub_80D35CC(i)); + } +} + +static void sub_80A2490(u8 taskId, u8 b, u8 mapObjId, const u8 *d) +{ + u8 var; + + if (FieldObjectIsSpecialAnimActive(&gMapObjects[mapObjId]) + && !FieldObjectClearAnimIfSpecialAnimFinished(&gMapObjects[mapObjId])) + return; + + var = *d; + if (var == 0xFE) + { + sub_80D355C(taskId, b); + FreezeMapObject(&gMapObjects[mapObjId]); + } + else + { + if (!FieldObjectSetSpecialAnim(&gMapObjects[mapObjId], var)) + { + d++; + npc_obj_offscreen_culling_and_flag_update(b, d); + } + } +} + diff --git a/src/text_window.c b/src/text_window.c index 33cd7cffe..c3b9f7197 100644 --- a/src/text_window.c +++ b/src/text_window.c @@ -7,26 +7,26 @@ #include "graphics.h" // const rom data -const u32 gTextWindowFrame1_Gfx[] = INCBIN_U32("graphics/text_window/1.4bpp"); -static const u32 sTextWindowFrame2_Gfx[] = INCBIN_U32("graphics/text_window/2.4bpp"); -static const u32 sTextWindowFrame3_Gfx[] = INCBIN_U32("graphics/text_window/3.4bpp"); -static const u32 sTextWindowFrame4_Gfx[] = INCBIN_U32("graphics/text_window/4.4bpp"); -static const u32 sTextWindowFrame5_Gfx[] = INCBIN_U32("graphics/text_window/5.4bpp"); -static const u32 sTextWindowFrame6_Gfx[] = INCBIN_U32("graphics/text_window/6.4bpp"); -static const u32 sTextWindowFrame7_Gfx[] = INCBIN_U32("graphics/text_window/7.4bpp"); -static const u32 sTextWindowFrame8_Gfx[] = INCBIN_U32("graphics/text_window/8.4bpp"); -static const u32 sTextWindowFrame9_Gfx[] = INCBIN_U32("graphics/text_window/9.4bpp"); -static const u32 sTextWindowFrame10_Gfx[] = INCBIN_U32("graphics/text_window/10.4bpp"); -static const u32 sTextWindowFrame11_Gfx[] = INCBIN_U32("graphics/text_window/11.4bpp"); -static const u32 sTextWindowFrame12_Gfx[] = INCBIN_U32("graphics/text_window/12.4bpp"); -static const u32 sTextWindowFrame13_Gfx[] = INCBIN_U32("graphics/text_window/13.4bpp"); -static const u32 sTextWindowFrame14_Gfx[] = INCBIN_U32("graphics/text_window/14.4bpp"); -static const u32 sTextWindowFrame15_Gfx[] = INCBIN_U32("graphics/text_window/15.4bpp"); -static const u32 sTextWindowFrame16_Gfx[] = INCBIN_U32("graphics/text_window/16.4bpp"); -static const u32 sTextWindowFrame17_Gfx[] = INCBIN_U32("graphics/text_window/17.4bpp"); -static const u32 sTextWindowFrame18_Gfx[] = INCBIN_U32("graphics/text_window/18.4bpp"); -static const u32 sTextWindowFrame19_Gfx[] = INCBIN_U32("graphics/text_window/19.4bpp"); -static const u32 sTextWindowFrame20_Gfx[] = INCBIN_U32("graphics/text_window/20.4bpp"); +const u8 gTextWindowFrame1_Gfx[] = INCBIN_U8("graphics/text_window/1.4bpp"); +static const u8 sTextWindowFrame2_Gfx[] = INCBIN_U8("graphics/text_window/2.4bpp"); +static const u8 sTextWindowFrame3_Gfx[] = INCBIN_U8("graphics/text_window/3.4bpp"); +static const u8 sTextWindowFrame4_Gfx[] = INCBIN_U8("graphics/text_window/4.4bpp"); +static const u8 sTextWindowFrame5_Gfx[] = INCBIN_U8("graphics/text_window/5.4bpp"); +static const u8 sTextWindowFrame6_Gfx[] = INCBIN_U8("graphics/text_window/6.4bpp"); +static const u8 sTextWindowFrame7_Gfx[] = INCBIN_U8("graphics/text_window/7.4bpp"); +static const u8 sTextWindowFrame8_Gfx[] = INCBIN_U8("graphics/text_window/8.4bpp"); +static const u8 sTextWindowFrame9_Gfx[] = INCBIN_U8("graphics/text_window/9.4bpp"); +static const u8 sTextWindowFrame10_Gfx[] = INCBIN_U8("graphics/text_window/10.4bpp"); +static const u8 sTextWindowFrame11_Gfx[] = INCBIN_U8("graphics/text_window/11.4bpp"); +static const u8 sTextWindowFrame12_Gfx[] = INCBIN_U8("graphics/text_window/12.4bpp"); +static const u8 sTextWindowFrame13_Gfx[] = INCBIN_U8("graphics/text_window/13.4bpp"); +static const u8 sTextWindowFrame14_Gfx[] = INCBIN_U8("graphics/text_window/14.4bpp"); +static const u8 sTextWindowFrame15_Gfx[] = INCBIN_U8("graphics/text_window/15.4bpp"); +static const u8 sTextWindowFrame16_Gfx[] = INCBIN_U8("graphics/text_window/16.4bpp"); +static const u8 sTextWindowFrame17_Gfx[] = INCBIN_U8("graphics/text_window/17.4bpp"); +static const u8 sTextWindowFrame18_Gfx[] = INCBIN_U8("graphics/text_window/18.4bpp"); +static const u8 sTextWindowFrame19_Gfx[] = INCBIN_U8("graphics/text_window/19.4bpp"); +static const u8 sTextWindowFrame20_Gfx[] = INCBIN_U8("graphics/text_window/20.4bpp"); const u16 gTextWindowFrame1_Pal[] = INCBIN_U16("graphics/text_window/1.gbapal"); static const u16 sTextWindowFrame2_Pal[] = INCBIN_U16("graphics/text_window/2.gbapal"); |