diff options
Diffstat (limited to 'src')
51 files changed, 8809 insertions, 193 deletions
diff --git a/src/battle_anim_sound_tasks.c b/src/battle_anim_sound_tasks.c index e956fd44f..2316b9759 100644 --- a/src/battle_anim_sound_tasks.c +++ b/src/battle_anim_sound_tasks.c @@ -386,7 +386,7 @@ void sub_8159308(u8 taskId) DestroyAnimVisualTask(taskId); } #else -ASM_DIRECT +NAKED void sub_8159308(u8 taskId) { asm_unified(" push {r4,r5,lr}\n\ diff --git a/src/battle_interface.c b/src/battle_interface.c index 0a8bf3ed7..9ef45020d 100644 --- a/src/battle_interface.c +++ b/src/battle_interface.c @@ -648,7 +648,7 @@ static void sub_8072308(s16 arg0, u16 *arg1, u8 arg2) } #else -ASM_DIRECT +NAKED static void sub_8072308(s16 arg0, u16 *arg1, u8 arg2) { asm(".syntax unified\n\ diff --git a/src/battle_main.c b/src/battle_main.c index 70eebed85..8649209c0 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -1830,7 +1830,7 @@ static void FreeRestoreBattleData(void) gScanlineEffect.state = 3; gMain.inBattle = 0; ZeroEnemyPartyMons(); - m4aSongNumStop(0x5A); + m4aSongNumStop(SE_HINSI); FreeMonSpritesGfx(); FreeBattleSpritesData(); FreeBattleResources(); @@ -3591,7 +3591,7 @@ static void BattleIntroOpponent1SendsOutMonAnimation(void) gBattleMainFunc = BattleIntroRecordMonsToDex; } #else -ASM_DIRECT +NAKED static void BattleIntroOpponent1SendsOutMonAnimation(void) { asm(".syntax unified\n\ @@ -5224,7 +5224,7 @@ static void ReturnFromBattleToOverworld(void) SetRoamerInactive(); } - m4aSongNumStop(0x5A); + m4aSongNumStop(SE_HINSI); SetMainCallback2(gMain.savedCallback); } diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index d1a18e38f..811aba128 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -3357,7 +3357,7 @@ static void atk23_getexp(void) if (!(gBattleTypeFlags & BATTLE_TYPE_TRAINER) && gBattleMons[0].hp && !gBattleStruct->wildVictorySong) { BattleStopLowHpSound(); - PlayBGM(0x161); + PlayBGM(MUS_KACHI2); gBattleStruct->wildVictorySong++; } @@ -3608,7 +3608,7 @@ static void atk24(void) } } #else -ASM_DIRECT +NAKED static void atk24(void) { asm("\n\ diff --git a/src/battle_setup.c b/src/battle_setup.c index 97e8f7041..48a2ef257 100644 --- a/src/battle_setup.c +++ b/src/battle_setup.c @@ -51,8 +51,6 @@ struct TrainerBattleParameter u8 ptrType; }; -extern void (*gFieldCallback)(void); - extern bool8 InBattlePyramid(void); extern bool8 InBattlePike(void); extern bool32 InTrainerHill(void); @@ -396,7 +394,7 @@ static void DoStandardWildBattle(void) gBattleTypeFlags = 0; if (InBattlePyramid()) { - VarSet(VAR_0x400E, 0); + VarSet(VAR_TEMP_E, 0); gBattleTypeFlags |= BATTLE_TYPE_PYRAMID; } CreateBattleStartTask(GetWildBattleTransition(), 0); @@ -1260,7 +1258,7 @@ void BattleSetup_StartTrainerBattle(void) if (InBattlePyramid()) { - VarSet(VAR_0x400E, 0); + VarSet(VAR_TEMP_E, 0); gBattleTypeFlags |= BATTLE_TYPE_PYRAMID; if (gNoOfApproachingTrainers == 2) diff --git a/src/battle_tv.c b/src/battle_tv.c index 777b4846f..e5d97be30 100644 --- a/src/battle_tv.c +++ b/src/battle_tv.c @@ -812,7 +812,7 @@ void TryPutLinkBattleTvShowOnAir(void) } #else -ASM_DIRECT +NAKED void TryPutLinkBattleTvShowOnAir(void) { asm_unified( diff --git a/src/berry_blender.c b/src/berry_blender.c index c3b0cc80d..2edb14748 100644 --- a/src/berry_blender.c +++ b/src/berry_blender.c @@ -151,15 +151,14 @@ extern const u8 gText_Space[]; extern const u8 gText_BlenderMaxSpeedRecord[]; extern const u8 gText_234Players[]; -extern void sub_81978B0(u16); extern void sub_800A418(void); extern u8 sub_800A9D8(void); -extern bool8 sub_800A4D8(u8); extern void sub_809882C(u8, u16, u8); extern void copy_textbox_border_tile_patterns_to_vram(u8, u16, u8); extern void sub_81AABF0(void (*callback)(void)); extern void sub_800B4C0(void); extern void ClearLinkCallback(void); +extern void sub_8009F8C(void); extern void sub_8153430(void); extern bool8 sub_8153474(void); extern void sub_80EECEC(void); @@ -818,7 +817,7 @@ static bool8 LoadBerryBlenderGfx(void) switch (sBerryBlenderData->loadGfxState) { case 0: - sBerryBlenderData->tilesBuffer = AllocZeroed(sub_8034974(sBlenderCenterGfx) + 100); + sBerryBlenderData->tilesBuffer = AllocZeroed(GetDecompressedDataSize(sBlenderCenterGfx) + 100); LZDecompressWram(sBlenderCenterGfx, sBerryBlenderData->tilesBuffer); sBerryBlenderData->loadGfxState++; break; @@ -829,7 +828,7 @@ static bool8 LoadBerryBlenderGfx(void) sBerryBlenderData->loadGfxState++; break; case 2: - LoadBgTiles(2, sBerryBlenderData->tilesBuffer, sub_8034974(sBlenderCenterGfx), 0); + LoadBgTiles(2, sBerryBlenderData->tilesBuffer, GetDecompressedDataSize(sBlenderCenterGfx), 0); sBerryBlenderData->loadGfxState++; break; case 3: @@ -837,7 +836,7 @@ static bool8 LoadBerryBlenderGfx(void) sBerryBlenderData->loadGfxState++; break; case 4: - LoadBgTiles(1, sBerryBlenderData->tilesBuffer, sub_8034974(gUnknown_08D91DB8), 0); + LoadBgTiles(1, sBerryBlenderData->tilesBuffer, GetDecompressedDataSize(gUnknown_08D91DB8), 0); sBerryBlenderData->loadGfxState++; break; case 5: @@ -845,7 +844,7 @@ static bool8 LoadBerryBlenderGfx(void) sBerryBlenderData->loadGfxState++; break; case 6: - CopyToBgTilemapBuffer(1, sBerryBlenderData->tilesBuffer, sub_8034974(gUnknown_08D927EC), 0); + CopyToBgTilemapBuffer(1, sBerryBlenderData->tilesBuffer, GetDecompressedDataSize(gUnknown_08D927EC), 0); CopyBgTilemapBufferToVram(1); sBerryBlenderData->loadGfxState++; break; @@ -463,7 +463,7 @@ bool8 IsDma3ManagerBusyWithBgCopy(void) return FALSE; } #else -ASM_DIRECT +NAKED bool8 IsDma3ManagerBusyWithBgCopy(void) { asm("push {r4-r7,lr}\n\ @@ -1048,7 +1048,7 @@ void CopyRectToBgTilemapBufferRect(u8 bg, const void* src, u8 srcX, u8 srcY, u8 } } }*/ -ASM_DIRECT +NAKED void CopyRectToBgTilemapBufferRect(u8 bg, const void* src, u8 srcX, u8 srcY, u8 srcWidth, u8 srcHeight, u8 destX, u8 destY, u8 rectWidth, u8 rectHeight, u8 palette1, u16 tileOffset, u16 palette2) { asm("push {r4-r7,lr}\n\ @@ -1495,7 +1495,7 @@ void CopyTileMapEntry(u16 *src, u16 *dest, s32 palette1, u32 tileOffset, u32 pal *dest = test; } #else -ASM_DIRECT +NAKED void CopyTileMapEntry(u16 *src, u16 *dest, s32 palette1, u32 tileOffset, u32 palette2) { asm("push {r4-r6,lr}\n\ diff --git a/src/bike.c b/src/bike.c index 782eceb8e..e827707cd 100644 --- a/src/bike.c +++ b/src/bike.c @@ -13,7 +13,6 @@ extern bool8 gBikeCyclingChallenge; extern u8 gBikeCollisions; -extern u8 sub_8093514(u8 direction); extern u8 sub_808B980(u8 direction); extern u8 sub_808B9BC(u8 direction); extern u8 sub_808B9A4(u8 direction); diff --git a/src/daycare.c b/src/daycare.c index d567ff79a..5a6aa2b40 100644 --- a/src/daycare.c +++ b/src/daycare.c @@ -1,5 +1,6 @@ #include "global.h" #include "pokemon.h" +#include "battle.h" #include "daycare.h" #include "string_util.h" #include "constants/species.h" @@ -22,8 +23,6 @@ #define EGG_MOVES_ARRAY_COUNT 10 #define EGG_LVL_UP_MOVES_ARRAY_COUNT 50 -extern u16 gMoveToLearn; - // text extern const u8 gText_MaleSymbol4[]; extern const u8 gText_FemaleSymbol4[]; @@ -48,7 +47,7 @@ extern void sub_81B9328(void); extern void CB2_ReturnToField(void); // this file's functions -static void ClearDaycareMonMisc(struct DaycareMiscMon *misc); +static void ClearDaycareMonMail(struct DayCareMail *mail); static void SetInitialEggData(struct Pokemon *mon, u16 species, struct DayCare *daycare); static u8 GetDaycareCompatibilityScore(struct DayCare *daycare); static void DaycarePrintMonInfo(u8 windowId, s32 daycareSlotId, u8 y); @@ -180,13 +179,13 @@ static void StorePokemonInDaycare(struct Pokemon *mon, struct DaycareMon *daycar { u8 mailId; - StringCopy(daycareMon->misc.OT_name, gSaveBlock2Ptr->playerName); - GetMonNick(mon, daycareMon->misc.monName); - StripExtCtrlCodes(daycareMon->misc.monName); - daycareMon->misc.gameLanguage = LANGUAGE_ENGLISH; - daycareMon->misc.monLanguage = GetMonData(mon, MON_DATA_LANGUAGE); + StringCopy(daycareMon->mail.OT_name, gSaveBlock2Ptr->playerName); + GetMonNick(mon, daycareMon->mail.monName); + StripExtCtrlCodes(daycareMon->mail.monName); + daycareMon->mail.gameLanguage = LANGUAGE_ENGLISH; + daycareMon->mail.monLanguage = GetMonData(mon, MON_DATA_LANGUAGE); mailId = GetMonData(mon, MON_DATA_MAIL); - daycareMon->misc.mail = gSaveBlock1Ptr->mail[mailId]; + daycareMon->mail.message = gSaveBlock1Ptr->mail[mailId]; TakeMailFromMon(mon); } @@ -220,10 +219,10 @@ static void ShiftDaycareSlots(struct DayCare *daycare) daycare->mons[0].mon = daycare->mons[1].mon; ZeroBoxMonData(&daycare->mons[1].mon); - daycare->mons[0].misc = daycare->mons[1].misc; + daycare->mons[0].mail = daycare->mons[1].mail; daycare->mons[0].steps = daycare->mons[1].steps; daycare->mons[1].steps = 0; - ClearDaycareMonMisc(&daycare->mons[1].misc); + ClearDaycareMonMail(&daycare->mons[1].mail); } } @@ -278,10 +277,10 @@ static u16 TakeSelectedPokemonFromDaycare(struct DaycareMon *daycareMon) } gPlayerParty[PARTY_SIZE - 1] = pokemon; - if (daycareMon->misc.mail.itemId) + if (daycareMon->mail.message.itemId) { - GiveMailToMon2(&gPlayerParty[PARTY_SIZE - 1], &daycareMon->misc.mail); - ClearDaycareMonMisc(&daycareMon->misc); + GiveMailToMon2(&gPlayerParty[PARTY_SIZE - 1], &daycareMon->mail.message); + ClearDaycareMonMail(&daycareMon->mail); } ZeroBoxMonData(&daycareMon->mon); @@ -365,23 +364,23 @@ u8 GetNumLevelsGainedFromDaycare(void) return 0; } -static void ClearDaycareMonMisc(struct DaycareMiscMon *misc) +static void ClearDaycareMonMail(struct DayCareMail *mail) { s32 i; for (i = 0; i < OT_NAME_LENGTH + 1; i++) - misc->OT_name[i] = 0; + mail->OT_name[i] = 0; for (i = 0; i < POKEMON_NAME_LENGTH + 1; i++) - misc->monName[i] = 0; + mail->monName[i] = 0; - ClearMailStruct(&misc->mail); + ClearMailStruct(&mail->message); } static void ClearDaycareMon(struct DaycareMon *daycareMon) { ZeroBoxMonData(&daycareMon->mon); daycareMon->steps = 0; - ClearDaycareMonMisc(&daycareMon->misc); + ClearDaycareMonMail(&daycareMon->mail); } static void ClearAllDaycareData(struct DayCare *daycare) diff --git a/src/decompress.c b/src/decompress.c index fb288bf4a..83a9db0b6 100644 --- a/src/decompress.c +++ b/src/decompress.c @@ -117,7 +117,7 @@ void Unused_LZDecompressWramIndirect(const void **src, void *dest) } // This one (unused) function is really challenging, won't even try to decompile it. -ASM_DIRECT +NAKED void sub_803471C() { asm(".syntax unified\n\ @@ -459,7 +459,7 @@ _08034964:\n\ .syntax divided"); } -u32 sub_8034974(const u8 *ptr) +u32 GetDecompressedDataSize(const u8 *ptr) { return (ptr[3] << 16) | (ptr[2] << 8) | (ptr[1]); } diff --git a/src/decoration.c b/src/decoration.c index f376c2115..08287a3cc 100644 --- a/src/decoration.c +++ b/src/decoration.c @@ -21,7 +21,6 @@ #include "list_menu.h" #include "menu_helpers.h" #include "menu.h" -#include "menu_indicators.h" #include "sound.h" #include "event_scripts.h" #include "event_data.h" @@ -38,8 +37,6 @@ #include "decoration.h" #include "graphics.h" -extern void (*gFieldCallback)(void); - // Static type declarations #define OVERWORLD_PLACE_DECOR_SELECTOR_PAL_TAG 0xbe5 @@ -1294,7 +1291,7 @@ void sub_8128060(u8 taskId) gTasks[taskId].data[2] = 2; break; case 2: - if (sub_80ABDFC() == TRUE) + if (IsWeatherNotFadingIn() == TRUE) { gTasks[taskId].data[12] = 0; sub_8128FD8(taskId); @@ -1710,7 +1707,7 @@ void sub_8128C64(u8 taskId) data[2] ++; break; case 3: - if (sub_80ABDFC() == TRUE) + if (IsWeatherNotFadingIn() == TRUE) { gTasks[taskId].func = sub_812764C; } @@ -2220,7 +2217,7 @@ void sub_81298EC(u8 taskId) gTasks[taskId].data[2] = 3; break; case 3: - if (sub_80ABDFC() == TRUE) + if (IsWeatherNotFadingIn() == TRUE) { StringExpandPlaceholders(gStringVar4, gText_DecorationReturnedToPC); DisplayItemMessageOnField(taskId, gStringVar4, sub_8129D64); @@ -2290,7 +2287,7 @@ void sub_8129ABC(u8 taskId) data[2] = 2; break; case 2: - if (sub_80ABDFC() == TRUE) + if (IsWeatherNotFadingIn() == TRUE) { data[12] = 1; sub_8129B34(taskId); @@ -2616,7 +2613,7 @@ void sub_812A2C4(u8 taskId) data[2] ++; break; case 3: - if (sub_80ABDFC() == TRUE) + if (IsWeatherNotFadingIn() == TRUE) { gTasks[taskId].func = sub_8126B80; } diff --git a/src/dewford_trend.c b/src/dewford_trend.c index 3ceec6563..44b42c123 100644 --- a/src/dewford_trend.c +++ b/src/dewford_trend.c @@ -158,7 +158,7 @@ static void sub_8122804(struct EasyChatPair *s, u16 b, u8 c) } } -void sub_812287C(void *a, u32 b, u8 unused) +void ReceiveEasyChatPairsData(void *a, u32 b, u8 unused) { u16 i, j, r3, players; struct EasyChatPair *buffer1, *buffer2, *src, *dst, *foo_of_buffer2; diff --git a/src/egg_hatch.c b/src/egg_hatch.c index e64a98ab1..1ed38c67e 100644 --- a/src/egg_hatch.c +++ b/src/egg_hatch.c @@ -25,6 +25,7 @@ #include "window.h" #include "constants/abilities.h" #include "daycare.h" +#include "overworld.h" #include "battle.h" // to get rid of later struct EggHatchData @@ -44,8 +45,6 @@ struct EggHatchData u8 textColor[3]; }; -extern void (*gFieldCallback)(void); - extern const struct CompressedSpriteSheet gMonFrontPicTable[]; extern const u8 gBattleTextboxTiles[]; extern const u8 gBattleTextboxTilemap[]; @@ -391,13 +390,13 @@ static bool8 sub_807158C(struct DayCare *daycare, u8 daycareId) struct DaycareMon *daycareMon = &daycare->mons[daycareId]; GetBoxMonNick(&daycareMon->mon, nick); - if (daycareMon->misc.mail.itemId != 0 - && (StringCompareWithoutExtCtrlCodes(nick, daycareMon->misc.monName) != 0 - || StringCompareWithoutExtCtrlCodes(gSaveBlock2Ptr->playerName, daycareMon->misc.OT_name) != 0)) + if (daycareMon->mail.message.itemId != 0 + && (StringCompareWithoutExtCtrlCodes(nick, daycareMon->mail.monName) != 0 + || StringCompareWithoutExtCtrlCodes(gSaveBlock2Ptr->playerName, daycareMon->mail.OT_name) != 0)) { StringCopy(gStringVar1, nick); - TVShowConvertInternationalString(gStringVar2, daycareMon->misc.OT_name, daycareMon->misc.gameLanguage); - TVShowConvertInternationalString(gStringVar3, daycareMon->misc.monName, daycareMon->misc.monLanguage); + TVShowConvertInternationalString(gStringVar2, daycareMon->mail.OT_name, daycareMon->mail.gameLanguage); + TVShowConvertInternationalString(gStringVar3, daycareMon->mail.monName, daycareMon->mail.monLanguage); return TRUE; } return FALSE; @@ -575,10 +574,10 @@ static void Task_EggHatchPlayBGM(u8 taskID) play_some_sound(); } if (gTasks[taskID].data[0] == 1) - PlayBGM(376); + PlayBGM(MUS_ME_SHINKA); if (gTasks[taskID].data[0] > 60) { - PlayBGM(377); + PlayBGM(MUS_SHINKA); DestroyTask(taskID); // UB: task is destroyed, yet the value is incremented } diff --git a/src/field_effect.c b/src/field_effect.c index 628dc776a..692090779 100644 --- a/src/field_effect.c +++ b/src/field_effect.c @@ -1,15 +1,3897 @@ // Includes #include "global.h" +#include "field_effect.h" +#include "battle_dome_cards.h" +#include "decompress.h" +#include "field_camera.h" +#include "field_effect_helpers.h" +#include "field_map_obj.h" +#include "field_map_obj_helpers.h" +#include "field_player_avatar.h" +#include "field_screen.h" +#include "field_weather.h" +#include "fieldmap.h" +#include "fldeff_groundshake.h" +#include "gpu_regs.h" +#include "main.h" +#include "menu.h" +#include "metatile_behavior.h" +#include "overworld.h" +#include "palette.h" +#include "party_menu.h" +#include "pokemon.h" +#include "script.h" +#include "sound.h" +#include "sprite.h" +#include "task.h" +#include "trig.h" +#include "util.h" +#include "constants/rgb.h" +#include "constants/songs.h" + +#define subsprite_table(ptr) {.subsprites = ptr, .subspriteCount = (sizeof ptr) / (sizeof(struct Subsprite))} + +EWRAM_DATA s32 gFieldEffectArguments[8] = {0}; // Static type declarations // Static RAM declarations -IWRAM_DATA u8 gUnknown_03000F58[32]; +static IWRAM_DATA u8 sActiveList[32]; // Static ROM declarations +extern u8 *gFieldEffectScriptPointers[]; + // .rodata +const u32 gNewGameBirchPic[] = INCBIN_U32("graphics/birch_speech/birch.4bpp"); +const u32 gUnusedBirchBeauty[] = INCBIN_U32("graphics/unused/intro_birch_beauty.4bpp"); +const u16 gNewGameBirchPalette[16] = INCBIN_U16("graphics/birch_speech/birch.gbapal"); +const u32 gSpriteImage_855A970[] = INCBIN_U32("graphics/misc/pokeball_glow.4bpp"); +const u16 gFieldEffectObjectPalette4[16] = INCBIN_U16("graphics/map_objects/palettes/field_effect_object_palette_04.gbapal"); +const u32 gSpriteImage_855A9B0[] = INCBIN_U32("graphics/misc/pokecenter_monitor/0.4bpp"); +const u32 gSpriteImage_855AA70[] = INCBIN_U32("graphics/misc/pokecenter_monitor/1.4bpp"); +const u32 gSpriteImage_855AB30[] = INCBIN_U32("graphics/misc/big_hof_monitor.4bpp"); +const u8 gSpriteImage_855AD30[] = INCBIN_U8("graphics/misc/small_hof_monitor.4bpp"); +const u16 gFieldEffectObjectPalette5[16] = INCBIN_U16("graphics/map_objects/palettes/field_effect_object_palette_05.gbapal"); + +// Graphics for the lights streaking past your Pokemon when it uses a field move. +const u32 gFieldMoveStreaksTiles[] = INCBIN_U32("graphics/misc/field_move_streaks.4bpp"); +const u16 gFieldMoveStreaksPalette[16] = INCBIN_U16("graphics/misc/field_move_streaks.gbapal"); +const u16 gFieldMoveStreaksTilemap[] = INCBIN_U16("graphics/misc/field_move_streaks_map.bin"); + +// The following light streaks effect is used when the map is dark (e.g. a cave). +const u32 gDarknessFieldMoveStreaksTiles[] = INCBIN_U32("graphics/misc/darkness_field_move_streaks.4bpp"); +const u16 gDarknessFieldMoveStreaksPalette[16] = INCBIN_U16("graphics/misc/darkness_field_move_streaks.gbapal"); +const u16 gDarknessFieldMoveStreaksTilemap[] = INCBIN_U16("graphics/misc/darkness_field_move_streaks_map.bin"); + +const u16 gUnknown_0855B610[16] = INCBIN_U16("graphics/misc/spotlight.gbapal"); +const u8 gUnknown_0855B630[] = INCBIN_U8("graphics/misc/spotlight.4bpp"); +const u8 gUnknown_0855C170[] = INCBIN_U8("graphics/unknown/unknown_55C170.4bpp"); +const u8 gUnknown_0855C190[] = INCBIN_U8("graphics/unknown/unknown_55C190.4bpp"); +const u8 gUnknown_0855C1B0[] = INCBIN_U8("graphics/unknown/unknown_55C1B0.4bpp"); +const u8 gUnknown_0855C1D0[] = INCBIN_U8("graphics/unknown/unknown_55C1D0.4bpp"); + +bool8 (*const gFieldEffectScriptFuncs[])(u8 **, u32 *) = { + FieldEffectCmd_loadtiles, + FieldEffectCmd_loadfadedpal, + FieldEffectCmd_loadpal, + FieldEffectCmd_callnative, + FieldEffectCmd_end, + FieldEffectCmd_loadgfx_callnative, + FieldEffectCmd_loadtiles_callnative, + FieldEffectCmd_loadfadedpal_callnative, +}; + +const struct OamData gNewGameBirchOamAttributes = {.size = 3}; +const struct OamData gOamData_855C218 = {.size = 0}; +const struct OamData gOamData_855C220 = {.size = 1}; + +const struct SpriteFrameImage gNewGameBirchPicTable[] = { + obj_frame_tiles(gNewGameBirchPic) +}; +const struct SpritePalette gNewGameBirchObjectPaletteInfo = {.data = gNewGameBirchPalette, .tag = 0x1006}; + +const union AnimCmd gNewGameBirchImageAnim[] = { + ANIMCMD_FRAME(.imageValue = 0, .duration = 1), + ANIMCMD_END +}; + +const union AnimCmd *const gNewGameBirchImageAnimTable[] = { + gNewGameBirchImageAnim +}; + +const struct SpriteTemplate gNewGameBirchObjectTemplate = { + .tileTag = 0xffff, + .paletteTag = 4102, + .oam = &gNewGameBirchOamAttributes, + .anims = gNewGameBirchImageAnimTable, + .images = gNewGameBirchPicTable, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = SpriteCallbackDummy +}; + +const struct SpritePalette gFieldEffectObjectPaletteInfo4 = {.data = gFieldEffectObjectPalette4, .tag = 0x1007}; +const struct SpritePalette gFieldEffectObjectPaletteInfo5 = {.data = gFieldEffectObjectPalette5, .tag = 0x1010}; +const struct OamData gOamData_855C26C = { + .shape = 1, + .size = 2 +}; + +const struct SpriteFrameImage gSpriteImageTable_855C274[] = { + obj_frame_tiles(gSpriteImage_855A970) +}; + +const struct SpriteFrameImage gSpriteImageTable_855C27C[] = { + obj_frame_tiles(gSpriteImage_855A9B0), + obj_frame_tiles(gSpriteImage_855AA70) +}; + +const struct SpriteFrameImage gSpriteImageTable_855C28C[] = { + obj_frame_tiles(gSpriteImage_855AB30) +}; + +const struct SpriteFrameImage gSpriteImageTable_855C294[] = { + {.data = gSpriteImage_855AD30, .size = 0x200} // the macro breaks down here +}; + +const struct Subsprite gSubspriteTable_855C29C[] = { + {.x = -12, .y = -8, .priority = 2, .tileOffset = 0, .shape = 1, .size = 0}, + {.x = 4, .y = -8, .priority = 2, .tileOffset = 2, .shape = 0, .size = 0}, + {.x = -12, .y = 0, .priority = 2, .tileOffset = 3, .shape = 1, .size = 0}, + {.x = 4, .y = 0, .priority = 2, .tileOffset = 5, .shape = 0, .size = 0} +}; + +const struct SubspriteTable gUnknown_0855C2AC = subsprite_table(gSubspriteTable_855C29C); + +const struct Subsprite gSubspriteTable_855C2B4[] = { + {.x = -32, .y = -8, .priority = 2, .tileOffset = 0, .shape = 1, .size = 1}, + {.x = 0, .y = -8, .priority = 2, .tileOffset = 4, .shape = 1, .size = 1}, + {.x = -32, .y = 0, .priority = 2, .tileOffset = 8, .shape = 1, .size = 1}, + {.x = 0, .y = 0, .priority = 2, .tileOffset = 12, .shape = 1, .size = 1} +}; + +const struct SubspriteTable gUnknown_0855C2C4 = subsprite_table(gSubspriteTable_855C2B4); + +const union AnimCmd gSpriteAnim_855C2CC[] = { + ANIMCMD_FRAME(.imageValue = 0, .duration = 1), + ANIMCMD_JUMP(0) +}; + +const union AnimCmd gSpriteAnim_855C2D4[] = { + ANIMCMD_FRAME(.imageValue = 0, .duration = 16), + ANIMCMD_FRAME(.imageValue = 1, .duration = 16), + ANIMCMD_FRAME(.imageValue = 0, .duration = 16), + ANIMCMD_FRAME(.imageValue = 1, .duration = 16), + ANIMCMD_FRAME(.imageValue = 0, .duration = 16), + ANIMCMD_FRAME(.imageValue = 1, .duration = 16), + ANIMCMD_FRAME(.imageValue = 0, .duration = 16), + ANIMCMD_FRAME(.imageValue = 1, .duration = 16), + ANIMCMD_END +}; + +const union AnimCmd *const gSpriteAnimTable_855C2F8[] = { + gSpriteAnim_855C2CC, + gSpriteAnim_855C2D4 +}; + +const union AnimCmd *const gSpriteAnimTable_855C300[] = { + gSpriteAnim_855C2CC +}; + +const struct SpriteTemplate gSpriteTemplate_855C304 = { + .tileTag = 0xffff, + .paletteTag = 4103, + .oam = &gOamData_855C218, + .anims = gSpriteAnimTable_855C2F8, + .images = gSpriteImageTable_855C274, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = SpriteCB_PokeballGlow +}; + +const struct SpriteTemplate gSpriteTemplate_855C31C = { + .tileTag = 0xffff, + .paletteTag = 4100, + .oam = &gOamData_855C220, + .anims = gSpriteAnimTable_855C2F8, + .images = gSpriteImageTable_855C27C, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = SpriteCB_PokecenterMonitor +}; + +const struct SpriteTemplate gSpriteTemplate_855C334 = { + .tileTag = 0xffff, + .paletteTag = 4112, + .oam = &gOamData_855C220, + .anims = gSpriteAnimTable_855C300, + .images = gSpriteImageTable_855C28C, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = SpriteCB_HallOfFameMonitor +}; + +const struct SpriteTemplate gSpriteTemplate_855C34C = { + .tileTag = 0xffff, + .paletteTag = 4112, + .oam = &gOamData_855C26C, + .anims = gSpriteAnimTable_855C300, + .images = gSpriteImageTable_855C294, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = SpriteCB_HallOfFameMonitor +}; + +void (*const gUnknown_0855C364[])(struct Task *) = { + PokecenterHealEffect_0, + PokecenterHealEffect_1, + PokecenterHealEffect_2, + PokecenterHealEffect_3 +}; + +void (*const gUnknown_0855C374[])(struct Task *) = { + HallOfFameRecordEffect_0, + HallOfFameRecordEffect_1, + HallOfFameRecordEffect_2, + HallOfFameRecordEffect_3 +}; + +void (*const gUnknown_0855C384[])(struct Sprite *) = { + PokeballGlowEffect_0, + PokeballGlowEffect_1, + PokeballGlowEffect_2, + PokeballGlowEffect_3, + PokeballGlowEffect_4, + PokeballGlowEffect_5, + PokeballGlowEffect_6, + PokeballGlowEffect_7 +}; + +const struct Coords16 gUnknown_0855C3A4[] = { + {.x = 0, .y = 0}, + {.x = 6, .y = 0}, + {.x = 0, .y = 4}, + {.x = 6, .y = 4}, + {.x = 0, .y = 8}, + {.x = 6, .y = 8} +}; + +const u8 gUnknown_0855C3BC[] = {16, 12, 8, 0}; +const u8 gUnknown_0855C3C0[] = {16, 12, 8, 0}; +const u8 gUnknown_0855C3C4[] = { 0, 0, 0, 0}; + +bool8 (*const gUnknown_0855C3C8[])(struct Task *) = { + sub_80B6BCC, + sub_80B6C74, + sub_80B6C90, + sub_80B6D04, + sub_80B6DBC, + sub_80B6DD8, + sub_80B6E18, +}; + +bool8 (*const gUnknown_0855C3E4[])(struct Task *) = { + sub_80B6EC0, + sub_80B6EE0, + sub_80B6F50, + sub_80B6F74, + sub_80B6F84, + sub_80B6FA8, +}; + +bool8 (*const gUnknown_0855C3FC[])(struct Task *) = { + sub_80B7114, + sub_80B7190, + sub_80B71D0, + sub_80B7230, + sub_80B7270, + sub_80B72D0, + sub_80B72F4, +}; + +bool8 (*const gUnknown_0855C418[])(struct Task *, struct MapObject *) = { + sub_80B73D0, + waterfall_1_do_anim_probably, + waterfall_2_wait_anim_finish_probably, + sub_80B7450, + sub_80B7478, +}; + +bool8 (*const gUnknown_0855C42C[])(struct Task *) = { + dive_1_lock, + dive_2_unknown, + dive_3_unknown, +}; + +bool8 (*const gUnknown_0855C438[])(struct Task *, struct MapObject *, struct Sprite *) = { + sub_80B764C, + sub_80B7684, + sub_80B76B8, + sub_80B7704, + sub_80B77F8, + sub_80B7814, +}; + +bool8 (*const gUnknown_0855C450[])(struct Task *, struct MapObject *, struct Sprite *) = { + sub_80B78EC, + sub_80B791C, + sub_80B7968, + sub_80B79BC, +}; + +bool8 (*const gUnknown_0855C460[])(struct Task *, struct MapObject *, struct Sprite *) = { + sub_80B7AE8, + sub_80B7B18, + sub_80B7B94, + sub_80B7BCC, + sub_80B7BF4, +}; + +void (*const gUnknown_0855C474[])(struct Task *) = { + sub_80B7D14, + sub_80B7D34, +}; // .text + +u32 FieldEffectStart(u8 id) +{ + u8 *script; + u32 val; + + FieldEffectActiveListAdd(id); + + script = gFieldEffectScriptPointers[id]; + + while (gFieldEffectScriptFuncs[*script](&script, &val)) + ; + + return val; +} + +bool8 FieldEffectCmd_loadtiles(u8 **script, u32 *val) +{ + (*script)++; + FieldEffectScript_LoadTiles(script); + return TRUE; +} + +bool8 FieldEffectCmd_loadfadedpal(u8 **script, u32 *val) +{ + (*script)++; + FieldEffectScript_LoadFadedPalette(script); + return TRUE; +} + +bool8 FieldEffectCmd_loadpal(u8 **script, u32 *val) +{ + (*script)++; + FieldEffectScript_LoadPalette(script); + return TRUE; +} + +bool8 FieldEffectCmd_callnative(u8 **script, u32 *val) +{ + (*script)++; + FieldEffectScript_CallNative(script, val); + return TRUE; +} + +bool8 FieldEffectCmd_end(u8 **script, u32 *val) +{ + return FALSE; +} + +bool8 FieldEffectCmd_loadgfx_callnative(u8 **script, u32 *val) +{ + (*script)++; + FieldEffectScript_LoadTiles(script); + FieldEffectScript_LoadFadedPalette(script); + FieldEffectScript_CallNative(script, val); + return TRUE; +} + +bool8 FieldEffectCmd_loadtiles_callnative(u8 **script, u32 *val) +{ + (*script)++; + FieldEffectScript_LoadTiles(script); + FieldEffectScript_CallNative(script, val); + return TRUE; +} + +bool8 FieldEffectCmd_loadfadedpal_callnative(u8 **script, u32 *val) +{ + (*script)++; + FieldEffectScript_LoadFadedPalette(script); + FieldEffectScript_CallNative(script, val); + return TRUE; +} + +u32 FieldEffectScript_ReadWord(u8 **script) +{ + return (*script)[0] + + ((*script)[1] << 8) + + ((*script)[2] << 16) + + ((*script)[3] << 24); +} + +void FieldEffectScript_LoadTiles(u8 **script) +{ + struct SpriteSheet *sheet = (struct SpriteSheet *)FieldEffectScript_ReadWord(script); + if (GetSpriteTileStartByTag(sheet->tag) == 0xFFFF) + LoadSpriteSheet(sheet); + (*script) += 4; +} + +void FieldEffectScript_LoadFadedPalette(u8 **script) +{ + struct SpritePalette *palette = (struct SpritePalette *)FieldEffectScript_ReadWord(script); + LoadSpritePalette(palette); + UpdateSpritePaletteWithWeather(IndexOfSpritePaletteTag(palette->tag)); + (*script) += 4; +} + +void FieldEffectScript_LoadPalette(u8 **script) +{ + struct SpritePalette *palette = (struct SpritePalette *)FieldEffectScript_ReadWord(script); + LoadSpritePalette(palette); + (*script) += 4; +} + +void FieldEffectScript_CallNative(u8 **script, u32 *val) +{ + u32 (*func)(void) = (u32 (*)(void))FieldEffectScript_ReadWord(script); + *val = func(); + (*script) += 4; +} + +void FieldEffectFreeGraphicsResources(struct Sprite *sprite) +{ + u16 sheetTileStart = sprite->sheetTileStart; + u32 paletteNum = sprite->oam.paletteNum; + DestroySprite(sprite); + FieldEffectFreeTilesIfUnused(sheetTileStart); + FieldEffectFreePaletteIfUnused(paletteNum); +} + +void FieldEffectStop(struct Sprite *sprite, u8 id) +{ + FieldEffectFreeGraphicsResources(sprite); + FieldEffectActiveListRemove(id); +} + +void FieldEffectFreeTilesIfUnused(u16 tileStart) +{ + u8 i; + u16 tag = GetSpriteTileTagByTileStart(tileStart); + + if (tag != 0xFFFF) + { + for (i = 0; i < MAX_SPRITES; i++) + if (gSprites[i].inUse && gSprites[i].usingSheet && tileStart == gSprites[i].sheetTileStart) + return; + FreeSpriteTilesByTag(tag); + } +} + +void FieldEffectFreePaletteIfUnused(u8 paletteNum) +{ + u8 i; + u16 tag = GetSpritePaletteTagByPaletteNum(paletteNum); + + if (tag != 0xFFFF) + { + for (i = 0; i < MAX_SPRITES; i++) + if (gSprites[i].inUse && gSprites[i].oam.paletteNum == paletteNum) + return; + FreeSpritePaletteByTag(tag); + } +} + +void FieldEffectActiveListClear(void) +{ + u8 i; + for (i = 0; i < ARRAY_COUNT(sActiveList); i++) + sActiveList[i] = 0xFF; +} + +void FieldEffectActiveListAdd(u8 id) +{ + u8 i; + for (i = 0; i < ARRAY_COUNT(sActiveList); i++) + { + if (sActiveList[i] == 0xFF) + { + sActiveList[i] = id; + return; + } + } +} + +void FieldEffectActiveListRemove(u8 id) +{ + u8 i; + for (i = 0; i < ARRAY_COUNT(sActiveList); i++) + { + if (sActiveList[i] == id) + { + sActiveList[i] = 0xFF; + return; + } + } +} + +bool8 FieldEffectActiveListContains(u8 id) +{ + u8 i; + for (i = 0; i < ARRAY_COUNT(sActiveList); i++) + if (sActiveList[i] == id) + return TRUE; + return FALSE; +} + +u8 CreateTrainerSprite(u8 trainerSpriteID, s16 x, s16 y, u8 subpriority, u8 *buffer) +{ + struct SpriteTemplate spriteTemplate; + LoadCompressedObjectPaletteOverrideBuffer(&gTrainerFrontPicPaletteTable[trainerSpriteID], buffer); + LoadCompressedObjectPicOverrideBuffer(&gTrainerFrontPicTable[trainerSpriteID], buffer); + spriteTemplate.tileTag = gTrainerFrontPicTable[trainerSpriteID].tag; + spriteTemplate.paletteTag = gTrainerFrontPicPaletteTable[trainerSpriteID].tag; + spriteTemplate.oam = &gNewGameBirchOamAttributes; + spriteTemplate.anims = gDummySpriteAnimTable; + spriteTemplate.images = NULL; + spriteTemplate.affineAnims = gDummySpriteAffineAnimTable; + spriteTemplate.callback = SpriteCallbackDummy; + return CreateSprite(&spriteTemplate, x, y, subpriority); +} + +void LoadTrainerGfx_TrainerCard(u8 gender, u16 palOffset, u8 *dest) +{ + LZDecompressVram(gTrainerFrontPicTable[gender].data, dest); + LoadCompressedPalette(gTrainerFrontPicPaletteTable[gender].data, palOffset, 0x20); +} + +u8 AddNewGameBirchObject(s16 x, s16 y, u8 subpriority) +{ + LoadSpritePalette(&gNewGameBirchObjectPaletteInfo); + return CreateSprite(&gNewGameBirchObjectTemplate, x, y, subpriority); +} + +#ifdef NONMATCHING +u8 CreateMonSprite_PicBox(u16 species, s16 x, s16 y) +{ + u16 spriteId = sub_818D7D8(species, 0, 0x8000, 1, x, y, 0, gMonPaletteTable[species].tag); + PreservePaletteInWeather(IndexOfSpritePaletteTag(gMonPaletteTable[species].tag) + 0x10); + if (spriteId == 0xFFFF) + return 0x40; + + return spriteId; +} +#else +NAKED +u8 CreateMonSprite_PicBox(u16 species, s16 x, s16 y) +{ + asm_unified("push {r4,r5,lr}\n\ + sub sp, 0x10\n\ + lsls r0, 16\n\ + lsrs r0, 16\n\ + movs r3, 0x80\n\ + lsls r3, 8\n\ + lsls r1, 16\n\ + asrs r1, 16\n\ + str r1, [sp]\n\ + lsls r2, 16\n\ + asrs r2, 16\n\ + str r2, [sp, 0x4]\n\ + movs r1, 0\n\ + str r1, [sp, 0x8]\n\ + ldr r1, =gMonPaletteTable\n\ + lsls r4, r0, 3\n\ + adds r4, r1\n\ + ldrh r1, [r4, 0x4]\n\ + str r1, [sp, 0xC]\n\ + movs r1, 0\n\ + adds r2, r3, 0\n\ + movs r3, 0x1\n\ + bl sub_818D7D8\n\ + lsls r0, 16\n\ + lsrs r5, r0, 16\n\ + ldrh r0, [r4, 0x4]\n\ + bl IndexOfSpritePaletteTag\n\ + adds r0, 0x10\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + bl PreservePaletteInWeather\n\ + ldr r0, =0x0000ffff\n\ + cmp r5, r0\n\ + beq _080B5FDC\n\ + lsls r0, r5, 24\n\ + lsrs r0, 24\n\ + b _080B5FDE\n\ + .pool\n\ +_080B5FDC:\n\ + movs r0, 0x40\n\ +_080B5FDE:\n\ + add sp, 0x10\n\ + pop {r4,r5}\n\ + pop {r1}\n\ + bx r1"); +} +#endif //NONMATCHING + +u8 CreateMonSprite_FieldMove(u16 species, u32 d, u32 g, s16 x, s16 y, u8 subpriority) +{ + const struct CompressedSpritePalette *spritePalette = GetMonSpritePalStructFromOtIdPersonality(species, d, g); + u16 spriteId = sub_818D7D8(species, d, g, 1, x, y, 0, spritePalette->tag); + PreservePaletteInWeather(IndexOfSpritePaletteTag(spritePalette->tag) + 0x10); + if (spriteId == 0xFFFF) + return 0x40; + + return spriteId; +} + +void FreeResourcesAndDestroySprite(struct Sprite *sprite, u8 spriteId) +{ + ResetPreservedPalettesInWeather(); + if (sprite->oam.affineMode != 0) + { + FreeOamMatrix(sprite->oam.matrixNum); + } + sub_818D820(spriteId); +} + +#ifdef NONMATCHING +void MultiplyInvertedPaletteRGBComponents(u16 i, u8 r, u8 g, u8 b) +{ + int curRed; + int curGreen; + int curBlue; + + curRed = gPlttBufferUnfaded[i] & 0x1f; + curGreen = (gPlttBufferUnfaded[i] & (0x1f << 5)) >> 5; + curBlue = (gPlttBufferUnfaded[i] & (0x1f << 10)) >> 10; + curRed += (((0x1f - curRed) * r) >> 4); + curGreen += (((0x1f - curGreen) * g) >> 4); + curBlue += (((0x1f - curBlue) * b) >> 4); + gPlttBufferFaded[i] = RGB(curRed, curGreen, curBlue); +} + +void MultiplyPaletteRGBComponents(u16 i, u8 r, u8 g, u8 b) +{ + int curRed; + int curGreen; + int curBlue; + + curRed = gPlttBufferUnfaded[i] & 0x1f; + curGreen = (gPlttBufferUnfaded[i] & (0x1f << 5)) >> 5; + curBlue = (gPlttBufferUnfaded[i] & (0x1f << 10)) >> 10; + curRed -= ((curRed * r) >> 4); + curGreen -= ((curGreen * g) >> 4); + curBlue -= ((curBlue * b) >> 4); + gPlttBufferFaded[i] = RGB(curRed, curGreen, curBlue); +} +#else +NAKED +void MultiplyInvertedPaletteRGBComponents(u16 i, u8 r, u8 g, u8 b) +{ + asm(".syntax unified\n" + "\tpush {r4-r7,lr}\n" + "\tmov r7, r9\n" + "\tmov r6, r8\n" + "\tpush {r6,r7}\n" + "\tlsls r0, 16\n" + "\tlsls r1, 24\n" + "\tlsrs r1, 24\n" + "\tlsls r2, 24\n" + "\tlsrs r2, 24\n" + "\tlsls r3, 24\n" + "\tlsrs r3, 24\n" + "\tldr r4, _08085D00 @ =gPlttBufferUnfaded\n" + "\tlsrs r0, 15\n" + "\tadds r4, r0, r4\n" + "\tldrh r4, [r4]\n" + "\tmovs r5, 0x1F\n" + "\tmov r9, r5\n" + "\tmov r8, r4\n" + "\tmov r6, r8\n" + "\tands r6, r5\n" + "\tmov r8, r6\n" + "\tmovs r6, 0xF8\n" + "\tlsls r6, 2\n" + "\tands r6, r4\n" + "\tlsrs r6, 5\n" + "\tmovs r5, 0xF8\n" + "\tlsls r5, 7\n" + "\tands r4, r5\n" + "\tlsrs r4, 10\n" + "\tmov r7, r9\n" + "\tmov r5, r8\n" + "\tsubs r7, r5\n" + "\tmov r12, r7\n" + "\tmov r7, r12\n" + "\tmuls r7, r1\n" + "\tadds r1, r7, 0\n" + "\tasrs r1, 4\n" + "\tadd r8, r1\n" + "\tmov r5, r9\n" + "\tsubs r1, r5, r6\n" + "\tmuls r1, r2\n" + "\tasrs r1, 4\n" + "\tadds r6, r1\n" + "\tsubs r5, r4\n" + "\tmov r9, r5\n" + "\tmov r1, r9\n" + "\tmuls r1, r3\n" + "\tasrs r1, 4\n" + "\tadds r4, r1\n" + "\tmov r7, r8\n" + "\tlsls r7, 16\n" + "\tlsls r6, 21\n" + "\torrs r6, r7\n" + "\tlsls r4, 26\n" + "\torrs r4, r6\n" + "\tlsrs r4, 16\n" + "\tldr r1, _08085D04 @ =gPlttBufferFaded\n" + "\tadds r0, r1\n" + "\tstrh r4, [r0]\n" + "\tpop {r3,r4}\n" + "\tmov r8, r3\n" + "\tmov r9, r4\n" + "\tpop {r4-r7}\n" + "\tpop {r0}\n" + "\tbx r0\n" + "\t.align 2, 0\n" + "_08085D00: .4byte gPlttBufferUnfaded\n" + "_08085D04: .4byte gPlttBufferFaded\n" + ".syntax divided"); +} + +NAKED +void MultiplyPaletteRGBComponents(u16 i, u8 r, u8 g, u8 b) +{ + asm(".syntax unified\n" + "\tpush {r4-r6,lr}\n" + "\tmov r6, r8\n" + "\tpush {r6}\n" + "\tlsls r0, 16\n" + "\tlsls r1, 24\n" + "\tlsrs r1, 24\n" + "\tlsls r2, 24\n" + "\tlsrs r2, 24\n" + "\tlsls r3, 24\n" + "\tlsrs r3, 24\n" + "\tldr r4, _08085D78 @ =gPlttBufferUnfaded\n" + "\tlsrs r0, 15\n" + "\tadds r4, r0, r4\n" + "\tldrh r4, [r4]\n" + "\tmovs r5, 0x1F\n" + "\tmov r8, r5\n" + "\tmov r6, r8\n" + "\tands r6, r4\n" + "\tmov r8, r6\n" + "\tmovs r5, 0xF8\n" + "\tlsls r5, 2\n" + "\tands r5, r4\n" + "\tlsrs r5, 5\n" + "\tmovs r6, 0xF8\n" + "\tlsls r6, 7\n" + "\tands r4, r6\n" + "\tlsrs r4, 10\n" + "\tmov r6, r8\n" + "\tmuls r6, r1\n" + "\tadds r1, r6, 0\n" + "\tasrs r1, 4\n" + "\tmov r6, r8\n" + "\tsubs r6, r1\n" + "\tadds r1, r5, 0\n" + "\tmuls r1, r2\n" + "\tasrs r1, 4\n" + "\tsubs r5, r1\n" + "\tadds r1, r4, 0\n" + "\tmuls r1, r3\n" + "\tasrs r1, 4\n" + "\tsubs r4, r1\n" + "\tlsls r6, 16\n" + "\tlsls r5, 21\n" + "\torrs r5, r6\n" + "\tlsls r4, 26\n" + "\torrs r4, r5\n" + "\tlsrs r4, 16\n" + "\tldr r1, _08085D7C @ =gPlttBufferFaded\n" + "\tadds r0, r1\n" + "\tstrh r4, [r0]\n" + "\tpop {r3}\n" + "\tmov r8, r3\n" + "\tpop {r4-r6}\n" + "\tpop {r0}\n" + "\tbx r0\n" + "\t.align 2, 0\n" + "_08085D78: .4byte gPlttBufferUnfaded\n" + "_08085D7C: .4byte gPlttBufferFaded\n" + ".syntax divided"); +} +#endif + +void Task_PokecenterHeal(u8 taskId); +u8 CreatePokeballGlowSprite(s16, s16, s16, u16); +u8 PokecenterHealEffectHelper(s16, s16); + +bool8 FldEff_PokecenterHeal(void) +{ + u8 nPokemon; + struct Task *task; + + nPokemon = CalculatePlayerPartyCount(); + task = &gTasks[CreateTask(Task_PokecenterHeal, 0xff)]; + task->data[1] = nPokemon; + task->data[2] = 0x5d; + task->data[3] = 0x24; + task->data[4] = 0x7c; + task->data[5] = 0x18; + return FALSE; +} + +void Task_PokecenterHeal(u8 taskId) +{ + struct Task *task; + task = &gTasks[taskId]; + gUnknown_0855C364[task->data[0]](task); +} + +void PokecenterHealEffect_0(struct Task *task) +{ + task->data[0]++; + task->data[6] = CreatePokeballGlowSprite(task->data[1], task->data[2], task->data[3], 1); + task->data[7] = PokecenterHealEffectHelper(task->data[4], task->data[5]); +} + +void PokecenterHealEffect_1(struct Task *task) +{ + if (gSprites[task->data[6]].data[0] > 1) + { + gSprites[task->data[7]].data[0]++; + task->data[0]++; + } +} + +void PokecenterHealEffect_2(struct Task *task) +{ + if (gSprites[task->data[6]].data[0] > 4) + { + task->data[0]++; + } +} + +void PokecenterHealEffect_3(struct Task *task) +{ + if (gSprites[task->data[6]].data[0] > 6) + { + DestroySprite(&gSprites[task->data[6]]); + FieldEffectActiveListRemove(FLDEFF_POKECENTER_HEAL); + DestroyTask(FindTaskIdByFunc(Task_PokecenterHeal)); + } +} + +void Task_HallOfFameRecord(u8 taskId); +void HallOfFameRecordEffectHelper(s16, s16, s16, u8); + +bool8 FldEff_HallOfFameRecord(void) +{ + u8 nPokemon; + struct Task *task; + + nPokemon = CalculatePlayerPartyCount(); + task = &gTasks[CreateTask(Task_HallOfFameRecord, 0xff)]; + task->data[1] = nPokemon; + task->data[2] = 0x75; + task->data[3] = 0x34; + return FALSE; +} + +void Task_HallOfFameRecord(u8 taskId) +{ + struct Task *task; + task = &gTasks[taskId]; + gUnknown_0855C374[task->data[0]](task); +} + +void HallOfFameRecordEffect_0(struct Task *task) +{ + u8 taskId; + task->data[0]++; + task->data[6] = CreatePokeballGlowSprite(task->data[1], task->data[2], task->data[3], 0); + taskId = FindTaskIdByFunc(Task_HallOfFameRecord); + HallOfFameRecordEffectHelper(taskId, 0x78, 0x18, 0); + HallOfFameRecordEffectHelper(taskId, 0x28, 0x08, 1); + HallOfFameRecordEffectHelper(taskId, 0x48, 0x08, 1); + HallOfFameRecordEffectHelper(taskId, 0xa8, 0x08, 1); + HallOfFameRecordEffectHelper(taskId, 0xc8, 0x08, 1); +} + +void HallOfFameRecordEffect_1(struct Task *task) +{ + if (gSprites[task->data[6]].data[0] > 1) + { + task->data[15]++; // was this ever initialized? is this ever used? + task->data[0]++; + } +} + +void HallOfFameRecordEffect_2(struct Task *task) +{ + if (gSprites[task->data[6]].data[0] > 4) + { + task->data[0]++; + } +} + +void HallOfFameRecordEffect_3(struct Task *task) +{ + if (gSprites[task->data[6]].data[0] > 6) + { + DestroySprite(&gSprites[task->data[6]]); + FieldEffectActiveListRemove(FLDEFF_HALL_OF_FAME_RECORD); + DestroyTask(FindTaskIdByFunc(Task_HallOfFameRecord)); + } +} + +void SpriteCB_PokeballGlowEffect(struct Sprite *); + +u8 CreatePokeballGlowSprite(s16 data6, s16 x, s16 y, u16 data5) +{ + u8 spriteId; + struct Sprite *sprite; + spriteId = CreateInvisibleSprite(SpriteCB_PokeballGlowEffect); + sprite = &gSprites[spriteId]; + sprite->pos2.x = x; + sprite->pos2.y = y; + sprite->data[5] = data5; + sprite->data[6] = data6; + sprite->data[7] = spriteId; + return spriteId; +} + +void SpriteCB_PokeballGlowEffect(struct Sprite *sprite) +{ + gUnknown_0855C384[sprite->data[0]](sprite); +} + +void PokeballGlowEffect_0(struct Sprite *sprite) +{ + u8 endSpriteId; + if (sprite->data[1] == 0 || (--sprite->data[1]) == 0) + { + sprite->data[1] = 25; + endSpriteId = CreateSpriteAtEnd(&gSpriteTemplate_855C304, gUnknown_0855C3A4[sprite->data[2]].x + sprite->pos2.x, gUnknown_0855C3A4[sprite->data[2]].y + sprite->pos2.y, 0); + gSprites[endSpriteId].oam.priority = 2; + gSprites[endSpriteId].data[0] = sprite->data[7]; + sprite->data[2]++; + sprite->data[6]--; + PlaySE(SE_BOWA); + } + if (sprite->data[6] == 0) + { + sprite->data[1] = 32; + sprite->data[0]++; + } +} + +void PokeballGlowEffect_1(struct Sprite *sprite) +{ + if ((--sprite->data[1]) == 0) + { + sprite->data[0]++; + sprite->data[1] = 8; + sprite->data[2] = 0; + sprite->data[3] = 0; + if (sprite->data[5]) + { + PlayFanfare(MUS_ME_ASA); + } + } +} + +void PokeballGlowEffect_2(struct Sprite *sprite) +{ + u8 phase; + if ((--sprite->data[1]) == 0) + { + sprite->data[1] = 8; + sprite->data[2]++; + sprite->data[2] &= 3; + if (sprite->data[2] == 0) + { + sprite->data[3]++; + } + } + phase = (sprite->data[2] + 3) & 3; + MultiplyInvertedPaletteRGBComponents((IndexOfSpritePaletteTag(0x1007) << 4) + 0x108, gUnknown_0855C3BC[phase], gUnknown_0855C3C0[phase], gUnknown_0855C3C4[phase]); + phase = (sprite->data[2] + 2) & 3; + MultiplyInvertedPaletteRGBComponents((IndexOfSpritePaletteTag(0x1007) << 4) + 0x106, gUnknown_0855C3BC[phase], gUnknown_0855C3C0[phase], gUnknown_0855C3C4[phase]); + phase = (sprite->data[2] + 1) & 3; + MultiplyInvertedPaletteRGBComponents((IndexOfSpritePaletteTag(0x1007) << 4) + 0x102, gUnknown_0855C3BC[phase], gUnknown_0855C3C0[phase], gUnknown_0855C3C4[phase]); + phase = sprite->data[2]; + MultiplyInvertedPaletteRGBComponents((IndexOfSpritePaletteTag(0x1007) << 4) + 0x105, gUnknown_0855C3BC[phase], gUnknown_0855C3C0[phase], gUnknown_0855C3C4[phase]); + MultiplyInvertedPaletteRGBComponents((IndexOfSpritePaletteTag(0x1007) << 4) + 0x103, gUnknown_0855C3BC[phase], gUnknown_0855C3C0[phase], gUnknown_0855C3C4[phase]); + if (sprite->data[3] > 2) + { + sprite->data[0]++; + sprite->data[1] = 8; + sprite->data[2] = 0; + } +} + +void PokeballGlowEffect_3(struct Sprite *sprite) +{ + u8 phase; + if ((--sprite->data[1]) == 0) + { + sprite->data[1] = 8; + sprite->data[2]++; + sprite->data[2] &= 3; + if (sprite->data[2] == 3) + { + sprite->data[0]++; + sprite->data[1] = 30; + } + } + phase = sprite->data[2]; + MultiplyInvertedPaletteRGBComponents((IndexOfSpritePaletteTag(0x1007) << 4) + 0x108, gUnknown_0855C3BC[phase], gUnknown_0855C3C0[phase], gUnknown_0855C3C4[phase]); + MultiplyInvertedPaletteRGBComponents((IndexOfSpritePaletteTag(0x1007) << 4) + 0x106, gUnknown_0855C3BC[phase], gUnknown_0855C3C0[phase], gUnknown_0855C3C4[phase]); + MultiplyInvertedPaletteRGBComponents((IndexOfSpritePaletteTag(0x1007) << 4) + 0x102, gUnknown_0855C3BC[phase], gUnknown_0855C3C0[phase], gUnknown_0855C3C4[phase]); + MultiplyInvertedPaletteRGBComponents((IndexOfSpritePaletteTag(0x1007) << 4) + 0x105, gUnknown_0855C3BC[phase], gUnknown_0855C3C0[phase], gUnknown_0855C3C4[phase]); + MultiplyInvertedPaletteRGBComponents((IndexOfSpritePaletteTag(0x1007) << 4) + 0x103, gUnknown_0855C3BC[phase], gUnknown_0855C3C0[phase], gUnknown_0855C3C4[phase]); +} + +void PokeballGlowEffect_4(struct Sprite *sprite) +{ + if ((--sprite->data[1]) == 0) + { + sprite->data[0]++; + } +} + +void PokeballGlowEffect_5(struct Sprite *sprite) +{ + sprite->data[0]++; +} + +void PokeballGlowEffect_6(struct Sprite *sprite) +{ + if (sprite->data[5] == 0 || IsFanfareTaskInactive()) + { + sprite->data[0]++; + } +} + +void PokeballGlowEffect_7(struct Sprite *sprite) +{ +} + +void SpriteCB_PokeballGlow(struct Sprite *sprite) +{ + if (gSprites[sprite->data[0]].data[0] > 4) + { + FieldEffectFreeGraphicsResources(sprite); + } +} + +u8 PokecenterHealEffectHelper(s16 x, s16 y) +{ + u8 spriteIdAtEnd; + struct Sprite *sprite; + spriteIdAtEnd = CreateSpriteAtEnd(&gSpriteTemplate_855C31C, x, y, 0); + sprite = &gSprites[spriteIdAtEnd]; + sprite->oam.priority = 2; + sprite->invisible = 1; + SetSubspriteTables(sprite, &gUnknown_0855C2AC); + return spriteIdAtEnd; +} + +void SpriteCB_PokecenterMonitor(struct Sprite *sprite) +{ + if (sprite->data[0] != 0) + { + sprite->data[0] = 0; + sprite->invisible = 0; + StartSpriteAnim(sprite, 1); + } + if (sprite->animEnded) + { + FieldEffectFreeGraphicsResources(sprite); + } +} + +void HallOfFameRecordEffectHelper(s16 a0, s16 a1, s16 a2, u8 a3) +{ + u8 spriteIdAtEnd; + if (!a3) + { + spriteIdAtEnd = CreateSpriteAtEnd(&gSpriteTemplate_855C334, a1, a2, 0); + SetSubspriteTables(&gSprites[spriteIdAtEnd], &gUnknown_0855C2C4); + } else + { + spriteIdAtEnd = CreateSpriteAtEnd(&gSpriteTemplate_855C34C, a1, a2, 0); + } + gSprites[spriteIdAtEnd].invisible = 1; + gSprites[spriteIdAtEnd].data[0] = a0; +} + +void SpriteCB_HallOfFameMonitor(struct Sprite *sprite) +{ + if (gTasks[sprite->data[0]].data[15]) + { + if (sprite->data[1] == 0 || (--sprite->data[1]) == 0) + { + sprite->data[1] = 16; + sprite->invisible ^= 1; + } + sprite->data[2]++; + } + if (sprite->data[2] > 127) + { + FieldEffectFreeGraphicsResources(sprite); + } +} + +void mapldr_080842E8(void); +void mapldr_08084390(void); +void task00_8084310(u8); +void c3_080843F8(u8); + +void sub_80B69DC(void) +{ + SetMainCallback2(CB2_ReturnToField); + gFieldCallback = mapldr_080842E8; +} + +void mapldr_080842E8(void) +{ + pal_fill_black(); + CreateTask(task00_8084310, 0); + ScriptContext2_Enable(); + FreezeMapObjects(); + gFieldCallback = NULL; +} + +void task00_8084310(u8 taskId) +{ + struct Task *task; + task = &gTasks[taskId]; + if (!task->data[0]) + { + if (!IsWeatherNotFadingIn()) + { + return; + } + gFieldEffectArguments[0] = GetCursorSelectionMonId(); + if ((int)gFieldEffectArguments[0] > 5) + { + gFieldEffectArguments[0] = 0; + } + FieldEffectStart(FLDEFF_USE_FLY); + task->data[0]++; + } + if (!FieldEffectActiveListContains(FLDEFF_USE_FLY)) + { + Overworld_ResetStateAfterFly(); + warp_in(); + SetMainCallback2(CB2_LoadMap); + gFieldCallback = mapldr_08084390; + DestroyTask(taskId); + } +} + +void mapldr_08084390(void) +{ + Overworld_PlaySpecialMapMusic(); + pal_fill_black(); + CreateTask(c3_080843F8, 0); + gMapObjects[gPlayerAvatar.mapObjectId].mapobj_bit_13 = 1; + if (gPlayerAvatar.flags & 0x08) + { + FieldObjectTurn(&gMapObjects[gPlayerAvatar.mapObjectId], DIR_WEST); + } + ScriptContext2_Enable(); + FreezeMapObjects(); + gFieldCallback = NULL; +} + +void c3_080843F8(u8 taskId) +{ + struct Task *task; + task = &gTasks[taskId]; + if (task->data[0] == 0) + { + if (gPaletteFade.active) + { + return; + } + FieldEffectStart(FLDEFF_FLY_IN); + task->data[0]++; + } + if (!FieldEffectActiveListContains(FLDEFF_FLY_IN)) + { + ScriptContext2_Disable(); + UnfreezeMapObjects(); + DestroyTask(taskId); + } +} + +extern void pal_fill_for_maplights(void); +void sub_80B6B94(u8); +extern void CameraObjectReset2(void); +extern void CameraObjectReset1(void); + +void sub_80B6B68(void) +{ + Overworld_PlaySpecialMapMusic(); + pal_fill_for_maplights(); + ScriptContext2_Enable(); + FreezeMapObjects(); + CreateTask(sub_80B6B94, 0); + gFieldCallback = NULL; +} + +void sub_80B6B94(u8 taskId) +{ + struct Task *task; + task = &gTasks[taskId]; + while (gUnknown_0855C3C8[task->data[0]](task)); // return code signifies whether to continue blocking here +} + +bool8 sub_80B6BCC(struct Task *task) // gUnknown_0855C3C8[0] +{ + struct MapObject *playerObject; + struct Sprite *playerSprite; + playerObject = &gMapObjects[gPlayerAvatar.mapObjectId]; + playerSprite = &gSprites[gPlayerAvatar.spriteId]; + CameraObjectReset2(); + gMapObjects[gPlayerAvatar.mapObjectId].mapobj_bit_13 = 1; + gPlayerAvatar.preventStep = TRUE; + FieldObjectSetSpecialAnim(playerObject, GetFaceDirectionAnimId(player_get_direction_lower_nybble())); + task->data[4] = playerSprite->subspriteMode; + playerObject->mapobj_bit_26 = 1; + playerSprite->oam.priority = 1; + playerSprite->subspriteMode = 2; + task->data[0]++; + return TRUE; +} + +bool8 sub_80B6C74(struct Task *task) // gUnknown_0855C3C8[1] +{ + if (IsWeatherNotFadingIn()) + { + task->data[0]++; + } + return FALSE; +} + +bool8 sub_80B6C90(struct Task *task) // gUnknown_0855C3C8[2] +{ + struct Sprite *sprite; + s16 centerToCornerVecY; + sprite = &gSprites[gPlayerAvatar.spriteId]; + centerToCornerVecY = -(sprite->centerToCornerVecY << 1); + sprite->pos2.y = -(sprite->pos1.y + sprite->centerToCornerVecY + gSpriteCoordOffsetY + centerToCornerVecY); + task->data[1] = 1; + task->data[2] = 0; + gMapObjects[gPlayerAvatar.mapObjectId].mapobj_bit_13 = 0; + PlaySE(SE_RU_HYUU); + task->data[0]++; + return FALSE; +} + +bool8 sub_80B6D04(struct Task *task) +{ + struct MapObject *mapObject; + struct Sprite *sprite; + + mapObject = &gMapObjects[gPlayerAvatar.mapObjectId]; + sprite = &gSprites[gPlayerAvatar.spriteId]; + sprite->pos2.y += task->data[1]; + if (task->data[1] < 8) + { + task->data[2] += task->data[1]; + if (task->data[2] & 0xf) + { + task->data[1] <<= 1; + } + } + if (task->data[3] == 0 && sprite->pos2.y >= -16) + { + task->data[3]++; + mapObject->mapobj_bit_26 = 0; + sprite->subspriteMode = task->data[4]; + mapObject->mapobj_bit_2 = 1; + } + if (sprite->pos2.y >= 0) + { + PlaySE(SE_W070); + mapObject->mapobj_bit_3 = 1; + mapObject->mapobj_bit_5 = 1; + sprite->pos2.y = 0; + task->data[0]++; + } + return FALSE; +} + +bool8 sub_80B6DBC(struct Task *task) +{ + task->data[0]++; + task->data[1] = 4; + task->data[2] = 0; + SetCameraPanningCallback(NULL); + return TRUE; +} + +bool8 sub_80B6DD8(struct Task *task) +{ + SetCameraPanning(0, task->data[1]); + task->data[1] = -task->data[1]; + task->data[2]++; + if ((task->data[2] & 3) == 0) + { + task->data[1] >>= 1; + } + if (task->data[1] == 0) + { + task->data[0]++; + } + return FALSE; +} + +bool8 sub_80B6E18(struct Task *task) +{ + gPlayerAvatar.preventStep = FALSE; + ScriptContext2_Disable(); + CameraObjectReset1(); + UnfreezeMapObjects(); + InstallCameraPanAheadCallback(); + DestroyTask(FindTaskIdByFunc(sub_80B6B94)); + return FALSE; +} + +void sub_80B6E88(u8); +extern void sub_80E1558(u8); +extern void sub_80AF0B4(void); + +void sub_80B6FB8(struct Task *); +void sub_80B7004(struct Task *); +void sub_80B7050(void); +void sub_80B7060(void); +bool8 sub_80859A0(void); +void sub_80B70B4(void); +void sub_80E1570(void); +void sub_80B70DC(u8); + +void sub_80B6E4C(u8 a0, u8 priority) +{ + u8 taskId; + taskId = CreateTask(sub_80B6E88, priority); + gTasks[taskId].data[1] = 0; + if (a0 == 0x6a) + { + gTasks[taskId].data[1] = 1; + } +} + +void sub_80B6E88(u8 taskId) +{ + struct Task *task; + task = &gTasks[taskId]; + while (gUnknown_0855C3E4[task->data[0]](task)); +} + +bool8 sub_80B6EC0(struct Task *task) +{ + FreezeMapObjects(); + CameraObjectReset2(); + sub_80E1558(task->data[1]); + task->data[0]++; + return FALSE; +} + +bool8 sub_80B6EE0(struct Task *task) +{ + struct MapObject *mapObject; + mapObject = &gMapObjects[gPlayerAvatar.mapObjectId]; + if (!FieldObjectIsSpecialAnimOrDirectionSequenceAnimActive(mapObject) || FieldObjectClearAnimIfSpecialAnimFinished(mapObject)) + { + FieldObjectSetSpecialAnim(mapObject, GetFaceDirectionAnimId(player_get_direction_lower_nybble())); + task->data[0]++; + task->data[2] = 0; + task->data[3] = 0; + if ((u8)task->data[1] == 0) + { + task->data[0] = 4; + } + PlaySE(SE_ESUKA); + } + return FALSE; +} + +bool8 sub_80B6F50(struct Task *task) +{ + sub_80B6FB8(task); + if (task->data[2] > 3) + { + sub_80B7050(); + task->data[0]++; + } + return FALSE; +} + +bool8 sub_80B6F74(struct Task *task) +{ + sub_80B6FB8(task); + sub_80B7060(); + return FALSE; +} + +bool8 sub_80B6F84(struct Task *task) +{ + sub_80B7004(task); + if (task->data[2] > 3) + { + sub_80B7050(); + task->data[0]++; + } + return FALSE; +} + +bool8 sub_80B6FA8(struct Task *task) +{ + sub_80B7004(task); + sub_80B7060(); + return FALSE; +} + +void sub_80B6FB8(struct Task *task) +{ + struct Sprite *sprite; + sprite = &gSprites[gPlayerAvatar.spriteId]; + sprite->pos2.x = Cos(0x84, task->data[2]); + sprite->pos2.y = Sin(0x94, task->data[2]); + task->data[3]++; + if (task->data[3] & 1) + { + task->data[2]++; + } +} + +void sub_80B7004(struct Task *task) +{ + struct Sprite *sprite; + sprite = &gSprites[gPlayerAvatar.spriteId]; + sprite->pos2.x = Cos(0x7c, task->data[2]); + sprite->pos2.y = Sin(0x76, task->data[2]); + task->data[3]++; + if (task->data[3] & 1) + { + task->data[2]++; + } +} + +void sub_80B7050(void) +{ + music_something(); + sub_80AF0B4(); +} + +void sub_80B7060(void) +{ + if (!gPaletteFade.active && sub_80859A0() == TRUE) + { + sub_80E1570(); + warp_in(); + gFieldCallback = sub_80B70B4; + SetMainCallback2(CB2_LoadMap); + DestroyTask(FindTaskIdByFunc(sub_80B6E88)); + } +} + +void sub_80B70B4(void) +{ + Overworld_PlaySpecialMapMusic(); + pal_fill_for_maplights(); + ScriptContext2_Enable(); + CreateTask(sub_80B70DC, 0); + gFieldCallback = NULL; +} + +void sub_80B70DC(u8 taskId) +{ + struct Task *task; + task = &gTasks[taskId]; + while (gUnknown_0855C3FC[task->data[0]](task)); +} + +bool8 sub_80B7114(struct Task *task) +{ + struct MapObject *mapObject; + s16 x; + s16 y; + u8 behavior; + CameraObjectReset2(); + mapObject = &gMapObjects[gPlayerAvatar.mapObjectId]; + FieldObjectSetSpecialAnim(mapObject, GetFaceDirectionAnimId(DIR_EAST)); + PlayerGetDestCoords(&x, &y); + behavior = MapGridGetMetatileBehaviorAt(x, y); + task->data[0]++; + task->data[1] = 16; + if (behavior == 0x6b) + { + behavior = 1; + task->data[0] = 3; + } else + { + behavior = 0; + } + sub_80E1558(behavior); + return TRUE; +} + +bool8 sub_80B7190(struct Task *task) +{ + struct Sprite *sprite; + sprite = &gSprites[gPlayerAvatar.spriteId]; + sprite->pos2.x = Cos(0x84, task->data[1]); + sprite->pos2.y = Sin(0x94, task->data[1]); + task->data[0]++; + return FALSE; +} + +bool8 sub_80B71D0(struct Task *task) +{ + struct Sprite *sprite; + sprite = &gSprites[gPlayerAvatar.spriteId]; + sprite->pos2.x = Cos(0x84, task->data[1]); + sprite->pos2.y = Sin(0x94, task->data[1]); + task->data[2]++; + if (task->data[2] & 1) + { + task->data[1]--; + } + if (task->data[1] == 0) + { + sprite->pos2.x = 0; + sprite->pos2.y = 0; + task->data[0] = 5; + } + return FALSE; +} + +bool8 sub_80B7230(struct Task *task) +{ + struct Sprite *sprite; + sprite = &gSprites[gPlayerAvatar.spriteId]; + sprite->pos2.x = Cos(0x7c, task->data[1]); + sprite->pos2.y = Sin(0x76, task->data[1]); + task->data[0]++; + return FALSE; +} + +bool8 sub_80B7270(struct Task *task) +{ + struct Sprite *sprite; + sprite = &gSprites[gPlayerAvatar.spriteId]; + sprite->pos2.x = Cos(0x7c, task->data[1]); + sprite->pos2.y = Sin(0x76, task->data[1]); + task->data[2]++; + if (task->data[2] & 1) + { + task->data[1]--; + } + if (task->data[1] == 0) + { + sprite->pos2.x = 0; + sprite->pos2.y = 0; + task->data[0]++; + } + return FALSE; +} + +extern bool8 sub_80E1584(void); + +bool8 sub_80B72D0(struct Task *task) +{ + if (sub_80E1584()) + { + return FALSE; + } + sub_80E1570(); + task->data[0]++; + return TRUE; +} + +bool8 sub_80B72F4(struct Task *task) +{ + struct MapObject *mapObject; + mapObject = &gMapObjects[gPlayerAvatar.mapObjectId]; + if (FieldObjectClearAnimIfSpecialAnimFinished(mapObject)) + { + CameraObjectReset1(); + ScriptContext2_Disable(); + FieldObjectSetSpecialAnim(mapObject, GetGoSpeed0AnimId(DIR_EAST)); + DestroyTask(FindTaskIdByFunc(sub_80B70DC)); + } + return FALSE; +} + +void sub_80B7384(u8); + +bool8 FldEff_UseWaterfall(void) +{ + u8 taskId; + taskId = CreateTask(sub_80B7384, 0xff); + gTasks[taskId].data[1] = gFieldEffectArguments[0]; + sub_80B7384(taskId); + return FALSE; +} + +void sub_80B7384(u8 taskId) +{ + while (gUnknown_0855C418[gTasks[taskId].data[0]](&gTasks[taskId], &gMapObjects[gPlayerAvatar.mapObjectId])); +} + +bool8 sub_80B73D0(struct Task *task, struct MapObject *mapObject) +{ + ScriptContext2_Enable(); + gPlayerAvatar.preventStep = TRUE; + task->data[0]++; + return FALSE; +} + +bool8 waterfall_1_do_anim_probably(struct Task *task, struct MapObject *mapObject) +{ + ScriptContext2_Enable(); + if (!FieldObjectIsSpecialAnimOrDirectionSequenceAnimActive(mapObject)) + { + FieldObjectClearAnimIfSpecialAnimFinished(mapObject); + gFieldEffectArguments[0] = task->data[1]; + FieldEffectStart(FLDEFF_FIELD_MOVE_SHOW_MON_INIT); + task->data[0]++; + } + return FALSE; +} + +bool8 waterfall_2_wait_anim_finish_probably(struct Task *task, struct MapObject *mapObject) +{ + if (FieldEffectActiveListContains(FLDEFF_FIELD_MOVE_SHOW_MON)) + { + return FALSE; + } + task->data[0]++; + return TRUE; +} + +bool8 sub_80B7450(struct Task *task, struct MapObject *mapObject) +{ + FieldObjectSetSpecialAnim(mapObject, GetSimpleGoAnimId(DIR_NORTH)); + task->data[0]++; + return FALSE; +} + +bool8 sub_80B7478(struct Task *task, struct MapObject *mapObject) +{ + if (!FieldObjectClearAnimIfSpecialAnimFinished(mapObject)) + { + return FALSE; + } + if (MetatileBehavior_IsWaterfall(mapObject->mapobj_unk_1E)) + { + task->data[0] = 3; + return TRUE; + } + ScriptContext2_Disable(); + gPlayerAvatar.preventStep = FALSE; + DestroyTask(FindTaskIdByFunc(sub_80B7384)); + FieldEffectActiveListRemove(FLDEFF_USE_WATERFALL); + return FALSE; +} + +void Task_Dive(u8); +extern int dive_warp(struct MapPosition *, u16); + +bool8 FldEff_UseDive(void) +{ + u8 taskId; + taskId = CreateTask(Task_Dive, 0xff); + gTasks[taskId].data[15] = gFieldEffectArguments[0]; + gTasks[taskId].data[14] = gFieldEffectArguments[1]; + Task_Dive(taskId); + return FALSE; +} + +void Task_Dive(u8 taskId) +{ + while (gUnknown_0855C42C[gTasks[taskId].data[0]](&gTasks[taskId])); +} + +bool8 dive_1_lock(struct Task *task) +{ + gPlayerAvatar.preventStep = TRUE; + task->data[0]++; + return FALSE; +} + +bool8 dive_2_unknown(struct Task *task) +{ + ScriptContext2_Enable(); + gFieldEffectArguments[0] = task->data[15]; + FieldEffectStart(FLDEFF_FIELD_MOVE_SHOW_MON_INIT); + task->data[0]++; + return FALSE; +} + +bool8 dive_3_unknown(struct Task *task) +{ + struct MapPosition mapPosition; + PlayerGetDestCoords(&mapPosition.x, &mapPosition.y); + if (!FieldEffectActiveListContains(FLDEFF_FIELD_MOVE_SHOW_MON)) + { + dive_warp(&mapPosition, gMapObjects[gPlayerAvatar.mapObjectId].mapobj_unk_1E); + DestroyTask(FindTaskIdByFunc(Task_Dive)); + FieldEffectActiveListRemove(FLDEFF_USE_DIVE); + } + return FALSE; +} + +void sub_80B75F0(u8); +void mapldr_080851BC(void); + +void sub_80B75D8(u8 priority) +{ + CreateTask(sub_80B75F0, priority); +} + +void sub_80B75F0(u8 taskId) +{ + while (gUnknown_0855C438[gTasks[taskId].data[0]](&gTasks[taskId], &gMapObjects[gPlayerAvatar.mapObjectId], &gSprites[gPlayerAvatar.spriteId])); +} + +bool8 sub_80B764C(struct Task *task, struct MapObject *mapObject, struct Sprite *sprite) +{ + FreezeMapObjects(); + CameraObjectReset2(); + SetCameraPanningCallback(NULL); + gPlayerAvatar.preventStep = TRUE; + mapObject->mapobj_bit_26 = 1; + task->data[1] = 1; + task->data[0]++; + return TRUE; +} + +bool8 sub_80B7684(struct Task *task, struct MapObject *mapObject, struct Sprite *sprite) +{ + SetCameraPanning(0, task->data[1]); + task->data[1] = -task->data[1]; + task->data[2]++; + if (task->data[2] > 7) + { + task->data[2] = 0; + task->data[0]++; + } + return FALSE; +} + +bool8 sub_80B76B8(struct Task *task, struct MapObject *mapObject, struct Sprite *sprite) +{ + sprite->pos2.y = 0; + task->data[3] = 1; + gFieldEffectArguments[0] = mapObject->coords2.x; + gFieldEffectArguments[1] = mapObject->coords2.y; + gFieldEffectArguments[2] = sprite->subpriority - 1; + gFieldEffectArguments[3] = sprite->oam.priority; + FieldEffectStart(FLDEFF_LAVARIDGE_GYM_WARP); + PlaySE(SE_W153); + task->data[0]++; + return TRUE; +} + +bool8 sub_80B7704(struct Task *task, struct MapObject *mapObject, struct Sprite *sprite) +{ + s16 centerToCornerVecY; + SetCameraPanning(0, task->data[1]); + if (task->data[1] = -task->data[1], ++task->data[2] <= 17) + { + if (!(task->data[2] & 1) && (task->data[1] <= 3)) + { + task->data[1] <<= 1; + } + } else if (!(task->data[2] & 4) && (task->data[1] > 0)) + { + task->data[1] >>= 1; + } + if (task->data[2] > 6) + { + centerToCornerVecY = -(sprite->centerToCornerVecY << 1); + if (sprite->pos2.y > -(sprite->pos1.y + sprite->centerToCornerVecY + gSpriteCoordOffsetY + centerToCornerVecY)) + { + sprite->pos2.y -= task->data[3]; + if (task->data[3] <= 7) + { + task->data[3]++; + } + } else + { + task->data[4] = 1; + } + } + if (task->data[5] == 0 && sprite->pos2.y < -0x10) + { + task->data[5]++; + mapObject->mapobj_bit_26 = 1; + sprite->oam.priority = 1; + sprite->subspriteMode = 2; + } + if (task->data[1] == 0 && task->data[4] != 0) + { + task->data[0]++; + } + return FALSE; +} + +bool8 sub_80B77F8(struct Task *task, struct MapObject *mapObject, struct Sprite *sprite) +{ + music_something(); + sub_80AF0B4(); + task->data[0]++; + return FALSE; +} + +bool8 sub_80B7814(struct Task *task, struct MapObject *mapObject, struct Sprite *sprite) +{ + if (!gPaletteFade.active && sub_80859A0() == TRUE) + { + warp_in(); + gFieldCallback = mapldr_080851BC; + SetMainCallback2(CB2_LoadMap); + DestroyTask(FindTaskIdByFunc(sub_80B75F0)); + } + return FALSE; +} + +void sub_80B7890(u8); + +void mapldr_080851BC(void) +{ + Overworld_PlaySpecialMapMusic(); + pal_fill_for_maplights(); + ScriptContext2_Enable(); + gFieldCallback = NULL; + CreateTask(sub_80B7890, 0); +} + +void sub_80B7890(u8 taskId) +{ + while (gUnknown_0855C450[gTasks[taskId].data[0]](&gTasks[taskId], &gMapObjects[gPlayerAvatar.mapObjectId], &gSprites[gPlayerAvatar.spriteId])); +} + +bool8 sub_80B78EC(struct Task *task, struct MapObject *mapObject, struct Sprite *sprite) +{ + CameraObjectReset2(); + FreezeMapObjects(); + gPlayerAvatar.preventStep = TRUE; + mapObject->mapobj_bit_13 = 1; + task->data[0]++; + return FALSE; +} + +bool8 sub_80B791C(struct Task *task, struct MapObject *mapObject, struct Sprite *sprite) +{ + if (IsWeatherNotFadingIn()) + { + gFieldEffectArguments[0] = mapObject->coords2.x; + gFieldEffectArguments[1] = mapObject->coords2.y; + gFieldEffectArguments[2] = sprite->subpriority - 1; + gFieldEffectArguments[3] = sprite->oam.priority; + task->data[1] = FieldEffectStart(FLDEFF_POP_OUT_OF_ASH); + task->data[0]++; + } + return FALSE; +} + +bool8 sub_80B7968(struct Task *task, struct MapObject *mapObject, struct Sprite *sprite) +{ + sprite = &gSprites[task->data[1]]; + if (sprite->animCmdIndex > 1) + { + task->data[0]++; + mapObject->mapobj_bit_13 = 0; + CameraObjectReset1(); + PlaySE(SE_W091); + FieldObjectSetSpecialAnim(mapObject, sub_8093514(DIR_EAST)); + } + return FALSE; +} + +bool8 sub_80B79BC(struct Task *task, struct MapObject *mapObject, struct Sprite *sprite) +{ + if (FieldObjectClearAnimIfSpecialAnimFinished(mapObject)) + { + gPlayerAvatar.preventStep = FALSE; + ScriptContext2_Disable(); + UnfreezeMapObjects(); + DestroyTask(FindTaskIdByFunc(sub_80B7890)); + } + return FALSE; +} + +extern const struct SpriteTemplate *const gFieldEffectObjectTemplatePointers[36]; + +u8 FldEff_LavaridgeGymWarp(void) +{ + u8 spriteId; + sub_80930E0((s16 *)&gFieldEffectArguments[0], (s16 *)&gFieldEffectArguments[1], 8, 8); + spriteId = CreateSpriteAtEnd(gFieldEffectObjectTemplatePointers[33], gFieldEffectArguments[0], gFieldEffectArguments[1], gFieldEffectArguments[2]); + gSprites[spriteId].oam.priority = gFieldEffectArguments[3]; + gSprites[spriteId].coordOffsetEnabled = 1; + return spriteId; +} + +void sub_80B7A58(struct Sprite *sprite) +{ + if (sprite->animEnded) + { + FieldEffectStop(sprite, FLDEFF_LAVARIDGE_GYM_WARP); + } +} + +void sub_80B7A8C(u8); + +void sub_80B7A74(u8 priority) +{ + CreateTask(sub_80B7A8C, priority); +} + +void sub_80B7A8C(u8 taskId) +{ + while(gUnknown_0855C460[gTasks[taskId].data[0]](&gTasks[taskId], &gMapObjects[gPlayerAvatar.mapObjectId], &gSprites[gPlayerAvatar.spriteId])); +} + +bool8 sub_80B7AE8(struct Task *task, struct MapObject *mapObject, struct Sprite *sprite) +{ + FreezeMapObjects(); + CameraObjectReset2(); + gPlayerAvatar.preventStep = TRUE; + mapObject->mapobj_bit_26 = 1; + task->data[0]++; + return FALSE; +} + +bool8 sub_80B7B18(struct Task *task, struct MapObject *mapObject, struct Sprite *sprite) +{ + if (FieldObjectClearAnimIfSpecialAnimFinished(mapObject)) + { + if (task->data[1] > 3) + { + gFieldEffectArguments[0] = mapObject->coords2.x; + gFieldEffectArguments[1] = mapObject->coords2.y; + gFieldEffectArguments[2] = sprite->subpriority - 1; + gFieldEffectArguments[3] = sprite->oam.priority; + task->data[1] = FieldEffectStart(FLDEFF_POP_OUT_OF_ASH); + task->data[0]++; + } else + { + task->data[1]++; + FieldObjectSetSpecialAnim(mapObject, GetStepInPlaceDelay4AnimId(mapObject->mapobj_unk_18)); + PlaySE(SE_FU_ZUZUZU); + } + } + return FALSE; +} + +bool8 sub_80B7B94(struct Task *task, struct MapObject *mapObject, struct Sprite *sprite) +{ + if (gSprites[task->data[1]].animCmdIndex == 2) + { + mapObject->mapobj_bit_13 = 1; + task->data[0]++; + } + return FALSE; +} + +bool8 sub_80B7BCC(struct Task *task, struct MapObject *mapObject, struct Sprite *sprite) +{ + if (!FieldEffectActiveListContains(FLDEFF_POP_OUT_OF_ASH)) + { + music_something(); + sub_80AF0B4(); + task->data[0]++; + } + return FALSE; +} + +void sub_80B7CE4(u8); +void mapldr_080859D4(void); + +bool8 sub_80B7BF4(struct Task *task, struct MapObject *mapObject, struct Sprite *sprite) +{ + if (!gPaletteFade.active && sub_80859A0() == TRUE) + { + warp_in(); + gFieldCallback = sub_80B6B68; + SetMainCallback2(CB2_LoadMap); + DestroyTask(FindTaskIdByFunc(sub_80B7A8C)); + } + return FALSE; +} + +u8 FldEff_PopOutOfAsh(void) +{ + u8 spriteId; + sub_80930E0((s16 *)&gFieldEffectArguments[0], (s16 *)&gFieldEffectArguments[1], 8, 8); + spriteId = CreateSpriteAtEnd(gFieldEffectObjectTemplatePointers[32], gFieldEffectArguments[0], gFieldEffectArguments[1], gFieldEffectArguments[2]); + gSprites[spriteId].oam.priority = gFieldEffectArguments[3]; + gSprites[spriteId].coordOffsetEnabled = 1; + return spriteId; +} + +void sub_80B7CAC(struct Sprite *sprite) +{ + if (sprite->animEnded) + { + FieldEffectStop(sprite, FLDEFF_POP_OUT_OF_ASH); + } +} + +void sub_80B7CC8(void) +{ + ScriptContext2_Enable(); + FreezeMapObjects(); + CreateTask(sub_80B7CE4, 0x50); +} + +void sub_80B7CE4(u8 taskId) +{ + gUnknown_0855C474[gTasks[taskId].data[0]](&gTasks[taskId]); +} + +void sub_80B7D14(struct Task *task) +{ + task->data[0]++; + task->data[14] = 64; + task->data[15] = player_get_direction_lower_nybble(); +} + +void sub_80B7D34(struct Task *task) +{ + struct MapObject *mapObject; + u8 spinDirections[5] = {1, 3, 4, 2, 1}; + if (task->data[14] != 0 && (--task->data[14]) == 0) + { + music_something(); + sub_80AF0B4(); + } + mapObject = &gMapObjects[gPlayerAvatar.mapObjectId]; + if (!FieldObjectIsSpecialAnimOrDirectionSequenceAnimActive(mapObject) || FieldObjectClearAnimIfSpecialAnimFinished(mapObject)) + { + if (task->data[14] == 0 && !gPaletteFade.active && sub_80859A0() == TRUE) + { + FieldObjectSetDirection(mapObject, task->data[15]); + sub_8084E14(); + warp_in(); + gFieldCallback = mapldr_080859D4; + SetMainCallback2(CB2_LoadMap); + DestroyTask(FindTaskIdByFunc(sub_80B7CE4)); + } else if (task->data[1] == 0 || (--task->data[1]) == 0) + { + FieldObjectSetSpecialAnim(mapObject, GetFaceDirectionAnimId(spinDirections[mapObject->mapobj_unk_18])); + if (task->data[2] < 12) + { + task->data[2]++; + } + task->data[1] = 8 >> (task->data[2] >> 2); + } + } +} + +void (*const gUnknown_0855C484[])(struct Task *) = { + sub_80B7EC4, + sub_80B7EE8 +}; + +void sub_80B7E94(u8); + +void mapldr_080859D4(void) +{ + Overworld_PlaySpecialMapMusic(); + pal_fill_for_maplights(); + ScriptContext2_Enable(); + FreezeMapObjects(); + gFieldCallback = NULL; + gMapObjects[gPlayerAvatar.mapObjectId].mapobj_bit_13 = 1; + CreateTask(sub_80B7E94, 0); +} + +void sub_80B7E94(u8 taskId) +{ + gUnknown_0855C484[gTasks[taskId].data[0]](&gTasks[taskId]); +} + +void sub_80B7EC4(struct Task *task) +{ + if (IsWeatherNotFadingIn()) + { + task->data[0]++; + task->data[15] = player_get_direction_lower_nybble(); + } +} + +void sub_80B7EE8(struct Task *task) +{ + u8 spinDirections[5] = {1, 3, 4, 2, 1}; + struct MapObject *mapObject = &gMapObjects[gPlayerAvatar.mapObjectId]; + if (task->data[1] == 0 || (--task->data[1]) == 0) + { + if (FieldObjectIsSpecialAnimOrDirectionSequenceAnimActive(mapObject) && !FieldObjectClearAnimIfSpecialAnimFinished(mapObject)) + { + return; + } + if (task->data[2] >= 32 && task->data[15] == player_get_direction_lower_nybble()) + { + mapObject->mapobj_bit_13 = 0; + ScriptContext2_Disable(); + UnfreezeMapObjects(); + DestroyTask(FindTaskIdByFunc(sub_80B7E94)); + return; + } + FieldObjectSetSpecialAnim(mapObject, GetFaceDirectionAnimId(spinDirections[mapObject->mapobj_unk_18])); + if (task->data[2] < 32) + { + task->data[2]++; + } + task->data[1] = task->data[2] >> 2; + } + mapObject->mapobj_bit_13 ^= 1; +} + +static void ExecuteTeleportFieldEffectTask(u8); +static void TeleportFieldEffectTask1(struct Task*); +static void TeleportFieldEffectTask2(struct Task*); +static void TeleportFieldEffectTask3(struct Task*); +static void TeleportFieldEffectTask4(struct Task*); +static void mapldr_08085D88(void); + +void CreateTeleportFieldEffectTask(void) +{ + CreateTask(ExecuteTeleportFieldEffectTask, 0); +} + +static void (*const sTeleportFieldEffectTasks[])(struct Task *) = { + TeleportFieldEffectTask1, + TeleportFieldEffectTask2, + TeleportFieldEffectTask3, + TeleportFieldEffectTask4 +}; + +static void ExecuteTeleportFieldEffectTask(u8 taskId) +{ + sTeleportFieldEffectTasks[gTasks[taskId].data[0]](&gTasks[taskId]); +} + +static void TeleportFieldEffectTask1(struct Task *task) +{ + ScriptContext2_Enable(); + FreezeMapObjects(); + CameraObjectReset2(); + task->data[15] = player_get_direction_lower_nybble(); + task->data[0]++; +} + +static void TeleportFieldEffectTask2(struct Task *task) +{ + u8 spinDirections[5] = {DIR_SOUTH, DIR_WEST, DIR_EAST, DIR_NORTH, DIR_SOUTH}; + struct MapObject *mapObject = &gMapObjects[gPlayerAvatar.mapObjectId]; + if (task->data[1] == 0 || (--task->data[1]) == 0) + { + FieldObjectTurn(mapObject, spinDirections[mapObject->mapobj_unk_18]); + task->data[1] = 8; + task->data[2]++; + } + if (task->data[2] > 7 && task->data[15] == mapObject->mapobj_unk_18) + { + task->data[0]++; + task->data[1] = 4; + task->data[2] = 8; + task->data[3] = 1; + PlaySE(SE_TK_WARPIN); + } +} + +static void TeleportFieldEffectTask3(struct Task *task) +{ + u8 spinDirections[5] = {DIR_SOUTH, DIR_WEST, DIR_EAST, DIR_NORTH, DIR_SOUTH}; + struct MapObject *mapObject = &gMapObjects[gPlayerAvatar.mapObjectId]; + struct Sprite *sprite = &gSprites[gPlayerAvatar.spriteId]; + if ((--task->data[1]) <= 0) + { + task->data[1] = 4; + FieldObjectTurn(mapObject, spinDirections[mapObject->mapobj_unk_18]); + } + sprite->pos1.y -= task->data[3]; + task->data[4] += task->data[3]; + if ((--task->data[2]) <= 0 && (task->data[2] = 4, task->data[3] < 8)) + { + task->data[3] <<= 1; + } + if (task->data[4] > 8 && (sprite->oam.priority = 1, sprite->subspriteMode != 0)) + { + sprite->subspriteMode = 2; + } + if (task->data[4] >= 0xa8) + { + task->data[0]++; + music_something(); + sub_80AF0B4(); + } +} + +static void TeleportFieldEffectTask4(struct Task *task) +{ + if (!gPaletteFade.active) + { + if (task->data[5] == FALSE) + { + sub_81BE72C(); + task->data[5] = TRUE; + } + + if (sub_80859A0() == TRUE) + { + Overworld_SetWarpDestToLastHealLoc(); + warp_in(); + SetMainCallback2(CB2_LoadMap); + gFieldCallback = mapldr_08085D88; + DestroyTask(FindTaskIdByFunc(ExecuteTeleportFieldEffectTask)); + } + } +} + +void sub_80B8250(u8); + +static void mapldr_08085D88(void) +{ + Overworld_PlaySpecialMapMusic(); + pal_fill_for_maplights(); + ScriptContext2_Enable(); + FreezeMapObjects(); + gFieldCallback = NULL; + gMapObjects[gPlayerAvatar.mapObjectId].mapobj_bit_13 = 1; + CameraObjectReset2(); + CreateTask(sub_80B8250, 0); +} + +void (*const gUnknown_0855C49C[])(struct Task *) = { + sub_80B8280, + sub_80B830C, + sub_80B8410 +}; + +void sub_80B8250(u8 taskId) +{ + gUnknown_0855C49C[gTasks[taskId].data[0]](&gTasks[taskId]); +} + +void sub_80B8280(struct Task *task) +{ + struct Sprite *sprite; + s16 centerToCornerVecY; + if (IsWeatherNotFadingIn()) + { + sprite = &gSprites[gPlayerAvatar.spriteId]; + centerToCornerVecY = -(sprite->centerToCornerVecY << 1); + sprite->pos2.y = -(sprite->pos1.y + sprite->centerToCornerVecY + gSpriteCoordOffsetY + centerToCornerVecY); + gMapObjects[gPlayerAvatar.mapObjectId].mapobj_bit_13 = 0; + task->data[0]++; + task->data[1] = 8; + task->data[2] = 1; + task->data[14] = sprite->subspriteMode; + task->data[15] = player_get_direction_lower_nybble(); + PlaySE(SE_TK_WARPIN); + } +} + +void sub_80B830C(struct Task *task) +{ + u8 spinDirections[5] = {1, 3, 4, 2, 1}; + struct MapObject *mapObject = &gMapObjects[gPlayerAvatar.mapObjectId]; + struct Sprite *sprite = &gSprites[gPlayerAvatar.spriteId]; + if ((sprite->pos2.y += task->data[1]) >= -8) + { + if (task->data[13] == 0) + { + task->data[13]++; + mapObject->mapobj_bit_2 = 1; + sprite->subspriteMode = task->data[14]; + } + } else + { + sprite->oam.priority = 1; + if (sprite->subspriteMode != 0) + { + sprite->subspriteMode = 2; + } + } + if (sprite->pos2.y >= -0x30 && task->data[1] > 1 && !(sprite->pos2.y & 1)) + { + task->data[1]--; + } + if ((--task->data[2]) == 0) + { + task->data[2] = 4; + FieldObjectTurn(mapObject, spinDirections[mapObject->mapobj_unk_18]); + } + if (sprite->pos2.y >= 0) + { + sprite->pos2.y = 0; + task->data[0]++; + task->data[1] = 1; + task->data[2] = 0; + } +} + +void sub_80B8410(struct Task *task) +{ + u8 spinDirections[5] = {1, 3, 4, 2, 1}; + struct MapObject *mapObject = &gMapObjects[gPlayerAvatar.mapObjectId]; + if ((--task->data[1]) == 0) + { + FieldObjectTurn(mapObject, spinDirections[mapObject->mapobj_unk_18]); + task->data[1] = 8; + if ((++task->data[2]) > 4 && task->data[14] == mapObject->mapobj_unk_18) + { + ScriptContext2_Disable(); + CameraObjectReset1(); + UnfreezeMapObjects(); + DestroyTask(FindTaskIdByFunc(sub_80B8250)); + } + } +} + +void sub_80B8554(u8); +void sub_80B88B4(u8); +u8 sub_80B8C60(u32, u32, u32); +void sub_80B880C(void); +void sub_80B8874(u16); +void sub_80B8CC0(struct Sprite *); + +bool8 FldEff_FieldMoveShowMon(void) +{ + u8 taskId; + if (is_map_type_1_2_3_5_or_6(Overworld_GetMapTypeOfSaveblockLocation()) == TRUE) + { + taskId = CreateTask(sub_80B8554, 0xff); + } else + { + taskId = CreateTask(sub_80B88B4, 0xff); + } + gTasks[taskId].data[15] = sub_80B8C60(gFieldEffectArguments[0], gFieldEffectArguments[1], gFieldEffectArguments[2]); + return FALSE; +} + +bool8 FldEff_FieldMoveShowMonInit(void) +{ + struct Pokemon *pokemon; + u32 flag = gFieldEffectArguments[0] & 0x80000000; + pokemon = &gPlayerParty[(u8)gFieldEffectArguments[0]]; + gFieldEffectArguments[0] = GetMonData(pokemon, MON_DATA_SPECIES); + gFieldEffectArguments[1] = GetMonData(pokemon, MON_DATA_OT_ID); + gFieldEffectArguments[2] = GetMonData(pokemon, MON_DATA_PERSONALITY); + gFieldEffectArguments[0] |= flag; + FieldEffectStart(FLDEFF_FIELD_MOVE_SHOW_MON); + FieldEffectActiveListRemove(FLDEFF_FIELD_MOVE_SHOW_MON_INIT); + return FALSE; +} + +void (*const gUnknown_0855C4A8[])(struct Task *) = { + sub_80B8584, + sub_80B85F8, + sub_80B8660, + sub_80B86EC, + sub_80B871C, + sub_80B8770, + overworld_bg_setup_2, +}; + +void sub_80B8554(u8 taskId) +{ + gUnknown_0855C4A8[gTasks[taskId].data[0]](&gTasks[taskId]); +} + +void sub_80B8584(struct Task *task) +{ + task->data[11] = REG_WININ; + task->data[12] = REG_WINOUT; + StoreWordInTwoHalfwords(&task->data[13], (u32)gMain.vblankCallback); + task->data[1] = 0xf0f1; + task->data[2] = 0x5051; + task->data[3] = 0x3f; + task->data[4] = 0x3e; + SetGpuReg(REG_OFFSET_WIN0H, task->data[1]); + SetGpuReg(REG_OFFSET_WIN0V, task->data[2]); + SetGpuReg(REG_OFFSET_WININ, task->data[3]); + SetGpuReg(REG_OFFSET_WINOUT, task->data[4]); + SetVBlankCallback(sub_80B880C); + task->data[0]++; +} + +void sub_80B85F8(struct Task *task) +{ + u16 offset; + u16 delta; + offset = ((REG_BG0CNT >> 2) << 14); + delta = ((REG_BG0CNT >> 8) << 11); + CpuCopy16(gFieldMoveStreaksTiles, (void *)(VRAM + offset), 0x200); + CpuFill32(0, (void *)(VRAM + delta), 0x800); + LoadPalette(gFieldMoveStreaksPalette, 0xf0, 0x20); + sub_80B8874(delta); + task->data[0]++; +} + +void sub_80B8660(struct Task *task) +{ + s16 v0; + s16 v2; + s16 v3; + task->data[5] -= 16; + v0 = ((u16)task->data[1] >> 8); + v2 = ((u16)task->data[2] >> 8); + v3 = ((u16)task->data[2] & 0xff); + v0 -= 16; + v2 -= 2; + v3 += 2; + if (v0 < 0) + { + v0 = 0; + } + if (v2 < 0x28) + { + v2 = 0x28; + } + if (v3 > 0x78) + { + v3 = 0x78; + } + task->data[1] = (v0 << 8) | (task->data[1] & 0xff); + task->data[2] = (v2 << 8) | v3; + if (v0 == 0 && v2 == 0x28 && v3 == 0x78) + { + gSprites[task->data[15]].callback = sub_80B8CC0; + task->data[0]++; + } +} + +void sub_80B86EC(struct Task *task) +{ + task->data[5] -= 16; + if (gSprites[task->data[15]].data[7]) + { + task->data[0]++; + } +} + +void sub_80B871C(struct Task *task) +{ + s16 v2; + s16 v3; + task->data[5] -= 16; + v2 = (task->data[2] >> 8); + v3 = (task->data[2] & 0xff); + v2 += 6; + v3 -= 6; + if (v2 > 0x50) + { + v2 = 0x50; + } + if (v3 < 0x51) + { + v3 = 0x51; + } + task->data[2] = (v2 << 8) | v3; + if (v2 == 0x50 && v3 == 0x51) + { + task->data[0]++; + } +} + +void sub_80B8770(struct Task *task) +{ + u16 bg0cnt; + bg0cnt = (REG_BG0CNT >> 8) << 11; + CpuFill32(0, (void *)VRAM + bg0cnt, 0x800); + task->data[1] = 0xf1; + task->data[2] = 0xa1; + task->data[3] = task->data[11]; + task->data[4] = task->data[12]; + task->data[0]++; +} + +void overworld_bg_setup_2(struct Task *task) +{ + IntrCallback callback; + LoadWordFromTwoHalfwords((u16 *)&task->data[13], (u32 *)&callback); + SetVBlankCallback(callback); + sub_8197200(); + FreeResourcesAndDestroySprite(&gSprites[task->data[15]], task->data[15]); + FieldEffectActiveListRemove(FLDEFF_FIELD_MOVE_SHOW_MON); + DestroyTask(FindTaskIdByFunc(sub_80B8554)); +} + +void sub_80B880C(void) +{ + struct Task *task; + IntrCallback callback; + task = &gTasks[FindTaskIdByFunc(sub_80B8554)]; + LoadWordFromTwoHalfwords((u16 *)&task->data[13], (u32 *)&callback); + callback(); + SetGpuReg(REG_OFFSET_WIN0H, task->data[1]); + SetGpuReg(REG_OFFSET_WIN0V, task->data[2]); + SetGpuReg(REG_OFFSET_WININ, task->data[3]); + SetGpuReg(REG_OFFSET_WINOUT, task->data[4]); + SetGpuReg(REG_OFFSET_BG0HOFS, task->data[5]); + SetGpuReg(REG_OFFSET_BG0VOFS, task->data[6]); +} + +void sub_80B8874(u16 offs) +{ + u16 i; + u16 *dest; + dest = (u16 *)(VRAM + 0x140 + offs); + for (i = 0; i < 0x140; i++, dest++) + { + *dest = gFieldMoveStreaksTilemap[i] | 0xf000; + } +} + +void sub_80B8AE0(void); +bool8 sub_80B8B38(struct Task *); +void sub_80B8B28(struct Task *); +bool8 sub_80B8BF0(struct Task *); + +void (*const gUnknown_0855C4C4[])(struct Task *) = { + sub_80B88E4, + sub_80B8920, + sub_80B898C, + sub_80B89DC, + sub_80B8A0C, + sub_80B8A44, + sub_80B8A64, +}; + +void sub_80B88B4(u8 taskId) +{ + gUnknown_0855C4C4[gTasks[taskId].data[0]](&gTasks[taskId]); +} + +void sub_80B88E4(struct Task *task) +{ + SetGpuReg(REG_OFFSET_BG0HOFS, task->data[1]); + SetGpuReg(REG_OFFSET_BG0VOFS, task->data[2]); + StoreWordInTwoHalfwords((u16 *)&task->data[13], (u32)gMain.vblankCallback); + SetVBlankCallback(sub_80B8AE0); + task->data[0]++; +} + +void sub_80B8920(struct Task *task) +{ + u16 offset; + u16 delta; + offset = ((REG_BG0CNT >> 2) << 14); + delta = ((REG_BG0CNT >> 8) << 11); + task->data[12] = delta; + CpuCopy16(gDarknessFieldMoveStreaksTiles, (void *)(VRAM + offset), 0x80); + CpuFill32(0, (void *)(VRAM + delta), 0x800); + LoadPalette(gDarknessFieldMoveStreaksPalette, 0xf0, 0x20); + task->data[0]++; +} + +void sub_80B898C(struct Task *task) +{ + if (sub_80B8B38(task)) + { + SetGpuReg(REG_OFFSET_WIN1H, 0x00f0); + SetGpuReg(REG_OFFSET_WIN1V, 0x2878); + gSprites[task->data[15]].callback = sub_80B8CC0; + task->data[0]++; + } + sub_80B8B28(task); +} + +void sub_80B89DC(struct Task *task) +{ + sub_80B8B28(task); + if (gSprites[task->data[15]].data[7]) + { + task->data[0]++; + } +} + +void sub_80B8A0C(struct Task *task) +{ + sub_80B8B28(task); + task->data[3] = task->data[1] & 7; + task->data[4] = 0; + SetGpuReg(REG_OFFSET_WIN1H, 0xffff); + SetGpuReg(REG_OFFSET_WIN1V, 0xffff); + task->data[0]++; +} + +void sub_80B8A44(struct Task *task) +{ + sub_80B8B28(task); + if (sub_80B8BF0(task)) + { + task->data[0]++; + } +} + +void sub_80B8A64(struct Task *task) +{ + IntrCallback intrCallback; + u16 bg0cnt; + bg0cnt = (REG_BG0CNT >> 8) << 11; + CpuFill32(0, (void *)VRAM + bg0cnt, 0x800); + LoadWordFromTwoHalfwords((u16 *)&task->data[13], (u32 *)&intrCallback); + SetVBlankCallback(intrCallback); + sub_8197200(); + FreeResourcesAndDestroySprite(&gSprites[task->data[15]], task->data[15]); + FieldEffectActiveListRemove(FLDEFF_FIELD_MOVE_SHOW_MON); + DestroyTask(FindTaskIdByFunc(sub_80B88B4)); +} + +void sub_80B8AE0(void) +{ + IntrCallback intrCallback; + struct Task *task; + task = &gTasks[FindTaskIdByFunc(sub_80B88B4)]; + LoadWordFromTwoHalfwords((u16 *)&task->data[13], (u32 *)&intrCallback); + intrCallback(); + SetGpuReg(REG_OFFSET_BG0HOFS, task->data[1]); + SetGpuReg(REG_OFFSET_BG0VOFS, task->data[2]); +} + +void sub_80B8B28(struct Task *task) +{ + task->data[1] -= 16; + task->data[3] += 16; +} + +#ifdef NONMATCHING +bool8 sub_80B8B38(struct Task *task) +{ + u16 i; + u16 srcOffs; + u16 dstOffs; + u16 *dest; + if (task->data[4] >= 32) + { + return TRUE; + } + dstOffs = (task->data[3] >> 3) & 0x1f; + if (dstOffs >= task->data[4]) + { + dstOffs = (32 - dstOffs) & 0x1f; + srcOffs = (32 - task->data[4]) & 0x1f; + dest = (u16 *)(VRAM + 0x140 + (u16)task->data[12]); + for (i=0; i<10; i++) + { + dest[dstOffs + i * 32] = gDarknessFieldMoveStreaksTilemap[srcOffs + i * 32] | 0xf000; + dest[((dstOffs + 1) & 0x1f) + i * 32] = gDarknessFieldMoveStreaksTilemap[((srcOffs + 1) & 0x1f) + i * 32] | 0xf000; + } + task->data[4] += 2; + } + return FALSE; +} +#else +NAKED +bool8 sub_80B8B38(struct Task *task) +{ + asm_unified("\tpush {r4-r7,lr}\n" + "\tmov r7, r10\n" + "\tmov r6, r9\n" + "\tmov r5, r8\n" + "\tpush {r5-r7}\n" + "\tsub sp, 0x4\n" + "\tadds r5, r0, 0\n" + "\tldrh r2, [r5, 0x10]\n" + "\tmovs r1, 0x10\n" + "\tldrsh r0, [r5, r1]\n" + "\tcmp r0, 0x1F\n" + "\tble _08088724\n" + "\tmovs r0, 0x1\n" + "\tb _080887A8\n" + "_08088724:\n" + "\tldrh r0, [r5, 0xE]\n" + "\tlsls r0, 16\n" + "\tasrs r3, r0, 19\n" + "\tmovs r1, 0x1F\n" + "\tands r3, r1\n" + "\tmovs r4, 0x10\n" + "\tldrsh r0, [r5, r4]\n" + "\tcmp r3, r0\n" + "\tblt _080887A6\n" + "\tmovs r0, 0x20\n" + "\tsubs r3, r0, r3\n" + "\tands r3, r1\n" + "\tsubs r0, r2\n" + "\tmov r12, r0\n" + "\tmov r7, r12\n" + "\tands r7, r1\n" + "\tmov r12, r7\n" + "\tldrh r0, [r5, 0x20]\n" + "\tldr r1, _080887B8 @ =0x06000140\n" + "\tadds r1, r0\n" + "\tmov r8, r1\n" + "\tmovs r4, 0\n" + "\tldr r7, _080887BC @ =gDarknessFieldMoveStreaksTilemap\n" + "\tmov r10, r7\n" + "\tmovs r0, 0xF0\n" + "\tlsls r0, 8\n" + "\tmov r9, r0\n" + "\tadds r1, r3, 0x1\n" + "\tmovs r0, 0x1F\n" + "\tands r1, r0\n" + "\tstr r1, [sp]\n" + "\tmov r6, r12\n" + "\tadds r6, 0x1\n" + "\tands r6, r0\n" + "_08088768:\n" + "\tlsls r1, r4, 5\n" + "\tadds r2, r1, r3\n" + "\tlsls r2, 1\n" + "\tadd r2, r8\n" + "\tmov r7, r12\n" + "\tadds r0, r7, r1\n" + "\tlsls r0, 1\n" + "\tadd r0, r10\n" + "\tldrh r0, [r0]\n" + "\tmov r7, r9\n" + "\torrs r0, r7\n" + "\tstrh r0, [r2]\n" + "\tldr r0, [sp]\n" + "\tadds r2, r1, r0\n" + "\tlsls r2, 1\n" + "\tadd r2, r8\n" + "\tadds r1, r6, r1\n" + "\tlsls r1, 1\n" + "\tadd r1, r10\n" + "\tldrh r0, [r1]\n" + "\tmov r1, r9\n" + "\torrs r0, r1\n" + "\tstrh r0, [r2]\n" + "\tadds r0, r4, 0x1\n" + "\tlsls r0, 16\n" + "\tlsrs r4, r0, 16\n" + "\tcmp r4, 0x9\n" + "\tbls _08088768\n" + "\tldrh r0, [r5, 0x10]\n" + "\tadds r0, 0x2\n" + "\tstrh r0, [r5, 0x10]\n" + "_080887A6:\n" + "\tmovs r0, 0\n" + "_080887A8:\n" + "\tadd sp, 0x4\n" + "\tpop {r3-r5}\n" + "\tmov r8, r3\n" + "\tmov r9, r4\n" + "\tmov r10, r5\n" + "\tpop {r4-r7}\n" + "\tpop {r1}\n" + "\tbx r1\n" + "\t.align 2, 0\n" + "_080887B8: .4byte 0x06000140\n" + "_080887BC: .4byte gDarknessFieldMoveStreaksTilemap"); +} +#endif + +bool8 sub_80B8BF0(struct Task *task) +{ + u16 i; + u16 dstOffs; + u16 *dest; + if (task->data[4] >= 32) + { + return TRUE; + } + dstOffs = task->data[3] >> 3; + if (dstOffs >= task->data[4]) + { + dstOffs = (task->data[1] >> 3) & 0x1f; + dest = (u16 *)(VRAM + 0x140 + (u16)task->data[12]); + for (i=0; i<10; i++) + { + dest[dstOffs + i * 32] = 0xf000; + dest[((dstOffs + 1) & 0x1f) + i * 32] = 0xf000; + } + task->data[4] += 2; + } + return FALSE; +} + +u8 sub_80B8C60(u32 a0, u32 a1, u32 a2) +{ + u16 v0; + u8 monSprite; + struct Sprite *sprite; + v0 = (a0 & 0x80000000) >> 16; + a0 &= 0x7fffffff; + monSprite = CreateMonSprite_FieldMove(a0, a1, a2, 0x140, 0x50, 0); + sprite = &gSprites[monSprite]; + sprite->callback = SpriteCallbackDummy; + sprite->oam.priority = 0; + sprite->data[0] = a0; + sprite->data[6] = v0; + return monSprite; +} + +void sub_80B8D04(struct Sprite *); + +void sub_80B8CC0(struct Sprite *sprite) +{ + if ((sprite->pos1.x -= 20) <= 0x78) + { + sprite->pos1.x = 0x78; + sprite->data[1] = 30; + sprite->callback = sub_80B8D04; + if (sprite->data[6]) + { + PlayCry2(sprite->data[0], 0, 0x7d, 0xa); + } else + { + PlayCry1(sprite->data[0], 0); + } + } +} + +void sub_80B8D20(struct Sprite *); + +void sub_80B8D04(struct Sprite *sprite) +{ + if ((--sprite->data[1]) == 0) + { + sprite->callback = sub_80B8D20; + } +} + +void sub_80B8D20(struct Sprite *sprite) +{ + if (sprite->pos1.x < -0x40) + { + sprite->data[7] = 1; + } else + { + sprite->pos1.x -= 20; + } +} + +void sub_80B8D84(u8); + +u8 FldEff_UseSurf(void) +{ + u8 taskId; + taskId = CreateTask(sub_80B8D84, 0xff); + gTasks[taskId].data[15] = gFieldEffectArguments[0]; + Overworld_ClearSavedMusic(); + Overworld_ChangeMusicTo(MUS_NAMINORI); + return FALSE; +} + +void (*const gUnknown_0855C4E0[])(struct Task *) = { + sub_80B8DB4, + sub_80B8E14, + sub_80B8E60, + sub_80B8EA8, + sub_80B8F24, +}; + +void sub_80B8D84(u8 taskId) +{ + gUnknown_0855C4E0[gTasks[taskId].data[0]](&gTasks[taskId]); +} + +void sub_80B8DB4(struct Task *task) +{ + ScriptContext2_Enable(); + FreezeMapObjects(); + gPlayerAvatar.preventStep = TRUE; + SetPlayerAvatarStateMask(8); + PlayerGetDestCoords(&task->data[1], &task->data[2]); + MoveCoords(gMapObjects[gPlayerAvatar.mapObjectId].placeholder18, &task->data[1], &task->data[2]); + task->data[0]++; +} + +void sub_80B8E14(struct Task *task) +{ + struct MapObject *mapObject; + mapObject = &gMapObjects[gPlayerAvatar.mapObjectId]; + if (!FieldObjectIsSpecialAnimOrDirectionSequenceAnimActive(mapObject) || FieldObjectClearAnimIfSpecialAnimFinished(mapObject)) + { + sub_808C114(); + FieldObjectSetSpecialAnim(mapObject, 0x39); + task->data[0]++; + } +} + +void sub_80B8E60(struct Task *task) +{ + struct MapObject *mapObject; + mapObject = &gMapObjects[gPlayerAvatar.mapObjectId]; + if (FieldObjectCheckIfSpecialAnimFinishedOrInactive(mapObject)) + { + gFieldEffectArguments[0] = task->data[15] | 0x80000000; + FieldEffectStart(FLDEFF_FIELD_MOVE_SHOW_MON_INIT); + task->data[0]++; + } +} + +void sub_80B8EA8(struct Task *task) +{ + struct MapObject *mapObject; + if (!FieldEffectActiveListContains(FLDEFF_FIELD_MOVE_SHOW_MON)) + { + mapObject = &gMapObjects[gPlayerAvatar.mapObjectId]; + FieldObjectSetGraphicsId(mapObject, GetPlayerAvatarGraphicsIdByStateId(3)); + FieldObjectClearAnimIfSpecialAnimFinished(mapObject); + FieldObjectSetSpecialAnim(mapObject, sub_8093540(mapObject->placeholder18)); + gFieldEffectArguments[0] = task->data[1]; + gFieldEffectArguments[1] = task->data[2]; + gFieldEffectArguments[2] = gPlayerAvatar.mapObjectId; + mapObject->mapobj_unk_1A = FieldEffectStart(FLDEFF_SURF_BLOB); + task->data[0]++; + } +} + +void sub_80B8F24(struct Task *task) +{ + struct MapObject *mapObject; + mapObject = &gMapObjects[gPlayerAvatar.mapObjectId]; + if (FieldObjectClearAnimIfSpecialAnimFinished(mapObject)) + { + gPlayerAvatar.preventStep = FALSE; + gPlayerAvatar.flags &= 0xdf; + FieldObjectSetSpecialAnim(mapObject, GetFaceDirectionAnimId(mapObject->placeholder18)); + sub_81555AC(mapObject->mapobj_unk_1A, 1); + UnfreezeMapObjects(); + ScriptContext2_Disable(); + FieldEffectActiveListRemove(FLDEFF_USE_SURF); + DestroyTask(FindTaskIdByFunc(sub_80B8D84)); + } +} + +#ifdef NONMATCHING +u8 sub_80B8F98(void) +{ + u8 spriteId, i, j, k, l; + struct Sprite *sprite; + spriteId = CreateSprite(gFieldEffectObjectTemplatePointers[36], 0x78, -0x18, 1); + sprite = &gSprites[spriteId]; + sprite->oam.priority = 1; + sprite->oam.paletteNum = 4; + sprite->data[0] = 0; + sprite->data[1] = 0; + sprite->data[2] = 0; + sprite->data[3] = -1; + sprite->data[4] = sprite->pos1.y; + sprite->data[5] = 0; + SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT1_BG0 | BLDCNT_EFFECT_BLEND | BLDCNT_TGT2_BG1 | BLDCNT_TGT2_BG2 | BLDCNT_TGT2_BG3 | BLDCNT_TGT2_OBJ | BLDCNT_TGT2_BD); + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(14, 14)); + SetGpuReg(REG_OFFSET_WININ, 0x3F3F); + LoadPalette(gUnknown_0855B610, 0xC0, sizeof(gUnknown_0855B610)); + SetGpuReg(REG_OFFSET_BG0VOFS, 120); + for (i = 3; i < 15; i++) + { + for (j = 12; j < 18; j++) + { + ((u16*)(VRAM + 0xF800))[i * 32 + j] = 0xBFF4 + i * 6 + j + 1; + } + } + for (k = 0; k < 90; k++) + { + for (l = 0; l < 8; l++) + { + *(u16*)(VRAM + 0x8000 + (k + 1) * 32 + l * 4) = (gUnknown_0855B630[k * 32 + l * 4 + 1] << 8) + gUnknown_0855B630[k * 32 + l * 4]; + *(u16*)(VRAM + 0x8000 + (k + 1) * 32 + l * 4 + 2) = (gUnknown_0855B630[k * 32 + l * 4 + 3] << 8) + gUnknown_0855B630[k * 32 + l * 4 + 2]; + } + } + return spriteId; +} +#else +NAKED +u8 sub_80B8F98(void) +{ + asm_unified("push {r4-r7,lr}\n\ + mov r7, r8\n\ + push {r7}\n\ + ldr r0, =gFieldEffectObjectTemplatePointers\n\ + adds r0, 0x90\n\ + ldr r0, [r0]\n\ + movs r2, 0x18\n\ + negs r2, r2\n\ + movs r1, 0x78\n\ + movs r3, 0x1\n\ + bl CreateSprite\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + mov r8, r0\n\ + lsls r1, r0, 4\n\ + add r1, r8\n\ + lsls r1, 2\n\ + ldr r0, =gSprites\n\ + adds r1, r0\n\ + ldrb r2, [r1, 0x5]\n\ + movs r0, 0xD\n\ + negs r0, r0\n\ + ands r0, r2\n\ + movs r2, 0x4\n\ + orrs r0, r2\n\ + movs r2, 0xF\n\ + ands r0, r2\n\ + movs r2, 0x40\n\ + orrs r0, r2\n\ + strb r0, [r1, 0x5]\n\ + movs r2, 0\n\ + strh r2, [r1, 0x2E]\n\ + strh r2, [r1, 0x30]\n\ + strh r2, [r1, 0x32]\n\ + ldr r0, =0x0000ffff\n\ + strh r0, [r1, 0x34]\n\ + ldrh r0, [r1, 0x22]\n\ + strh r0, [r1, 0x36]\n\ + strh r2, [r1, 0x38]\n\ + ldr r1, =0x00003e41\n\ + movs r0, 0x50\n\ + bl SetGpuReg\n\ + ldr r1, =0x00000e0e\n\ + movs r0, 0x52\n\ + bl SetGpuReg\n\ + ldr r1, =0x00003f3f\n\ + movs r0, 0x48\n\ + bl SetGpuReg\n\ + ldr r0, =gUnknown_0855B610\n\ + movs r1, 0xC0\n\ + movs r2, 0x20\n\ + bl LoadPalette\n\ + movs r0, 0x12\n\ + movs r1, 0x78\n\ + bl SetGpuReg\n\ + movs r4, 0x3\n\ + ldr r7, =0x0600f800\n\ + ldr r0, =0x0000bff4\n\ + adds r6, r0, 0\n\ +_080B901A:\n\ + movs r2, 0xC\n\ + lsls r0, r4, 1\n\ + lsls r5, r4, 5\n\ + adds r0, r4\n\ + lsls r3, r0, 1\n\ +_080B9024:\n\ + adds r0, r5, r2\n\ + lsls r0, 1\n\ + adds r0, r7\n\ + adds r1, r2, r6\n\ + adds r1, r3, r1\n\ + adds r1, 0x1\n\ + strh r1, [r0]\n\ + adds r0, r2, 0x1\n\ + lsls r0, 24\n\ + lsrs r2, r0, 24\n\ + cmp r2, 0x11\n\ + bls _080B9024\n\ + adds r0, r4, 0x1\n\ + lsls r0, 24\n\ + lsrs r4, r0, 24\n\ + cmp r4, 0xE\n\ + bls _080B901A\n\ + movs r0, 0\n\ + ldr r5, =gUnknown_0855B630\n\ +_080B904A:\n\ + movs r4, 0\n\ + adds r7, r0, 0x1\n\ + lsls r6, r0, 5\n\ +_080B9050:\n\ + lsls r1, r4, 2\n\ + adds r1, r6, r1\n\ + ldr r0, =0x06008020\n\ + adds r3, r1, r0\n\ + adds r0, r1, 0x1\n\ + adds r0, r5\n\ + ldrb r2, [r0]\n\ + lsls r2, 8\n\ + adds r0, r1, r5\n\ + ldrb r0, [r0]\n\ + adds r0, r2\n\ + strh r0, [r3]\n\ + ldr r0, =0x06008022\n\ + adds r3, r1, r0\n\ + adds r0, r1, 0x3\n\ + adds r0, r5\n\ + ldrb r2, [r0]\n\ + lsls r2, 8\n\ + adds r1, 0x2\n\ + adds r1, r5\n\ + ldrb r0, [r1]\n\ + adds r0, r2\n\ + strh r0, [r3]\n\ + adds r0, r4, 0x1\n\ + lsls r0, 24\n\ + lsrs r4, r0, 24\n\ + cmp r4, 0x7\n\ + bls _080B9050\n\ + lsls r0, r7, 24\n\ + lsrs r0, 24\n\ + cmp r0, 0x59\n\ + bls _080B904A\n\ + mov r0, r8\n\ + pop {r3}\n\ + mov r8, r3\n\ + pop {r4-r7}\n\ + pop {r1}\n\ + bx r1\n\ + .pool"); +} +#endif // NONMATCHING + +void sub_80B9128(struct Sprite *); + +u8 FldEff_NPCFlyOut(void) +{ + u8 spriteId; + struct Sprite *sprite; + spriteId = CreateSprite(gFieldEffectObjectTemplatePointers[26], 0x78, 0, 1); + sprite = &gSprites[spriteId]; + sprite->oam.paletteNum = 0; + sprite->oam.priority = 1; + sprite->callback = sub_80B9128; + sprite->data[1] = gFieldEffectArguments[0]; + PlaySE(SE_W019); + return spriteId; +} + +void sub_80B9128(struct Sprite *sprite) +{ + struct Sprite *npcSprite; + sprite->pos2.x = Cos(sprite->data[2], 0x8c); + sprite->pos2.y = Sin(sprite->data[2], 0x48); + sprite->data[2] = (sprite->data[2] + 4) & 0xff; + if (sprite->data[0]) + { + npcSprite = &gSprites[sprite->data[1]]; + npcSprite->coordOffsetEnabled = 0; + npcSprite->pos1.x = sprite->pos1.x + sprite->pos2.x; + npcSprite->pos1.y = sprite->pos1.y + sprite->pos2.y - 8; + npcSprite->pos2.x = 0; + npcSprite->pos2.y = 0; + } + if (sprite->data[2] >= 0x80) + { + FieldEffectStop(sprite, FLDEFF_NPCFLY_OUT); + } +} + +void sub_80B91D4(u8); +extern void sub_81555D8(u8, u8); +u8 sub_80B94C4(void); +bool8 sub_80B9508(u8); +void sub_80B9524(u8); +void sub_80B9560(u8, u8); +void sub_80B957C(struct Sprite *); +void sub_80B963C(struct Sprite *); + +u8 FldEff_UseFly(void) +{ + u8 taskId; + taskId = CreateTask(sub_80B91D4, 0xfe); + gTasks[taskId].data[1] = gFieldEffectArguments[0]; + return 0; +} + +void (*const gUnknown_0855C4F4[])(struct Task *) = { + sub_80B9204, + sub_80B925C, + sub_80B92A0, + sub_80B92F8, + sub_80B933C, + sub_80B9390, + sub_80B9418, + sub_80B9474, + sub_80B9494, +}; + +void sub_80B91D4(u8 taskId) +{ + gUnknown_0855C4F4[gTasks[taskId].data[0]](&gTasks[taskId]); +} + +void sub_80B9204(struct Task *task) +{ + struct MapObject *mapObject; + mapObject = &gMapObjects[gPlayerAvatar.mapObjectId]; + if (!FieldObjectIsSpecialAnimOrDirectionSequenceAnimActive(mapObject) || FieldObjectClearAnimIfSpecialAnimFinished(mapObject)) + { + task->data[15] = gPlayerAvatar.flags; + gPlayerAvatar.preventStep = TRUE; + SetPlayerAvatarStateMask(1); + sub_808C114(); + FieldObjectSetSpecialAnim(mapObject, 0x39); + task->data[0]++; + } +} + +void sub_80B925C(struct Task *task) +{ + struct MapObject *mapObject; + mapObject = &gMapObjects[gPlayerAvatar.mapObjectId]; + if (FieldObjectClearAnimIfSpecialAnimFinished(mapObject)) + { + task->data[0]++; + gFieldEffectArguments[0] = task->data[1]; + FieldEffectStart(FLDEFF_FIELD_MOVE_SHOW_MON_INIT); + } +} + +void sub_80B92A0(struct Task *task) +{ + struct MapObject *mapObject; + if (!FieldEffectActiveListContains(FLDEFF_FIELD_MOVE_SHOW_MON)) + { + mapObject = &gMapObjects[gPlayerAvatar.mapObjectId]; + if (task->data[15] & 0x08) + { + sub_81555AC(mapObject->mapobj_unk_1A, 2); + sub_81555D8(mapObject->mapobj_unk_1A, 0); + } + task->data[1] = sub_80B94C4(); + task->data[0]++; + } +} + +void sub_80B92F8(struct Task *task) +{ + if (sub_80B9508(task->data[1])) + { + task->data[0]++; + task->data[2] = 16; + SetPlayerAvatarTransitionFlags(PLAYER_AVATAR_FLAG_ON_FOOT); + FieldObjectSetSpecialAnim(&gMapObjects[gPlayerAvatar.mapObjectId], 0x02); + } +} + +void sub_80B933C(struct Task *task) +{ + struct MapObject *mapObject; + mapObject = &gMapObjects[gPlayerAvatar.mapObjectId]; + if ((task->data[2] == 0 || (--task->data[2]) == 0) && FieldObjectClearAnimIfSpecialAnimFinished(mapObject)) + { + task->data[0]++; + PlaySE(SE_W019); + sub_80B9524(task->data[1]); + } +} + +void sub_80B9390(struct Task *task) +{ + struct MapObject *mapObject; + if ((++task->data[2]) >= 8) + { + mapObject = &gMapObjects[gPlayerAvatar.mapObjectId]; + FieldObjectSetGraphicsId(mapObject, GetPlayerAvatarGraphicsIdByStateId(0x03)); + StartSpriteAnim(&gSprites[mapObject->spriteId], 0x16); + mapObject->mapobj_bit_12 = 1; + FieldObjectSetSpecialAnim(mapObject, 0x48); + if (task->data[15] & 0x08) + { + DestroySprite(&gSprites[mapObject->mapobj_unk_1A]); + } + task->data[0]++; + task->data[2] = 0; + } +} + +void sub_80B9418(struct Task *task) +{ + struct MapObject *mapObject; + if ((++task->data[2]) >= 10) + { + mapObject = &gMapObjects[gPlayerAvatar.mapObjectId]; + FieldObjectClearAnimIfSpecialAnimActive(mapObject); + mapObject->mapobj_bit_12 = 0; + mapObject->mapobj_bit_22 = 0; + sub_80B9560(task->data[1], mapObject->spriteId); + CameraObjectReset2(); + task->data[0]++; + } +} + +void sub_80B9474(struct Task *task) +{ + if (sub_80B9508(task->data[1])) + { + sub_80AF0B4(); + task->data[0]++; + } +} + +void sub_80B9494(struct Task *task) +{ + if (!gPaletteFade.active) + { + FieldEffectActiveListRemove(FLDEFF_USE_FLY); + DestroyTask(FindTaskIdByFunc(sub_80B91D4)); + } +} + +u8 sub_80B94C4(void) +{ + u8 spriteId; + struct Sprite *sprite; + spriteId = CreateSprite(gFieldEffectObjectTemplatePointers[26], 0xff, 0xb4, 0x1); + sprite = &gSprites[spriteId]; + sprite->oam.paletteNum = 0; + sprite->oam.priority = 1; + sprite->callback = sub_80B957C; + return spriteId; +} + +u8 sub_80B9508(u8 spriteId) +{ + return gSprites[spriteId].data[7]; +} + +void sub_80B9524(u8 spriteId) +{ + struct Sprite *sprite; + sprite = &gSprites[spriteId]; + sprite->callback = sub_80B963C; + sprite->pos1.x = 0x78; + sprite->pos1.y = 0x00; + sprite->pos2.x = 0; + sprite->pos2.y = 0; + memset(&sprite->data[0], 0, 8 * sizeof(u16) /* zero all data cells */); + sprite->data[6] = 0x40; +} + +void sub_80B9560(u8 a0, u8 a1) +{ + gSprites[a0].data[6] = a1; +} + +const union AffineAnimCmd SpriteAffineAnim_855C518[] = { + AFFINEANIMCMD_FRAME(8, 8, -30, 0), + AFFINEANIMCMD_FRAME(28, 28, 0, 30), + AFFINEANIMCMD_END +}; + +const union AffineAnimCmd SpriteAffineAnim_855C530[] = { + AFFINEANIMCMD_FRAME(256, 256, 64, 0), + AFFINEANIMCMD_FRAME(-10, -10, 0, 22), + AFFINEANIMCMD_END +}; + +const union AffineAnimCmd *const gSpriteAffineAnimTable_0855C548[] = { + SpriteAffineAnim_855C518, + SpriteAffineAnim_855C530 +}; + +void sub_80B957C(struct Sprite *sprite) +{ + if (sprite->data[7] == 0) + { + if (sprite->data[0] == 0) + { + sprite->oam.affineMode = 3; + sprite->affineAnims = gSpriteAffineAnimTable_0855C548; + InitSpriteAffineAnim(sprite); + StartSpriteAffineAnim(sprite, 0); + sprite->pos1.x = 0x76; + sprite->pos1.y = -0x30; + sprite->data[0]++; + sprite->data[1] = 0x40; + sprite->data[2] = 0x100; + } + sprite->data[1] += (sprite->data[2] >> 8); + sprite->pos2.x = Cos(sprite->data[1], 0x78); + sprite->pos2.y = Sin(sprite->data[1], 0x78); + if (sprite->data[2] < 0x800) + { + sprite->data[2] += 0x60; + } + if (sprite->data[1] > 0x81) + { + sprite->data[7]++; + sprite->oam.affineMode = 0; + FreeOamMatrix(sprite->oam.matrixNum); + CalcCenterToCornerVec(sprite, sprite->oam.shape, sprite->oam.size, 0); + } + } +} + +void sub_80B963C(struct Sprite *sprite) +{ + struct Sprite *sprite1; + sprite->pos2.x = Cos(sprite->data[2], 0x8c); + sprite->pos2.y = Sin(sprite->data[2], 0x48); + sprite->data[2] = (sprite->data[2] + 4) & 0xff; + if (sprite->data[6] != 0x40) + { + sprite1 = &gSprites[sprite->data[6]]; + sprite1->coordOffsetEnabled = 0; + sprite1->pos1.x = sprite->pos1.x + sprite->pos2.x; + sprite1->pos1.y = sprite->pos1.y + sprite->pos2.y - 8; + sprite1->pos2.x = 0; + sprite1->pos2.y = 0; + } + if (sprite->data[2] >= 0x80) + { + sprite->data[7] = 1; + } +} + +void sub_80B96B0(struct Sprite *sprite) +{ + if (sprite->data[7] == 0) + { + if (sprite->data[0] == 0) + { + sprite->oam.affineMode = 3; + sprite->affineAnims = gSpriteAffineAnimTable_0855C548; + InitSpriteAffineAnim(sprite); + StartSpriteAffineAnim(sprite, 1); + sprite->pos1.x = 0x5e; + sprite->pos1.y = -0x20; + sprite->data[0]++; + sprite->data[1] = 0xf0; + sprite->data[2] = 0x800; + sprite->data[4] = 0x80; + } + sprite->data[1] += sprite->data[2] >> 8; + sprite->data[3] += sprite->data[2] >> 8; + sprite->data[1] &= 0xff; + sprite->pos2.x = Cos(sprite->data[1], 0x20); + sprite->pos2.y = Sin(sprite->data[1], 0x78); + if (sprite->data[2] > 0x100) + { + sprite->data[2] -= sprite->data[4]; + } + if (sprite->data[4] < 0x100) + { + sprite->data[4] += 24; + } + if (sprite->data[2] < 0x100) + { + sprite->data[2] = 0x100; + } + if (sprite->data[3] >= 60) + { + sprite->data[7]++; + sprite->oam.affineMode = 0; + FreeOamMatrix(sprite->oam.matrixNum); + sprite->invisible = 1; + } + } +} + +void sub_80B9794(u8 spriteId) +{ + sub_80B9524(spriteId); + gSprites[spriteId].callback = sub_80B96B0; +} + +void sub_80B97D4(u8); + +u8 FldEff_FlyIn(void) +{ + CreateTask(sub_80B97D4, 0xfe); + return 0; +} + +void (*const gUnknown_0855C550[])(struct Task *) = { + sub_80B9804, + sub_80B98B8, + sub_80B9924, + sub_80B9978, + sub_80B99F0, + sub_80B9A28, + sub_80B9A60, +}; + +void sub_80B97D4(u8 taskId) +{ + gUnknown_0855C550[gTasks[taskId].data[0]](&gTasks[taskId]); +} + +void sub_80B9804(struct Task *task) +{ + struct MapObject *mapObject; + mapObject = &gMapObjects[gPlayerAvatar.mapObjectId]; + if (!FieldObjectIsSpecialAnimOrDirectionSequenceAnimActive(mapObject) || FieldObjectClearAnimIfSpecialAnimFinished(mapObject)) + { + task->data[0]++; + task->data[2] = 17; + task->data[15] = gPlayerAvatar.flags; + gPlayerAvatar.preventStep = TRUE; + SetPlayerAvatarStateMask(0x01); + if (task->data[15] & 0x08) + { + sub_81555AC(mapObject->mapobj_unk_1A, 0); + } + FieldObjectSetGraphicsId(mapObject, GetPlayerAvatarGraphicsIdByStateId(0x3)); + CameraObjectReset2(); + FieldObjectTurn(mapObject, DIR_WEST); + StartSpriteAnim(&gSprites[mapObject->spriteId], 0x16); + mapObject->mapobj_bit_13 = 0; + task->data[1] = sub_80B94C4(); + sub_80B9524(task->data[1]); + sub_80B9560(task->data[1], mapObject->spriteId); + } +} + +void sub_80B98B8(struct Task *task) +{ + struct MapObject *mapObject; + struct Sprite *sprite; + if (task->data[2] == 0 || (--task->data[2]) == 0) + { + mapObject = &gMapObjects[gPlayerAvatar.mapObjectId]; + sprite = &gSprites[mapObject->spriteId]; + sub_80B9560(task->data[1], 0x40); + sprite->pos1.x += sprite->pos2.x; + sprite->pos1.y += sprite->pos2.y; + sprite->pos2.x = 0; + sprite->pos2.y = 0; + task->data[0]++; + task->data[2] = 0; + } +} + +void sub_80B9924(struct Task *task) +{ + s16 unknown_0855C56C[18] = { + -2, + -4, + -5, + -6, + -7, + -8, + -8, + -8, + -7, + -7, + -6, + -5, + -3, + -2, + 0, + 2, + 4, + 8 + }; + struct Sprite *sprite = &gSprites[gPlayerAvatar.spriteId]; + sprite->pos2.y = unknown_0855C56C[task->data[2]]; + if ((++task->data[2]) >= 18) + { + task->data[0]++; + } +} + +void sub_80B9978(struct Task *task) +{ + struct MapObject *mapObject; + struct Sprite *sprite; + if (sub_80B9508(task->data[1])) + { + mapObject = &gMapObjects[gPlayerAvatar.mapObjectId]; + sprite = &gSprites[mapObject->spriteId]; + mapObject->mapobj_bit_12 = 0; + sub_808EB08(mapObject, mapObject->coords2.x, mapObject->coords2.y); + sprite->pos2.x = 0; + sprite->pos2.y = 0; + sprite->coordOffsetEnabled = 1; + sub_808C114(); + FieldObjectSetSpecialAnim(mapObject, 0x39); + task->data[0]++; + } +} + +void sub_80B99F0(struct Task *task) +{ + if (FieldObjectClearAnimIfSpecialAnimFinished(&gMapObjects[gPlayerAvatar.mapObjectId])) + { + task->data[0]++; + sub_80B9794(task->data[1]); + } +} + +void sub_80B9A28(struct Task *task) +{ + if (sub_80B9508(task->data[1])) + { + DestroySprite(&gSprites[task->data[1]]); + task->data[0]++; + task->data[1] = 0x10; + } +} + +void sub_80B9A60(struct Task *task) +{ + u8 state; + struct MapObject *mapObject; + if ((--task->data[1]) == 0) + { + mapObject = &gMapObjects[gPlayerAvatar.mapObjectId]; + state = 0; + if (task->data[15] & 0x08) + { + state = 3; + sub_81555AC(mapObject->mapobj_unk_1A, 1); + } + FieldObjectSetGraphicsId(mapObject, GetPlayerAvatarGraphicsIdByStateId(state)); + FieldObjectTurn(mapObject, DIR_SOUTH); + gPlayerAvatar.flags = task->data[15]; + gPlayerAvatar.preventStep = FALSE; + FieldEffectActiveListRemove(FLDEFF_FLY_IN); + DestroyTask(FindTaskIdByFunc(sub_80B97D4)); + } +} + +void sub_80B9BE8(u8 taskId); + +bool8 sub_80B9ADC(void) +{ + u8 taskId; + u8 mapObjectIdBuffer; + if (!TryGetFieldObjectIdByLocalIdAndMap(gFieldEffectArguments[0], gFieldEffectArguments[1], gFieldEffectArguments[2], &mapObjectIdBuffer)) + { + taskId = CreateTask(sub_80B9BE8, 0x50); + gTasks[taskId].data[2] = mapObjectIdBuffer; + gTasks[taskId].data[6] = gFieldEffectArguments[0]; + gTasks[taskId].data[7] = gFieldEffectArguments[1]; + gTasks[taskId].data[8] = gFieldEffectArguments[2]; + } + else + { + FieldEffectActiveListRemove(0x41); + } + return FALSE; +} + +void sub_80B9B3C(u8 taskId) +{ + s16 *data = gTasks[taskId].data; + if (data[7] != 0) + { + if (++data[6] > 20) + { + data[6] = 0; + if (data[5] != 0) + data[5]--; + } + } + else + { + data[5] = 4; + } + + if (++data[0] > 1) + { + data[0] = 0; + if (++data[1] & 1) + { + SetCameraPanning(0, -data[5]); + } + else + { + SetCameraPanning(0, data[5]); + } + } + UpdateCameraPanning(); + if (data[5] == 0) + DestroyTask(taskId); +} + +void sub_80B9BD0(u8 taskId) +{ + gTasks[taskId].data[7] = 1; +} + +void (*const gUnknown_0855C590[])(s16*, u8) = { + sub_80B9C28, + sub_80B9C54, + sub_80B9CDC, +}; + +void sub_80B9BE8(u8 taskId) +{ + s16 *data = gTasks[taskId].data; + InstallCameraPanAheadCallback(); + SetCameraPanningCallback(0); + gUnknown_0855C590[data[1]](data, taskId); +} + +void sub_80B9C28(s16* data, u8 taskId) +{ + u8 newTaskId = CreateTask(sub_80B9B3C, 0x5A); + PlaySE(SE_T_KAMI2); + data[5] = newTaskId; + data[1]++; +} + +void sub_80B9D24(struct Sprite*); + +void sub_80B9C54(s16* data, u8 taskId) +{ + if (++data[3] > 0x78) + { + struct Sprite *sprite = &gSprites[gMapObjects[data[2]].spriteId]; + gMapObjects[data[2]].mapobj_bit_13 = TRUE; + BlendPalettes(0x0000FFFF, 0x10, RGB_WHITE); + BeginNormalPaletteFade(0x0000FFFF, 0, 0x10, 0, RGB_WHITE); + sub_80B9D24(sprite); + PlaySE(SE_T_KAMI); + sub_80B9BD0(data[5]); + data[3] = 0; + data[1]++; + } +} + +void sub_80B9CDC(s16* a0, u8 taskId) +{ + if (!gPaletteFade.active && !FuncIsActiveTask(sub_80B9B3C)) + { + InstallCameraPanAheadCallback(); + RemoveFieldObjectByLocalIdAndMap(a0[6], a0[7], a0[8]); + FieldEffectActiveListRemove(0x41); + DestroyTask(taskId); + } +} + +void sub_80B9DB8(struct Sprite* sprite); + +const struct SpriteFrameImage gSpriteImageTable_855C59C[] = { + obj_frame_tiles(gUnknown_0855C170), + obj_frame_tiles(gUnknown_0855C190), + obj_frame_tiles(gUnknown_0855C1B0), + obj_frame_tiles(gUnknown_0855C1D0), +}; + +const union AnimCmd gSpriteAnim_855C5BC[] = { + ANIMCMD_FRAME(.imageValue = 0), + ANIMCMD_END +}; + +const union AnimCmd gSpriteAnim_855C5C4[] = { + ANIMCMD_FRAME(.imageValue = 1), + ANIMCMD_END +}; + +const union AnimCmd gSpriteAnim_855C5CC[] = { + ANIMCMD_FRAME(.imageValue = 2), + ANIMCMD_END +}; + +const union AnimCmd gSpriteAnim_855C5D4[] = { + ANIMCMD_FRAME(.imageValue = 3), + ANIMCMD_END +}; + +const union AnimCmd *const gSpriteAnimTable_855C5DC[] = { + gSpriteAnim_855C5BC, + gSpriteAnim_855C5C4, + gSpriteAnim_855C5CC, + gSpriteAnim_855C5D4, +}; + +const struct SpriteTemplate gUnknown_0855C5EC = { + .tileTag = 0xffff, + .paletteTag = 4378, + .oam = &gOamData_855C218, + .anims = gSpriteAnimTable_855C5DC, + .images = gSpriteImageTable_855C59C, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_80B9DB8 +}; + +void sub_80B9D24(struct Sprite* sprite) +{ + int i; + int xPos = (s16)gUnknown_03005DEC + sprite->pos1.x + sprite->pos2.x; + int yPos = (s16)gUnknown_03005DE8 + sprite->pos1.y + sprite->pos2.y - 4; + + for (i = 0; i < 4; i++) + { + u8 spriteId = CreateSprite(&gUnknown_0855C5EC, xPos, yPos, 0); + if (spriteId != 0x40) + { + StartSpriteAnim(&gSprites[spriteId], i); + gSprites[spriteId].data[0] = i; + gSprites[spriteId].oam.paletteNum = sprite->oam.paletteNum; + } + } +} + +void sub_80B9DB8(struct Sprite* sprite) +{ + switch (sprite->data[0]) + { + case 0: + sprite->pos1.x -= 16; + sprite->pos1.y -= 12; + break; + case 1: + sprite->pos1.x += 16; + sprite->pos1.y -= 12; + break; + case 2: + sprite->pos1.x -= 16; + sprite->pos1.y += 12; + break; + case 3: + sprite->pos1.x += 16; + sprite->pos1.y += 12; + break; + } + if ((u16)(sprite->pos1.x + 4) > 0xF8 || sprite->pos1.y < -4 || sprite->pos1.y > 0xA4) + DestroySprite(sprite); +} + +void sub_80B9EDC(u8 taskId); + +bool8 sub_80B9E28(struct Sprite* sprite) +{ + u8 mapObjectIdBuffer; + if (!TryGetFieldObjectIdByLocalIdAndMap(gFieldEffectArguments[0], gFieldEffectArguments[1], gFieldEffectArguments[2], &mapObjectIdBuffer)) + { + struct MapObject *object; + int xPos, yPos; + u8 taskId; + object = &gMapObjects[mapObjectIdBuffer]; + xPos = object->coords2.x - 7; + yPos = object->coords2.y - 7; + xPos = (gFieldEffectArguments[3] - xPos) * 16; + yPos = (gFieldEffectArguments[4] - yPos) * 16; + npc_coords_shift(object, gFieldEffectArguments[3] + 7, gFieldEffectArguments[4] + 7); + taskId = CreateTask(sub_80B9EDC, 0x50); + gTasks[taskId].data[1] = object->spriteId; + gTasks[taskId].data[2] = gSprites[object->spriteId].pos1.x + xPos; + gTasks[taskId].data[3] = gSprites[object->spriteId].pos1.y + yPos; + gTasks[taskId].data[8] = gFieldEffectArguments[5]; + gTasks[taskId].data[9] = mapObjectIdBuffer; + } + return FALSE; +} + +void sub_80B9EDC(u8 taskId) +{ + // BUG: Possible divide by zero + s16 *data = gTasks[taskId].data; + struct Sprite *sprite = &gSprites[data[1]]; + switch (data[0]) + { + case 0: + data[4] = sprite->pos1.x << 4; + data[5] = sprite->pos1.y << 4; + data[6] = (data[2] * 16 - data[4]) / data[8]; + data[7] = (data[3] * 16 - data[5]) / data[8]; + data[0]++; + case 1: + if (data[8] != 0) + { + data[8]--; + data[4] += data[6]; + data[5] += data[7]; + sprite->pos1.x = data[4] >> 4; + sprite->pos1.y = data[5] >> 4; + } + else + { + struct MapObject *object = &gMapObjects[data[9]]; + sprite->pos1.x = data[2]; + sprite->pos1.y = data[3]; + npc_coords_shift_still(object); + object->mapobj_bit_3 = TRUE; + FieldEffectActiveListRemove(0x42); + DestroyTask(taskId); + } + break; + } +} diff --git a/src/field_map_obj.c b/src/field_map_obj.c index 81cbe5210..af018eb16 100644 --- a/src/field_map_obj.c +++ b/src/field_map_obj.c @@ -353,7 +353,7 @@ static u8 InitFieldObjectStateFromTemplate(struct MapObjectTemplate *template, u return slot; } #else -static __attribute__((naked)) u8 InitFieldObjectStateFromTemplate(struct MapObjectTemplate *template, u8 mapId, u8 mapGroupId) +static NAKED u8 InitFieldObjectStateFromTemplate(struct MapObjectTemplate *template, u8 mapId, u8 mapGroupId) { asm_unified("\tpush {r4-r7,lr}\n" "\tmov r7, r9\n" diff --git a/src/field_tasks.c b/src/field_tasks.c new file mode 100644 index 000000000..d9c3078da --- /dev/null +++ b/src/field_tasks.c @@ -0,0 +1,776 @@ +#include "global.h" +#include "task.h" +#include "main.h" +#include "constants/vars.h" +#include "bike.h" +#include "item.h" +#include "constants/items.h" +#include "event_data.h" +#include "overworld.h" +#include "clock.h" +#include "script.h" +#include "field_special_scene.h" +#include "field_effect_helpers.h" +#include "secret_base.h" +#include "metatile_behavior.h" +#include "fieldmap.h" +#include "field_player_avatar.h" +#include "field_camera.h" +#include "constants/songs.h" +#include "sound.h" +#include "field_tasks.h" + +struct MetatileOffset +{ + s8 x; + s8 y; + u16 tileId; +}; + +// this file's functions +static void DummyPerStepCallback(u8 taskId); +static void PerStepCallback_8069F64(u8 taskId); +static void PerStepCallback_8069AA0(u8 taskId); +static void PerStepCallback_8069864(u8 taskId); +static void PerStepCallback_8069DD4(u8 taskId); +static void PerStepCallback_806A07C(u8 taskId); +static void Task_MuddySlope(u8 taskId); + +// const rom data +static void (*const gUnknown_08510348[])(u8) = +{ + DummyPerStepCallback, + PerStepCallback_8069F64, + PerStepCallback_8069AA0, + PerStepCallback_8069864, + PerStepCallback_8069DD4, + EndTruckSequence, + sub_80EA3E4, + PerStepCallback_806A07C +}; + +// they are in pairs but declared as 1D array +static const struct MetatileOffset gUnknown_08510368[] = +{ + { 0, 0,0x259}, { 0, 1,0x261}, + { 0, -1,0x259}, { 0, 0,0x261}, + { 0, 0,0x252}, { 1, 0,0x253}, + { -1, 0,0x252}, { 0, 0,0x253} +}; + +static const struct MetatileOffset gUnknown_08510388[] = +{ + { 0, 0,0x25A}, { 0, 1,0x262}, + { 0, -1,0x25A}, { 0, 0,0x262}, + { 0, 0,0x254}, { 1, 0,0x255}, + { -1, 0,0x254}, { 0, 0,0x255} +}; + +static const struct MetatileOffset gUnknown_085103A8[] = +{ + { 0, 0,0x258}, { 0, 1,0x260}, + { 0, -1,0x258}, { 0, 0,0x260}, + { 0, 0,0x250}, { 1, 0,0x251}, + { -1, 0,0x250}, { 0, 0,0x251} +}; + +static const u16 gUnknown_085103C8[] = +{ + 0, + 0, + 0, + 0, + 0, + 0, + VAR_TEMP_1, + VAR_TEMP_2, + VAR_TEMP_3, + VAR_TEMP_4, + 0, + 0, + VAR_TEMP_5, + VAR_TEMP_6, + VAR_TEMP_7, + 0, + 0, + VAR_TEMP_8, + VAR_TEMP_9, + VAR_TEMP_A, + 0, + 0, + 0, + 0, + 0, + 0 +}; + +static const u16 gUnknown_085103FC[] = {0xe8, 0xeb, 0xea, 0xe9}; + +// code +static void Task_RunPerStepCallback(u8 taskId) +{ + int idx = gTasks[taskId].data[0]; + gUnknown_08510348[idx](taskId); +} + +#define tState data[0] +#define tAmbientCryState data[1] +#define tAmbientCryDelay data[2] + +static void RunTimeBasedEvents(s16 *data) +{ + switch (tState) + { + case 0: + if (gMain.vblankCounter1 & 0x1000) + { + DoTimeBasedEvents(); + tState++; + } + break; + case 1: + if (!(gMain.vblankCounter1 & 0x1000)) + { + tState--; + } + break; + } +} + +static void Task_RunTimeBasedEvents(u8 taskId) +{ + s16 *data = gTasks[taskId].data; + + if (!ScriptContext2_IsEnabled()) + { + RunTimeBasedEvents(data); + UpdateAmbientCry(&tAmbientCryState, &tAmbientCryDelay); + } +} + +#undef tState +#undef tAmbientCryState +#undef tAmbientCryDelay + +void SetUpFieldTasks(void) +{ + if (!FuncIsActiveTask(Task_RunPerStepCallback)) + { + u8 taskId = CreateTask(Task_RunPerStepCallback, 0x50); + gTasks[taskId].data[0] = 0; + } + if (!FuncIsActiveTask(Task_MuddySlope)) + { + CreateTask(Task_MuddySlope, 0x50); + } + if (!FuncIsActiveTask(Task_RunTimeBasedEvents)) + { + CreateTask(Task_RunTimeBasedEvents, 0x50); + } +} + +void ActivatePerStepCallback(u8 callbackId) +{ + u8 taskId = FindTaskIdByFunc(Task_RunPerStepCallback); + if (taskId != 0xff) + { + s32 i; + s16 *data = gTasks[taskId].data; + + for (i = 0; i < 16; i++) + data[i] = 0; + + if (callbackId >= ARRAY_COUNT(gUnknown_08510348)) + { + data[0] = 0; + } + else + { + data[0] = callbackId; + } + } +} + +void ResetFieldTasksArgs(void) +{ + u8 taskId; + s16 *data; + + taskId = FindTaskIdByFunc(Task_RunPerStepCallback); + if (taskId != 0xff) + { + data = gTasks[taskId].data; + } + taskId = FindTaskIdByFunc(Task_RunTimeBasedEvents); + if (taskId != 0xff) + { + data = gTasks[taskId].data; + data[1] = 0; + data[2] = 0; + } +} + +static void DummyPerStepCallback(u8 taskId) +{ + +} + +static const struct MetatileOffset *sub_809DA30(const struct MetatileOffset *offsets, u16 metatileBehavior) +{ + if (MetatileBehavior_IsPacifilogVerticalLog1(metatileBehavior)) + return &offsets[0 * 2]; + else if (MetatileBehavior_IsPacifilogVerticalLog2(metatileBehavior)) + return &offsets[1 * 2]; + else if (MetatileBehavior_IsPacifilogHorizontalLog1(metatileBehavior)) + return &offsets[2 * 2]; + else if (MetatileBehavior_IsPacifilogHorizontalLog2(metatileBehavior)) + return &offsets[3 * 2]; + else + return NULL; +} + +static void sub_809DA88(const struct MetatileOffset *offsets, s16 x, s16 y, bool32 flag) +{ + offsets = sub_809DA30(offsets, MapGridGetMetatileBehaviorAt(x, y)); + + if (offsets != NULL) + { + MapGridSetMetatileIdAt(x + offsets[0].x, y + offsets[0].y, offsets[0].tileId); + if (flag) + CurrentMapDrawMetatileAt(x + offsets[0].x, y + offsets[0].y); + + MapGridSetMetatileIdAt(x + offsets[1].x, y + offsets[1].y, offsets[1].tileId); + if (flag) + CurrentMapDrawMetatileAt(x + offsets[1].x, y + offsets[1].y); + } +} + +static void sub_809DB10(s16 x, s16 y, bool32 flag) +{ + sub_809DA88(gUnknown_08510368, x, y, flag); +} + +static void sub_809DB34(s16 x, s16 y, bool32 flag) +{ + sub_809DA88(gUnknown_08510388, x, y, flag); +} + +static void sub_809DB58(s16 x, s16 y, bool32 flag) +{ + sub_809DA88(gUnknown_085103A8, x, y, flag); +} + +static bool32 sub_809DB7C(s16 x1, s16 y1, s16 x2, s16 y2) +{ + u16 metatileBehavior = MapGridGetMetatileBehaviorAt(x2, y2); + + if (MetatileBehavior_IsPacifilogVerticalLog1(metatileBehavior)) + { + if (y1 > y2) + return FALSE; + } + else if (MetatileBehavior_IsPacifilogVerticalLog2(metatileBehavior)) + { + if (y1 < y2) + return FALSE; + } + else if (MetatileBehavior_IsPacifilogHorizontalLog1(metatileBehavior)) + { + if (x1 > x2) + return FALSE; + } + else if (MetatileBehavior_IsPacifilogHorizontalLog2(metatileBehavior)) + { + if (x1 < x2) + return FALSE; + } + return TRUE; +} + +static bool32 sub_809DC18(s16 x1, s16 y1, s16 x2, s16 y2) +{ + u16 metatileBehavior = MapGridGetMetatileBehaviorAt(x1, y1); + + if (MetatileBehavior_IsPacifilogVerticalLog1(metatileBehavior)) + { + if (y1 < y2) + return FALSE; + } + else if (MetatileBehavior_IsPacifilogVerticalLog2(metatileBehavior)) + { + if (y1 > y2) + return FALSE; + } + else if (MetatileBehavior_IsPacifilogHorizontalLog1(metatileBehavior)) + { + if (x1 < x2) + return FALSE; + } + else if (MetatileBehavior_IsPacifilogHorizontalLog2(metatileBehavior)) + { + if (x1 > x2) + return FALSE; + } + return TRUE; +} + +static void PerStepCallback_8069864(u8 taskId) +{ + s16 *data; + s16 x, y; + data = gTasks[taskId].data; + PlayerGetDestCoords(&x, &y); + switch (data[1]) + { + case 0: + data[2] = x; + data[3] = y; + sub_809DB34(x, y, TRUE); + data[1] = 1; + break; + case 1: + if (x != data[2] || y != data[3]) + { + if (sub_809DB7C(x, y, data[2], data[3])) + { + sub_809DB10(data[2], data[3], TRUE); + sub_809DB58(data[2], data[3], FALSE); + data[4] = data[2]; + data[5] = data[3]; + data[1] = 2; + data[6] = 8; + } + else + { + data[4] = -1; + data[5] = -1; + } + if (sub_809DC18(x, y, data[2], data[3])) + { + sub_809DB10(x, y, TRUE); + data[1] = 2; + data[6] = 8; + } + data[2] = x; + data[3] = y; + if (MetatileBehavior_IsPacifidlogLog(MapGridGetMetatileBehaviorAt(x, y))) + { + PlaySE(SE_MIZU); + } + } + break; + case 2: + if ((--data[6]) == 0) + { + sub_809DB34(x, y, TRUE); + if (data[4] != -1 && data[5] != -1) + { + sub_809DB58(data[4], data[5], TRUE); + } + data[1] = 1; + } + break; + } +} + +static void sub_809DE28(s16 x, s16 y) +{ + u8 z = PlayerGetZCoord(); + if (!(z & 0x01)) + { + switch (MapGridGetMetatileIdAt(x, y)) + { + case 0x24e: + MapGridSetMetatileIdAt(x, y, 0x24f); + break; + case 0x256: + MapGridSetMetatileIdAt(x, y, 0x257); + break; + } + } +} + +static void sub_809DE8C(s16 x, s16 y) +{ + u8 z = PlayerGetZCoord(); + if (!(z & 0x01)) + { + switch (MapGridGetMetatileIdAt(x, y)) + { + case 0x24f: + MapGridSetMetatileIdAt(x, y, 0x24e); + break; + case 0x257: + MapGridSetMetatileIdAt(x, y, 0x256); + break; + } + } +} + +static void PerStepCallback_8069AA0(u8 taskId) +{ + bool8 isFortreeBridgeCur; + bool8 isFortreeBridgePrev; + u8 z, flag; + s16 x, y, x2, y2; + s16 *data = gTasks[taskId].data; + PlayerGetDestCoords(&x, &y); + switch (data[1]) + { + default: + break; + case 0: + data[2] = x; + data[3] = y; + if (MetatileBehavior_IsFortreeBridge(MapGridGetMetatileBehaviorAt(x, y))) + { + sub_809DE28(x, y); + CurrentMapDrawMetatileAt(x, y); + } + data[1] = 1; + break; + case 1: + x2 = data[2]; + y2 = data[3]; + if (x == x2 && y == y2) + { + break; + } + isFortreeBridgeCur = MetatileBehavior_IsFortreeBridge(MapGridGetMetatileBehaviorAt(x, y)); + isFortreeBridgePrev = MetatileBehavior_IsFortreeBridge(MapGridGetMetatileBehaviorAt(x2, y2)); + z = PlayerGetZCoord(); + flag = 0; + if ((u8)(z & 1) == 0) + { + flag = 1; + } + if (flag && (isFortreeBridgeCur == 1 || isFortreeBridgePrev == 1)) + { + PlaySE(SE_HASHI); + } + if (isFortreeBridgePrev) + { + sub_809DE8C(x2, y2); + CurrentMapDrawMetatileAt(x2, y2); + sub_809DE28(x, y); + CurrentMapDrawMetatileAt(x, y); + } + data[4] = x2; + data[5] = y2; + data[2] = x; + data[3] = y; + if (!isFortreeBridgePrev) + { + break; + } + data[6] = 16; + data[1] = 2; + // fallthrough + case 2: + data[6]--; + x2 = data[4]; + y2 = data[5]; + switch (data[6] % 7) + { + case 0: + CurrentMapDrawMetatileAt(x2, y2); + case 1: + case 2: + case 3: + break; + case 4: + sub_809DE28(x2, y2); + CurrentMapDrawMetatileAt(x2, y2); + sub_809DE8C(x2, y2); + case 5: + case 6: + case 7: + break; + } + if (data[6] == 0) + { + data[1] = 1; + } + break; + } +} + +static bool32 sub_809E108(s16 x, s16 y) +{ + if ((u16)(x - 3) < 11 && (u16)(y - 6) < 14 && gUnknown_085103C8[y]) + return TRUE; + else + return FALSE; +} + +static void sub_809E14C(s16 x, s16 y) +{ + if (sub_809E108(x, y)) + *GetVarPointer(gUnknown_085103C8[y]) |= (1 << (x - 3)); +} + +static bool32 sub_809E184(s16 x, s16 y) +{ + u32 var; + if (!sub_809E108(x, y)) + return FALSE; + + var = VarGet(gUnknown_085103C8[y]) << 16; + if (((1 << 16) << (x - 3)) & var) // TODO: fix that if + return TRUE; + else + return FALSE; +} + +void SetSootopolisGymCrackedIceMetatiles(void) +{ + s32 x, y; + s32 width = gMapHeader.mapData->width; + s32 height = gMapHeader.mapData->height; + for (x = 0; x < width; x++) + { + for (y = 0; y < height; y++) + { + if (sub_809E184(x, y) == TRUE) + { + MapGridSetMetatileIdAt(x + 7, y + 7, 0x20e); + } + } + } +} + +static void PerStepCallback_8069DD4(u8 taskId) +{ + s16 x, y; + u16 tileBehavior; + u16 *var; + s16 *data = gTasks[taskId].data; + switch (data[1]) + { + case 0: + PlayerGetDestCoords(&x, &y); + data[2] = x; + data[3] = y; + data[1] = 1; + break; + case 1: + PlayerGetDestCoords(&x, &y); + if (x != data[2] || y != data[3]) + { + data[2] = x; + data[3] = y; + tileBehavior = MapGridGetMetatileBehaviorAt(x, y); + var = GetVarPointer(VAR_ICE_STEP_COUNT); + if (MetatileBehavior_IsThinIce(tileBehavior) == TRUE) + { + (*var)++; + data[6] = 4; + data[1] = 2; + data[4] = x; + data[5] = y; + } + else if (MetatileBehavior_IsCrackedIce(tileBehavior) == TRUE) + { + *var = 0; + data[6] = 4; + data[1] = 3; + data[4] = x; + data[5] = y; + } + } + break; + case 2: + if (data[6] != 0) + { + data[6]--; + } + else + { + x = data[4]; + y = data[5]; + PlaySE(SE_RU_BARI); + MapGridSetMetatileIdAt(x, y, 0x20e); + CurrentMapDrawMetatileAt(x, y); + sub_809E14C(x - 7, y - 7); + data[1] = 1; + } + break; + case 3: + if (data[6] != 0) + { + data[6]--; + } + else + { + x = data[4]; + y = data[5]; + PlaySE(SE_RU_GASYAN); + MapGridSetMetatileIdAt(x, y, 0x206); + CurrentMapDrawMetatileAt(x, y); + data[1] = 1; + } + break; + } +} + +static void PerStepCallback_8069F64(u8 taskId) +{ + s16 x, y; + u16 *var; + s16 *data = gTasks[taskId].data; + PlayerGetDestCoords(&x, &y); + if (x != data[1] || y != data[2]) + { + data[1] = x; + data[2] = y; + if (MetatileBehavior_IsAsh(MapGridGetMetatileBehaviorAt(x, y))) + { + if (MapGridGetMetatileIdAt(x, y) == 0x20a) + { + ash(x, y, 0x212, 4); + } + else + { + ash(x, y, 0x206, 4); + } + if (CheckBagHasItem(ITEM_SOOT_SACK, 1)) + { + var = GetVarPointer(VAR_ASH_GATHER_COUNT); + if (*var < 9999) + { + (*var)++; + } + } + } + } +} + +static void sub_809E490(s16 x, s16 y) +{ + MapGridSetMetatileIdAt(x, y, MapGridGetMetatileIdAt(x, y) == 0x22f ? 0x206 : 0x237); + CurrentMapDrawMetatileAt(x, y); +} + +static void PerStepCallback_806A07C(u8 taskId) +{ + s16 x, y; + u16 behavior; + s16 *data = gTasks[taskId].data; + PlayerGetDestCoords(&x, &y); + behavior = MapGridGetMetatileBehaviorAt(x, y); + if (data[4] != 0 && (--data[4]) == 0) + { + sub_809E490(data[5], data[6]); + } + if (data[7] != 0 && (--data[7]) == 0) + { + sub_809E490(data[8], data[9]); + } + if (MetatileBehavior_IsCrackedFloorHole(behavior)) + { + VarSet(VAR_ICE_STEP_COUNT, 0); // this var does double duty + } + if ((x != data[2] || y != data[3])) + { + data[2] = x; + data[3] = y; + if (MetatileBehavior_IsCrackedFloor(behavior)) + { + if (GetPlayerSpeed() != 4) + { + VarSet(VAR_ICE_STEP_COUNT, 0); // this var does double duty + } + if (data[4] == 0) + { + data[4] = 3; + data[5] = x; + data[6] = y; + } + else if (data[7] == 0) + { + data[7] = 3; + data[8] = x; + data[9] = y; + } + } + } +} + +static void sub_809E5DC(s16 *data, s16 x, s16 y) +{ + u16 tile; + if ((--data[0]) == 0) + { + tile = 0xe8; + } + else + { + tile = gUnknown_085103FC[data[0] / 8]; + } + MapGridSetMetatileIdAt(x, y, tile); + CurrentMapDrawMetatileAt(x, y); + MapGridSetMetatileIdAt(x, y, 0xe8); +} + +static void Task_MuddySlope(u8 taskId) +{ + s16 x, y, x2, y2; + int i; + u16 mapIndices; + s16 *data = gTasks[taskId].data; + PlayerGetDestCoords(&x, &y); + mapIndices = (gSaveBlock1Ptr->location.mapGroup << 8) | gSaveBlock1Ptr->location.mapNum; + switch (data[1]) + { + case 0: + data[0] = mapIndices; + data[2] = x; + data[3] = y; + data[1] = 1; + data[4] = 0; + data[7] = 0; + data[10] = 0; + data[13] = 0; + break; + case 1: + if (data[2] != x || data[3] != y) + { + data[2] = x; + data[3] = y; + if (MetatileBehavior_IsMuddySlope(MapGridGetMetatileBehaviorAt(x, y))) + { + for (i=4; i<14; i+=3) + { + if (data[i] == 0) + { + data[i] = 32; + data[i + 1] = x; + data[i + 2] = y; + break; + } + } + } + } + break; + } + if (gCamera.active && mapIndices != data[0]) + { + data[0] = mapIndices; + x2 = gCamera.x; + y2 = gCamera.y; + } + else + { + x2 = 0; + y2 = 0; + } + for (i = 4; i < 14; i += 3) + { + if (data[i]) + { + data[i + 1] -= x2; + data[i + 2] -= y2; + sub_809E5DC(&data[i], data[i + 1], data[i + 2]); + } + } +} diff --git a/src/fldeff_teleport.c b/src/fldeff_teleport.c index e675ef0a5..1b88b42d7 100644 --- a/src/fldeff_teleport.c +++ b/src/fldeff_teleport.c @@ -37,7 +37,7 @@ bool8 FldEff_UseTeleport(void) void sub_817C94C(void) { FieldEffectActiveListRemove(FLDEFF_USE_TELEPORT); - sub_80B7FC8(); + CreateTeleportFieldEffectTask(); } diff --git a/src/fossil_specials.c b/src/fossil_specials.c index 95fafc17b..060915fa6 100644 --- a/src/fossil_specials.c +++ b/src/fossil_specials.c @@ -335,7 +335,7 @@ static void sub_81BED50(u8 taskId) } #else -ASM_DIRECT +NAKED static void sub_81BED50(u8 taskId) { asm("\n\ diff --git a/src/hof_pc.c b/src/hof_pc.c index e5b6f96f8..44b929337 100644 --- a/src/hof_pc.c +++ b/src/hof_pc.c @@ -7,7 +7,6 @@ #include "script_menu.h" #include "task.h" -extern void (*gFieldCallback)(void); extern void (*gUnknown_0300485C)(void); extern void Overworld_PlaySpecialMapMusic(void); diff --git a/src/item.c b/src/item.c index 975fef3ae..319d167fc 100644 --- a/src/item.c +++ b/src/item.c @@ -234,7 +234,7 @@ bool8 CheckBagHasSpace(u16 itemId, u16 count) } } #else -ASM_DIRECT +NAKED bool8 CheckBagHasSpace(u16 itemId, u16 count) { asm_unified("push {r4-r7,lr}\n\ diff --git a/src/item_menu.c b/src/item_menu.c index d7edea301..c4b4b15b1 100755 --- a/src/item_menu.c +++ b/src/item_menu.c @@ -26,7 +26,6 @@ #include "malloc.h" #include "map_name_popup.h" #include "menu.h" -#include "menu_indicators.h" #include "money.h" #include "overworld.h" #include "palette.h" @@ -265,14 +264,12 @@ struct TempWallyStruct { }; EWRAM_DATA struct UnkBagStruct *gUnknown_0203CE54 = 0; -EWRAM_DATA struct BagStruct gUnknown_0203CE58 = {0, 0, 0, {0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}}; +EWRAM_DATA struct BagStruct gUnknown_0203CE58 = {0}; EWRAM_DATA struct ListBuffer1 *gUnknown_0203CE74 = 0; EWRAM_DATA struct ListBuffer2 *gUnknown_0203CE78 = 0; EWRAM_DATA u16 gSpecialVar_ItemId = 0; EWRAM_DATA struct TempWallyStruct *gUnknown_0203CE80 = 0; -void (*gFieldCallback)(void); - extern u8 *gPocketNamesStringsTable[]; extern u8 gUnknown_08D9A88C[]; extern struct ListMenuTemplate gUnknown_08613F9C; @@ -752,7 +749,7 @@ void sub_81AB824(void) void bag_menu_add_list_scroll_arrow_indicators_maybe(void) { if (gUnknown_0203CE54->unk81B != 1 && gUnknown_0203CE54->unk81F == 0xFF) - gUnknown_0203CE54->unk81F = AddScrollIndicatorArrowPair(&gUnknown_08614094, gUnknown_0203CE58.unk6); + gUnknown_0203CE54->unk81F = AddScrollIndicatorArrowPair(&gUnknown_08614094, &gUnknown_0203CE58.unk6); } void sub_81AB89C(void) diff --git a/src/item_use.c b/src/item_use.c index 80b33220e..d036da6d3 100755 --- a/src/item_use.c +++ b/src/item_use.c @@ -91,7 +91,6 @@ extern u8* sub_806CF78(u16); extern void sub_81B89F0(void); extern u8 GetItemEffectType(u16); extern struct MapConnection *sub_8088A8C(s16, s16); -extern void (*gFieldCallback)(void); void MapPostLoadHook_UseItem(void); void sub_80AF6D4(void); @@ -167,7 +166,7 @@ void MapPostLoadHook_UseItem(void) void Task_CallItemUseOnFieldCallback(u8 taskId) { - if (sub_80ABDFC() == 1) + if (IsWeatherNotFadingIn() == 1) gUnknown_0203A0F4(taskId); } diff --git a/src/lilycove_lady.c b/src/lilycove_lady.c index ea244b6a0..1012a8e08 100644 --- a/src/lilycove_lady.c +++ b/src/lilycove_lady.c @@ -237,11 +237,11 @@ void sub_818D9C0(void) { LilycoveLady *lilycoveLady; - VarSet(VAR_0x4010, sUnknown_0860B07E[GetLilycoveLadyId()]); + VarSet(VAR_OBJ_GFX_ID_0, sUnknown_0860B07E[GetLilycoveLadyId()]); if (GetLilycoveLadyId() == LILYCOVE_LADY_CONTEST) { lilycoveLady = &gSaveBlock1Ptr->lilycoveLady; - VarSet(VAR_0x4011, sUnknown_0860B074[lilycoveLady->contest.category]); + VarSet(VAR_OBJ_GFX_ID_1, sUnknown_0860B074[lilycoveLady->contest.category]); gSpecialVar_Result = TRUE; } else @@ -801,26 +801,26 @@ void sub_818E564(void) EnableBothScriptContexts(); } -void sub_818E570(const struct LilycoveLadyQuiz *quiz) +void sub_818E570(const LilycoveLady *lilycoveLady) { u8 i; gUnknown_0203CD68 = &gSaveBlock1Ptr->lilycoveLady.quiz; - if (quiz->unk_02c < 16 && gUnknown_0203CD68->id == LILYCOVE_LADY_QUIZ) + if (lilycoveLady->quiz.unk_02c < 16 && gUnknown_0203CD68->id == LILYCOVE_LADY_QUIZ) { for (i = 0; i < 4; i ++) { - if (quiz->unk_02c != gUnknown_0203CD68->unk_02b) + if (lilycoveLady->quiz.unk_02c != gUnknown_0203CD68->unk_02b) { break; } gUnknown_0203CD68->unk_02b = Random() % 16; } - if (quiz->unk_02c == gUnknown_0203CD68->unk_02b) + if (lilycoveLady->quiz.unk_02c == gUnknown_0203CD68->unk_02b) { gUnknown_0203CD68->unk_02b = (gUnknown_0203CD68->unk_02b + 1) % 16; } - gUnknown_0203CD68->unk_02c = quiz->unk_02c; + gUnknown_0203CD68->unk_02c = lilycoveLady->quiz.unk_02c; } } diff --git a/src/link.c b/src/link.c index 292ffecf2..acdb6cae0 100644 --- a/src/link.c +++ b/src/link.c @@ -798,7 +798,7 @@ bool32 sub_800A040(void) return TRUE; } -bool32 sub_800A064(void) +bool32 Link_AnyPartnersPlayingRubyOrSapphire(void) { if (sub_8009FF8(VERSION_RUBY, VERSION_SAPPHIRE) >= 0) { diff --git a/src/link_rfu.c b/src/link_rfu.c index a1917ed24..37aa20950 100644 --- a/src/link_rfu.c +++ b/src/link_rfu.c @@ -2051,7 +2051,7 @@ u8 sub_800DD1C(u8 maxFlags) return 0; } #else -ASM_DIRECT u8 sub_800DD1C(u8 maxFlags) +NAKED u8 sub_800DD1C(u8 maxFlags) { asm_unified("\tpush {r4-r7,lr}\n" "\tlsls r0, 24\n" @@ -2897,7 +2897,7 @@ void sub_800EFB0(void) CpuFill16(0, gRecvCmds, sizeof gRecvCmds); } #else -ASM_DIRECT void sub_800EFB0(void) +NAKED void sub_800EFB0(void) { asm_unified("\tpush {r4-r7,lr}\n" "\tsub sp, 0x4\n" @@ -3233,7 +3233,7 @@ void sub_800F638(u8 unused, u32 flags) } } #else -ASM_DIRECT void sub_800F638(u8 unused, u32 flags) +NAKED void sub_800F638(u8 unused, u32 flags) { asm_unified("\tpush {r4-r7,lr}\n" "\tmov r7, r10\n" @@ -3601,7 +3601,7 @@ void sub_800FD14(u16 command) } } #else -ASM_DIRECT void sub_800FD14(u16 command) +NAKED void sub_800FD14(u16 command) { asm_unified("\tpush {r4,r5,lr}\n" "\tlsls r0, 16\n" @@ -4699,7 +4699,7 @@ void sub_801120C(u8 a0) } } #else -ASM_DIRECT void sub_801120C(u8 a0) +NAKED void sub_801120C(u8 a0) { asm_unified("\tpush {r4-r7,lr}\n" "\tmov r7, r10\n" diff --git a/src/list_menu.c b/src/list_menu.c index c78d32bb3..de7de8269 100644 --- a/src/list_menu.c +++ b/src/list_menu.c @@ -5,11 +5,16 @@ #include "text_window.h" #include "main.h" #include "task.h" -#include "menu_indicators.h" +#include "trig.h" +#include "decompress.h" +#include "palette.h" +#include "malloc.h" #include "strings.h" #include "sound.h" #include "constants/songs.h" +// This file needs better labels and function names. + struct UnknownMysteryGiftLinkMenuStruct { s32 field_0; @@ -29,7 +34,71 @@ struct UnknownListMenuPals u8 field_3_7:1; }; -extern struct UnknownMysteryGiftLinkMenuStruct gUnknown_0203CE84; +struct UnkIndicatorsStruct +{ + u8 field_0; + u16 *field_4; + u16 field_8; + u16 field_A; + u16 field_C; + u16 field_E; + u8 field_10; + u8 field_11; + u8 field_12; + u8 field_13; + u8 field_14_0:4; + u8 field_14_1:4; + u8 field_15_0:4; + u8 field_15_1:4; + u8 field_16_0:3; + u8 field_16_1:3; + u8 field_16_2:2; + u8 field_17_0:6; + u8 field_17_1:2; +}; + +struct UnkIndicatorsStruct2 +{ + u8 field_0; + u16 *field_4; + u16 field_8; + u16 field_A; + u8 field_C; + u8 field_D; + u16 tileTag; + u16 palTag; + u16 field_12; + u16 field_14; + u16 field_16; + u16 field_18; + u16 field_1A; + u16 field_1C; + s16 field_1E; +}; + +struct UnkIndicatorsStruct3 +{ + struct SubspriteTable subspriteTable; + struct Subsprite *subspritesPtr; // not a const pointer + u8 spriteId; + u16 tileTag; + u16 palTag; +}; + +struct UnkIndicatorsStruct4 +{ + u8 field_0; + u16 tileTag; + u16 palTag; +}; + +struct UnkSmallIndicatorsStruct +{ + u8 field_0_0:4; + u8 field_0_1:4; + u8 field_1; + u16 field_2; +}; // this file's functions static u8 ListMenuInitInternal(struct ListMenuTemplate *listMenuTemplate, u16 scrollOffset, u16 selectedRow); @@ -38,11 +107,220 @@ static void ListMenuPrintEntries(struct ListMenu *list, u16 startIndex, u16 yOff static void ListMenuDrawCursor(struct ListMenu *list); static void ListMenuCallSelectionChangedCallback(struct ListMenu *list, u8 a2); static u8 ListMenuAddCursorObject(struct ListMenu *list, u32 cursorKind); +static void Task_ScrollIndicatorArrowPair(u8 taskId); +static u8 ListMenuAddRedOutlineCursorObject(struct CursorStruct *cursor); +static u8 ListMenuAddRedArrowCursorObject(struct CursorStruct *cursor); +static void ListMenuUpdateRedOutlineCursorObject(u8 taskId, u16 x, u16 y); +static void ListMenuUpdateRedArrowCursorObject(u8 taskId, u16 x, u16 y); +static void ListMenuRemoveRedOutlineCursorObject(u8 taskId); +static void ListMenuRemoveRedArrowCursorObject(u8 taskId); +static u8 ListMenuAddCursorObjectInternal(struct CursorStruct *cursor, u32 cursorKind); +static void ListMenuUpdateCursorObject(u8 taskId, u16 x, u16 y, u32 cursorKind); +static void ListMenuRemoveCursorObject(u8 taskId, u32 cursorKind); +static void sub_81AF264(struct Sprite *sprite); +static void ObjectCB_RedArrowCursor(struct Sprite *sprite); + +// EWRAM vars + EWRAM_DATA struct UnknownMysteryGiftLinkMenuStruct gUnknown_0203CE84 = {0}; + EWRAM_DATA struct ArrowStruct gUnknown_0203CE8C = {0}; // IWRAM common struct UnknownListMenuPals gUnknown_03006300; struct ListMenuTemplate gMultiuseListMenuTemplate; +// const rom data +static const struct UnkSmallIndicatorsStruct gUnknown_086141FC[] = +{ + {0, 0, 2, 8}, + {1, 0, 2, -8}, + {2, 1, 2, 8}, + {3, 1, 2, -8}, +}; + +static const struct OamData sOamData_861420C = +{ + .y = 0, + .affineMode = 0, + .objMode = 0, + .mosaic = 0, + .bpp = 0, + .shape = 0, + .x = 0, + .matrixNum = 0, + .size = 1, + .tileNum = 0, + .priority = 0, + .paletteNum = 0, + .affineParam = 0 +}; + +static const union AnimCmd sSpriteAnim_8614214[] = +{ + ANIMCMD_FRAME(0, 30), + ANIMCMD_END +}; + +static const union AnimCmd sSpriteAnim_861421C[] = +{ + ANIMCMD_FRAME(0, 30, 1, 0), + ANIMCMD_END +}; + +static const union AnimCmd sSpriteAnim_8614224[] = +{ + ANIMCMD_FRAME(4, 30), + ANIMCMD_END +}; + +static const union AnimCmd sSpriteAnim_861422C[] = +{ + ANIMCMD_FRAME(4, 30, 0, 1), + ANIMCMD_END +}; + +static const union AnimCmd *const sSpriteAnimTable_8614234[] = +{ + sSpriteAnim_8614214, + sSpriteAnim_861421C, + sSpriteAnim_8614224, + sSpriteAnim_861422C +}; + +static const struct SpriteTemplate gUnknown_08614244 = +{ + .tileTag = 0, + .paletteTag = 0, + .oam = &sOamData_861420C, + .anims = sSpriteAnimTable_8614234, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_81AF264, +}; + +static const struct Subsprite sSubsprite_861425C = +{ + .x = 0, + .y = 0, + .shape = 0, + .size = 0, + .tileOffset = 0, + .priority = 0, +}; + +static const struct Subsprite sSubsprite_8614260 = +{ + .x = 0, + .y = 0, + .shape = 0, + .size = 0, + .tileOffset = 1, + .priority = 0, +}; + +static const struct Subsprite sSubsprite_8614264 = +{ + .x = 0, + .y = 0, + .shape = 0, + .size = 0, + .tileOffset = 2, + .priority = 0, +}; + +static const struct Subsprite sSubsprite_8614268 = +{ + .x = 0, + .y = 0, + .shape = 0, + .size = 0, + .tileOffset = 3, + .priority = 0, +}; + +static const struct Subsprite sSubsprite_861426C = +{ + .x = 0, + .y = 0, + .shape = 0, + .size = 0, + .tileOffset = 4, + .priority = 0, +}; + +static const struct Subsprite sSubsprite_8614270 = +{ + .x = 0, + .y = 0, + .shape = 0, + .size = 0, + .tileOffset = 5, + .priority = 0, +}; + +static const struct Subsprite sSubsprite_8614274 = +{ + .x = 0, + .y = 0, + .shape = 0, + .size = 0, + .tileOffset = 6, + .priority = 0, +}; + +static const struct Subsprite sSubsprite_8614278 = +{ + .x = 0, + .y = 0, + .shape = 0, + .size = 0, + .tileOffset = 7, + .priority = 0, +}; + +static const struct OamData sOamData_861427C = +{ + .y = 0, + .affineMode = 0, + .objMode = 0, + .mosaic = 0, + .bpp = 0, + .shape = 0, + .x = 0, + .matrixNum = 0, + .size = 1, + .tileNum = 0, + .priority = 0, + .paletteNum = 0, + .affineParam = 0 +}; + +static const union AnimCmd sSpriteAnim_8614284[] = +{ + ANIMCMD_FRAME(0, 30), + ANIMCMD_END +}; + +static const union AnimCmd *const sSpriteAnimTable_861428C[] = +{ + sSpriteAnim_8614284 +}; + +static const struct SpriteTemplate gUnknown_08614290 = +{ + .tileTag = 0, + .paletteTag = 0, + .oam = &sOamData_861427C, + .anims = sSpriteAnimTable_861428C, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = ObjectCB_RedArrowCursor, +}; + +static const u16 gUnknown_086142A8[] = INCBIN_U16("graphics/interface/red_arrow.gbapal"); +static const u8 gUnknown_086142C8[] = INCBIN_U8("graphics/interface/red_arrow_other.4bpp.lz"); +static const u8 gUnknown_08614338[] = INCBIN_U8("graphics/interface/selector_outline.4bpp.lz"); +static const u8 gUnknown_08614378[] = INCBIN_U8("graphics/interface/red_arrow.4bpp.lz"); + // code static void ListMenuDummyTask(u8 taskId) { @@ -415,9 +693,9 @@ static u8 ListMenuAddCursorObject(struct ListMenu *list, u32 cursorKind) cursor.unk1 = 0xA0; cursor.unk2 = GetWindowAttribute(list->template.windowId, WINDOW_WIDTH) * 8 + 2; cursor.unk4 = GetFontAttribute(list->template.fontId, 1) + 2; - cursor.unk6 = 0x4000; - cursor.unk8 = 0xFFFF; - cursor.unkA = 0xF; + cursor.tileTag = 0x4000; + cursor.palTag = 0xFFFF; + cursor.palNum = 0xF; return ListMenuAddCursorObjectInternal(&cursor, cursorKind); } @@ -631,3 +909,547 @@ void sub_81AF078(s32 arg0, u8 arg1, struct ListMenu *list) if (!arg1) PlaySE(SE_SELECT); } + +// unused +s32 sub_81AF08C(u8 taskId, u8 field) +{ + struct UnkIndicatorsStruct *data = (void*) gTasks[taskId].data; + + switch (field) + { + case 0: + case 1: + return (s32)(data->field_4); + case 2: + return data->field_C; + case 3: + return data->field_E; + case 4: + return data->field_10; + case 5: + return data->field_11; + case 6: + return data->field_12; + case 7: + return data->field_13; + case 8: + return data->field_14_0; + case 9: + return data->field_14_1; + case 10: + return data->field_15_0; + case 11: + return data->field_15_1; + case 12: + return data->field_16_0; + case 13: + return data->field_16_1; + case 14: + return data->field_16_2; + case 15: + return data->field_17_0; + case 16: + return data->field_17_1; + default: + return -1; + } +} + +// unused +void sub_81AF15C(u8 taskId, u8 field, s32 value) +{ + struct UnkIndicatorsStruct *data = (void*) &gTasks[taskId].data; + + switch (field) + { + case 0: + case 1: + data->field_4 = (void*)(value); + break; + case 2: + data->field_C = value; + break; + case 3: + data->field_E = value; + break; + case 4: + data->field_10 = value; + break; + case 5: + data->field_11 = value; + break; + case 6: + data->field_12 = value; + break; + case 7: + data->field_13 = value; + break; + case 8: + data->field_14_0 = value; + break; + case 9: + data->field_14_1 = value; + break; + case 10: + data->field_15_0 = value; + break; + case 11: + data->field_15_1 = value; + break; + case 12: + data->field_16_0 = value; + break; + case 13: + data->field_16_1 = value; + break; + case 14: + data->field_16_2 = value; + break; + case 15: + data->field_17_0 = value; + break; + case 16: + data->field_17_1 = value; + break; + } +} + +static void sub_81AF264(struct Sprite *sprite) +{ + s32 multiplier; + + switch (sprite->data[0]) + { + case 0: + StartSpriteAnim(sprite, sprite->data[1]); + sprite->data[0]++; + break; + case 1: + switch (sprite->data[2]) + { + case 0: + multiplier = sprite->data[3]; + sprite->pos2.x = (gSineTable[(u8)(sprite->data[5])] * multiplier) / 256; + break; + case 1: + multiplier = sprite->data[3]; + sprite->pos2.y = (gSineTable[(u8)(sprite->data[5])] * multiplier) / 256; + break; + } + sprite->data[5] += sprite->data[4]; + break; + } +} + +static u8 AddScrollIndicatorArrowObject(u8 arg0, u8 x, u8 y, u16 tileTag, u16 palTag) +{ + u8 spriteId; + struct SpriteTemplate spriteTemplate; + + spriteTemplate = gUnknown_08614244; + spriteTemplate.tileTag = tileTag; + spriteTemplate.paletteTag = palTag; + + spriteId = CreateSprite(&spriteTemplate, x, y, 0); + gSprites[spriteId].invisible = 1; + gSprites[spriteId].data[0] = 0; + gSprites[spriteId].data[1] = gUnknown_086141FC[arg0].field_0_0; + gSprites[spriteId].data[2] = gUnknown_086141FC[arg0].field_0_1; + gSprites[spriteId].data[3] = gUnknown_086141FC[arg0].field_1; + gSprites[spriteId].data[4] = gUnknown_086141FC[arg0].field_2; + gSprites[spriteId].data[5] = 0; + + return spriteId; +} + +u8 AddScrollIndicatorArrowPair(const struct ArrowStruct *arrowInfo, u16 *arg1) +{ + struct CompressedSpriteSheet spriteSheet; + struct SpritePalette spritePal; + struct UnkIndicatorsStruct2 *data; + u8 taskId; + + spriteSheet.data = gUnknown_086142C8; + spriteSheet.size = 0x100; + spriteSheet.tag = arrowInfo->tileTag; + LoadCompressedObjectPic(&spriteSheet); + + if (arrowInfo->palTag == 0xFFFF) + { + LoadPalette(gUnknown_086142A8, (16 * arrowInfo->palNum) + 0x100, 0x20); + } + else + { + spritePal.data = gUnknown_086142A8; + spritePal.tag = arrowInfo->palTag; + LoadSpritePalette(&spritePal); + } + + taskId = CreateTask(Task_ScrollIndicatorArrowPair, 0); + data = (void*) gTasks[taskId].data; + + data->field_0 = 0; + data->field_4 = arg1; + data->field_8 = arrowInfo->unk6; + data->field_A = arrowInfo->unk8; + data->tileTag = arrowInfo->tileTag; + data->palTag = arrowInfo->palTag; + data->field_C = AddScrollIndicatorArrowObject(arrowInfo->unk0, arrowInfo->unk1, arrowInfo->unk2, arrowInfo->tileTag, arrowInfo->palTag); + data->field_D = AddScrollIndicatorArrowObject(arrowInfo->unk3, arrowInfo->unk4, arrowInfo->unk5, arrowInfo->tileTag, arrowInfo->palTag); + + if (arrowInfo->palTag == 0xFFFF) + { + gSprites[data->field_C].oam.paletteNum = arrowInfo->palNum; + gSprites[data->field_D].oam.paletteNum = arrowInfo->palNum; + } + + return taskId; +} + +u8 AddScrollIndicatorArrowPairParametrized(u32 arg0, s32 arg1, s32 arg2, s32 arg3, s32 arg4, s32 tileTag, s32 palTag, void *arg7) +{ + if (arg0 == 2 || arg0 == 3) + { + gUnknown_0203CE8C.unk0 = 2; + gUnknown_0203CE8C.unk1 = arg1; + gUnknown_0203CE8C.unk2 = arg2; + gUnknown_0203CE8C.unk3 = 3; + gUnknown_0203CE8C.unk4 = arg1; + gUnknown_0203CE8C.unk5 = arg3; + } + else + { + gUnknown_0203CE8C.unk0 = 0; + gUnknown_0203CE8C.unk1 = arg2; + gUnknown_0203CE8C.unk2 = arg1; + gUnknown_0203CE8C.unk3 = 1; + gUnknown_0203CE8C.unk4 = arg3; + gUnknown_0203CE8C.unk5 = arg1; + } + + gUnknown_0203CE8C.unk6 = 0; + gUnknown_0203CE8C.unk8 = arg4; + gUnknown_0203CE8C.tileTag = tileTag; + gUnknown_0203CE8C.palTag = palTag; + gUnknown_0203CE8C.palNum = 0; + + return AddScrollIndicatorArrowPair(&gUnknown_0203CE8C, arg7); +} + +static void Task_ScrollIndicatorArrowPair(u8 taskId) +{ + struct UnkIndicatorsStruct2 *data = (void*) gTasks[taskId].data; + u16 var = (*data->field_4); + + if (var == data->field_8 && var != 0xFFFF) + gSprites[data->field_C].invisible = 1; + else + gSprites[data->field_C].invisible = 0; + + if (var == data->field_A) + gSprites[data->field_D].invisible = 1; + else + gSprites[data->field_D].invisible = 0; +} + +void Task_ScrollIndicatorArrowPairOnMainMenu(u8 taskId) +{ + struct UnkIndicatorsStruct2 *data = (void*) gTasks[taskId].data; + + if (data->field_1E != 0) + { + gSprites[data->field_C].invisible = 0; + gSprites[data->field_D].invisible = 1; + } + else + { + gSprites[data->field_C].invisible = 1; + gSprites[data->field_D].invisible = 0; + } +} + +void RemoveScrollIndicatorArrowPair(u8 taskId) +{ + struct UnkIndicatorsStruct2 *data = (void*) gTasks[taskId].data; + + if (data->tileTag != 0xFFFF) + FreeSpriteTilesByTag(data->tileTag); + if (data->palTag != 0xFFFF) + FreeSpritePaletteByTag(data->palTag); + + DestroySprite(&gSprites[data->field_C]); + DestroySprite(&gSprites[data->field_D]); + + DestroyTask(taskId); +} + +static u8 ListMenuAddCursorObjectInternal(struct CursorStruct *cursor, u32 cursorKind) +{ + switch (cursorKind) + { + case 0: + default: + return ListMenuAddRedOutlineCursorObject(cursor); + case 1: + return ListMenuAddRedArrowCursorObject(cursor); + } +} + +static void ListMenuUpdateCursorObject(u8 taskId, u16 x, u16 y, u32 cursorKind) +{ + switch (cursorKind) + { + case 0: + ListMenuUpdateRedOutlineCursorObject(taskId, x, y); + break; + case 1: + ListMenuUpdateRedArrowCursorObject(taskId, x, y); + break; + } +} + +static void ListMenuRemoveCursorObject(u8 taskId, u32 cursorKind) +{ + switch (cursorKind) + { + case 0: + ListMenuRemoveRedOutlineCursorObject(taskId); + break; + case 1: + ListMenuRemoveRedArrowCursorObject(taskId); + break; + } +} + +static void Task_RedOutlineCursor(u8 taskId) +{ + +} + +u8 ListMenuGetRedOutlineCursorSpriteCount(u16 arg0, u16 arg1) +{ + s32 i; + s32 count = 4; + + if (arg0 > 16) + { + for (i = 8; i < (arg0 - 8); i += 8) + count += 2; + } + if (arg1 > 16) + { + for (i = 8; i < (arg1 - 8); i += 8) + count += 2; + } + + return count; +} + +void ListMenuSetUpRedOutlineCursorSpriteOamTable(u16 arg0, u16 arg1, struct Subsprite *subsprites) +{ + s32 i, j, id = 0; + + subsprites[id] = sSubsprite_861425C; + subsprites[id].x = 136; + subsprites[id].y = 136; + id++; + + subsprites[id] = sSubsprite_8614260; + subsprites[id].x = arg0 + 128; + subsprites[id].y = 136; + id++; + + subsprites[id] = sSubsprite_8614274; + subsprites[id].x = 136; + subsprites[id].y = arg1 + 128; + id++; + + subsprites[id] = sSubsprite_8614278; + subsprites[id].x = arg0 + 128; + subsprites[id].y = arg1 + 128; + id++; + + if (arg0 > 16) + { + for (i = 8; i < arg0 - 8; i += 8) + { + subsprites[id] = sSubsprite_8614264; + subsprites[id].x = i - 120; + subsprites[id].y = 136; + id++; + + subsprites[id] = sSubsprite_8614270; + subsprites[id].x = i - 120; + subsprites[id].y = arg1 + 128; + id++; + } + } + + if (arg1 > 16) + { + for (j = 8; j < arg1 - 8; j += 8) + { + subsprites[id] = sSubsprite_8614268; + subsprites[id].x = 136; + subsprites[id].y = j - 120; + id++; + + subsprites[id] = sSubsprite_861426C; + subsprites[id].x = arg0 + 128; + subsprites[id].y = j - 120; + id++; + } + } +} + +static u8 ListMenuAddRedOutlineCursorObject(struct CursorStruct *cursor) +{ + struct CompressedSpriteSheet spriteSheet; + struct SpritePalette spritePal; + struct UnkIndicatorsStruct3 *data; + struct SpriteTemplate spriteTemplate; + u8 taskId; + + spriteSheet.data = gUnknown_08614338; + spriteSheet.size = 0x100; + spriteSheet.tag = cursor->tileTag; + LoadCompressedObjectPic(&spriteSheet); + + if (cursor->palTag == 0xFFFF) + { + LoadPalette(gUnknown_086142A8, (16 * cursor->palNum) + 0x100, 0x20); + } + else + { + spritePal.data = gUnknown_086142A8; + spritePal.tag = cursor->palTag; + LoadSpritePalette(&spritePal); + } + + taskId = CreateTask(Task_RedOutlineCursor, 0); + data = (void*) gTasks[taskId].data; + + data->tileTag = cursor->tileTag; + data->palTag = cursor->palTag; + data->subspriteTable.subspriteCount = ListMenuGetRedOutlineCursorSpriteCount(cursor->unk2, cursor->unk4); + data->subspriteTable.subsprites = data->subspritesPtr = Alloc(data->subspriteTable.subspriteCount * 4); + ListMenuSetUpRedOutlineCursorSpriteOamTable(cursor->unk2, cursor->unk4, data->subspritesPtr); + + spriteTemplate = gDummySpriteTemplate; + spriteTemplate.tileTag = cursor->tileTag; + spriteTemplate.paletteTag = cursor->palTag; + + data->spriteId = CreateSprite(&spriteTemplate, cursor->unk0 + 120, cursor->unk1 + 120, 0); + SetSubspriteTables(&gSprites[data->spriteId], &data->subspriteTable); + gSprites[data->spriteId].oam.priority = 0; + gSprites[data->spriteId].subpriority = 0; + gSprites[data->spriteId].subspriteTableNum = 0; + + if (cursor->palTag == 0xFFFF) + { + gSprites[data->spriteId].oam.paletteNum = cursor->palNum; + } + + return taskId; +} + +static void ListMenuUpdateRedOutlineCursorObject(u8 taskId, u16 x, u16 y) +{ + struct UnkIndicatorsStruct3 *data = (void*) gTasks[taskId].data; + + gSprites[data->spriteId].pos1.x = x + 120; + gSprites[data->spriteId].pos1.y = y + 120; +} + +static void ListMenuRemoveRedOutlineCursorObject(u8 taskId) +{ + struct UnkIndicatorsStruct3 *data = (void*) gTasks[taskId].data; + + Free(data->subspritesPtr); + + if (data->tileTag != 0xFFFF) + FreeSpriteTilesByTag(data->tileTag); + if (data->palTag != 0xFFFF) + FreeSpritePaletteByTag(data->palTag); + + DestroySprite(&gSprites[data->spriteId]); + DestroyTask(taskId); +} + +static void ObjectCB_RedArrowCursor(struct Sprite *sprite) +{ + sprite->pos2.x = gSineTable[(u8)(sprite->data[0])] / 64; + sprite->data[0] += 8; +} + +static void Task_RedArrowCursor(u8 taskId) +{ + +} + +static u8 ListMenuAddRedArrowCursorObject(struct CursorStruct *cursor) +{ + struct CompressedSpriteSheet spriteSheet; + struct SpritePalette spritePal; + struct UnkIndicatorsStruct4 *data; + struct SpriteTemplate spriteTemplate; + u8 taskId; + + spriteSheet.data = gUnknown_08614378; + spriteSheet.size = 0x80; + spriteSheet.tag = cursor->tileTag; + LoadCompressedObjectPic(&spriteSheet); + + if (cursor->palTag == 0xFFFF) + { + LoadPalette(gUnknown_086142A8, (16 * cursor->palNum) + 0x100, 0x20); + } + else + { + spritePal.data = gUnknown_086142A8; + spritePal.tag = cursor->palTag; + LoadSpritePalette(&spritePal); + } + + taskId = CreateTask(Task_RedArrowCursor, 0); + data = (void*) gTasks[taskId].data; + + data->tileTag = cursor->tileTag; + data->palTag = cursor->palTag; + + spriteTemplate = gUnknown_08614290; + spriteTemplate.tileTag = cursor->tileTag; + spriteTemplate.paletteTag = cursor->palTag; + + data->field_0 = CreateSprite(&spriteTemplate, cursor->unk0, cursor->unk1, 0); + gSprites[data->field_0].pos2.x = 8; + gSprites[data->field_0].pos2.y = 8; + + if (cursor->palTag == 0xFFFF) + { + gSprites[data->field_0].oam.paletteNum = cursor->palNum; + } + + return taskId; +} + +static void ListMenuUpdateRedArrowCursorObject(u8 taskId, u16 x, u16 y) +{ + struct UnkIndicatorsStruct4 *data = (void*) gTasks[taskId].data; + + gSprites[data->field_0].pos1.x = x; + gSprites[data->field_0].pos1.y = y; +} + +static void ListMenuRemoveRedArrowCursorObject(u8 taskId) +{ + struct UnkIndicatorsStruct4 *data = (void*) gTasks[taskId].data; + + if (data->tileTag != 0xFFFF) + FreeSpriteTilesByTag(data->tileTag); + if (data->palTag != 0xFFFF) + FreeSpritePaletteByTag(data->palTag); + + DestroySprite(&gSprites[data->field_0]); + DestroyTask(taskId); +} diff --git a/src/main_menu.c b/src/main_menu.c index 3d6c1df76..3490424af 100644 --- a/src/main_menu.c +++ b/src/main_menu.c @@ -16,7 +16,7 @@ #include "link.h" #include "main.h" #include "menu.h" -#include "menu_indicators.h" +#include "list_menu.h" #include "mystery_event_menu.h" #include "naming_screen.h" #include "option_menu.h" diff --git a/src/map_name_popup.c b/src/map_name_popup.c index 59b1622eb..1782e9af8 100644 --- a/src/map_name_popup.c +++ b/src/map_name_popup.c @@ -276,7 +276,7 @@ static void sub_80D4A78(u8 bg, u8 x, u8 y, u8 deltaX, u8 deltaY, u8 unused) } } #else -ASM_DIRECT +NAKED static void sub_80D4A78(u8 bg, u8 x, u8 y, u8 deltaX, u8 deltaY, u8 unused) { asm("\n\ diff --git a/src/match_call.c b/src/match_call.c index 9c1e02947..aa6945161 100644 --- a/src/match_call.c +++ b/src/match_call.c @@ -980,7 +980,7 @@ static void sub_81D199C(const match_call_text_data_t *sub0, u16 idx, u8 *dest) } } #else -static ASM_DIRECT void sub_81D199C(const match_call_text_data_t *sub0, u16 idx, u8 *dest) +static NAKED void sub_81D199C(const match_call_text_data_t *sub0, u16 idx, u8 *dest) { asm_unified("\tpush {r4-r7,lr}\n" "\tmov r7, r10\n" @@ -1163,7 +1163,7 @@ const u8 *sub_81D1B40(u32 idx, u32 offset) return NULL; } #else -ASM_DIRECT const u8 *sub_81D1B40(u32 idx, u32 offset) +NAKED const u8 *sub_81D1B40(u32 idx, u32 offset) { asm_unified("\tpush {r4-r7,lr}\n" "\tmov r7, r9\n" diff --git a/src/mauville_old_man.c b/src/mauville_old_man.c index ea466b2ec..2ce8a271d 100644 --- a/src/mauville_old_man.c +++ b/src/mauville_old_man.c @@ -387,7 +387,7 @@ static void ResetStorytellerFlag(void) Storyteller_ResetFlag(); } -void ResetMauvilleOldManFlag(void) // ResetMauvilleOldManFlag +void ResetMauvilleOldManFlag(void) { switch (GetCurrentMauvilleOldMan()) { @@ -673,7 +673,7 @@ static void Task_BardSong(u8 taskId) void ScrSpecial_SetMauvilleOldManMapObjGfx(void) { - VarSet(VAR_0x4010, MAP_OBJ_GFX_BARD); + VarSet(VAR_OBJ_GFX_ID_0, MAP_OBJ_GFX_BARD); } // Language fixers? @@ -793,11 +793,11 @@ void sub_8120C0C(union OldMan * oldMan, u32 r8, u32 r7, u32 r3) } } -void sub_8120CD0(union OldMan * oldMan, u32 unused, u32 a2) +void SanitizeReceivedEmeraldOldMan(union OldMan * oldMan, u32 version, u32 language) { u8 sp00[8]; s32 i; - if (oldMan->common.id == MAUVILLE_MAN_STORYTELLER && a2 == LANGUAGE_JAPANESE) + if (oldMan->common.id == MAUVILLE_MAN_STORYTELLER && language == LANGUAGE_JAPANESE) { struct MauvilleManStoryteller * storyteller = &oldMan->storyteller; @@ -816,9 +816,10 @@ void sub_8120CD0(union OldMan * oldMan, u32 unused, u32 a2) } } -void sub_8120D34(union OldMan * oldMan, u32 r1, u32 r6) +void SanitizeReceivedRubyOldMan(union OldMan * oldMan, u32 version, u32 language) { - u32 r2 = (r1 == LANGUAGE_JAPANESE || r1 == LANGUAGE_ENGLISH) ? 1 : 0; + bool32 isRuby = (version == VERSION_SAPPHIRE || version == VERSION_RUBY); + switch (oldMan->common.id) { case MAUVILLE_MAN_TRADER: @@ -826,7 +827,7 @@ void sub_8120D34(union OldMan * oldMan, u32 r1, u32 r6) struct MauvilleOldManTrader * trader = &oldMan->trader; s32 i; - if (r2) + if (isRuby) { for (i = 0; i < 4; i++) { @@ -837,7 +838,7 @@ void sub_8120D34(union OldMan * oldMan, u32 r1, u32 r6) trader->language[i] = LANGUAGE_JAPANESE; } else - trader->language[i] = r6; + trader->language[i] = language; } } else @@ -858,12 +859,12 @@ void sub_8120D34(union OldMan * oldMan, u32 r1, u32 r6) struct MauvilleManStoryteller * storyteller = &oldMan->storyteller; s32 i; - if (r2) + if (isRuby) { for (i = 0; i < 4; i++) { if (storyteller->gameStatIDs[i] != 0) - storyteller->language[i] = r6; + storyteller->language[i] = language; } } } @@ -872,9 +873,9 @@ void sub_8120D34(union OldMan * oldMan, u32 r1, u32 r6) { struct MauvilleManBard * bard = &oldMan->bard; - if (r2) + if (isRuby) { - bard->language = r6; + bard->language = language; } } break; @@ -882,9 +883,9 @@ void sub_8120D34(union OldMan * oldMan, u32 r1, u32 r6) { struct MauvilleManHipster * hipster = &oldMan->hipster; - if (r2) + if (isRuby) { - hipster->language = r6; + hipster->language = language; } } break; @@ -892,9 +893,9 @@ void sub_8120D34(union OldMan * oldMan, u32 r1, u32 r6) { struct MauvilleManGiddy * giddy = &oldMan->giddy; - if (r2) + if (isRuby) { - giddy->language = r6; + giddy->language = language; } } break; diff --git a/src/menu.c b/src/menu.c index 0aaf2d186..dedfcc3be 100644 --- a/src/menu.c +++ b/src/menu.c @@ -2080,7 +2080,7 @@ void sub_819A080(struct UnkStruct_819A080 *a0, struct UnkStruct_819A080 *a1, u16 } } #else -__attribute__((naked)) +NAKED void sub_819A080(struct UnkStruct_819A080 *a0, struct UnkStruct_819A080 *a1, u16 a2, u16 a3, u16 a4, u16 a5, u16 a6, u16 a7) { asm("push {r4-r7,lr}\n\ diff --git a/src/menu_helpers.c b/src/menu_helpers.c new file mode 100644 index 000000000..178fbb5fa --- /dev/null +++ b/src/menu_helpers.c @@ -0,0 +1,455 @@ +#include "global.h" +#include "task.h" +#include "window.h" +#include "menu.h" +#include "menu_helpers.h" +#include "gpu_regs.h" +#include "bg.h" +#include "main.h" +#include "text.h" +#include "link.h" +#include "string_util.h" +#include "sound.h" +#include "mail.h" +#include "overworld.h" +#include "decompress.h" +#include "constants/songs.h" +#include "constants/items.h" +#include "constants/maps.h" + +extern bool32 sub_800B504(void); + +extern const u8 gBagSwapLineGfx[]; +extern const u8 gBagSwapLinePal[]; + +// this file's functions +static void Task_ContinueTaskAfterMessagePrints(u8 taskId); +static void Task_CallYesOrNoCallback(u8 taskId); + +// EWRAM vars +EWRAM_DATA static struct YesNoFuncTable gUnknown_0203A138 = {0}; +EWRAM_DATA static u8 gUnknown_0203A140 = 0; + +// IWRAM bss vars +IWRAM_DATA static TaskFunc gUnknown_0300117C; + +// const rom data +static const struct OamData sOamData_859F4E8 = +{ + .y = 0, + .affineMode = 0, + .objMode = 0, + .mosaic = 0, + .bpp = 0, + .shape = 0, + .x = 0, + .matrixNum = 0, + .size = 1, + .tileNum = 0, + .priority = 0, + .paletteNum = 0, + .affineParam = 0 +}; + +static const union AnimCmd sSpriteAnim_859F4F0[] = +{ + ANIMCMD_FRAME(0, 0), + ANIMCMD_END +}; + +static const union AnimCmd sSpriteAnim_859F4F8[] = +{ + ANIMCMD_FRAME(4, 0), + ANIMCMD_END +}; + +static const union AnimCmd sSpriteAnim_859F500[] = +{ + ANIMCMD_FRAME(0, 0, 1, 0), + ANIMCMD_END +}; + +static const union AnimCmd *const sSpriteAnimTable_859F508[] = +{ + sSpriteAnim_859F4F0, + sSpriteAnim_859F4F8, + sSpriteAnim_859F500 +}; + +static const struct CompressedSpriteSheet gUnknown_0859F514 = +{ + gBagSwapLineGfx, 0x100, 109 +}; + +static const struct CompressedSpritePalette gUnknown_0859F51C = +{ + gBagSwapLinePal, 109 +}; + +static const struct SpriteTemplate gUnknown_0859F524 = +{ + .tileTag = 109, + .paletteTag = 109, + .oam = &sOamData_859F4E8, + .anims = sSpriteAnimTable_859F508, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = SpriteCallbackDummy, +}; + +// code +void ResetVramOamAndBgCntRegs(void) +{ + SetGpuReg(REG_OFFSET_DISPCNT, 0); + SetGpuReg(REG_OFFSET_BG3CNT, 0); + SetGpuReg(REG_OFFSET_BG2CNT, 0); + SetGpuReg(REG_OFFSET_BG1CNT, 0); + SetGpuReg(REG_OFFSET_BG0CNT, 0); + CpuFill16(0, (void*) VRAM, VRAM_SIZE); + CpuFill32(0, (void*) OAM, OAM_SIZE); + CpuFill16(0, (void*) PLTT, PLTT_SIZE); +} + +void ResetAllBgsCoordinates(void) +{ + ChangeBgX(0, 0, 0); + ChangeBgY(0, 0, 0); + ChangeBgX(1, 0, 0); + ChangeBgY(1, 0, 0); + ChangeBgX(2, 0, 0); + ChangeBgY(2, 0, 0); + ChangeBgX(3, 0, 0); + ChangeBgY(3, 0, 0); +} + +void SetVBlankHBlankCallbacksToNull(void) +{ + SetVBlankCallback(NULL); + SetHBlankCallback(NULL); +} + +void DisplayMessageAndContinueTask(u8 taskId, u8 windowId, u16 arg2, u8 arg3, u8 fontId, u8 textSpeed, const u8 *string, void *taskFunc) +{ + gUnknown_0203A140 = windowId; + sub_8197B1C(windowId, TRUE, arg2, arg3); + + if (string != gStringVar4) + StringExpandPlaceholders(gStringVar4, string); + + gTextFlags.flag_0 = 1; + AddTextPrinterParameterized(windowId, fontId, gStringVar4, textSpeed, NULL, 2, 1, 3); + gUnknown_0300117C = taskFunc; + gTasks[taskId].func = Task_ContinueTaskAfterMessagePrints; +} + +bool16 RunTextPrintersRetIsActive(u8 textPrinterId) +{ + RunTextPrinters(); + return IsTextPrinterActive(textPrinterId); +} + +static void Task_ContinueTaskAfterMessagePrints(u8 taskId) +{ + if (!RunTextPrintersRetIsActive(gUnknown_0203A140)) + gUnknown_0300117C(taskId); +} + +void sub_8121F68(u8 taskId, const struct YesNoFuncTable *data) +{ + gUnknown_0203A138 = *data; + gTasks[taskId].func = Task_CallYesOrNoCallback; +} + +void CreateYesNoMenuWithCallbacks(u8 taskId, const struct WindowTemplate *template, u8 arg2, u8 arg3, u8 arg4, u16 tileStart, u8 palette, const struct YesNoFuncTable *yesNo) +{ + CreateYesNoMenu(template, tileStart, palette, 0); + gUnknown_0203A138 = *yesNo; + gTasks[taskId].func = Task_CallYesOrNoCallback; +} + +static void Task_CallYesOrNoCallback(u8 taskId) +{ + switch (ProcessMenuInputNoWrap_()) + { + case 0: + PlaySE(SE_SELECT); + gUnknown_0203A138.yesFunc(taskId); + break; + case 1: + case MENU_B_PRESSED: + PlaySE(SE_SELECT); + gUnknown_0203A138.noFunc(taskId); + break; + } +} + +bool8 AdjustQuantityAccordingToDPadInput(s16 *arg0, u16 arg1) +{ + s16 valBefore = (*arg0); + + if ((gMain.newAndRepeatedKeys & DPAD_ANY) == DPAD_UP) + { + (*arg0)++; + if ((*arg0) > arg1) + (*arg0) = 1; + + if ((*arg0) == valBefore) + { + return FALSE; + } + else + { + PlaySE(SE_SELECT); + return TRUE; + } + } + else if ((gMain.newAndRepeatedKeys & DPAD_ANY) == DPAD_DOWN) + { + (*arg0)--; + if ((*arg0) <= 0) + (*arg0) = arg1; + + if ((*arg0) == valBefore) + { + return FALSE; + } + else + { + PlaySE(SE_SELECT); + return TRUE; + } + } + else if ((gMain.newAndRepeatedKeys & DPAD_ANY) == DPAD_RIGHT) + { + (*arg0) += 10; + if ((*arg0) > arg1) + (*arg0) = arg1; + + if ((*arg0) == valBefore) + { + return FALSE; + } + else + { + PlaySE(SE_SELECT); + return TRUE; + } + } + else if ((gMain.newAndRepeatedKeys & DPAD_ANY) == DPAD_LEFT) + { + (*arg0) -= 10; + if ((*arg0) <= 0) + (*arg0) = 1; + + if ((*arg0) == valBefore) + { + return FALSE; + } + else + { + PlaySE(SE_SELECT); + return TRUE; + } + } + + return FALSE; +} + +u8 GetLRKeysState(void) +{ + if (gSaveBlock2Ptr->optionsButtonMode == OPTIONS_BUTTON_MODE_LR) + { + if (gMain.newKeys & L_BUTTON) + return 1; + if (gMain.newKeys & R_BUTTON) + return 2; + } + + return 0; +} + +u8 sub_812210C(void) +{ + if (gSaveBlock2Ptr->optionsButtonMode == OPTIONS_BUTTON_MODE_LR) + { + if (gMain.newAndRepeatedKeys & L_BUTTON) + return 1; + if (gMain.newAndRepeatedKeys & R_BUTTON) + return 2; + } + + return 0; +} + +bool8 sub_8122148(u16 itemId) +{ + if (itemId != ITEM_ENIGMA_BERRY) + return TRUE; + else if (gSaveBlock1Ptr->location.mapGroup == MAP_GROUP(TRADE_CENTER) && gSaveBlock1Ptr->location.mapNum == MAP_NUM(TRADE_CENTER)) + return FALSE; + else if (InUnionRoom() != TRUE) + return TRUE; + else + return FALSE; +} + +bool8 itemid_80BF6D8_mail_related(u16 itemId) +{ + if (is_c1_link_related_active() != TRUE && InUnionRoom() != TRUE) + return TRUE; + else if (ItemIsMail(itemId) != TRUE) + return TRUE; + else + return FALSE; +} + +bool8 sub_81221AC(void) +{ + if (is_c1_link_related_active() == TRUE || gReceivedRemoteLinkPlayers == 1) + return TRUE; + else + return FALSE; +} + +static bool8 sub_81221D0(void) +{ + if (!sub_81221AC()) + return FALSE; + else + return sub_8087598(); +} + +bool8 sub_81221EC(void) +{ + if (sub_81221D0() == TRUE) + return TRUE; + else if (sub_800B504() != TRUE) + return FALSE; + else + return TRUE; +} + +void sub_812220C(struct ItemSlot *slots, u8 count, u8 *arg2, u8 *usedSlotsCount, u8 maxUsedSlotsCount) +{ + u16 i; + struct ItemSlot *slots_ = slots; + + (*usedSlotsCount) = 0; + for (i = 0; i < count; i++) + { + if (slots_[i].itemId != ITEM_NONE) + (*usedSlotsCount)++; + } + + (*usedSlotsCount)++; + if ((*usedSlotsCount) > maxUsedSlotsCount) + *arg2 = maxUsedSlotsCount; + else + *arg2 = (*usedSlotsCount); +} + +void sub_812225C(u16 *arg0, u16 *arg1, u8 arg2, u8 arg3) +{ + if ((*arg0) != 0 && (*arg0) + arg2 > arg3) + (*arg0) = arg3 - arg2; + + if ((*arg0) + (*arg1) >= arg3) + { + if (arg3 == 0) + (*arg1) = 0; + else + (*arg1) = arg3 - 1; + } +} + +void sub_8122298(u16 *arg0, u16 *arg1, u8 arg2, u8 arg3, u8 arg4) +{ + u8 i; + + if (arg4 % 2 != 0) + { + if ((*arg1) >= arg4 / 2) + { + for (i = 0; i < (*arg1) - (arg4 / 2); i++) + { + if ((*arg0) + arg2 == arg3) + break; + (*arg1)--; + (*arg0)++; + } + } + } + else + { + if ((*arg1) >= (arg4 / 2) + 1) + { + for (i = 0; i <= (*arg1) - (arg4 / 2); i++) + { + if ((*arg0) + arg2 == arg3) + break; + (*arg1)--; + (*arg0)++; + } + } + } +} + +void LoadListMenuArrowsGfx(void) +{ + LoadCompressedObjectPic(&gUnknown_0859F514); + LoadCompressedObjectPalette(&gUnknown_0859F51C); +} + +void sub_8122344(u8 *spriteIds, u8 count) +{ + u8 i; + + for (i = 0; i < count; i++) + { + spriteIds[i] = CreateSprite(&gUnknown_0859F524, i * 16, 0, 0); + if (i != 0) + StartSpriteAnim(&gSprites[spriteIds[i]], 1); + + gSprites[spriteIds[i]].invisible = 1; + } +} + +void sub_81223B0(u8 *spriteIds, u8 count) +{ + u8 i; + + for (i = 0; i < count; i++) + { + if (i == count - 1) + DestroySpriteAndFreeResources(&gSprites[spriteIds[i]]); + else + DestroySprite(&gSprites[spriteIds[i]]); + } +} + +void sub_81223FC(u8 *spriteIds, u8 count, bool8 invisible) +{ + u8 i; + + for (i = 0; i < count; i++) + { + gSprites[spriteIds[i]].invisible = invisible; + } +} + +void sub_8122448(u8 *spriteIds, u8 count, s16 x, u16 y) +{ + u8 i; + bool8 unknownBit = count & 0x80; + count &= ~(0x80); + + for (i = 0; i < count; i++) + { + if (i == count - 1 && unknownBit) + gSprites[spriteIds[i]].pos2.x = x - 8; + else + gSprites[spriteIds[i]].pos2.x = x; + + gSprites[spriteIds[i]].pos1.y = 1 + y; + } +} diff --git a/src/mon_markings.c b/src/mon_markings.c index 147872ab6..7f320002d 100644 --- a/src/mon_markings.c +++ b/src/mon_markings.c @@ -2,7 +2,8 @@ #include "dma3.h" #include "graphics.h" #include "main.h" -#include "menu_indicators.h" +#include "window.h" +#include "list_menu.h" #include "mon_markings.h" #include "constants/songs.h" #include "sound.h" diff --git a/src/new_game.c b/src/new_game.c index 37336016e..c387bce65 100644 --- a/src/new_game.c +++ b/src/new_game.c @@ -119,11 +119,10 @@ void ClearAllContestWinnerPics(void) void sub_8084400(void) { // probably clearing one struct for battle frontier - CpuFill32(0, gSaveBlock2Ptr->field_64C, 2272); + CpuFill32(0, &gSaveBlock2Ptr->battleTower, 2272); - // those look like strings - gSaveBlock2Ptr->field_EE1 = 0xFF; - gSaveBlock2Ptr->field_EE9 = 0xFF; + gSaveBlock2Ptr->field_EE1[0][0] = EOS; + gSaveBlock2Ptr->field_EE1[1][0] = EOS; } void WarpToTruck(void) diff --git a/src/overworld.c b/src/overworld.c index f42f0db7f..3d9a1bdc2 100644 --- a/src/overworld.c +++ b/src/overworld.c @@ -38,6 +38,7 @@ #include "roamer.h" // #include "rotating_gate.h" #include "safari_zone.h" +#include "save.h" #include "script.h" // #include "script_pokemon_80C4.h" #include "secret_base.h" @@ -87,12 +88,11 @@ extern const struct MapHeader *const *const gMapGroups[]; extern const s32 gMaxFlashLevel; extern const u16 gUnknown_82EC7C4[]; -extern u16 gSaveFileStatus; -extern u16 gUnknown_03005DA8; -extern bool8 (*gUnknown_03005DB0)(void); -extern u8 gUnknown_03005DB4; -extern u8 gFieldLinkPlayerCount; -extern MainCallback gFieldCallback; +u16 gUnknown_03005DA8; +MainCallback gFieldCallback; +bool8 (*gUnknown_03005DB0)(void); +u8 gUnknown_03005DB4; +u8 gFieldLinkPlayerCount; // functions extern void HealPlayerParty(void); @@ -713,7 +713,7 @@ void sub_8084D5C(s16 a1, s16 a2) { u8 currMapType = Overworld_GetMapTypeOfSaveblockLocation(); u8 destMapType = GetMapTypeByGroupAndId(sWarpDestination.mapGroup, sWarpDestination.mapNum); - if (is_light_level_1_2_3_5_or_6(currMapType) && is_light_level_1_2_3_5_or_6(destMapType) != TRUE) + if (is_map_type_1_2_3_5_or_6(currMapType) && is_map_type_1_2_3_5_or_6(destMapType) != TRUE) sub_8084DD4(gSaveBlock1Ptr->location.mapGroup, gSaveBlock1Ptr->location.mapNum, -1, a1 - 7, a2 - 6); } @@ -872,7 +872,7 @@ static void mli0_load_map(u32 a1) LoadMapObjTemplatesFromHeader(); } - v2 = is_light_level_1_2_3_5_or_6(gMapHeader.mapType); + v2 = is_map_type_1_2_3_5_or_6(gMapHeader.mapType); indoors = Overworld_MapTypeIsIndoors(gMapHeader.mapType); sub_80EB218(); @@ -1365,7 +1365,7 @@ u8 get_map_light_from_warp0(void) return GetMapTypeByWarpData(&gUnknown_020322DC); } -bool8 is_light_level_1_2_3_5_or_6(u8 mapType) +bool8 is_map_type_1_2_3_5_or_6(u8 mapType) { if (mapType == MAP_TYPE_ROUTE || mapType == MAP_TYPE_TOWN diff --git a/src/player_pc.c b/src/player_pc.c index 6f39fa449..c10c63dda 100644 --- a/src/player_pc.c +++ b/src/player_pc.c @@ -18,7 +18,6 @@ #include "malloc.h" #include "menu.h" #include "menu_helpers.h" -#include "menu_indicators.h" #include "overworld.h" #include "palette.h" #include "party_menu.h" @@ -43,9 +42,6 @@ struct Struct203BCC4 u8 spriteIds[7]; }; -// extern offset -void (*gFieldCallback)(void); - // static functions static void InitPlayerPCMenu(u8 taskId); static void PlayerPCProcessMenuInput(u8 taskId); @@ -436,7 +432,7 @@ void Mailbox_DoRedrawMailboxMenuAfterReturn(void) static void ItemStorage_HandleReturnToProcessInput(u8 taskId) { - if (sub_80ABDFC() == TRUE) + if (IsWeatherNotFadingIn() == TRUE) gTasks[taskId].func = ItemStorageMenuProcessInput; } @@ -673,7 +669,7 @@ static void pal_fill_for_maplights_or_black(void) static void Mailbox_HandleReturnToProcessInput(u8 taskId) { - if(sub_80ABDFC() == TRUE) + if(IsWeatherNotFadingIn() == TRUE) gTasks[taskId].func = Mailbox_ProcessInput; } diff --git a/src/pokeblock.c b/src/pokeblock.c index 60087b5bf..216c9e2c5 100644 --- a/src/pokeblock.c +++ b/src/pokeblock.c @@ -24,11 +24,11 @@ #include "constants/songs.h" #include "sound.h" #include "berry.h" -#include "menu_indicators.h" #include "event_data.h" #include "battle_message.h" #include "safari_zone.h" #include "lilycove_lady.h" +#include "overworld.h" #define POKEBLOCK_MAX_FEEL 99 #define FIELD_E75_COUNT 7 @@ -70,7 +70,6 @@ enum }; extern u16 gSpecialVar_ItemId; -extern void (*gFieldCallback)(void); extern const u16 gUnknown_0860F074[]; diff --git a/src/pokemon_animation.c b/src/pokemon_animation.c index 02755fe40..c50aa4a75 100644 --- a/src/pokemon_animation.c +++ b/src/pokemon_animation.c @@ -1184,7 +1184,7 @@ static void sub_817F9F4(struct Sprite *sprite) } #else -__attribute__((naked)) +NAKED static void sub_817F9F4(struct Sprite *sprite) { asm(".syntax unified\n\ diff --git a/src/pokemon_summary_screen.c b/src/pokemon_summary_screen.c index f77b7c38c..74dc11973 100644 --- a/src/pokemon_summary_screen.c +++ b/src/pokemon_summary_screen.c @@ -1417,7 +1417,7 @@ void sub_81C14BC(struct Pokemon *mon, u8 swappingFromId, u8 swappingToId) *ppBonusesPtr = localPpBonuses; } #else -ASM_DIRECT +NAKED void sub_81C14BC(struct Pokemon *mon, u8 swappingFromId, u8 swappingToId) { asm(".syntax unified\n\ @@ -1628,7 +1628,7 @@ void sub_81C15EC(struct BoxPokemon *mon, u8 swappingFromId, u8 swappingToId) *ppBonusesPtr = localPpBonuses; } #else -ASM_DIRECT +NAKED void sub_81C15EC(struct BoxPokemon *mon, u8 swappingFromId, u8 swappingToId) { asm(".syntax unified\n\ @@ -1825,7 +1825,7 @@ void sub_81C174C(u8 taskId) } else { - PlaySE(0x20); + PlaySE(SE_HAZURE); sub_81C18F4(taskId); } } @@ -2039,7 +2039,7 @@ void sub_81C1CB0(struct UnkStruct_61CC04 *a, u16 *b, u8 c, u8 d) Free(alloced); } #else -ASM_DIRECT +NAKED void sub_81C1CB0(struct UnkStruct_61CC04 *a, u16 *b, u8 c, u8 d) { asm(".syntax unified\n\ @@ -2341,7 +2341,7 @@ void sub_81C2194(u16 *a, u16 b, u8 c) } } #else -ASM_DIRECT +NAKED void sub_81C2194(u16 *a, u16 b, u8 c) { asm(".syntax unified\n\ @@ -3026,7 +3026,7 @@ void sub_81C335C() sub_81C25A4(r4, gText_FiveMarks, r5, 1, 0, 1); } #else -ASM_DIRECT +NAKED void sub_81C335C() { asm(".syntax unified\n\ @@ -3369,7 +3369,7 @@ void sub_81C3B08(u8 a) sub_81C25A4(sp, text, offset, (a<<4), 0, r5); } #else -ASM_DIRECT +NAKED void sub_81C3B08(u8 a) { asm(".syntax unified\n\ diff --git a/src/record_mixing.c b/src/record_mixing.c index 151835e5e..35e518d8a 100644 --- a/src/record_mixing.c +++ b/src/record_mixing.c @@ -1,28 +1,2282 @@ - -// Includes #include "global.h" +#include "malloc.h" +#include "random.h" +#include "constants/items.h" +#include "text.h" +#include "item.h" +#include "task.h" +#include "constants/species.h" +#include "save.h" +#include "load_save.h" +#include "pokemon.h" +#include "cable_club.h" +#include "link.h" +#include "link_rfu.h" +#include "tv.h" +#include "battle_tower.h" +#include "window.h" +#include "mystery_event_script.h" +#include "secret_base.h" +#include "mauville_old_man.h" +#include "sound.h" +#include "constants/songs.h" +#include "menu.h" +#include "overworld.h" +#include "field_screen.h" +#include "fldeff_80F9BCC.h" +#include "script.h" +#include "event_data.h" +#include "lilycove_lady.h" +#include "strings.h" +#include "string_util.h" +#include "record_mixing.h" +#include "new_game.h" +#include "daycare.h" +#include "international_string_util.h" + +extern void ReceiveSecretBasesData(struct SecretBaseRecord *, size_t, u8); +extern void ReceiveEasyChatPairsData(struct EasyChatPair *, size_t, u8); // Static type declarations +struct UnknownRecMixingStruct +{ + u32 field_0; + u16 field_4; + u8 field_6[9]; +}; + +struct UnknownRecMixingStruct2 +{ + u32 field_0; + u16 field_4; + u16 field_6; + u16 field_8; + u8 field_A[16]; +}; + +struct UnknownRecMixingStruct3 +{ + u8 field_0[0x810]; +}; + +struct PlayerRecordsRS +{ + struct SecretBaseRecord secretBases[SECRET_BASES_COUNT]; + TVShow tvShows[TV_SHOWS_COUNT]; + PokeNews pokeNews[POKE_NEWS_COUNT]; + OldMan oldMan; + struct EasyChatPair easyChatPairs[5]; + struct RecordMixingDayCareMail dayCareMail; + struct RSBattleTowerRecord battleTowerRecord; + u16 filler11C8[0x32]; +}; + +struct PlayerRecordsEmerald +{ + /* 0x0000 */ struct SecretBaseRecord secretBases[SECRET_BASES_COUNT]; + /* 0x0c80 */ TVShow tvShows[TV_SHOWS_COUNT]; + /* 0x1004 */ PokeNews pokeNews[POKE_NEWS_COUNT]; + /* 0x1044 */ OldMan oldMan; + /* 0x1084 */ struct EasyChatPair easyChatPairs[5]; + /* 0x10ac */ struct RecordMixingDayCareMail dayCareMail; + /* 0x1124 */ struct EmeraldBattleTowerRecord battleTowerRecord; + /* 0x1210 */ u16 unk_1210; + /* 0x1214 */ LilycoveLady lilycoveLady; + /* 0x1254 */ struct UnkRecordMixingStruct unk_1254[2]; + /* 0x12dc */ struct UnkRecordMixingStruct2 unk_12dc; + /* 0x1434 */ u8 field_1434[0x10]; +}; // 0x1444 + +union PlayerRecords +{ + struct PlayerRecordsRS ruby; + struct PlayerRecordsEmerald emerald; +}; + // Static RAM declarations -IWRAM_DATA bool8 gUnknown_03001130; -IWRAM_DATA struct SecretBaseRecord *gUnknown_03001134; -IWRAM_DATA TVShow *gUnknown_03001138; -IWRAM_DATA struct UnknownSaveStruct2ABC *gUnknown_0300113C; -IWRAM_DATA OldMan *gUnknown_03001140; -IWRAM_DATA struct EasyChatPair *gUnknown_03001144; -IWRAM_DATA struct DaycareData *gUnknown_03001148; -IWRAM_DATA void *gUnknown_0300114C; // gSaveBlock2Ptr->field_64C -IWRAM_DATA LilycoveLady *gUnknown_03001150; -IWRAM_DATA void *gUnknown_03001154; // gSaveBlock2Ptr->field_0DC; -IWRAM_DATA void *gUnknown_03001158; // gSaveBlock2Ptr->field_64C -IWRAM_DATA u32 gUnknown_0300115C; -IWRAM_DATA u8 gUnknown_03001160[8]; -IWRAM_DATA u32 gUnknown_03001168[3]; +static IWRAM_DATA bool8 gUnknown_03001130; +static IWRAM_DATA struct SecretBaseRecord *sSecretBasesSave; +static IWRAM_DATA TVShow *sTvShowsSave; +static IWRAM_DATA PokeNews *sPokeNewsSave; +static IWRAM_DATA OldMan *sOldManSave; +static IWRAM_DATA struct EasyChatPair *sEasyChatPairsSave; +static IWRAM_DATA struct RecordMixingDayCareMail *gUnknown_03001148; +static IWRAM_DATA void *sBattleTowerSave; +static IWRAM_DATA LilycoveLady *sLilycoveLadySave; +static IWRAM_DATA void *gUnknown_03001154; // gSaveBlock2Ptr->field_0DC; +static IWRAM_DATA void *sBattleTowerSave_Duplicate; +static IWRAM_DATA u32 sRecordStructSize; +static IWRAM_DATA u8 gUnknown_03001160; +static IWRAM_DATA u32 filler_03001164; +static IWRAM_DATA u32 gUnknown_03001168[3]; + +static EWRAM_DATA struct RecordMixingDayCareMail gUnknown_02039F9C = {0}; +static EWRAM_DATA union PlayerRecords *sReceivedRecords = NULL; +static EWRAM_DATA union PlayerRecords *sSentRecord = NULL; // Static ROM declarations +static void Task_RecordMixing_Main(u8 taskId); +static void sub_80E7324(u8 taskId); +static void Task_SendPacket(u8 taskId); +static void Task_CopyReceiveBuffer(u8 taskId); +static void Task_SendPacket_SwitchToReceive(u8 taskId); +static void *LoadPtrFromTaskData(const u16 *asShort); +static void StorePtrInTaskData(void *records, u16 *a1); +static u8 GetMultiplayerId_(void); +static void *GetPlayerRecvBuffer(u8); +static void ReceiveOldManData(OldMan *, size_t, u8); +static void ReceiveBattleTowerData(void *battleTowerRecord, size_t, u8); +static void ReceiveLilycoveLadyData(LilycoveLady *, size_t, u8); +static void sub_80E7B2C(const u8 *); +static void ReceiveDaycareMailData(struct RecordMixingDayCareMail *, size_t, u8, TVShow *); +static void sub_80E7F68(u16 *item, u8 which); +static void sub_80E7FF8(u8 taskId); +static void sub_80E8110(struct UnkRecordMixingStruct *arg0, struct UnkRecordMixingStruct *arg1); +static void sub_80E8468(struct UnkRecordMixingStruct *arg0, size_t arg1, u32 arg2); +static void sub_80E89AC(struct UnkRecordMixingStruct2 *arg0, size_t arg1, u32 arg2); +static void sub_80E89F8(struct RecordMixingDayCareMail *dst); +static void SanitizeDayCareMailForRuby(struct RecordMixingDayCareMail *src); +static void SanitizeEmeraldBattleTowerRecord(struct EmeraldBattleTowerRecord *arg0); +static void SanitizeRubyBattleTowerRecord(struct RSBattleTowerRecord *src); + // .rodata +static const u8 gUnknown_0858CF8C[] = {1, 0}; + +static const u8 gUnknown_0858CF8E[][3] = +{ + {1, 2, 0}, + {2, 0, 1}, +}; + +static const u8 gUnknown_0858CF94[][4] = +{ + {1, 0, 3, 2}, + {3, 0, 1, 2}, + {2, 0, 3, 1}, + {1, 3, 0, 2}, + {2, 3, 0, 1}, + {3, 2, 0, 1}, + {1, 2, 3, 0}, + {2, 3, 1, 0}, + {3, 2, 1, 0}, +}; + +static const u8 gUnknown_0858CFB8[3][2] = +{ + {0, 1}, + {1, 2}, + {2, 0}, +}; + +static const u8 gUnknown_0858CFBE[3][4] = +{ + {0, 1, 2, 3}, + {0, 2, 1, 3}, + {0, 3, 2, 1}, +}; + // .text + +#define BUFFER_CHUNK_SIZE 200 + +void sub_80E6BE8(void) +{ + sub_80B37D4(Task_RecordMixing_Main); +} + +// these variables were const in R/S, but had to become changeable because of saveblocks changing RAM position +static void SetSrcLookupPointers(void) +{ + sSecretBasesSave = gSaveBlock1Ptr->secretBases; + sTvShowsSave = gSaveBlock1Ptr->tvShows; + sPokeNewsSave = gSaveBlock1Ptr->pokeNews; + sOldManSave = &gSaveBlock1Ptr->oldMan; + sEasyChatPairsSave = gSaveBlock1Ptr->easyChatPairs; + gUnknown_03001148 = &gUnknown_02039F9C; + sBattleTowerSave = &gSaveBlock2Ptr->battleTower; + sLilycoveLadySave = &gSaveBlock1Ptr->lilycoveLady; + gUnknown_03001154 = gSaveBlock2Ptr->field_DC; + sBattleTowerSave_Duplicate = &gSaveBlock2Ptr->battleTower; +} + +static void PrepareUnknownExchangePacket(struct PlayerRecordsRS *dest) +{ + memcpy(dest->secretBases, sSecretBasesSave, sizeof(dest->secretBases)); + memcpy(dest->tvShows, sTvShowsSave, sizeof(dest->tvShows)); + sub_80F14F8(dest->tvShows); + memcpy(dest->pokeNews, sPokeNewsSave, sizeof(dest->pokeNews)); + memcpy(&dest->oldMan, sOldManSave, sizeof(dest->oldMan)); + memcpy(dest->easyChatPairs, sEasyChatPairsSave, sizeof(dest->easyChatPairs)); + sub_80E89F8(&dest->dayCareMail); + sub_81659DC(sBattleTowerSave, &dest->battleTowerRecord); + + if (GetMultiplayerId() == 0) + dest->battleTowerRecord.unk_11c8 = GetRecordMixingGift(); +} + +static void PrepareExchangePacketForRubySapphire(struct PlayerRecordsRS *dest) +{ + memcpy(dest->secretBases, sSecretBasesSave, sizeof(dest->secretBases)); + sub_80EB18C(dest->secretBases); + memcpy(dest->tvShows, sTvShowsSave, sizeof(dest->tvShows)); + sub_80F1208(dest->tvShows); + memcpy(dest->pokeNews, sPokeNewsSave, sizeof(dest->pokeNews)); + memcpy(&dest->oldMan, sOldManSave, sizeof(dest->oldMan)); + sub_8120B70(&dest->oldMan); + memcpy(dest->easyChatPairs, sEasyChatPairsSave, sizeof(dest->easyChatPairs)); + sub_80E89F8(&dest->dayCareMail); + SanitizeDayCareMailForRuby(&dest->dayCareMail); + sub_81659DC(sBattleTowerSave, &dest->battleTowerRecord); + SanitizeRubyBattleTowerRecord(&dest->battleTowerRecord); + + if (GetMultiplayerId() == 0) + dest->battleTowerRecord.unk_11c8 = GetRecordMixingGift(); +} + +static void PrepareExchangePacket(void) +{ + sub_80E9914(); + sub_80F0BB8(); + SetSrcLookupPointers(); + + if (Link_AnyPartnersPlayingRubyOrSapphire()) + { + if (sub_800A03C() == 0) + PrepareUnknownExchangePacket(&sSentRecord->ruby); + else + PrepareExchangePacketForRubySapphire(&sSentRecord->ruby); + } + else + { + memcpy(sSentRecord->emerald.secretBases, sSecretBasesSave, sizeof(sSentRecord->emerald.secretBases)); + memcpy(sSentRecord->emerald.tvShows, sTvShowsSave, sizeof(sSentRecord->emerald.tvShows)); + memcpy(sSentRecord->emerald.pokeNews, sPokeNewsSave, sizeof(sSentRecord->emerald.pokeNews)); + memcpy(&sSentRecord->emerald.oldMan, sOldManSave, sizeof(sSentRecord->emerald.oldMan)); + memcpy(&sSentRecord->emerald.lilycoveLady, sLilycoveLadySave, sizeof(sSentRecord->emerald.lilycoveLady)); + memcpy(sSentRecord->emerald.easyChatPairs, sEasyChatPairsSave, sizeof(sSentRecord->emerald.easyChatPairs)); + sub_80E89F8(&sSentRecord->emerald.dayCareMail); + memcpy(&sSentRecord->emerald.battleTowerRecord, sBattleTowerSave, sizeof(sSentRecord->emerald.battleTowerRecord)); + SanitizeEmeraldBattleTowerRecord(&sSentRecord->emerald.battleTowerRecord); + + if (GetMultiplayerId() == 0) + sSentRecord->emerald.unk_1210 = GetRecordMixingGift(); + + sub_80E8110(sSentRecord->emerald.unk_1254, gUnknown_03001154); + sub_80E8260(&sSentRecord->emerald.unk_12dc); + } +} + +static void ReceiveExchangePacket(u32 which) +{ + if (Link_AnyPartnersPlayingRubyOrSapphire()) + { + // Ruby/Sapphire + sub_80E7B2C((void *)sReceivedRecords->ruby.tvShows); + ReceiveSecretBasesData(sReceivedRecords->ruby.secretBases, sizeof(struct PlayerRecordsRS), which); + ReceiveDaycareMailData(&sReceivedRecords->ruby.dayCareMail, sizeof(struct PlayerRecordsRS), which, sReceivedRecords->ruby.tvShows); + ReceiveBattleTowerData(&sReceivedRecords->ruby.battleTowerRecord, sizeof(struct PlayerRecordsRS), which); + ReceiveTvShowsData(sReceivedRecords->ruby.tvShows, sizeof(struct PlayerRecordsRS), which); + ReceivePokeNewsData(sReceivedRecords->ruby.pokeNews, sizeof(struct PlayerRecordsRS), which); + ReceiveOldManData(&sReceivedRecords->ruby.oldMan, sizeof(struct PlayerRecordsRS), which); + ReceiveEasyChatPairsData(sReceivedRecords->ruby.easyChatPairs, sizeof(struct PlayerRecordsRS), which); + sub_80E7F68(&sReceivedRecords->ruby.battleTowerRecord.unk_11c8, which); + } + else + { + // Emerald + sub_80E7B2C((void *)sReceivedRecords->emerald.tvShows); + ReceiveSecretBasesData(sReceivedRecords->emerald.secretBases, sizeof(struct PlayerRecordsEmerald), which); + ReceiveTvShowsData(sReceivedRecords->emerald.tvShows, sizeof(struct PlayerRecordsEmerald), which); + ReceivePokeNewsData(sReceivedRecords->emerald.pokeNews, sizeof(struct PlayerRecordsEmerald), which); + ReceiveOldManData(&sReceivedRecords->emerald.oldMan, sizeof(struct PlayerRecordsEmerald), which); + ReceiveEasyChatPairsData(sReceivedRecords->emerald.easyChatPairs, sizeof(struct PlayerRecordsEmerald), which); + ReceiveDaycareMailData(&sReceivedRecords->emerald.dayCareMail, sizeof(struct PlayerRecordsEmerald), which, sReceivedRecords->emerald.tvShows); + ReceiveBattleTowerData(&sReceivedRecords->emerald.battleTowerRecord, sizeof(struct PlayerRecordsEmerald), which); + sub_80E7F68(&sReceivedRecords->emerald.unk_1210, which); + ReceiveLilycoveLadyData(&sReceivedRecords->emerald.lilycoveLady, sizeof(struct PlayerRecordsEmerald), which); + sub_80E8468(sReceivedRecords->emerald.unk_1254, sizeof(struct PlayerRecordsEmerald), (u8) which); + sub_80E89AC(&sReceivedRecords->emerald.unk_12dc, sizeof(struct PlayerRecordsEmerald), (u8) which); + } +} + +static void PrintTextOnRecordMixing(const u8 *src) +{ + NewMenuHelpers_DrawDialogueFrame(0, 0); + PrintTextOnWindow(0, 1, src, 0, 1, 0, NULL); + CopyWindowToVram(0, 3); +} + +#define tCounter data[0] + +static void Task_RecordMixing_SoundEffect(u8 taskId) +{ + if (++gTasks[taskId].tCounter == 50) + { + PlaySE(SE_W213); + gTasks[taskId].tCounter = 0; + } +} + +#undef tCounter + +#define tState data[0] +#define tSndEffTaskId data[15] + +static void Task_RecordMixing_Main(u8 taskId) +{ + s16 *data = gTasks[taskId].data; + + switch (tState) + { + case 0: // init + sSentRecord = malloc(sizeof(union PlayerRecords)); + sReceivedRecords = malloc(sizeof(union PlayerRecords) * 4); + sub_8009628(gSpecialVar_0x8005); + VarSet(VAR_TEMP_0, 1); + gUnknown_03001130 = FALSE; + PrepareExchangePacket(); + CreateRecordMixingSprite(); + tState = 1; + data[10] = CreateTask(sub_80E7324, 80); + tSndEffTaskId = CreateTask(Task_RecordMixing_SoundEffect, 81); + break; + case 1: // wait for sub_80E7324 + if (!gTasks[data[10]].isActive) + { + tState = 2; + FlagSet(FLAG_SYS_MIX_RECORD); + DestroyRecordMixingSprite(); + DestroyTask(tSndEffTaskId); + } + break; + case 2: + data[10] = CreateTask(sub_80E7FF8, 10); + tState = 3; + PlaySE(SE_W226); + break; + case 3: // wait for sub_80E7FF8 + if (!gTasks[data[10]].isActive) + { + tState = 4; + if (gWirelessCommType == 0) + data[10] = sub_80B3050(); + + PrintTextOnRecordMixing(gText_RecordMixingComplete); + data[8] = 0; + } + break; + case 4: // wait 60 frames + if (++data[8] > 60) + tState = 5; + break; + case 5: + if (!gTasks[data[10]].isActive) + { + free(sReceivedRecords); + free(sSentRecord); + sub_808729C(); + if (gWirelessCommType != 0) + { + CreateTask(sub_80AF2B4, 10); + } + sub_8197434(0, 1); + DestroyTask(taskId); + EnableBothScriptContexts(); + } + break; + } +} + +#undef tState +#undef tSndEffTaskId + +static void sub_80E7324(u8 taskId) +{ + struct Task *task = &gTasks[taskId]; + + switch (task->data[0]) + { + case 0: + PrintTextOnRecordMixing(gText_MixingRecords); + task->data[8] = 0x708; + task->data[0] = 400; + ClearLinkCallback_2(); + break; + case 100: // wait 20 frames + if (++task->data[12] > 20) + { + task->data[12] = 0; + task->data[0] = 101; + } + break; + case 101: + { + u8 players = GetLinkPlayerCount_2(); + if (IsLinkMaster() == TRUE) + { + if (players == sub_800AA48()) + { + PlaySE(SE_PIN); + task->data[0] = 201; + task->data[12] = 0; + } + } + else + { + PlaySE(SE_BOO); + task->data[0] = 301; + } + } + break; + case 201: + if (sub_800AA48() == GetLinkPlayerCount_2() && ++task->data[12] > (GetLinkPlayerCount_2() * 30)) + { + sub_800A620(); + task->data[0] = 1; + } + break; + case 301: + if (sub_800AA48() == GetLinkPlayerCount_2()) + task->data[0] = 1; + break; + case 400: // wait 20 frames + if (++task->data[12] > 20) + { + task->data[0] = 1; + task->data[12] = 0; + } + break; + case 1: // wait for handshake + if (gReceivedRemoteLinkPlayers != 0) + { + ConvertIntToDecimalStringN(gStringVar1, GetMultiplayerId_(), STR_CONV_MODE_LEADING_ZEROS, 2); + task->data[0] = 5; + } + break; + case 2: + { + u8 subTaskId; + + task->data[6] = GetLinkPlayerCount_2(); + task->data[0] = 0; + task->data[5] = GetMultiplayerId_(); + task->func = Task_SendPacket; + if (Link_AnyPartnersPlayingRubyOrSapphire()) + { + StorePtrInTaskData(sSentRecord, (u16 *)&task->data[2]); + subTaskId = CreateTask(Task_CopyReceiveBuffer, 80); + task->data[10] = subTaskId; + gTasks[subTaskId].data[0] = taskId; + StorePtrInTaskData(sReceivedRecords, (u16 *)&gTasks[subTaskId].data[5]); + sRecordStructSize = sizeof(struct PlayerRecordsRS); + } + else + { + StorePtrInTaskData(sSentRecord, (u16 *)&task->data[2]); + subTaskId = CreateTask(Task_CopyReceiveBuffer, 80); + task->data[10] = subTaskId; + gTasks[subTaskId].data[0] = taskId; + StorePtrInTaskData(sReceivedRecords, (u16 *)&gTasks[subTaskId].data[5]); + sRecordStructSize = sizeof(struct PlayerRecordsEmerald); + } + } + break; + case 5: // wait 60 frames + if (++task->data[10] > 60) + { + task->data[10] = 0; + task->data[0] = 2; + } + break; + } +} + +static void Task_SendPacket(u8 taskId) +{ + struct Task *task = &gTasks[taskId]; + // does this send the data 24 times? + + switch (task->data[0]) + { + case 0: // Copy record data to send buffer + { + void *recordData = LoadPtrFromTaskData(&task->data[2]) + task->data[4] * BUFFER_CHUNK_SIZE; + + memcpy(gBlockSendBuffer, recordData, BUFFER_CHUNK_SIZE); + task->data[0]++; + } + break; + case 1: + if (GetMultiplayerId() == 0) + sub_800A4D8(1); + task->data[0]++; + break; + case 2: + break; + case 3: + task->data[4]++; + if (task->data[4] == sRecordStructSize / 200 + 1) + task->data[0]++; + else + task->data[0] = 0; + break; + case 4: + if (!gTasks[task->data[10]].isActive) + task->func = Task_SendPacket_SwitchToReceive; + break; + } +} + +static void Task_CopyReceiveBuffer(u8 taskId) +{ + struct Task *task = &gTasks[taskId]; + u8 status = GetBlockReceivedStatus(); + u8 handledPlayers = 0; + + if (status == sub_800A9D8()) + { + u8 i; + + for (i = 0; i < GetLinkPlayerCount(); i++) + { + void *dest; + void *src; + + if ((status >> i) & 1) + { + dest = LoadPtrFromTaskData((u16 *)&task->data[5]) + task->data[i + 1] * BUFFER_CHUNK_SIZE + sRecordStructSize * i; + src = GetPlayerRecvBuffer(i); + if ((task->data[i + 1] + 1) * BUFFER_CHUNK_SIZE > sRecordStructSize) + memcpy(dest, src, sRecordStructSize - task->data[i + 1] * BUFFER_CHUNK_SIZE); + else + memcpy(dest, src, BUFFER_CHUNK_SIZE); + ResetBlockReceivedFlag(i); + task->data[i + 1]++; + if (task->data[i + 1] == sRecordStructSize / BUFFER_CHUNK_SIZE + 1) + handledPlayers++; + } + } + gTasks[task->data[0]].data[0]++; + } + + if (handledPlayers == GetLinkPlayerCount()) + DestroyTask(taskId); +} + +static void sub_80E776C(u8 taskId) +{ + struct Task *task = &gTasks[taskId]; + + if (!gTasks[task->data[10]].isActive) + DestroyTask(taskId); +} + +static void Task_ReceivePacket(u8 taskId) +{ + struct Task *task = &gTasks[taskId]; + + task->func = sub_80E776C; + if (gUnknown_03001130 == TRUE) + ReceiveExchangePacket(task->data[5]); +} + +static void Task_SendPacket_SwitchToReceive(u8 taskId) +{ + gTasks[taskId].func = Task_ReceivePacket; + gUnknown_03001130 = TRUE; +} + +static void *LoadPtrFromTaskData(const u16 *asShort) +{ + return (void *)(asShort[0] | (asShort[1] << 16)); +} + +static void StorePtrInTaskData(void *records, u16 *asShort) +{ + asShort[0] = (u32)records; + asShort[1] = ((u32)records >> 16); +} + +static u8 GetMultiplayerId_(void) +{ + return GetMultiplayerId(); +} + +static void *GetPlayerRecvBuffer(u8 id) +{ + return gBlockRecvBuffer[id]; +} + +static void ShufflePlayerIndices(u32 *data) +{ + u32 i; + u32 linkTrainerId; + u32 players = GetLinkPlayerCount(); + + switch (players) + { + case 2: + for (i = 0; i < 2; i++) + data[i] = gUnknown_0858CF8C[i]; + break; + case 3: + linkTrainerId = GetLinkPlayerTrainerId(0) % 2; + for (i = 0; i < 3; i++) + data[i] = gUnknown_0858CF8E[linkTrainerId][i]; + break; + case 4: + linkTrainerId = GetLinkPlayerTrainerId(0) % 9; + for (i = 0; i < 4; i++) + data[i] = gUnknown_0858CF94[linkTrainerId][i]; + break; + } +} + +static void ReceiveOldManData(OldMan *oldMan, size_t recordSize, u8 which) +{ + u8 version; + u16 language; + OldMan *dest; + u32 mixIndices[4]; + + ShufflePlayerIndices(mixIndices); + dest = (void *)oldMan + recordSize * mixIndices[which]; + version = gLinkPlayers[mixIndices[which]].version; + language = gLinkPlayers[mixIndices[which]].language; + + if (Link_AnyPartnersPlayingRubyOrSapphire()) + SanitizeReceivedRubyOldMan(dest, version, language); + else + SanitizeReceivedEmeraldOldMan(dest, version, language); + + memcpy(sOldManSave, (void *)oldMan + recordSize * mixIndices[which], sizeof(OldMan)); + ResetMauvilleOldManFlag(); +} + +static void ReceiveBattleTowerData(void *battleTowerRecord, size_t recordSize, u8 which) +{ + struct EmeraldBattleTowerRecord *dest; + struct UnknownPokemonStruct *btPokemon; + u32 mixIndices[4]; + s32 i; + + ShufflePlayerIndices(mixIndices); + if (Link_AnyPartnersPlayingRubyOrSapphire()) + { + if (sub_816587C((void *)battleTowerRecord + recordSize * mixIndices[which], (void *)battleTowerRecord + recordSize * which) == TRUE) + { + dest = (void *)battleTowerRecord + recordSize * which; + dest->language = gLinkPlayers[mixIndices[which]].language; + CalcEmeraldBattleTowerChecksum(dest); + } + } + else + { + memcpy((void *)battleTowerRecord + recordSize * which, (void *)battleTowerRecord + recordSize * mixIndices[which], sizeof(union BattleTowerRecord)); + dest = (void *)battleTowerRecord + recordSize * which; + for (i = 0; i < 4; i ++) + { + btPokemon = &dest->party[i]; + if (btPokemon->species != SPECIES_NONE && IsStringJapanese(btPokemon->nickname)) + ConvertInternationalString(btPokemon->nickname, LANGUAGE_JAPANESE); + } + CalcEmeraldBattleTowerChecksum(dest); + } + sub_81628A0((void *)battleTowerRecord + recordSize * which); +} + +static void ReceiveLilycoveLadyData(LilycoveLady *lilycoveLady, size_t recordSize, u8 which) +{ + LilycoveLady *dest; + u32 mixIndices[4]; + + ShufflePlayerIndices(mixIndices); + memcpy((void *)lilycoveLady + recordSize * which, sLilycoveLadySave, sizeof(LilycoveLady)); + + if (GetLilycoveLadyId() == 0) + { + dest = malloc(sizeof(LilycoveLady)); + if (dest == NULL) + return; + + memcpy(dest, sLilycoveLadySave, sizeof(LilycoveLady)); + } + else + { + dest = NULL; + } + + memcpy(sLilycoveLadySave, (void *)lilycoveLady + recordSize * mixIndices[which], sizeof(LilycoveLady)); + sub_818DA78(); + if (dest != NULL) + { + sub_818E570(dest); + free(dest); + } +} + +static u8 sub_80E7A9C(struct DayCareMail *rmMail) +{ + return rmMail->message.itemId; +} + +static void sub_80E7AA4(struct RecordMixingDayCareMail *src, size_t recordSize, u8 (*idxs)[2], u8 which0, u8 which1) +{ + struct DayCareMail buffer; + struct RecordMixingDayCareMail *mail1; + struct RecordMixingDayCareMail *mail2; + + mail1 = (void *)src + recordSize * idxs[which0][0]; + memcpy(&buffer, &mail1->mail[idxs[which0][1]], sizeof(struct DayCareMail)); + mail2 = (void *)src + recordSize * idxs[which1][0]; + memcpy(&mail1->mail[idxs[which0][1]], &mail2->mail[idxs[which1][1]], sizeof(struct DayCareMail)); + memcpy(&mail2->mail[idxs[which1][1]], &buffer, sizeof(struct DayCareMail)); +} + +static void sub_80E7B2C(const u8 *src) +{ + u8 sum; + s32 i; + + sum = 0; + for (i = 0; i < 256; i ++) + sum += src[i]; + + gUnknown_03001160 = sum; +} + +static u8 sub_80E7B54(void) +{ + return gUnknown_03001160; +} + +#ifdef NONMATCHING +static void ReceiveDaycareMailData(struct RecordMixingDayCareMail *src, size_t recordSize, u8 which, TVShow *shows) +{ + // r9 = which + u16 i; + u16 j; + u8 linkPlayerCount; + u16 language; + u16 otNameLanguage; + u16 nicknameLanguage; + u32 version; + u8 dcMail1; + u8 dcMail2; + u8 r1_80e7b54; + struct DayCareMail *recordMixingMail; + struct RecordMixingDayCareMail *_src; + u8 sp04[4]; + u8 sp08[4]; + struct RecordMixingDayCareMail *sp0c[4]; // -> sp+48 + u8 sp1c[4][2]; // [][0] -> sp+4c, [][1] -> sp+50 + u8 sp24[4][2]; + // sp+2c = src + // sp+30 = recordSize + u8 sp34; + u16 oldSeed; + bool32 anyRS; // sp+3c + + oldSeed = Random2(); + SeedRng2(gLinkPlayers[0].trainerId); + linkPlayerCount = GetLinkPlayerCount(); + for (i = 0; i < 4; i ++) + { + sp04[i] = 0xFF; + sp08[i] = 0; + sp1c[i][0] = 0; + sp1c[i][1] = 0; + } + anyRS = Link_AnyPartnersPlayingRubyOrSapphire(); + for (i = 0; i < GetLinkPlayerCount(); i ++) // r8 = i + { + // sp+54 = linkPlayerCount << 16 + // sp+44 = which * recordSize + _src = (void *)src + i * recordSize; // r7 + language = gLinkPlayers[i].language; // r9 + version = (u8)gLinkPlayers[i].version; // sp+40 + for (j = 0; j < _src->unk_70; j ++) + { + // r10 = ~0x10 + recordMixingMail = &_src->unk_00[j]; + if (recordMixingMail->mail.itemId != ITEM_NONE) + { + if (anyRS) + { + if (StringLength(recordMixingMail->OT_name) <= 5) + { + otNameLanguage = LANGUAGE_JAPANESE; + } + else + { + StripExtCtrlCodes(recordMixingMail->OT_name); + otNameLanguage = language; + } + if (recordMixingMail->monName[0] == EXT_CTRL_CODE_BEGIN && recordMixingMail->monName[1] == EXT_CTRL_CODE_JPN) + { + StripExtCtrlCodes(recordMixingMail->monName); + nicknameLanguage = LANGUAGE_JAPANESE; + } + else + { + nicknameLanguage = language; + } + if (version == VERSION_RUBY || version == VERSION_SAPPHIRE) + { + recordMixingMail->language_maybe = otNameLanguage; + recordMixingMail->unknown = nicknameLanguage; + } + } + else if (language == LANGUAGE_JAPANESE) + { + if (IsStringJapanese(recordMixingMail->OT_name)) + { + recordMixingMail->language_maybe = LANGUAGE_JAPANESE; + } + else + { + recordMixingMail->language_maybe = GAME_LANGUAGE; + } + if (IsStringJapanese(recordMixingMail->monName)) + { + recordMixingMail->unknown = LANGUAGE_JAPANESE; + } + else + { + recordMixingMail->unknown = GAME_LANGUAGE; + } + } + } + } + } + sp34 = 0; + for (i = 0; i < linkPlayerCount; i ++) + { + _src = (void *)src + i * recordSize; // r7 + if (_src->unk_70 != 0) + { + for (j = 0; j < _src->unk_70; j ++) + { + if (_src->unk_74[j] == 0) + { + sp1c[i][j] = 1; + } + } + } + } + i = 0; + for (j = 0; j < linkPlayerCount; j ++) + { + _src = (void *)src + j * recordSize; + if (sp1c[j][0] == TRUE || sp1c[j][1] == TRUE) + { + sp34 ++; + } + if (sp1c[j][0] == TRUE && sp1c[j][1] == FALSE) + { + sp24[i][0] = j; + sp24[i][1] = 0; + i ++; + } + else if (sp1c[j][0] == FALSE && sp1c[j][1] == TRUE) + { + sp24[i][0] = j; + sp24[i][1] = 0; + i ++; + } + else if (sp1c[j][0] == TRUE && sp1c[j][1] == TRUE) + { + sp24[i][0] = j; + dcMail1 = sub_80E7A9C(&_src->unk_00[0]); + dcMail2 = sub_80E7A9C(&_src->unk_00[1]); + if (!dcMail1 && dcMail2) + { + sp24[i][1] = 1; + } + else if ((dcMail1 && dcMail2) || (!dcMail1 && !dcMail2)) + { + sp24[i][1] = Random2() % 2; + } + else + { + sp24[i][1] = 0; + } + i ++; + } + } + for (i = 0; i < 4; i ++) + { + _src = &src[which * recordSize]; + sp0c[i] = _src; + } + r1_80e7b54 = sub_80E7B54() % 3; + switch (sp34) + { + case 2: + sub_80E7AA4(src, recordSize, sp24, 0, 1); + break; + case 3: + sub_80E7AA4(src, recordSize, sp24, gUnknown_0858CFB8[r1_80e7b54][0], gUnknown_0858CFB8[r1_80e7b54][1]); + break; + case 4: + sub_80E7AA4(src, recordSize, sp24, gUnknown_0858CFBE[r1_80e7b54][0], gUnknown_0858CFBE[r1_80e7b54][1]); + sub_80E7AA4(src, recordSize, sp24, gUnknown_0858CFBE[r1_80e7b54][2], gUnknown_0858CFBE[r1_80e7b54][3]); + break; + } + _src = (void *)src + which * recordSize; + memcpy(&gSaveBlock1Ptr->daycare.mons[0].misc.mail, &_src->unk_00[0], sizeof(struct DayCareMail)); + memcpy(&gSaveBlock1Ptr->daycare.mons[1].misc.mail, &_src->unk_00[1], sizeof(struct DayCareMail)); + SeedRng(oldSeed); +} +#else +NAKED +static void ReceiveDaycareMailData(struct RecordMixingDayCareMail *src, size_t recordSize, u8 which, TVShow *shows) +{ + asm_unified("\tpush {r4-r7,lr}\n" + "\tmov r7, r10\n" + "\tmov r6, r9\n" + "\tmov r5, r8\n" + "\tpush {r5-r7}\n" + "\tsub sp, 0x58\n" + "\tstr r0, [sp, 0x2C]\n" + "\tstr r1, [sp, 0x30]\n" + "\tlsls r2, 24\n" + "\tlsrs r2, 24\n" + "\tmov r9, r2\n" + "\tbl Random2\n" + "\tlsls r0, 16\n" + "\tlsrs r0, 16\n" + "\tstr r0, [sp, 0x38]\n" + "\tldr r0, =gLinkPlayers\n" + "\tldrh r0, [r0, 0x4]\n" + "\tbl SeedRng2\n" + "\tbl GetLinkPlayerCount\n" + "\tlsls r0, 24\n" + "\tlsrs r4, r0, 24\n" + "\tmovs r0, 0\n" + "\tmov r8, r0\n" + "\tmov r1, sp\n" + "\tadds r1, 0x1C\n" + "\tstr r1, [sp, 0x4C]\n" + "\tmov r2, sp\n" + "\tadds r2, 0x1D\n" + "\tstr r2, [sp, 0x50]\n" + "\tmov r3, sp\n" + "\tadds r3, 0xC\n" + "\tstr r3, [sp, 0x48]\n" + "\tmovs r7, 0xFF\n" + "\tadd r3, sp, 0x8\n" + "\tmovs r2, 0\n" + "\tadds r6, r1, 0\n" + "\tldr r5, [sp, 0x50]\n" + "_080E7BB0:\n" + "\tmov r1, sp\n" + "\tadd r1, r8\n" + "\tadds r1, 0x4\n" + "\tldrb r0, [r1]\n" + "\torrs r0, r7\n" + "\tstrb r0, [r1]\n" + "\tmov r1, r8\n" + "\tadds r0, r3, r1\n" + "\tstrb r2, [r0]\n" + "\tlsls r1, 1\n" + "\tadds r0, r6, r1\n" + "\tstrb r2, [r0]\n" + "\tadds r1, r5, r1\n" + "\tstrb r2, [r1]\n" + "\tmov r0, r8\n" + "\tadds r0, 0x1\n" + "\tlsls r0, 16\n" + "\tlsrs r0, 16\n" + "\tmov r8, r0\n" + "\tcmp r0, 0x3\n" + "\tbls _080E7BB0\n" + "\tbl Link_AnyPartnersPlayingRubyOrSapphire\n" + "\tstr r0, [sp, 0x3C]\n" + "\tmovs r2, 0\n" + "\tmov r8, r2\n" + "\tlsls r4, 16\n" + "\tstr r4, [sp, 0x54]\n" + "\tldr r0, [sp, 0x30]\n" + "\tmov r3, r9\n" + "\tmuls r3, r0\n" + "\tstr r3, [sp, 0x44]\n" + "\tb _080E7D04\n" + "\t.pool\n" + "_080E7BF8:\n" + "\tldr r1, [sp, 0x30]\n" + "\tmov r0, r8\n" + "\tmuls r0, r1\n" + "\tldr r2, [sp, 0x2C]\n" + "\tadds r7, r2, r0\n" + "\tldr r1, =gLinkPlayers\n" + "\tmov r3, r8\n" + "\tlsls r0, r3, 3\n" + "\tsubs r0, r3\n" + "\tlsls r0, 2\n" + "\tadds r0, r1\n" + "\tldrh r1, [r0, 0x1A]\n" + "\tmov r9, r1\n" + "\tldrb r0, [r0]\n" + "\tstr r0, [sp, 0x40]\n" + "\tmovs r6, 0\n" + "\tldr r0, [r7, 0x70]\n" + "\tcmp r6, r0\n" + "\tbcs _080E7CFA\n" + "\tmovs r2, 0x10\n" + "\tnegs r2, r2\n" + "\tmov r10, r2\n" + "_080E7C24:\n" + "\tlsls r0, r6, 3\n" + "\tsubs r0, r6\n" + "\tlsls r0, 3\n" + "\tadds r5, r7, r0\n" + "\tldrh r0, [r5, 0x20]\n" + "\tcmp r0, 0\n" + "\tbeq _080E7CEE\n" + "\tldr r3, [sp, 0x3C]\n" + "\tcmp r3, 0\n" + "\tbeq _080E7C9A\n" + "\tadds r4, r5, 0\n" + "\tadds r4, 0x24\n" + "\tadds r0, r4, 0\n" + "\tbl StringLength\n" + "\tlsls r0, 16\n" + "\tlsrs r0, 16\n" + "\tcmp r0, 0x5\n" + "\tbhi _080E7C54\n" + "\tmovs r4, 0x1\n" + "\tb _080E7C5C\n" + "\t.pool\n" + "_080E7C54:\n" + "\tadds r0, r4, 0\n" + "\tbl StripExtCtrlCodes\n" + "\tmov r4, r9\n" + "_080E7C5C:\n" + "\tldrh r1, [r5, 0x2C]\n" + "\tldr r0, =0x000015fc\n" + "\tcmp r1, r0\n" + "\tbne _080E7C74\n" + "\tadds r0, r5, 0\n" + "\tadds r0, 0x2C\n" + "\tbl StripExtCtrlCodes\n" + "\tmovs r1, 0x1\n" + "\tb _080E7C76\n" + "\t.pool\n" + "_080E7C74:\n" + "\tmov r1, r9\n" + "_080E7C76:\n" + "\tldr r0, [sp, 0x40]\n" + "\tsubs r0, 0x1\n" + "\tcmp r0, 0x1\n" + "\tbhi _080E7CEE\n" + "\tadds r2, r5, 0\n" + "\tadds r2, 0x37\n" + "\tmovs r0, 0xF\n" + "\tands r4, r0\n" + "\tldrb r0, [r2]\n" + "\tmov r3, r10\n" + "\tands r0, r3\n" + "\torrs r0, r4\n" + "\tlsls r1, 4\n" + "\tmovs r3, 0xF\n" + "\tands r0, r3\n" + "\torrs r0, r1\n" + "\tstrb r0, [r2]\n" + "\tb _080E7CEE\n" + "_080E7C9A:\n" + "\tmov r0, r9\n" + "\tcmp r0, 0x1\n" + "\tbne _080E7CEE\n" + "\tadds r0, r5, 0\n" + "\tadds r0, 0x24\n" + "\tbl IsStringJapanese\n" + "\tcmp r0, 0\n" + "\tbeq _080E7CBA\n" + "\tadds r0, r5, 0\n" + "\tadds r0, 0x37\n" + "\tldrb r1, [r0]\n" + "\tmov r2, r10\n" + "\tands r1, r2\n" + "\tmovs r2, 0x1\n" + "\tb _080E7CC6\n" + "_080E7CBA:\n" + "\tadds r0, r5, 0\n" + "\tadds r0, 0x37\n" + "\tldrb r1, [r0]\n" + "\tmov r3, r10\n" + "\tands r1, r3\n" + "\tmovs r2, 0x2\n" + "_080E7CC6:\n" + "\torrs r1, r2\n" + "\tstrb r1, [r0]\n" + "\tadds r4, r0, 0\n" + "\tadds r0, r5, 0\n" + "\tadds r0, 0x2C\n" + "\tbl IsStringJapanese\n" + "\tcmp r0, 0\n" + "\tbeq _080E7CE2\n" + "\tldrb r0, [r4]\n" + "\tmovs r1, 0xF\n" + "\tands r1, r0\n" + "\tmovs r0, 0x10\n" + "\tb _080E7CEA\n" + "_080E7CE2:\n" + "\tldrb r0, [r4]\n" + "\tmovs r1, 0xF\n" + "\tands r1, r0\n" + "\tmovs r0, 0x20\n" + "_080E7CEA:\n" + "\torrs r1, r0\n" + "\tstrb r1, [r4]\n" + "_080E7CEE:\n" + "\tadds r0, r6, 0x1\n" + "\tlsls r0, 16\n" + "\tlsrs r6, r0, 16\n" + "\tldr r0, [r7, 0x70]\n" + "\tcmp r6, r0\n" + "\tbcc _080E7C24\n" + "_080E7CFA:\n" + "\tmov r0, r8\n" + "\tadds r0, 0x1\n" + "\tlsls r0, 16\n" + "\tlsrs r0, 16\n" + "\tmov r8, r0\n" + "_080E7D04:\n" + "\tbl GetLinkPlayerCount\n" + "\tlsls r0, 24\n" + "\tlsrs r0, 24\n" + "\tcmp r8, r0\n" + "\tbcs _080E7D12\n" + "\tb _080E7BF8\n" + "_080E7D12:\n" + "\tmovs r0, 0\n" + "\tstr r0, [sp, 0x34]\n" + "\tmov r8, r0\n" + "\tldr r1, [sp, 0x54]\n" + "\tlsrs r0, r1, 16\n" + "\tldr r2, [sp, 0x34]\n" + "\tcmp r2, r0\n" + "\tbcs _080E7D70\n" + "\tadds r5, r0, 0\n" + "_080E7D24:\n" + "\tldr r3, [sp, 0x30]\n" + "\tmov r0, r8\n" + "\tmuls r0, r3\n" + "\tldr r1, [sp, 0x2C]\n" + "\tadds r7, r1, r0\n" + "\tldr r0, [r7, 0x70]\n" + "\tcmp r0, 0\n" + "\tbeq _080E7D62\n" + "\tmovs r6, 0\n" + "\tcmp r6, r0\n" + "\tbcs _080E7D62\n" + "\tadds r3, r7, 0\n" + "\tadds r3, 0x74\n" + "\tldr r2, [sp, 0x4C]\n" + "\tmov r0, r8\n" + "\tlsls r1, r0, 1\n" + "\tmovs r4, 0x1\n" + "_080E7D46:\n" + "\tlsls r0, r6, 1\n" + "\tadds r0, r3, r0\n" + "\tldrh r0, [r0]\n" + "\tcmp r0, 0\n" + "\tbne _080E7D56\n" + "\tadds r0, r6, r1\n" + "\tadds r0, r2, r0\n" + "\tstrb r4, [r0]\n" + "_080E7D56:\n" + "\tadds r0, r6, 0x1\n" + "\tlsls r0, 16\n" + "\tlsrs r6, r0, 16\n" + "\tldr r0, [r7, 0x70]\n" + "\tcmp r6, r0\n" + "\tbcc _080E7D46\n" + "_080E7D62:\n" + "\tmov r0, r8\n" + "\tadds r0, 0x1\n" + "\tlsls r0, 16\n" + "\tlsrs r0, 16\n" + "\tmov r8, r0\n" + "\tcmp r8, r5\n" + "\tbcc _080E7D24\n" + "_080E7D70:\n" + "\tmovs r6, 0\n" + "\tmov r8, r6\n" + "\tldr r1, [sp, 0x54]\n" + "\tcmp r1, 0\n" + "\tbeq _080E7E64\n" + "\tadd r2, sp, 0x24\n" + "\tmov r10, r2\n" + "\tmovs r3, 0x25\n" + "\tadd r3, sp\n" + "\tmov r9, r3\n" + "_080E7D84:\n" + "\tldr r1, [sp, 0x30]\n" + "\tmov r0, r8\n" + "\tmuls r0, r1\n" + "\tldr r2, [sp, 0x2C]\n" + "\tadds r7, r2, r0\n" + "\tmov r3, r8\n" + "\tlsls r1, r3, 1\n" + "\tldr r2, [sp, 0x4C]\n" + "\tadds r0, r2, r1\n" + "\tldrb r0, [r0]\n" + "\tcmp r0, 0x1\n" + "\tbeq _080E7DA6\n" + "\tldr r3, [sp, 0x50]\n" + "\tadds r0, r3, r1\n" + "\tldrb r0, [r0]\n" + "\tcmp r0, 0x1\n" + "\tbne _080E7DB0\n" + "_080E7DA6:\n" + "\tldr r0, [sp, 0x34]\n" + "\tadds r0, 0x1\n" + "\tlsls r0, 24\n" + "\tlsrs r0, 24\n" + "\tstr r0, [sp, 0x34]\n" + "_080E7DB0:\n" + "\tldr r2, [sp, 0x4C]\n" + "\tadds r0, r2, r1\n" + "\tldrb r0, [r0]\n" + "\tcmp r0, 0x1\n" + "\tbne _080E7DD4\n" + "\tldr r3, [sp, 0x50]\n" + "\tadds r0, r3, r1\n" + "\tldrb r2, [r0]\n" + "\tcmp r2, 0\n" + "\tbne _080E7DD4\n" + "_080E7DC4:\n" + "\tlsls r1, r6, 1\n" + "\tmov r3, r10\n" + "\tadds r0, r3, r1\n" + "\tmov r3, r8\n" + "\tstrb r3, [r0]\n" + "\tadd r1, r9\n" + "\tstrb r2, [r1]\n" + "\tb _080E7E4E\n" + "_080E7DD4:\n" + "\tldr r2, [sp, 0x4C]\n" + "\tadds r0, r2, r1\n" + "\tldrb r0, [r0]\n" + "\tcmp r0, 0\n" + "\tbne _080E7DE8\n" + "\tldr r3, [sp, 0x50]\n" + "\tadds r0, r3, r1\n" + "\tldrb r2, [r0]\n" + "\tcmp r2, 0x1\n" + "\tbeq _080E7DC4\n" + "_080E7DE8:\n" + "\tldr r2, [sp, 0x4C]\n" + "\tadds r0, r2, r1\n" + "\tldrb r0, [r0]\n" + "\tcmp r0, 0x1\n" + "\tbne _080E7E54\n" + "\tldr r3, [sp, 0x50]\n" + "\tadds r0, r3, r1\n" + "\tldrb r0, [r0]\n" + "\tcmp r0, 0x1\n" + "\tbne _080E7E54\n" + "\tlsls r5, r6, 1\n" + "\tmov r1, r10\n" + "\tadds r0, r1, r5\n" + "\tmov r2, r8\n" + "\tstrb r2, [r0]\n" + "\tadds r0, r7, 0\n" + "\tbl sub_80E7A9C\n" + "\tadds r4, r0, 0\n" + "\tlsls r4, 24\n" + "\tlsrs r4, 24\n" + "\tadds r0, r7, 0\n" + "\tadds r0, 0x38\n" + "\tbl sub_80E7A9C\n" + "\tlsls r0, 24\n" + "\tlsrs r1, r0, 24\n" + "\tcmp r4, 0\n" + "\tbne _080E7E30\n" + "\tcmp r1, 0\n" + "\tbeq _080E7E34\n" + "\tmov r3, r9\n" + "\tadds r1, r3, r5\n" + "\tmovs r0, 0x1\n" + "\tstrb r0, [r1]\n" + "\tb _080E7E4E\n" + "_080E7E30:\n" + "\tcmp r1, 0\n" + "\tbeq _080E7E48\n" + "_080E7E34:\n" + "\tbl Random2\n" + "\tmov r1, r9\n" + "\tadds r2, r1, r5\n" + "\tlsls r0, 16\n" + "\tlsrs r0, 16\n" + "\tmovs r1, 0x1\n" + "\tands r0, r1\n" + "\tstrb r0, [r2]\n" + "\tb _080E7E4E\n" + "_080E7E48:\n" + "\tmov r2, r9\n" + "\tadds r0, r2, r5\n" + "\tstrb r1, [r0]\n" + "_080E7E4E:\n" + "\tadds r0, r6, 0x1\n" + "\tlsls r0, 16\n" + "\tlsrs r6, r0, 16\n" + "_080E7E54:\n" + "\tmov r0, r8\n" + "\tadds r0, 0x1\n" + "\tlsls r0, 16\n" + "\tlsrs r3, r0, 16\n" + "\tmov r8, r3\n" + "\tldr r1, [sp, 0x54]\n" + "\tcmp r0, r1\n" + "\tbcc _080E7D84\n" + "_080E7E64:\n" + "\tmovs r2, 0\n" + "\tmov r8, r2\n" + "\tldr r3, [sp, 0x44]\n" + "\tlsls r0, r3, 4\n" + "\tsubs r0, r3\n" + "\tlsls r0, 3\n" + "\tldr r1, [sp, 0x2C]\n" + "\tadds r7, r1, r0\n" + "\tldr r1, [sp, 0x48]\n" + "_080E7E76:\n" + "\tmov r2, r8\n" + "\tlsls r0, r2, 2\n" + "\tadds r0, r1, r0\n" + "\tstr r7, [r0]\n" + "\tmov r0, r8\n" + "\tadds r0, 0x1\n" + "\tlsls r0, 16\n" + "\tlsrs r0, 16\n" + "\tmov r8, r0\n" + "\tcmp r0, 0x3\n" + "\tbls _080E7E76\n" + "\tbl sub_80E7B54\n" + "\tlsls r0, 24\n" + "\tlsrs r0, 24\n" + "\tmovs r1, 0x3\n" + "\tbl __umodsi3\n" + "\tlsls r0, 24\n" + "\tlsrs r1, r0, 24\n" + "\tldr r3, [sp, 0x34]\n" + "\tcmp r3, 0x3\n" + "\tbeq _080E7EC8\n" + "\tcmp r3, 0x3\n" + "\tbgt _080E7EAE\n" + "\tcmp r3, 0x2\n" + "\tbeq _080E7EB6\n" + "\tb _080E7F1C\n" + "_080E7EAE:\n" + "\tldr r0, [sp, 0x34]\n" + "\tcmp r0, 0x4\n" + "\tbeq _080E7EE8\n" + "\tb _080E7F1C\n" + "_080E7EB6:\n" + "\tadd r2, sp, 0x24\n" + "\tmovs r0, 0x1\n" + "\tstr r0, [sp]\n" + "\tldr r0, [sp, 0x2C]\n" + "\tldr r1, [sp, 0x30]\n" + "\tmovs r3, 0\n" + "\tbl sub_80E7AA4\n" + "\tb _080E7F1C\n" + "_080E7EC8:\n" + "\tldr r0, =gUnknown_0858CFB8\n" + "\tlsls r1, 1\n" + "\tadds r2, r1, r0\n" + "\tldrb r3, [r2]\n" + "\tadds r0, 0x1\n" + "\tadds r1, r0\n" + "\tldrb r0, [r1]\n" + "\tadd r2, sp, 0x24\n" + "\tstr r0, [sp]\n" + "\tldr r0, [sp, 0x2C]\n" + "\tldr r1, [sp, 0x30]\n" + "\tbl sub_80E7AA4\n" + "\tb _080E7F1C\n" + "\t.pool\n" + "_080E7EE8:\n" + "\tadd r6, sp, 0x24\n" + "\tldr r4, =gUnknown_0858CFBE\n" + "\tlsls r5, r1, 2\n" + "\tadds r0, r5, r4\n" + "\tldrb r3, [r0]\n" + "\tadds r0, r4, 0x1\n" + "\tadds r0, r5, r0\n" + "\tldrb r0, [r0]\n" + "\tstr r0, [sp]\n" + "\tldr r0, [sp, 0x2C]\n" + "\tldr r1, [sp, 0x30]\n" + "\tadds r2, r6, 0\n" + "\tbl sub_80E7AA4\n" + "\tadds r0, r4, 0x2\n" + "\tadds r0, r5, r0\n" + "\tldrb r3, [r0]\n" + "\tadds r4, 0x3\n" + "\tadds r5, r4\n" + "\tldrb r0, [r5]\n" + "\tstr r0, [sp]\n" + "\tldr r0, [sp, 0x2C]\n" + "\tldr r1, [sp, 0x30]\n" + "\tadds r2, r6, 0\n" + "\tbl sub_80E7AA4\n" + "_080E7F1C:\n" + "\tldr r1, [sp, 0x2C]\n" + "\tldr r2, [sp, 0x44]\n" + "\tadds r7, r1, r2\n" + "\tldr r4, =gSaveBlock1Ptr\n" + "\tldr r0, [r4]\n" + "\tmovs r3, 0xC2\n" + "\tlsls r3, 6\n" + "\tadds r0, r3\n" + "\tadds r1, r7, 0\n" + "\tmovs r2, 0x38\n" + "\tbl memcpy\n" + "\tldr r0, [r4]\n" + "\tldr r1, =0x0000310c\n" + "\tadds r0, r1\n" + "\tadds r1, r7, 0\n" + "\tadds r1, 0x38\n" + "\tmovs r2, 0x38\n" + "\tbl memcpy\n" + "\tldr r0, [sp, 0x38]\n" + "\tbl SeedRng\n" + "\tadd sp, 0x58\n" + "\tpop {r3-r5}\n" + "\tmov r8, r3\n" + "\tmov r9, r4\n" + "\tmov r10, r5\n" + "\tpop {r4-r7}\n" + "\tpop {r0}\n" + "\tbx r0\n" + "\t.pool"); +} +#endif // NONMATCHING + +static void sub_80E7F68(u16 *item, u8 which) +{ + if (which != 0 && *item != ITEM_NONE && GetPocketByItemId(*item) == POCKET_KEY_ITEMS) + { + if (!CheckBagHasItem(*item, 1) && !CheckPCHasItem(*item, 1) && AddBagItem(*item, 1)) + { + VarSet(VAR_TEMP_1, *item); + StringCopy(gStringVar1, gLinkPlayers[0].name); + if (*item == ITEM_EON_TICKET) + FlagSet(FLAG_SYS_HAS_EON_TICKET); + } + else + { + VarSet(VAR_TEMP_1, ITEM_NONE); + } + } +} + +static void sub_80E7FF8(u8 taskId) +{ + struct Task *task = &gTasks[taskId]; + + switch (task->data[0]) + { + case 0: + task->data[0]++; + break; + case 1: + if (Link_AnyPartnersPlayingRubyOrSapphire()) + task->data[0]++; + else + task->data[0] = 6; + break; + case 2: + sub_8076D5C(); + sub_8153430(); + task->data[0] ++; + break; + case 3: + if (sub_8153474()) + { + sav2_gender2_inplace_and_xFE(); + task->data[0] = 4; + task->data[1] = 0; + } + break; + case 4: + if (++task->data[1] > 10) + { + sub_800AC34(); + task->data[0] ++; + } + break; + case 5: + if (gReceivedRemoteLinkPlayers == 0) + DestroyTask(taskId); + break; + case 6: + if (!sub_801048C(0)) + { + CreateTask(sub_8153688, 5); + task->data[0] ++; + } + break; + case 7: + if (!FuncIsActiveTask(sub_8153688)) + { + if (gWirelessCommType) + { + sub_801048C(1); + task->data[0] = 8; + } + else + { + task->data[0] = 4; + } + } + break; + case 8: + sub_800ADF8(); + task->data[0] ++; + break; + case 9: + if (sub_800A520()) + DestroyTask(taskId); + break; + } +} + +// New Emerald functions + +static void sub_80E8110(struct UnkRecordMixingStruct *dst, struct UnkRecordMixingStruct *src) +{ + s32 i, id; + s32 var_2C, var_28, var_24, r8; + + dst[0].field_38[0] = 0xFF; + dst[1].field_38[0] = 0xFF; + + dst[0] = src[0]; + + var_28 = 0; + var_24 = 0; + var_2C = 0; + r8 = 0; + for (i = 0; i < 2; i++) + { + id = ((i + gSaveBlock2Ptr->field_B2_1) % 3) + 1; + if (src[id].field_38[0] != 0xFF) + { + if (ReadUnalignedWord(src[id].playerId) != ReadUnalignedWord(gSaveBlock2Ptr->playerTrainerId)) + { + r8++; + var_2C = id; + } + if (ReadUnalignedWord(src[id].playerId) == ReadUnalignedWord(gSaveBlock2Ptr->playerTrainerId)) + { + var_24++; + var_28 = id; + } + } + } + + if (r8 == 0 && var_24 != 0) + { + r8 = var_24; + var_2C = var_28; + } + + switch (r8) + { + case 1: + dst[1] = src[var_2C]; + break; + case 2: + if (Random2() > 0x3333) + { + dst[1] = src[gSaveBlock2Ptr->field_B2_1 + 1]; + } + else + { + dst[1] = src[((gSaveBlock2Ptr->field_B2_1 + 1) % 3 + 1)]; + } + break; + } +} + +void sub_80E8260(struct UnkRecordMixingStruct2 *dst) +{ + s32 i, j; + + for (i = 0; i < 9; i++) + { + for (j = 0; j < 2; j++) + { + CopyUnalignedWord(dst->field_0[i][j].playerId, gSaveBlock2Ptr->playerTrainerId); + dst->field_0[i][j].language = GAME_LANGUAGE; + StringCopy(dst->field_0[i][j].playerName, gSaveBlock2Ptr->playerName); + } + } + + for (j = 0; j < 2; j++) + { + dst->field_120[j].language = GAME_LANGUAGE; + CopyUnalignedWord(dst->field_120[j].playerId1, gSaveBlock2Ptr->playerTrainerId); + CopyUnalignedWord(dst->field_120[j].playerId2, gSaveBlock2Ptr->field_EF1[j]); + StringCopy(dst->field_120[j].playerName1, gSaveBlock2Ptr->playerName); + StringCopy(dst->field_120[j].playerName2, gSaveBlock2Ptr->field_EE1[j]); + } + + for (i = 0; i < 2; i++) + { + dst->field_0[0][i].field_4 = gSaveBlock2Ptr->field_CF0[i]; + dst->field_0[1][i].field_4 = gSaveBlock2Ptr->field_CF4[i]; + dst->field_0[2][i].field_4 = gSaveBlock2Ptr->field_CF8[i]; + dst->field_0[3][i].field_4 = gSaveBlock2Ptr->field_D14[i]; + dst->field_0[4][i].field_4 = gSaveBlock2Ptr->field_DD0[i]; + dst->field_0[5][i].field_4 = gSaveBlock2Ptr->field_DDE[i]; + dst->field_0[6][i].field_4 = gSaveBlock2Ptr->field_DEA[i]; + dst->field_0[7][i].field_4 = gSaveBlock2Ptr->field_E08[i]; + dst->field_0[8][i].field_4 = gSaveBlock2Ptr->field_E1E[i]; + + dst->field_120[i].field_8 = gSaveBlock2Ptr->field_CFC[i]; + } +} + +static bool32 sub_80E841C(struct UnkRecordMixingStruct *arg0, struct UnkRecordMixingStruct *arg1) +{ + s32 i; + + for (i = 0; i < 4; i++) + { + if (ReadUnalignedWord(arg0->playerId) == ReadUnalignedWord(arg1[i].playerId) + && arg0->field_0[2] == arg1[i].field_0[2]) + { + return TRUE; + } + } + + return FALSE; +} + +static void sub_80E8468(struct UnkRecordMixingStruct *arg0, size_t arg1, u32 arg2) +{ + s32 i, r7, r8; + struct UnkRecordMixingStruct *structPtr; + u32 mixIndices[4]; + u32 structId; + + ShufflePlayerIndices(mixIndices); + structPtr = (void*)(arg0) + (arg1 * mixIndices[arg2]); + r7 = 0; + r8 = 0; + for (i = 0; i < 2; i++) + { + if (structPtr[i].field_38[0] != 0xFF && !sub_80E841C(&structPtr[i], gSaveBlock2Ptr->field_DC)) + { + r7++; + r8 = i; + } + } + + switch (r7) + { + case 1: + structId = gSaveBlock2Ptr->field_B2_1 + 1; + gSaveBlock2Ptr->field_DC[structId] = structPtr[r8]; + gSaveBlock2Ptr->field_B2_1 = (gSaveBlock2Ptr->field_B2_1 + 1) % 3; + break; + case 2: + for (i = 0; i < 2; i++) + { + structId = ((i ^ 1) + gSaveBlock2Ptr->field_B2_1) % 3 + 1; + gSaveBlock2Ptr->field_DC[structId] = structPtr[i]; + } + gSaveBlock2Ptr->field_B2_1 = (gSaveBlock2Ptr->field_B2_1 + 2) % 3; + break; + } +} + +NAKED +static void sub_80E8578(struct UnknownRecMixingStruct3 *arg0, struct UnkRecordMixingStruct2 *arg1, size_t arg2, u32 arg3, u32 arg4) +{ + asm_unified(" push {r4-r7,lr}\n\ + mov r7, r10\n\ + mov r6, r9\n\ + mov r5, r8\n\ + push {r5-r7}\n\ + sub sp, 0x54\n\ + str r0, [sp]\n\ + ldr r0, [sp, 0x74]\n\ + movs r4, 0\n\ + mov r8, r4\n\ + movs r5, 0\n\ + str r5, [sp, 0x4]\n\ + ldr r4, =gUnknown_03001168\n\ + b _080E85A0\n\ + .pool\n\ +_080E8598:\n\ + adds r1, r2\n\ + ldr r6, [sp, 0x4]\n\ + adds r6, 0x1\n\ + str r6, [sp, 0x4]\n\ +_080E85A0:\n\ + ldr r5, [sp, 0x4]\n\ + cmp r5, r0\n\ + bge _080E85B6\n\ + cmp r5, r3\n\ + beq _080E85B0\n\ + stm r4!, {r1}\n\ + movs r6, 0x1\n\ + add r8, r6\n\ +_080E85B0:\n\ + mov r5, r8\n\ + cmp r5, 0x3\n\ + bne _080E8598\n\ +_080E85B6:\n\ + movs r6, 0\n\ + str r6, [sp, 0x4]\n\ + subs r0, 0x1\n\ + str r0, [sp, 0x24]\n\ +_080E85BE:\n\ + movs r0, 0\n\ + str r0, [sp, 0x8]\n\ + ldr r1, [sp, 0x4]\n\ + adds r1, 0x1\n\ + str r1, [sp, 0x28]\n\ + ldr r2, [sp, 0x4]\n\ + lsls r2, 1\n\ + str r2, [sp, 0x34]\n\ + ldr r3, [sp, 0x4]\n\ + adds r3, r2, r3\n\ + str r3, [sp, 0x10]\n\ + movs r4, 0\n\ + str r4, [sp, 0x44]\n\ + movs r5, 0\n\ + str r5, [sp, 0x48]\n\ +_080E85DC:\n\ + movs r6, 0\n\ + mov r8, r6\n\ + ldr r0, =gSaveBlock2Ptr\n\ + ldr r1, [r0]\n\ + ldr r2, [sp, 0x10]\n\ + lsls r0, r2, 5\n\ + ldr r3, [sp, 0x48]\n\ + adds r0, r3, r0\n\ + adds r3, r0, r1\n\ + lsls r0, r2, 6\n\ + ldr r4, [sp, 0x44]\n\ + adds r0, r4, r0\n\ + ldr r5, [sp]\n\ + adds r2, r0, r5\n\ +_080E85F8:\n\ + adds r0, r2, 0\n\ + movs r6, 0x87\n\ + lsls r6, 2\n\ + adds r1, r3, r6\n\ + ldm r1!, {r4-r6}\n\ + stm r0!, {r4-r6}\n\ + ldr r1, [r1]\n\ + str r1, [r0]\n\ + adds r3, 0x10\n\ + adds r2, 0x10\n\ + movs r0, 0x1\n\ + add r8, r0\n\ + mov r1, r8\n\ + cmp r1, 0x2\n\ + ble _080E85F8\n\ + movs r2, 0\n\ + mov r8, r2\n\ + ldr r3, [sp, 0x24]\n\ + cmp r8, r3\n\ + bge _080E86DC\n\ + ldr r4, [sp, 0x4]\n\ + lsls r4, 5\n\ + mov r9, r4\n\ + ldr r5, [sp, 0x8]\n\ + lsls r7, r5, 4\n\ + ldr r6, [sp, 0x34]\n\ + ldr r1, [sp, 0x4]\n\ + adds r0, r6, r1\n\ + lsls r0, 6\n\ + str r0, [sp, 0x14]\n\ + ldr r2, [sp]\n\ + adds r0, r2, r0\n\ + ldr r3, [sp, 0x44]\n\ + str r3, [sp, 0x18]\n\ + adds r0, r3\n\ + str r0, [sp, 0x1C]\n\ + ldr r4, [sp, 0x14]\n\ + adds r0, r3, r4\n\ + adds r0, r2\n\ + adds r0, 0x30\n\ + mov r10, r0\n\ +_080E864A:\n\ + movs r5, 0\n\ + str r5, [sp, 0xC]\n\ + movs r3, 0\n\ + mov r6, r8\n\ + lsls r6, 2\n\ + str r6, [sp, 0x38]\n\ + ldr r1, [sp, 0x18]\n\ + ldr r2, [sp, 0x14]\n\ + adds r0, r1, r2\n\ + ldr r4, [sp]\n\ + adds r5, r0, r4\n\ + ldr r0, =gUnknown_03001168\n\ + adds r0, r6, r0\n\ + str r0, [sp, 0x50]\n\ +_080E8666:\n\ + lsls r0, r3, 4\n\ + ldr r6, [sp, 0x1C]\n\ + adds r0, r6, r0\n\ + str r3, [sp, 0x4C]\n\ + bl ReadUnalignedWord\n\ + adds r4, r0, 0\n\ + ldr r1, [sp, 0x50]\n\ + ldr r0, [r1]\n\ + add r0, r9\n\ + adds r0, r7\n\ + bl ReadUnalignedWord\n\ + ldr r3, [sp, 0x4C]\n\ + cmp r4, r0\n\ + bne _080E86A8\n\ + ldr r2, [sp, 0xC]\n\ + adds r2, 0x1\n\ + str r2, [sp, 0xC]\n\ + ldr r4, [sp, 0x50]\n\ + ldr r0, [r4]\n\ + mov r6, r9\n\ + adds r1, r7, r6\n\ + adds r1, r0, r1\n\ + ldrh r0, [r5, 0x4]\n\ + ldrh r2, [r1, 0x4]\n\ + cmp r0, r2\n\ + bcs _080E86A8\n\ + adds r0, r5, 0\n\ + ldm r1!, {r2,r4,r6}\n\ + stm r0!, {r2,r4,r6}\n\ + ldr r1, [r1]\n\ + str r1, [r0]\n\ +_080E86A8:\n\ + adds r5, 0x10\n\ + adds r3, 0x1\n\ + cmp r3, 0x2\n\ + ble _080E8666\n\ + ldr r3, [sp, 0xC]\n\ + cmp r3, 0\n\ + bne _080E86CE\n\ + ldr r0, =gUnknown_03001168\n\ + ldr r4, [sp, 0x38]\n\ + adds r0, r4, r0\n\ + ldr r0, [r0]\n\ + mov r5, r9\n\ + adds r2, r7, r5\n\ + mov r1, r10\n\ + adds r0, r2\n\ + ldm r0!, {r2,r3,r6}\n\ + stm r1!, {r2,r3,r6}\n\ + ldr r0, [r0]\n\ + str r0, [r1]\n\ +_080E86CE:\n\ + movs r4, 0x10\n\ + add r10, r4\n\ + movs r5, 0x1\n\ + add r8, r5\n\ + ldr r6, [sp, 0x24]\n\ + cmp r8, r6\n\ + blt _080E864A\n\ +_080E86DC:\n\ + ldr r0, [sp, 0x44]\n\ + adds r0, 0x60\n\ + str r0, [sp, 0x44]\n\ + ldr r1, [sp, 0x48]\n\ + adds r1, 0x30\n\ + str r1, [sp, 0x48]\n\ + ldr r2, [sp, 0x8]\n\ + adds r2, 0x1\n\ + str r2, [sp, 0x8]\n\ + cmp r2, 0x1\n\ + bgt _080E86F4\n\ + b _080E85DC\n\ +_080E86F4:\n\ + ldr r3, [sp, 0x28]\n\ + str r3, [sp, 0x4]\n\ + cmp r3, 0x8\n\ + bgt _080E86FE\n\ + b _080E85BE\n\ +_080E86FE:\n\ + movs r4, 0\n\ + str r4, [sp, 0x8]\n\ +_080E8702:\n\ + ldr r5, [sp, 0x8]\n\ + adds r5, 0x1\n\ + str r5, [sp, 0x2C]\n\ + ldr r0, =gSaveBlock2Ptr\n\ + ldr r1, [r0]\n\ + movs r0, 0x54\n\ + ldr r6, [sp, 0x8]\n\ + muls r0, r6\n\ + adds r3, r0, r1\n\ + movs r0, 0xA8\n\ + muls r0, r6\n\ + ldr r1, [sp]\n\ + adds r2, r0, r1\n\ + movs r4, 0x2\n\ + mov r8, r4\n\ +_080E8720:\n\ + movs r5, 0xD8\n\ + lsls r5, 3\n\ + adds r0, r2, r5\n\ + ldr r6, =0x0000057c\n\ + adds r1, r3, r6\n\ + ldm r1!, {r4-r6}\n\ + stm r0!, {r4-r6}\n\ + ldm r1!, {r4-r6}\n\ + stm r0!, {r4-r6}\n\ + ldr r1, [r1]\n\ + str r1, [r0]\n\ + adds r3, 0x1C\n\ + adds r2, 0x1C\n\ + movs r0, 0x1\n\ + negs r0, r0\n\ + add r8, r0\n\ + mov r1, r8\n\ + cmp r1, 0\n\ + bge _080E8720\n\ + movs r2, 0\n\ + mov r8, r2\n\ + ldr r3, [sp, 0x24]\n\ + cmp r8, r3\n\ + blt _080E8752\n\ + b _080E885A\n\ +_080E8752:\n\ + ldr r4, [sp, 0x8]\n\ + lsls r1, r4, 3\n\ + movs r0, 0xA8\n\ + adds r5, r4, 0\n\ + muls r5, r0\n\ + str r5, [sp, 0x20]\n\ + str r5, [sp, 0x3C]\n\ + subs r1, r4\n\ + lsls r1, 2\n\ + mov r10, r1\n\ +_080E8766:\n\ + movs r6, 0\n\ + str r6, [sp, 0xC]\n\ + mov r0, r8\n\ + lsls r0, 2\n\ + str r0, [sp, 0x38]\n\ + mov r1, r8\n\ + adds r1, 0x1\n\ + str r1, [sp, 0x30]\n\ + ldr r0, =gUnknown_03001168\n\ + ldr r2, [sp, 0x38]\n\ + adds r2, r0\n\ + mov r9, r2\n\ + ldr r3, [sp]\n\ + movs r4, 0xD8\n\ + lsls r4, 3\n\ + adds r0, r3, r4\n\ + ldr r5, [sp, 0x3C]\n\ + adds r7, r5, r0\n\ + str r6, [sp, 0x40]\n\ + movs r3, 0x2\n\ +_080E878E:\n\ + ldr r1, [sp, 0x20]\n\ + movs r2, 0xD8\n\ + lsls r2, 3\n\ + adds r0, r1, r2\n\ + ldr r4, [sp]\n\ + adds r0, r4, r0\n\ + ldr r6, [sp, 0x40]\n\ + adds r5, r0, r6\n\ + adds r0, r5, 0\n\ + str r3, [sp, 0x4C]\n\ + bl ReadUnalignedWord\n\ + adds r4, r0, 0\n\ + movs r6, 0x90\n\ + lsls r6, 1\n\ + add r6, r10\n\ + mov r1, r9\n\ + ldr r0, [r1]\n\ + adds r0, r6\n\ + bl ReadUnalignedWord\n\ + ldr r3, [sp, 0x4C]\n\ + cmp r4, r0\n\ + bne _080E8808\n\ + adds r0, r5, 0x4\n\ + bl ReadUnalignedWord\n\ + adds r4, r0, 0\n\ + mov r2, r9\n\ + ldr r0, [r2]\n\ + adds r0, r6\n\ + adds r0, 0x4\n\ + bl ReadUnalignedWord\n\ + ldr r3, [sp, 0x4C]\n\ + cmp r4, r0\n\ + bne _080E8808\n\ + ldr r4, [sp, 0xC]\n\ + adds r4, 0x1\n\ + str r4, [sp, 0xC]\n\ + mov r5, r9\n\ + ldr r0, [r5]\n\ + mov r6, r10\n\ + adds r2, r0, r6\n\ + movs r0, 0x94\n\ + lsls r0, 1\n\ + adds r1, r2, r0\n\ + ldrh r0, [r7, 0x8]\n\ + ldrh r1, [r1]\n\ + cmp r0, r1\n\ + bcs _080E8808\n\ + adds r0, r7, 0\n\ + movs r4, 0x90\n\ + lsls r4, 1\n\ + adds r1, r2, r4\n\ + ldm r1!, {r2,r5,r6}\n\ + stm r0!, {r2,r5,r6}\n\ + ldm r1!, {r4-r6}\n\ + stm r0!, {r4-r6}\n\ + ldr r1, [r1]\n\ + str r1, [r0]\n\ +_080E8808:\n\ + adds r7, 0x1C\n\ + ldr r0, [sp, 0x40]\n\ + adds r0, 0x1C\n\ + str r0, [sp, 0x40]\n\ + subs r3, 0x1\n\ + cmp r3, 0\n\ + bge _080E878E\n\ + ldr r1, [sp, 0xC]\n\ + cmp r1, 0\n\ + bne _080E8850\n\ + mov r0, r8\n\ + adds r0, 0x3\n\ + lsls r1, r0, 3\n\ + subs r1, r0\n\ + lsls r1, 2\n\ + ldr r2, [sp, 0x20]\n\ + adds r1, r2\n\ + ldr r3, [sp]\n\ + adds r1, r3, r1\n\ + ldr r0, =gUnknown_03001168\n\ + ldr r4, [sp, 0x38]\n\ + adds r0, r4, r0\n\ + ldr r0, [r0]\n\ + add r0, r10\n\ + movs r5, 0xD8\n\ + lsls r5, 3\n\ + adds r1, r5\n\ + movs r6, 0x90\n\ + lsls r6, 1\n\ + adds r0, r6\n\ + ldm r0!, {r2-r4}\n\ + stm r1!, {r2-r4}\n\ + ldm r0!, {r2,r5,r6}\n\ + stm r1!, {r2,r5,r6}\n\ + ldr r0, [r0]\n\ + str r0, [r1]\n\ +_080E8850:\n\ + ldr r3, [sp, 0x30]\n\ + mov r8, r3\n\ + ldr r4, [sp, 0x24]\n\ + cmp r8, r4\n\ + blt _080E8766\n\ +_080E885A:\n\ + ldr r5, [sp, 0x2C]\n\ + str r5, [sp, 0x8]\n\ + cmp r5, 0x1\n\ + bgt _080E8864\n\ + b _080E8702\n\ +_080E8864:\n\ + add sp, 0x54\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\ + "); +} + +static void sub_80E8880(struct UnknownRecMixingStruct *arg0, struct UnknownRecMixingStruct *arg1) +{ + s32 i, j; + + for (i = 0; i < 3; i++) + { + s32 r2 = 0; + s32 r4 = -1; + for (j = 0; j < 6; j++) + { + if (arg1[j].field_4 > r2) + { + r4 = j; + r2 = arg1[j].field_4; + } + } + + if (r4 >= 0) + { + arg0[i] = arg1[r4]; + arg1[r4].field_4 = 0; + } + } +} + +static void sub_80E88CC(struct UnknownRecMixingStruct2 *arg0, struct UnknownRecMixingStruct2 *arg1) +{ + s32 i, j; + + for (i = 0; i < 3; i++) + { + s32 r2 = 0; + s32 r4 = -1; + for (j = 0; j < 6; j++) + { + if (arg1[j].field_8 > r2) + { + r4 = j; + r2 = arg1[j].field_8; + } + } + + if (r4 >= 0) + { + arg0[i] = arg1[r4]; + arg1[r4].field_8 = 0; + } + } +} + +NAKED +static void sub_80E8924(struct UnknownRecMixingStruct3 *arg0) +{ + asm_unified("push {r4-r7,lr}\n\ + mov r7, r10\n\ + mov r6, r9\n\ + mov r5, r8\n\ + push {r5-r7}\n\ + mov r9, r0\n\ + movs r0, 0\n\ + ldr r1, =gSaveBlock2Ptr\n\ + mov r10, r1\n\ +_080E8936:\n\ + lsls r1, r0, 1\n\ + adds r2, r0, 0x1\n\ + mov r8, r2\n\ + adds r1, r0\n\ + lsls r0, r1, 5\n\ + movs r2, 0x87\n\ + lsls r2, 2\n\ + adds r7, r0, r2\n\ + lsls r1, 6\n\ + mov r0, r9\n\ + adds r4, r0, r1\n\ + movs r6, 0\n\ + movs r5, 0x1\n\ +_080E8950:\n\ + mov r1, r10\n\ + ldr r0, [r1]\n\ + adds r0, r7\n\ + adds r0, r6\n\ + adds r1, r4, 0\n\ + bl sub_80E8880\n\ + adds r4, 0x60\n\ + adds r6, 0x30\n\ + subs r5, 0x1\n\ + cmp r5, 0\n\ + bge _080E8950\n\ + mov r0, r8\n\ + cmp r0, 0x8\n\ + ble _080E8936\n\ + movs r5, 0\n\ + ldr r4, =gSaveBlock2Ptr\n\ +_080E8972:\n\ + movs r0, 0x54\n\ + adds r1, r5, 0\n\ + muls r1, r0\n\ + ldr r2, =0x0000057c\n\ + adds r1, r2\n\ + ldr r0, [r4]\n\ + adds r0, r1\n\ + movs r1, 0xA8\n\ + muls r1, r5\n\ + movs r2, 0xD8\n\ + lsls r2, 3\n\ + adds r1, r2\n\ + add r1, r9\n\ + bl sub_80E88CC\n\ + adds r5, 0x1\n\ + cmp r5, 0x1\n\ + ble _080E8972\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"); +} + +static void sub_80E89AC(struct UnkRecordMixingStruct2 *arg0, size_t arg1, u32 arg2) +{ + u8 linkPlayerCount = GetLinkPlayerCount(); + struct UnknownRecMixingStruct3 *largeStructPtr = AllocZeroed(sizeof(struct UnknownRecMixingStruct3)); + + sub_80E8578(largeStructPtr, arg0, arg1, arg2, linkPlayerCount); + sub_80E8924(largeStructPtr); + + Free(largeStructPtr); +} + +static void sub_80E89F8(struct RecordMixingDayCareMail *dst) +{ + gUnknown_02039F9C.mail[0] = gSaveBlock1Ptr->daycare.mons[0].mail; + gUnknown_02039F9C.mail[1] = gSaveBlock1Ptr->daycare.mons[1].mail; + InitDaycareMailRecordMixing(&gSaveBlock1Ptr->daycare, &gUnknown_02039F9C); + *dst = *gUnknown_03001148; +} + +static void SanitizeDayCareMailForRuby(struct RecordMixingDayCareMail *src) +{ + s32 i; + + for (i = 0; i < src->numDaycareMons; i++) + { + struct DayCareMail *mail = &src->mail[i]; + if (mail->message.itemId != 0) + { + if (mail->gameLanguage != LANGUAGE_JAPANESE) + PadNameString(mail->OT_name, 0xFC); + + ConvertInternationalString(mail->monName, mail->monLanguage); + } + } +} + +static void SanitizeRubyBattleTowerRecord(struct RSBattleTowerRecord *src) +{ + +} + +static void SanitizeEmeraldBattleTowerRecord(struct EmeraldBattleTowerRecord *dst) +{ + s32 i; + + for (i = 0; i < 4; i++) + { + struct UnknownPokemonStruct *towerMon = &dst->party[i]; + if (towerMon->species != 0) + StripExtCtrlCodes(towerMon->nickname); + } + + CalcEmeraldBattleTowerChecksum(dst); +} diff --git a/src/recorded_battle.c b/src/recorded_battle.c index 4cb2eab49..eb48ab15a 100644 --- a/src/recorded_battle.c +++ b/src/recorded_battle.c @@ -475,7 +475,7 @@ u32 MoveRecordedBattleToSaveData(void) } #else -ASM_DIRECT +NAKED u32 MoveRecordedBattleToSaveData(void) { asm(".syntax unified\n\ diff --git a/src/rom_8034C54.c b/src/rom_8034C54.c index 4d4492524..42df51295 100644 --- a/src/rom_8034C54.c +++ b/src/rom_8034C54.c @@ -1,5 +1,453 @@ #include "global.h" +#include "rom_8034C54.h" +#include "malloc.h" +#include "decompress.h" +#include "main.h" -IWRAM_DATA u32 gUnknown_03000DD4; -IWRAM_DATA u32 gUnknown_03000DD8; -IWRAM_DATA u32 gUnknown_03000DDC; +struct UnkStruct2 +{ + bool8 isActive; + u8 firstOamId; + u8 field_2; + u8 oamCount; + u8 palTagIndex; + u8 size; + u8 shape; + u8 priority; + u8 xDelta; + u8 field_9; + u16 tileStart; + s16 x; + s16 y; + u16 tileTag; + u16 palTag; + u32 field_14; + s32 field_18; +}; + +struct UnkStruct1 +{ + u32 count; + struct UnkStruct2 *array; +}; + +extern struct UnkStruct1 *gUnknown_02022E10; + +extern const struct SpriteTemplate gUnknown_0831AC88; + +// this file's functions +static u8 sub_8035518(u8 arg0);; +static void sub_8034EFC(struct UnkStruct2 *arg0); +static void sub_80350B0(struct UnkStruct2 *arg0, s32 arg1, bool32 arg2); +static void sub_8035164(struct UnkStruct2 *arg0, s32 arg1, bool32 arg2); +static void sub_80352C0(struct UnkStruct2 *arg0, s32 arg1, bool32 arg2); +static bool32 SharesTileWithAnyActive(u32 id); +static bool32 SharesPalWithAnyActive(u32 id); +static void sub_8035648(void); + +// iwram +static IWRAM_DATA s32 gUnknown_03000DD4; +static IWRAM_DATA s32 gUnknown_03000DD8; +static IWRAM_DATA s32 gUnknown_03000DDC; + +// const rom data +static const u8 gUnknown_082FF1C8[][4] = +{ + {0x01, 0x04, 0x10, 0x40}, + {0x02, 0x04, 0x08, 0x20}, + {0x02, 0x04, 0x08, 0x20}, + {0x00, 0x00, 0x00, 0x00} +}; + +// code +bool32 sub_8034C54(u32 count) +{ + u32 i; + + if (gUnknown_02022E10 != NULL) + sub_8034CC8(); + + gUnknown_02022E10 = Alloc(sizeof(*gUnknown_02022E10)); + if (gUnknown_02022E10 == NULL) + return FALSE; + + gUnknown_02022E10->array = Alloc(sizeof(struct UnkStruct2) * count); + if (gUnknown_02022E10->array == NULL) + { + Free(gUnknown_02022E10); + return FALSE; + } + + gUnknown_02022E10->count = count; + for (i = 0; i < count; i++) + { + gUnknown_02022E10->array[i].isActive = FALSE; + gUnknown_02022E10->array[i].firstOamId |= 0xFF; + } + + return TRUE; +} + +void sub_8034CC8(void) +{ + if (gUnknown_02022E10 != NULL) + { + if (gUnknown_02022E10->array != NULL) + { + u32 i; + + for (i = 0; i < gUnknown_02022E10->count; i++) + sub_80353DC(i); + + Free(gUnknown_02022E10->array); + } + + FREE_AND_SET_NULL(gUnknown_02022E10); + } +} + +bool32 sub_8034D14(u32 id, s32 arg1, const struct UnkStruct3 *arg2) +{ + u32 i; + + if (gUnknown_02022E10 == NULL) + return FALSE; + if (gUnknown_02022E10->array[id].isActive) + return FALSE; + + gUnknown_02022E10->array[id].firstOamId = sub_8035518(arg2->field_1); + if (gUnknown_02022E10->array[id].firstOamId == 0xFF) + return FALSE; + + gUnknown_02022E10->array[id].tileStart = GetSpriteTileStartByTag(arg2->spriteSheet->tag); + if (gUnknown_02022E10->array[id].tileStart == 0xFFFF) + { + if (arg2->spriteSheet->size != 0) + { + gUnknown_02022E10->array[id].tileStart = LoadSpriteSheet(arg2->spriteSheet); + } + else + { + struct CompressedSpriteSheet compSpriteSheet; + + compSpriteSheet = *(struct CompressedSpriteSheet*)(arg2->spriteSheet); + compSpriteSheet.size = GetDecompressedDataSize(arg2->spriteSheet->data); + gUnknown_02022E10->array[id].tileStart = LoadCompressedObjectPic(&compSpriteSheet); + } + + if (gUnknown_02022E10->array[id].tileStart == 0xFFFF) + return FALSE; + } + + gUnknown_02022E10->array[id].palTagIndex = IndexOfSpritePaletteTag(arg2->spritePal->tag); + if (gUnknown_02022E10->array[id].palTagIndex == 0xFF) + gUnknown_02022E10->array[id].palTagIndex = LoadSpritePalette(arg2->spritePal); + + gUnknown_02022E10->array[id].field_2 = arg2->field_0_0; + gUnknown_02022E10->array[id].oamCount = arg2->field_1; + gUnknown_02022E10->array[id].x = arg2->x; + gUnknown_02022E10->array[id].y = arg2->y; + gUnknown_02022E10->array[id].shape = arg2->shape; + gUnknown_02022E10->array[id].size = arg2->size; + gUnknown_02022E10->array[id].priority = arg2->priority; + gUnknown_02022E10->array[id].xDelta = arg2->xDelta; + gUnknown_02022E10->array[id].field_9 = sub_80355F8(arg2->shape, arg2->size); + gUnknown_02022E10->array[id].tileTag = arg2->spriteSheet->tag; + gUnknown_02022E10->array[id].palTag = arg2->spritePal->tag; + gUnknown_02022E10->array[id].isActive = TRUE; + gUnknown_02022E10->array[id].field_14 = 1; + + for (i = 1; i < arg2->field_1; i++) + gUnknown_02022E10->array[id].field_14 *= 10; + + sub_8034EFC(&gUnknown_02022E10->array[id]); + sub_8035044(id, arg1); + + return TRUE; +} + +static void sub_8034EFC(struct UnkStruct2 *arg0) +{ + u32 i; + u32 oamId = arg0->firstOamId; + u32 x = arg0->x; + u32 oamCount = arg0->oamCount + 1; + + CpuFill16(0, &gMain.oamBuffer[oamId], sizeof(struct OamData) * oamCount); + for (i = 0, oamId = arg0->firstOamId; i < oamCount; i++, oamId++) + { + gMain.oamBuffer[oamId].y = arg0->y; + gMain.oamBuffer[oamId].x = x; + gMain.oamBuffer[oamId].shape = arg0->shape; + gMain.oamBuffer[oamId].size = arg0->size; + gMain.oamBuffer[oamId].tileNum = arg0->tileStart; + gMain.oamBuffer[oamId].priority = arg0->priority; + gMain.oamBuffer[oamId].paletteNum = arg0->palTagIndex; + + x += arg0->xDelta; + } + + oamId--; + gMain.oamBuffer[oamId].x = arg0->x - arg0->xDelta; + gMain.oamBuffer[oamId].affineMode = 2; + gMain.oamBuffer[oamId].tileNum = arg0->tileStart + (arg0->field_9 * 10); +} + +void sub_8035044(u32 id, s32 arg1) +{ + bool32 r2; + + if (gUnknown_02022E10 == NULL) + return; + if (!gUnknown_02022E10->array[id].isActive) + return; + + gUnknown_02022E10->array[id].field_18 = arg1; + if (arg1 < 0) + { + r2 = TRUE; + arg1 *= -1; + } + else + { + r2 = FALSE; + } + + switch (gUnknown_02022E10->array[id].field_2) + { + case 0: + default: + sub_80350B0(&gUnknown_02022E10->array[id], arg1, r2); + break; + case 1: + sub_8035164(&gUnknown_02022E10->array[id], arg1, r2); + break; + case 2: + sub_80352C0(&gUnknown_02022E10->array[id], arg1, r2); + break; + } +} + +static void sub_80350B0(struct UnkStruct2 *arg0, s32 arg1, bool32 arg2) +{ + u32 r5 = arg0->field_14; + u32 oamId = arg0->firstOamId; + + while (r5 != 0) + { + u32 r4 = arg1 / r5; + arg1 -= (r4 * r5); + r5 /= 10; + + gMain.oamBuffer[oamId].tileNum = (r4 * arg0->field_9) + arg0->tileStart; + oamId++; + } + + if (arg2) + gMain.oamBuffer[oamId].affineMode = 0; + else + gMain.oamBuffer[oamId].affineMode = 2; +} + +static void sub_8035164(struct UnkStruct2 *arg0, s32 arg1, bool32 arg2) +{ + u32 r5 = arg0->field_14; + gUnknown_03000DD4 = arg0->firstOamId; + gUnknown_03000DD8 = 0; + gUnknown_03000DDC = -1; + + while (r5 != 0) + { + u32 r4 = arg1 / r5; + arg1 -= (r4 * r5); + r5 /= 10; + + if (r4 != 0 || gUnknown_03000DDC != -1 || r5 == 0) + { + gMain.oamBuffer[gUnknown_03000DD4].tileNum = (r4 * arg0->field_9) + arg0->tileStart; + gMain.oamBuffer[gUnknown_03000DD4].affineMode = 0; + + if (gUnknown_03000DDC == -1) + gUnknown_03000DDC = gUnknown_03000DD8; + } + else + { + gMain.oamBuffer[gUnknown_03000DD4].affineMode = 2; + } + + gUnknown_03000DD4++; + gUnknown_03000DD8++; + } + + if (arg2) + { + gMain.oamBuffer[gUnknown_03000DD4].affineMode = 0; + gMain.oamBuffer[gUnknown_03000DD4].x = arg0->x + ((gUnknown_03000DDC - 1) * arg0->xDelta); + } + else + { + gMain.oamBuffer[gUnknown_03000DD4].affineMode = 2; + } +} + +static void sub_80352C0(struct UnkStruct2 *arg0, s32 arg1, bool32 arg2) +{ + u32 r5 = arg0->field_14; + u32 oamId = arg0->firstOamId; + u32 var_28 = 0; + s32 r9 = 0; + + while (r5 != 0) + { + u32 r4 = arg1 / r5; + arg1 -= (r4 * r5); + r5 /= 10; + + if (r4 != 0 || var_28 != 0 || r5 == 0) + { + var_28 = 1; + gMain.oamBuffer[oamId].tileNum = (r4 * arg0->field_9) + arg0->tileStart; + gMain.oamBuffer[oamId].affineMode = 0; + + oamId++; + r9++; + } + } + + while (r9 < arg0->oamCount) + { + gMain.oamBuffer[oamId].affineMode = 2; + oamId++; + r9++; + } + + if (arg2) + gMain.oamBuffer[oamId].affineMode = 0; + else + gMain.oamBuffer[oamId].affineMode = 2; +} + +void sub_80353DC(u32 id) +{ + s32 oamId, oamCount, i; + + if (gUnknown_02022E10 == NULL) + return; + if (!gUnknown_02022E10->array[id].isActive) + return; + + oamCount = gUnknown_02022E10->array[id].oamCount + 1; + oamId = gUnknown_02022E10->array[id].firstOamId; + + for (i = 0; i < oamCount; i++, oamId++) + gMain.oamBuffer[oamId].affineMode = 2; + + if (!SharesTileWithAnyActive(id)) + FreeSpriteTilesByTag(gUnknown_02022E10->array[id].tileTag); + if (!SharesPalWithAnyActive(id)) + FreeSpritePaletteByTag(gUnknown_02022E10->array[id].palTag); + + gUnknown_02022E10->array[id].isActive = FALSE; +} + +void sub_803547C(u32 id, bool32 arg1) +{ + s32 oamId, oamCount, i; + + if (gUnknown_02022E10 == NULL) + return; + if (!gUnknown_02022E10->array[id].isActive) + return; + + oamCount = gUnknown_02022E10->array[id].oamCount + 1; + oamId = gUnknown_02022E10->array[id].firstOamId; + if (arg1) + { + for (i = 0; i < oamCount; i++, oamId++) + gMain.oamBuffer[oamId].affineMode = 2; + } + else + { + for (i = 0; i < oamCount; i++, oamId++) + gMain.oamBuffer[oamId].affineMode = 0; + + sub_8035044(id, gUnknown_02022E10->array[id].field_18); + } +} + +static u8 sub_8035518(u8 arg0) +{ + u32 i; + u16 oamCount = 64; + + for (i = 0; i < gUnknown_02022E10->count; i++) + { + if (!gUnknown_02022E10->array[i].isActive) + { + if (gUnknown_02022E10->array[i].firstOamId != 0xFF && gUnknown_02022E10->array[i].oamCount <= arg0) + return gUnknown_02022E10->array[i].firstOamId; + } + else + { + oamCount += 1 + gUnknown_02022E10->array[i].oamCount; + } + } + + if (oamCount + arg0 + 1 > 128) + return 0xFF; + else + return oamCount; +} + +static bool32 SharesTileWithAnyActive(u32 id) +{ + u32 i; + + for (i = 0; i < gUnknown_02022E10->count; i++) + { + if (gUnknown_02022E10->array[i].isActive && i != id + && gUnknown_02022E10->array[i].tileTag == gUnknown_02022E10->array[id].tileTag) + { + return TRUE; + } + } + + return FALSE; +} + +static bool32 SharesPalWithAnyActive(u32 id) +{ + u32 i; + + for (i = 0; i < gUnknown_02022E10->count; i++) + { + if (gUnknown_02022E10->array[i].isActive && i != id + && gUnknown_02022E10->array[i].palTag == gUnknown_02022E10->array[id].palTag) + { + return TRUE; + } + } + + return FALSE; +} + +u8 sub_80355F8(u32 arg0, u32 arg1) +{ + return gUnknown_082FF1C8[arg0][arg1]; +} + +static void sub_8035608(void) +{ + u8 spriteId; + + ResetSpriteData(); + spriteId = CreateSprite(&gUnknown_0831AC88, 0, 0, 0); + gSprites[spriteId].invisible = 1; + SetMainCallback2(sub_8035648); +} + +static void sub_8035648(void) +{ + AnimateSprites(); + BuildOamBuffer(); +} diff --git a/src/rotating_gate.c b/src/rotating_gate.c index db5935fc3..b07814f58 100644 --- a/src/rotating_gate.c +++ b/src/rotating_gate.c @@ -646,7 +646,7 @@ static void RotatingGate_ResetAllGateOrientations(void) s32 i; u8 *ptr; - ptr = (u8 *)GetVarPointer(VAR_0x4000); + ptr = (u8 *)GetVarPointer(VAR_TEMP_0); for (i = 0; i < gRotatingGate_PuzzleCount; i++) { @@ -656,12 +656,12 @@ static void RotatingGate_ResetAllGateOrientations(void) static s32 RotatingGate_GetGateOrientation(u8 gateId) { - return ((u8 *)GetVarPointer(VAR_0x4000))[gateId]; + return ((u8 *)GetVarPointer(VAR_TEMP_0))[gateId]; } static void RotatingGate_SetGateOrientation(u8 gateId, u8 orientation) { - ((u8 *)GetVarPointer(VAR_0x4000))[gateId] = orientation; + ((u8 *)GetVarPointer(VAR_TEMP_0))[gateId] = orientation; } static void RotatingGate_RotateInDirection(u8 gateId, u32 rotationDirection) @@ -925,7 +925,7 @@ static s32 RotatingGate_CanRotate(u8 gateId, s16 rotationDirection) } #else -ASM_DIRECT +NAKED static s32 RotatingGate_CanRotate(u8 a, s16 rotationDirection) { asm(".syntax unified\n\ diff --git a/src/secret_base.c b/src/secret_base.c index cd6143ed0..44e980c43 100644 --- a/src/secret_base.c +++ b/src/secret_base.c @@ -10,7 +10,6 @@ #include "list_menu.h" #include "menu.h" #include "menu_helpers.h" -#include "menu_indicators.h" #include "constants/maps.h" #include "constants/songs.h" #include "constants/species.h" @@ -40,8 +39,6 @@ #include "tv.h" #include "secret_base.h" -extern void (*gFieldCallback)(void); - extern void mapldr_default(void); // Static type declarations @@ -416,7 +413,7 @@ bool8 sub_80E909C(void) void sub_80E90C8(u8 taskId) { FieldObjectTurn(&gMapObjects[gPlayerAvatar.mapObjectId], DIR_NORTH); - if (sub_80ABDFC() == TRUE) + if (IsWeatherNotFadingIn() == TRUE) { EnableBothScriptContexts(); DestroyTask(taskId); @@ -594,7 +591,7 @@ void sub_80E9578(void) void sub_80E95D4(void) { - VarSet(VAR_0x401F, gUnknown_0858D060[sub_80EA20C(VarGet(VAR_0x4054))]); + VarSet(VAR_OBJ_GFX_ID_F, gUnknown_0858D060[sub_80EA20C(VarGet(VAR_0x4054))]); } void sub_80E9608(struct Coords16 *coords, struct MapEvents *events) @@ -1676,7 +1673,7 @@ void sub_80EAEF4(struct SecretBaseRecordMixer *mixers) sub_80EABA4(&mixers[2], 0); } -void sub_80EAF80(void *records, size_t recordSize, u8 linkIdx) +void ReceiveSecretBasesData(void *records, size_t recordSize, u8 linkIdx) { struct SecretBaseRecordMixer mixers[3]; u16 i; diff --git a/src/text.c b/src/text.c index eacfd2a1f..f7c68f549 100644 --- a/src/text.c +++ b/src/text.c @@ -375,7 +375,7 @@ void GenerateFontHalfRowLookupTable(u8 fgColor, u8 bgColor, u8 shadowColor) *(current++) = (shadowColor << 12) | (shadowColor << 8) | (shadowColor << 4) | shadowColor; } #else -ASM_DIRECT +NAKED void GenerateFontHalfRowLookupTable(u8 fgColor, u8 bgColor, u8 shadowColor) { asm("push {r4-r7,lr}\n\ @@ -871,7 +871,7 @@ void DecompressGlyphTile(const u16 *src, u16 *dest) *(dest) = (gFontHalfRowLookupTable[gFontHalfRowOffsets[src[1] & 0xFF]] << 16) | gFontHalfRowLookupTable[gFontHalfRowOffsets[src[1] >> 8]]; } #else -ASM_DIRECT +NAKED void DecompressGlyphTile(const u16 *src, u16 *dest) { asm("push {r4-r7,lr}\n\ @@ -1052,7 +1052,7 @@ u8 GetLastTextColor(u8 colorType) } } -ASM_DIRECT +NAKED void CopyGlyphToWindow(struct TextPrinter *x) { asm("push {r4-r7,lr}\n\ @@ -2341,7 +2341,7 @@ u16 RenderText(struct TextPrinter *textPrinter) return 1; } #else -__attribute__((naked)) +NAKED u16 RenderText(struct TextPrinter *textPrinter) { asm("push {r4-r6,lr}\n\ diff --git a/src/time_events.c b/src/time_events.c index 1f169a5c6..1f46e7705 100644 --- a/src/time_events.c +++ b/src/time_events.c @@ -81,7 +81,7 @@ void UpdateShoalTideFlag(void) 1, // 23 }; - if (is_light_level_1_2_3_5_or_6(get_map_light_from_warp0())) + if (is_map_type_1_2_3_5_or_6(get_map_light_from_warp0())) { RtcCalcLocalTime(); if (tide[gLocalTime.hours]) diff --git a/src/title_screen.c b/src/title_screen.c index 4e25c8152..15a0482dc 100644 --- a/src/title_screen.c +++ b/src/title_screen.c @@ -19,6 +19,7 @@ #include "gpu_regs.h" #include "trig.h" #include "constants/rgb.h" +#include "constants/songs.h" #define VERSION_BANNER_SHAPE 1 #define VERSION_BANNER_RIGHT_TILEOFFSET 64 @@ -574,7 +575,7 @@ void CB2_InitTitleScreen(void) | DISPCNT_OBJ_ON | DISPCNT_WIN0_ON | DISPCNT_OBJWIN_ON); - m4aSongNumStart(0x19D); + m4aSongNumStart(MUS_TITLE3); gMain.state = 5; break; case 5: @@ -3557,7 +3557,7 @@ void GetMomOrDadStringForTVMessage(void) if (gSaveBlock1Ptr->location.mapNum == MAP_NUM(LITTLEROOT_TOWN_BRENDANS_HOUSE_1F)) { StringCopy(gStringVar1, gText_Mom); - VarSet(VAR_0x4003, 1); + VarSet(VAR_TEMP_3, 1); } } else @@ -3565,21 +3565,21 @@ void GetMomOrDadStringForTVMessage(void) if (gSaveBlock1Ptr->location.mapNum == MAP_NUM(LITTLEROOT_TOWN_MAYS_HOUSE_1F)) { StringCopy(gStringVar1, gText_Mom); - VarSet(VAR_0x4003, 1); + VarSet(VAR_TEMP_3, 1); } } } - if (VarGet(VAR_0x4003) == 1) + if (VarGet(VAR_TEMP_3) == 1) { StringCopy(gStringVar1, gText_Mom); } - else if (VarGet(VAR_0x4003) == 2) + else if (VarGet(VAR_TEMP_3) == 2) { StringCopy(gStringVar1, gText_Dad); } - else if (VarGet(VAR_0x4003) > 2) + else if (VarGet(VAR_TEMP_3) > 2) { - if (VarGet(VAR_0x4003) % 2 == 0) + if (VarGet(VAR_TEMP_3) % 2 == 0) StringCopy(gStringVar1, gText_Mom); else StringCopy(gStringVar1, gText_Dad); @@ -3589,12 +3589,12 @@ void GetMomOrDadStringForTVMessage(void) if (Random() % 2 != 0) { StringCopy(gStringVar1, gText_Mom); - VarSet(VAR_0x4003, 1); + VarSet(VAR_TEMP_3, 1); } else { StringCopy(gStringVar1, gText_Dad); - VarSet(VAR_0x4003, 2); + VarSet(VAR_TEMP_3, 2); } } } @@ -3606,7 +3606,7 @@ void sub_80F01B8(void) FlagSet(0x396); } -void sub_80F01E8(void *src, u32 size, u8 masterIdx) +void ReceiveTvShowsData(void *src, u32 size, u8 masterIdx) { u8 i; u16 version; @@ -3931,7 +3931,7 @@ static void sub_80F0708(void) // FIXME: register allocation shenanigans } } #else -ASM_DIRECT static void sub_80F0708(void) +NAKED static void sub_80F0708(void) { asm_unified("\tpush {r4-r7,lr}\n" "\tmov r7, r9\n" @@ -4434,7 +4434,7 @@ static void sub_80F0C04(void) } } -void sub_80F0C7C(void *src, u32 size, u8 masterIdx) +void ReceivePokeNewsData(void *src, u32 size, u8 masterIdx) { u8 i; PokeNews (*rmBuffer2)[4][16]; diff --git a/src/util.c b/src/util.c index 4f9241b21..88be4e4a1 100644 --- a/src/util.c +++ b/src/util.c @@ -230,7 +230,7 @@ void CopySpriteTiles(u8 shape, u8 size, u8 *tiles, u16 *tilemap, u8 *output) } #else -ASM_DIRECT void CopySpriteTiles(u8 shape, u8 size, u8 *tiles, u16 *tilemap, u8 *output) +NAKED void CopySpriteTiles(u8 shape, u8 size, u8 *tiles, u16 *tilemap, u8 *output) { asm("\n\ .syntax unified\n\ diff --git a/src/walda_phrase.c b/src/walda_phrase.c index 04789bfb5..0aa6f5aca 100644 --- a/src/walda_phrase.c +++ b/src/walda_phrase.c @@ -6,8 +6,7 @@ #include "main.h" #include "text.h" #include "new_game.h" - -extern void (*gFieldCallback)(void); +#include "overworld.h" extern const u8 gText_Peekaboo[]; |