// Top level main game routines #include "sm_rtl.h" #include "ida_types.h" #include "variables.h" #include "funcs.h" #include "enemy_types.h" #define kDemoRoomData ((uint16*)RomPtr(0x82876c)) void CallDemoRoomDataFunc(uint32 ea) { switch (ea) { case fnDemoRoom_ChargeBeamRoomScroll21: DemoRoom_ChargeBeamRoomScroll21(); return; case fnnullsub_291: return; case fnDemoRoom_SetBG2TilemapBase: DemoRoom_SetBG2TilemapBase(); return; case fnDemoRoom_SetKraidFunctionTimer: DemoRoom_SetKraidFunctionTimer(); return; case fnDemoRoom_SetBrinstarBossBits: DemoRoom_SetBrinstarBossBits(); return; default: Unreachable(); } } CoroutineRet InitAndLoadGameData_Async(void) { // 0x828000 int16 v0; int16 v2; int16 v4; int16 v7; COROUTINE_BEGIN(coroutine_state_1, 0) if (game_state == kGameState_40_TransitionToDemo) { InitIoForGameplay(); LoadStdBG3andSpriteTilesClearTilemaps(); LoadInitialPalette(); Samus_Initialize(); LoadDemoRoomData(); } else { if (loading_game_state != kLoadingGameState_5_Main) { if (loading_game_state == kLoadingGameState_1F_StartingAtCeres) { area_index = 6; load_station_index = 0; ClearTimerRam(); } else if (loading_game_state == kLoadingGameState_22_EscapingCeres) { area_index = 0; load_station_index = 18; LoadMirrorOfExploredMapTiles(); } } InitIoForGameplay(); LoadStdBG3andSpriteTilesClearTilemaps(); LoadInitialPalette(); Samus_Initialize(); LoadFromLoadStation(); } COROUTINE_AWAIT(1, StartGameplay_Async()); InitializeHud(); // nullsub_4(); { v0 = 32; uint16 v1 = 0; do { target_palettes[(v1 >> 1) + 192] = palette_buffer[(v1 >> 1) + 192]; v1 += 2; v0 -= 2; } while (v0); } screen_fade_delay = 1; screen_fade_counter = 1; EnableNMI(); EnableEnemyProjectiles(); EnablePLMs(); EnablePaletteFx(); EnableHdmaObjects(); EnableAnimtiles(); SetLiquidPhysicsType(); if (game_state == kGameState_40_TransitionToDemo) { loop_counter_transfer_enemies_to_vram = 6; do { TransferEnemyTilesToVramAndInit(); COROUTINE_AWAIT(2, WaitForNMI_Async()); --loop_counter_transfer_enemies_to_vram; } while ((loop_counter_transfer_enemies_to_vram & 0x8000u) == 0); R18_ = 18 * (demo_scene - 1); R18_ = get_DemoRoomData(R18_ + kDemoRoomData[demo_set])->demo_code_ptr; CallDemoRoomDataFunc(R18_ | 0x820000); ++game_state; v7 = 512; uint16 v8 = 0; do { palette_buffer[v8 >> 1] = target_palettes[v8 >> 1]; v8 += 2; v7 -= 2; } while (v7); } else if (loading_game_state == kLoadingGameState_22_EscapingCeres) { QueueMusic_Delayed8(5u); loop_counter_transfer_enemies_to_vram = 15; do { TransferEnemyTilesToVramAndInit(); COROUTINE_AWAIT(3, WaitForNMI_Async()); --loop_counter_transfer_enemies_to_vram; } while ((loop_counter_transfer_enemies_to_vram & 0x8000u) == 0); ++game_state; v2 = 512; uint16 v3 = 0; do { palette_buffer[v3 >> 1] = target_palettes[v3 >> 1]; v3 += 2; v2 -= 2; } while (v2); } else { loop_counter_transfer_enemies_to_vram = 6; do { TransferEnemyTilesToVramAndInit(); COROUTINE_AWAIT(4, WaitForNMI_Async()); --loop_counter_transfer_enemies_to_vram; } while ((loop_counter_transfer_enemies_to_vram & 0x8000u) == 0); game_state = kGameState_7_MainGameplayFadeIn; v4 = 512; uint16 v5 = 0; do { palette_buffer[v5 >> 1] = target_palettes[v5 >> 1]; v5 += 2; v4 -= 2; } while (v4); if (loading_game_state == kLoadingGameState_1F_StartingAtCeres) { palette_buffer[223] = 0; CallSomeSamusCode(8u); } else { CallSomeSamusCode(9u); } } COROUTINE_END(0); } void InitIoForGameplay(void) { // 0x82819B InitCpuForGameplay(); InitPpuForGameplay(); } void InitCpuForGameplay(void) { // 0x8281A4 WriteReg(NMITIMEN, 1u); reg_NMITIMEN = 1; WriteReg(WRIO, 0); WriteReg(WRMPYA, 0); WriteReg(WRMPYB, 0); WriteReg(WRDIVL, 0); WriteReg(WRDIVH, 0); WriteReg(WRDIVB, 0); WriteReg(HTIMEL, 0); WriteReg(HTIMEH, 0); WriteReg(VTIMEL, 0); WriteReg(VTIMEH, 0); WriteReg(MDMAEN, 0); WriteReg(HDMAEN, 0); reg_HDMAEN = 0; WriteReg(MEMSEL, 1u); reg_MEMSEL = 1; } void InitPpuForGameplay(void) { // 0x8281DD WriteReg(INIDISP, 0x80); reg_INIDISP = 0x80; WriteReg(OBSEL, 3u); reg_OBSEL = 3; WriteReg(OAMADDL, 0); LOBYTE(reg_OAMaddr_UNUSED) = 0; WriteReg(OAMADDH, 0x80); HIBYTE(reg_OAMaddr_UNUSED) = 0x80; WriteReg(OAMDATA, 0); WriteReg(OAMDATA, 0); WriteReg(BGMODE, 9u); reg_BGMODE = 9; WriteReg(MOSAIC, 0); reg_MOSAIC = 0; reg_BG12NBA = 0; WriteReg(BG12NBA, 0); reg_BG34NBA = 4; WriteReg(BG34NBA, 4u); reg_BG1SC = 81; WriteReg(BG1SC, 0x51u); reg_BG2SC = 73; WriteReg(BG2SC, 0x49u); reg_BG3SC = 90; WriteReg(BG3SC, 0x5Au); reg_BG4SC = 0; WriteReg(BG4SC, 0); WriteReg(VMAIN, 0); WriteReg(W12SEL, 0); reg_W12SEL = 0; WriteReg(W12SEL, 0); reg_W12SEL = 0; WriteReg(W34SEL, 0); reg_W34SEL = 0; WriteReg(WOBJSEL, 0); reg_WOBJSEL = 0; WriteReg(WH0, 0); reg_WH0 = 0; WriteReg(WH1, 0); reg_WH1 = 0; WriteReg(WH2, 0); reg_WH2 = 0; WriteReg(WH3, 0); reg_WH3 = 0; WriteReg(WBGLOG, 0); reg_WBGLOG = 0; WriteReg(WOBJLOG, 0); reg_WOBJLOG = 0; WriteReg(TM, 0x17u); reg_TM = 23; WriteReg(TMW, 0); reg_TMW = 0; WriteReg(TS, 0); reg_TS = 0; WriteReg(TSW, 0); reg_TSW = 0; WriteReg(CGWSEL, 0); next_gameplay_CGWSEL = 0; WriteReg(CGADSUB, 0); next_gameplay_CGADSUB = 0; WriteReg(COLDATA, 0xE0u); WriteReg(SETINI, 0); reg_SETINI = 0; oam_next_ptr = 0; memset7E(ADDR16_OF_RAM(ram3000), 0, 0x7FEu); memset7E(ADDR16_OF_RAM(ram4000), 0x6Fu, 0x7FEu); memset7E(ADDR16_OF_RAM(ram4000.bg2_tilemap), 0x2C0Fu, 0xFEu); } #define kInitialPalette ((uint16*)RomPtr(0x9a8000)) void LoadInitialPalette(void) { // 0x8282C5 int16 v0; v0 = 512; uint16 v1 = 0; do { palette_buffer[v1 >> 1] = kInitialPalette[v1 >> 1]; v1 += 2; v0 -= 2; } while (v0); } void LoadStdBG3andSpriteTilesClearTilemaps(void) { // 0x8282E2 WriteReg(VMADDL, 0); WriteReg(VMADDH, 0x40u); WriteReg(VMAIN, 0x80); static const StartDmaCopy unk_8282F8 = { 1, 1, 0x18, LONGPTR(0x9ab200), 0x2000 }; SetupDmaTransfer(&unk_8282F8); WriteReg(MDMAEN, 2u); WriteReg(VMADDL, 0); WriteReg(VMADDH, 0x60u); WriteReg(VMAIN, 0x80); static const StartDmaCopy unk_828318 = { 1, 1, 0x18, LONGPTR(0x9ad200), 0x4000 }; SetupDmaTransfer(&unk_828318); WriteReg(MDMAEN, 2u); WriteReg(VMADDL, 0); WriteReg(VMADDH, 0x50u); WriteReg(VMAIN, 0x80); static const StartDmaCopy unk_828338 = { 1, 1, 0x18, LONGPTR(0x7e4000), 0x1000 }; SetupDmaTransfer(&unk_828338); WriteReg(MDMAEN, 2u); WriteReg(VMADDL, 0); WriteReg(VMADDH, 0x58u); WriteReg(VMAIN, 0x80); static const StartDmaCopy unk_828358 = { 1, 1, 0x18, LONGPTR(0x7e4000), 0x0800 }; SetupDmaTransfer(&unk_828358); WriteReg(MDMAEN, 2u); } CoroutineRet GameState_32_MadeItToCeresElevator(void) { // 0x828367 if (timer_status) DrawTimer(); GameState_8_MainGameplay(); bool v0 = (--reached_ceres_elevator_fade_timer & 0x8000u) != 0; if (!reached_ceres_elevator_fade_timer || v0) { ++game_state; screen_fade_delay = 0; screen_fade_counter = 0; } return kCoroutineNone; } CoroutineRet GameState_33_BlackoutFromCeres(void) { // 0x828388 if (timer_status) DrawTimer(); GameState_8_MainGameplay(); HandleFadeOut(); if (reg_INIDISP == 0x80) { EnableNMI(); WaitUntilEndOfVblankAndClearHdma(); DisableIrqInterrupts(); fx_layer_blending_config_a = 0; cur_irq_handler = 0; next_gameplay_CGWSEL = 0; next_gameplay_CGADSUB = 0; reg_TM = 16; reg_TS = 0; reg_TMW = 0; reg_TSW = 0; reg_BGMODE = 9; screen_fade_delay = 0; screen_fade_counter = 0; loading_game_state = kLoadingGameState_22_EscapingCeres; game_state = 34; SaveToSram(selected_save_slot); cinematic_function = FUNC16(CinematicFunctionBlackoutFromCeres); ceres_status = 0; timer_status = 0; QueueMusic_Delayed8(0); QueueSfx1_Max15(2u); QueueSfx2_Max15(0x71u); QueueSfx3_Max15(1u); } return kCoroutineNone; } CoroutineRet GameState_35_TimeUp(void) { // 0x828411 GameState_8_MainGameplay(); palette_change_denom = 8; if (AdvancePaletteFadeForAllPalettes()) { game_state = kGameState_36_WhitingOutFromTimeUp; screen_fade_delay = 0; screen_fade_counter = 0; } return kCoroutineNone; } CoroutineRet GameState_36_WhitingOutFromTimeUp(void) { // 0x828431 HandleFadeOut(); if (reg_INIDISP == 0x80) { EnableNMI(); WaitUntilEndOfVblankAndClearHdma(); DisableIrqInterrupts(); fx_layer_blending_config_a = 0; cur_irq_handler = 0; next_gameplay_CGWSEL = 0; next_gameplay_CGADSUB = 0; reg_TM = 16; reg_TS = 0; reg_TMW = 0; reg_TSW = 0; reg_BGMODE = 9; screen_fade_delay = 0; screen_fade_counter = 0; ceres_status = 0; timer_status = 0; QueueSfx1_Max15(2u); QueueSfx2_Max15(0x71u); QueueSfx3_Max15(1u); if (CheckEventHappened(0xEu)) { game_options_screen_index = 0; menu_index = 0; for (int i = 254; i >= 0; i -= 2) enemy_projectile_y_subpos[(i >> 1) + 15] = 0; game_state = kGameState_25_SamusNoHealth; } else { game_state = kGameState_37_CeresGoesBoomWithSamus; cinematic_function = FUNC16(CinematicFunctionBlackoutFromCeres); } } return kCoroutineNone; } CoroutineRet GameState_38_SamusEscapesFromZebes(void) { // 0x8284BD GameState_8_MainGameplay(); HandleFadeOut(); if (reg_INIDISP == 0x80) { EnableNMI(); WaitUntilEndOfVblankAndClearHdma(); DisableIrqInterrupts(); fx_layer_blending_config_a = 0; next_gameplay_CGWSEL = 0; next_gameplay_CGADSUB = 0; reg_TM = 16; reg_TS = 0; reg_TMW = 0; reg_TSW = 0; reg_BGMODE = 9; screen_fade_delay = 0; screen_fade_counter = 0; game_state = kGameState_39_EndingAndCredits; cinematic_function = FUNC16(CinematicFunctionEscapeFromCebes); timer_status = 0; QueueMusic_Delayed8(0); QueueSfx1_Max15(2u); QueueSfx2_Max15(0x71u); QueueSfx3_Max15(1u); } return kCoroutineNone; } CoroutineRet GameState_41_TransitionToDemo(void) { // 0x82852D GameState_8_MainGameplay(); HdmaObjectHandler(); ++game_state; reg_INIDISP = 15; return kCoroutineNone; } CoroutineRet GameState_42_PlayingDemo_Async(void) { // 0x828548 COROUTINE_BEGIN(coroutine_state_3, 0) // assert(0); GameState_8_MainGameplay(); if (joypad1_newkeys) { substate = 1; goto LABEL_10; } demo_timer--; if (!demo_timer || (demo_timer & 0x8000u) != 0) { substate = 0; my_counter = 90; while (1) { COROUTINE_AWAIT(1, WaitForNMI_Async()); if (joypad1_newkeys) break; if (!--my_counter) goto LABEL_10; } substate = 1; LABEL_10: ++game_state; debug_disable_sounds = 0; reg_INIDISP = 0x80; screen_fade_delay = 1; screen_fade_counter = 1; } COROUTINE_END(0); } CoroutineRet GameState_43_TransitionFromDemo(void) { // 0x828593 if (substate != 1) CheckForNextDemo(); EnableNMI(); ++game_state; screen_fade_delay = 0; screen_fade_counter = 0; WaitUntilEndOfVblankAndClearHdma(); DisableIrqInterrupts(); fx_layer_blending_config_a = 0; cur_irq_handler = 0; irqhandler_next_handler = 0; DisablePaletteFx(); ClearPaletteFXObjects(); for (int i = 656; i >= 0; i -= 2) *(uint16 *)((char *)&enemy_projectile_enable_flag + i) = 0; for (int j = 538; j >= 0; j -= 2) *(uint16 *)((char *)&hud_item_tilemap_palette_bits + j) = 0; next_gameplay_CGWSEL = 0; next_gameplay_CGADSUB = 0; reg_TM = 16; reg_TS = 0; reg_TMW = 0; reg_TSW = 0; return kCoroutineNone; } CoroutineRet GameState_44_TransitionFromDemo(void) { // 0x8285FB game_state = kGameState_1_OpeningCinematic; if ((substate & 0x8000u) != 0) { game_state = kGameState_40_TransitionToDemo; } else if (substate) { LoadTitleSequenceGraphics(); enemy_projectile_x_pos[4] = 2; cinematic_function = FUNC16(CinematicFunctionNone); } else { QueueMusic_Delayed8(0); debug_disable_sounds = 0; cinematic_function = FUNC16(CinematicFunctionOpening); } return kCoroutineNone; } #define kDemoRoomData ((uint16*)RomPtr(0x82876c)) void CheckForNextDemo(void) { // 0x828637 R18_ = 2 * (demo_scene + 8 * demo_scene); if (*(uint16 *)RomPtr_82(R18_ + kDemoRoomData[demo_set]) == 0xFFFF) { substate = 0; uint16 v0 = demo_set + 1; if ((uint16)(demo_set + 1) >= num_demo_sets) v0 = 0; demo_set = v0; demo_scene = 0; } else { substate = 0x8000; } } void LoadDemoRoomData(void) { // 0x828679 DemoRoomData *drd; door_def_ptr = 0; R18_ = 18 * demo_scene; drd = get_DemoRoomData(18 * demo_scene + kDemoRoomData[demo_set]); room_ptr = drd->room_ptr_; door_def_ptr = drd->door_ptr; door_bts = drd->door_slot; layer1_x_pos = drd->screen_x_pos; bg1_x_offset = layer1_x_pos; layer1_y_pos = drd->screen_y_pos; bg1_y_offset = layer1_y_pos; samus_y_pos = layer1_y_pos + drd->samus_x_offs; samus_prev_y_pos = samus_y_pos; samus_x_pos = drd->samus_y_offs + layer1_x_pos + 128; samus_prev_x_pos = samus_x_pos; demo_timer = drd->demo_length; LOBYTE(area_index) = get_RoomDefHeader(room_ptr)->area_index_; reg_BG1HOFS = 0; reg_BG1VOFS = 0; ++demo_scene; uint16 v1 = 0; do { int v2 = v1 >> 1; WORD(room_chozo_bits[v1]) = -1; *(uint16 *)&item_bit_array[v1] = -1; UNUSED_word_7ED8F0[v2] = -1; *(uint16 *)&map_station_byte_array[v1] = -1; *(uint16 *)&used_save_stations_and_elevators[v1] = -1; *(uint16 *)&used_save_stations_and_elevators[v1 + 8] = -1; WORD(opened_door_bit_array[v1]) = 0; WORD(events_that_happened[v1]) = 0; *(uint16 *)&boss_bits_for_area[v1] = 0; v1 += 2; } while ((int16)(v1 - 8) < 0); do { int v3 = v1 >> 1; WORD(room_chozo_bits[v1]) = -1; *(uint16 *)&item_bit_array[v1] = -1; WORD(opened_door_bit_array[v1]) = 0; v1 += 2; } while ((int16)(v1 - 64) < 0); uint16 v4 = 0; do { explored_map_tiles_saved[v4 >> 1] = 0; v4 += 2; } while ((int16)(v4 - 1536) < 0); samus_max_reserve_health = 0; samus_reserve_health = 0; reserve_health_mode = 0; loading_game_state = kLoadingGameState_0_Intro; debug_disable_minimap = 0; } void DemoRoom_ChargeBeamRoomScroll21(void) { // 0x82891A scrolls[33] = 0; } void DemoRoom_SetBG2TilemapBase(void) { // 0x828925 *(uint16 *)®_BG2SC = 74; } void DemoRoom_SetKraidFunctionTimer(void) { // 0x82892B enemy_data[0].ai_preinstr = 60; } void DemoRoom_SetBrinstarBossBits(void) { // 0x828932 boss_bits_for_area[1] = 1; } static Func_V_Coroutine *const kGameStateFuncs[45] = { GameState_0_Reset_Async, GameState_1_OpeningCinematic, GameState_2_GameOptionsMenu, GameState_3_Null, GameState_4_FileSelectMenus, GameState_5_FileSelectMap, InitAndLoadGameData_Async, GameState_7_MainGameplayFadeIn, GameState_8_MainGameplay, GameState_9_HitDoorBlock, GameState_10_LoadingNextRoom_Async, GameState_11_LoadingNextRoom_Async, GameState_12_Pausing_Darkening_Async, GameState_13_Pausing_Async, GameState_14_Paused_Async, GameState_15_Paused_Async, GameState_16_Unpausing_Async, GameState_17_Unpausing_Async, GameState_18_Unpausing, GameState_19_SamusNoHealth, GameState_20_SamusNoHealth_BlackOut, GameState_21_SamusNoHealth, GameState_22_SamusNoHealth_Dying, GameState_23_SamusNoHealth_Flashing, GameState_24_SamusNoHealth_Explosion, GameState_25_SamusNoHealth_BlackOut, GameState_26_GameOverMenu, GameState_27_ReserveTanksAuto, GameState_28_Unused, GameState_29_DebugGameOverMenu, GameState_37_CeresGoesBoomWithSamus, InitAndLoadGameData_Async, GameState_32_MadeItToCeresElevator, GameState_33_BlackoutFromCeres, GameState_37_CeresGoesBoomWithSamus, GameState_35_TimeUp, GameState_36_WhitingOutFromTimeUp, GameState_37_CeresGoesBoomWithSamus, GameState_38_SamusEscapesFromZebes, GameState_39_EndingAndCredits, InitAndLoadGameData_Async, GameState_41_TransitionToDemo, GameState_42_PlayingDemo_Async, GameState_43_TransitionFromDemo, GameState_44_TransitionFromDemo, }; CoroutineRet RunGameStateTrampoline_Async(void) { // printf("gamestate %d\n", game_state); return kGameStateFuncs[(uint16)(2 * (uint8)game_state) >> 1](); } CoroutineRet RunOneFrameOfGameInner(void) { COROUTINE_BEGIN(coroutine_state_0, 1: case 2: case 3); COROUTINE_AWAIT_ONLY(Vector_RESET_Async()) COROUTINE_MANUAL_POS(0); ReadJoypadInputs(); HdmaObjectHandler(); NextRandom(); ClearOamExt(); oam_next_ptr = 0; nmi_copy_samus_halves = 0; nmi_copy_samus_top_half_src = 0; nmi_copy_samus_bottom_half_src = 0; COROUTINE_AWAIT(4, RunGameStateTrampoline_Async()); HandleSoundEffects(); ClearUnusedOam(); ShowSpareCpu(); COROUTINE_END(0); } void RunOneFrameOfGame(void) { // 0x828948 CoroutineRet ret = RunOneFrameOfGameInner(); if (ret == 0) waiting_for_nmi = 1; Vector_NMI(); } CoroutineRet GameState_29_DebugGameOverMenu(void) { // 0x8289DB DebugGameOverMenu(); return kCoroutineNone; } CoroutineRet GameState_26_GameOverMenu(void) { // 0x8289E0 GameOverMenu(); return kCoroutineNone; } CoroutineRet GameState_4_FileSelectMenus(void) { // 0x8289E5 FileSelectMenu(); return kCoroutineNone; } CoroutineRet GameState_5_FileSelectMap(void) { // 0x8289EA FileSelectMap(); return kCoroutineNone; } static Func_Y_V *const kSfxHandlers[5] = { // 0x8289EF SfxHandlers_0_SendToApu, SfxHandlers_1_WaitForAck, SfxHandlers_2_ClearRequest, SfxHandlers_3_WaitForAck, SfxHandlers_4_Reset, }; void HandleSoundEffects(void) { if ((int8)(sound_handler_downtime - 1) >= 0) { LOBYTE(sound_handler_downtime) = sound_handler_downtime - 1; RtlApuWrite(APUI01, 0); sfx_cur[0] = 0; RtlApuWrite(APUI02, 0); sfx_cur[1] = 0; RtlApuWrite(APUI03, 0); sfx_cur[2] = 0; } else { for (int i = 0; i < 3; ++i) kSfxHandlers[sfx_state[i]](i); } } void SfxHandlers_0_SendToApu(uint16 j) { // 0x828A2C if (sfx_readpos[j] != sfx_writepos[j]) { uint8 v2 = sfx_readpos[j] + j * 16; uint8 v3 = sfx1_queue[v2]; RtlApuWrite((SnesRegs)(j + APUI01), v3); sfx_cur[j] = v3; sfx_readpos[j] = (v2 + 1) & 0xF; ++sfx_state[j]; } } void SfxHandlers_1_WaitForAck(uint16 j) { // 0x828A55 // Modified from original uint8 v1 = sfx_cur[j]; ++sfx_state[j]; sfx_clear_delay[j] = 6; } void SfxHandlers_2_ClearRequest(uint16 j) { // 0x828A6C // Modified from original if (sfx_clear_delay[j]-- == 1) { sfx_cur[j] = 0; ++sfx_state[j]; } } void SfxHandlers_3_WaitForAck(uint16 j) { // 0x828A7C // Modified from original uint8 v1 = sfx_cur[j]; sfx_state[j] = 0; SfxHandlers_0_SendToApu(j); } void SfxHandlers_4_Reset(uint16 j) { // 0x828A90 if (sfx_clear_delay[j]-- == 1) sfx_state[j] = 0; } void ResetSoundQueues(void) { // 0x828A9A *(uint16 *)sfx_readpos = 0; *(uint16 *)&sfx_readpos[2] = 0; *(uint16 *)&sfx_writepos[1] = 0; *(uint16 *)sfx_state = 0; sfx_state[2] = 0; } void ShowSpareCpu(void) { // 0x828AB0 if ((joypad_dbg_1 & 0x4000) != 0) debug_spare_cpu_display_flag = debug_spare_cpu_display_flag == 0; if (debug_spare_cpu_display_flag) WriteReg(INIDISP, reg_INIDISP & 0xF0 | 5); joypad1_input_samusfilter = joypad1_lastkeys; } CoroutineRet GameState_0_Reset_Async(void) { // 0x828AE4 UNUSED_word_7E0DF8 = 0; UNUSED_word_7E0DFA = 0; UNUSED_word_7E0DFC = 0; cinematic_function = FUNC16(CinematicFunctionOpening); demo_set = 0; if (num_demo_sets == 4) demo_set = 3; ++game_state; return kCoroutineNone; } CoroutineRet GameState_1_OpeningCinematic(void) { // 0x828B08 return GameState_1_OpeningCinematic_(); } CoroutineRet GameState_3_Null(void) { return kCoroutineNone; } CoroutineRet GameState_37_CeresGoesBoomWithSamus(void) { // 0x828B0E return GameState_37_CeresGoesBoomWithSamus_(); } CoroutineRet GameState_39_EndingAndCredits(void) { // 0x828B13 return GameState_39_EndingAndCredits_(); } CoroutineRet GameState_7_MainGameplayFadeIn(void) { // 0x828B20 GameState_8_MainGameplay(); HandleFadeIn(); if (reg_INIDISP == 15) { screen_fade_delay = 0; screen_fade_counter = 0; ++game_state; } return kCoroutineNone; } CoroutineRet GameState_28_Unused(void) { // 0x828B3F GameState_28_Unused_(); return kCoroutineNone; } CoroutineRet GameState_8_MainGameplay(void) { // 0x828B44 COROUTINE_BEGIN(coroutine_state_1, 0); DetermineWhichEnemiesToProcess(); if (1) { // !DebugHandler()) { PaletteFxHandler(); HandleControllerInputForGamePhysics(); if (!debug_disable_sprite_interact) SamusProjectileInteractionHandler(); EnemyMain(); if (queued_message_box_index) { COROUTINE_AWAIT(1, DisplayMessageBox_Async(queued_message_box_index)); queued_message_box_index = 0; } HandleSamusMovementAndPause(); EprojRunAll(); COROUTINE_AWAIT(2, PlmHandler_Async()); AnimtilesHandler(); if (!debug_disable_sprite_interact) { EprojSamusCollDetect(); EprojProjCollDet(); ProcessEnemyPowerBombInteraction(); } MainScrollingRoutine(); int debug_scrolling_enabled = 0; if (debug_scrolling_enabled) DebugScrollPosSaveLoad(); DrawSamusEnemiesAndProjectiles(); QueueEnemyBG2TilemapTransfers(); } HandleHudTilemap(); CalculateLayer2PosAndScrollsWhenScrolling(); RunRoomMainCode(); HandleSamusOutOfHealthAndGameTile(); HandleRoomShaking(); DecrementSamusTimers(); COROUTINE_END(0); } void DeleteAllOptionsMenuObjects_(void) { for (int i = 14; i >= 0; i -= 2) { int v1 = i >> 1; enemy_projectile_y_pos[v1 + 5] = 0; enemy_projectile_y_vel[v1 + 17] = 0; } } void CallOptionsEntryFunc(uint32 ea, uint16 j) { switch (ea) { case fnsub_82F296: sub_82F296(j); return; case fnsub_82F34B: sub_82F34B(j); return; case fnsub_82F353: sub_82F353(j); return; case fnsub_82F35B: sub_82F35B(j); return; case fnsub_82F363: sub_82F363(j); return; case fnsub_82F419: sub_82F419(j); return; default: Unreachable(); } } uint8 CreateOptionsMenuObject_(uint16 a, uint16 j) { options_menu_init_param = a; uint16 v3 = 14; while (optionsmenu_instr_ptr[v3 >> 1]) { v3 -= 2; if ((v3 & 0x8000u) != 0) return 1; } uint8 *v5 = RomPtr_82(j); int v6 = v3 >> 1; optionsmenu_arr1[v6] = *((uint16 *)v5 + 1); optionsmenu_instr_ptr[v6] = *((uint16 *)v5 + 2); optionsmenu_instr_timer[v6] = 1; optionsmenu_cur_data[v6] = 0; optionsmenu_arr5[v6] = 0; optionsmenu_arr6[v6] = 0; optionsmenu_arr7[v6] = 0; CallOptionsEntryFunc(*(uint16 *)v5 | 0x820000, v3); return 0; } void OptionsPreInstr_nullsub_57(uint16 k) { // 0x828C10 ; } void OptionsMenuFunc1(void) { // 0x828C11 for (int i = 14; i >= 0; i -= 2) { optionsmenu_index = i; if (optionsmenu_instr_ptr[i >> 1]) { OptionsMenuFunc2(i); i = optionsmenu_index; } } } void CallOptionsPreInstr(uint32 ea, uint16 k) { switch (ea) { case fnOptionsPreInstr_nullsub_57: OptionsPreInstr_nullsub_57(k); return; case fnOptionsPreInstr_F2A9: OptionsPreInstr_F2A9(k); return; case fnOptionsPreInstr_F376: OptionsPreInstr_F376(k); return; case fnOptionsPreInstr_F3A0: OptionsPreInstr_F3A0(k); return; case fnOptionsPreInstr_F3E2: OptionsPreInstr_F3E2(k); return; case fnOptionsPreInstr_F42C: OptionsPreInstr_F42C(k); return; default: Unreachable(); } } uint16 CallOptionsInstr(uint32 ea, uint16 k, uint16 j) { switch (ea) { case fnOptionsInstr_Destroy: return OptionsInstr_Destroy(k, j); case fnOptionsInstr_8C64: return OptionsInstr_8C64(k, j); case fnOptionsInstr_SetPreInstr: return OptionsInstr_SetPreInstr(k, j); case fnOptionsInstr_8C79: return OptionsInstr_8C79(k, j); case fnOptionsInstr_Goto: return OptionsInstr_Goto(k, j); case fnOptionsInstr_8C89: return OptionsInstr_8C89(k, j); case fnOptionsInstr_8C93: return OptionsInstr_8C93(k, j); default: return Unreachable(); } } void OptionsMenuFunc2(uint16 k) { // 0x828C2B CallOptionsPreInstr(optionsmenu_arr1[k >> 1] | 0x820000, k); uint16 v1 = optionsmenu_index; int v2 = optionsmenu_index >> 1; if (optionsmenu_instr_timer[v2]-- == 1) { uint16 v4 = optionsmenu_instr_ptr[v2], v6; while (1) { uint16 *v5 = (uint16 *)RomPtr_82(v4); v6 = *v5; if ((*v5 & 0x8000u) == 0) break; R18_ = *v5; v4 = CallOptionsInstr(v6 | 0x820000, v1, v4 + 2); if (!v4) return; } int v7 = v1 >> 1; optionsmenu_instr_timer[v7] = v6; optionsmenu_cur_data[v7] = *((uint16 *)RomPtr_82(v4) + 1); optionsmenu_instr_ptr[v7] = v4 + 4; } } uint16 OptionsInstr_Destroy(uint16 k, uint16 j) { // 0x828C5A int v2 = k >> 1; optionsmenu_cur_data[v2] = 0; optionsmenu_instr_ptr[v2] = 0; return 0; } uint16 OptionsInstr_8C64(uint16 k, uint16 j) { // 0x828C64 optionsmenu_instr_ptr[k >> 1] = j - 2; return 0; } uint16 OptionsInstr_SetPreInstr(uint16 k, uint16 j) { // 0x828C6E optionsmenu_arr1[k >> 1] = *(uint16 *)RomPtr_82(j); return j + 2; } uint16 OptionsInstr_8C79(uint16 k, uint16 j) { // 0x828C79 optionsmenu_arr1[k >> 1] = FUNC16(locret_828C81); return j; } uint16 OptionsInstr_Goto(uint16 k, uint16 j) { // 0x828C82 return *(uint16 *)RomPtr_82(j); } uint16 OptionsInstr_8C89(uint16 k, uint16 j) { // 0x828C89 int v2 = k >> 1; if (optionsmenu_arr5[v2]-- == 1) return j + 2; else return OptionsInstr_Goto(k, j); } uint16 OptionsInstr_8C93(uint16 k, uint16 j) { // 0x828C93 optionsmenu_arr5[k >> 1] = *(uint16 *)RomPtr_82(j); return j + 2; } void DrawOptionsMenuSpritemaps(void) { // 0x828CA1 for (int i = 14; i >= 0; i -= 2) { int v1 = i >> 1; if (optionsmenu_cur_data[v1]) { uint16 v2 = optionsmenu_cur_data[v1]; R22_ = optionsmenu_arr10[v1]; R20_ = optionsmenu_arr8[v1]; R18_ = optionsmenu_arr9[v1]; DrawSpritemap(0x82u, v2); } } } CoroutineRet GameState_12_Pausing_Darkening_Async(void) { // 0x828CCF GameState_8_MainGameplay(); HandleFadeOut(); if ((reg_INIDISP & 0xF) == 0) { EnableNMI(); screen_fade_delay = 0; screen_fade_counter = 0; ++game_state; } return kCoroutineNone; } void CallPauseHook(uint32 ea) { switch (ea) { case fnPauseHook_Empty: return; case fnPauseHook_DraygonRoom: PauseHook_DraygonRoom(); return; case fnUnpauseHook_DraygonRoom: UnpauseHook_DraygonRoom(); return; case fnUnpauseHook_Kraid_IsDead: UnpauseHook_Kraid_IsDead(); return; case fnUnpauseHook_Kraid_IsAlive: UnpauseHook_Kraid_IsAlive(); return; case fnKraid_UnpauseHook_IsSinking: Kraid_UnpauseHook_IsSinking(); return; case fnPauseHook_Kraid: PauseHook_Kraid(); return; case fnMotherBrainsBody_UnpauseHook: MotherBrainsBody_UnpauseHook(); return; default: Unreachable(); } } CoroutineRet GameState_13_Pausing_Async(void) { // 0x828CEF DisableHdmaObjects(); reg_HDMAEN = 0; WriteReg(HDMAEN, 0); DisableAnimtiles(); BackupBG2TilemapForPauseMenu(); CallPauseHook(Load24(&pause_hook)); CancelSoundEffects(); BackupSomeGfxStateForPause(); LoadPauseMenuTilesAndClearBG2(); LoadPauseScreenBaseTilemaps(); LoadPauseMenuMapTilemapAndAreaLabel(); BackupGameplayPalettesAndLoadForPause(); ContinueInitPauseMenu(); screen_fade_delay = 1; screen_fade_counter = 1; pausemenu_leftarrow_animation_frame = 0; pausemenu_palette_animation_timer = 1; map_scrolling_direction = 0; map_scrolling_speed_index = 0; QueueClearingOfFxTilemap(); ++game_state; return kCoroutineNone; } void BackupBG2TilemapForPauseMenu(void) { // 0x828D51 WriteReg(VMADDL, 1u); WriteReg(VMADDH, reg_BG2SC & 0xFC); WriteReg(DMAP1, 0x81u); WriteReg(BBAD1, 0x39u); WriteReg(A1T1L, 0x5C); WriteReg(A1T1H, 0xDFu); WriteReg(A1B1, 0x7Eu); WriteReg(DAS1L, 0); WriteReg(DAS1H, 0x10u); WriteReg(DAS10, 0); WriteReg(A2A1L, 0); WriteReg(A2A1H, 0); WriteReg(NTRL1, 0); WriteReg(MDMAEN, 2u); } void RestoreBG2TilemapFromPauseScreen(void) { // 0x828D96 WriteReg(VMADDL, 0); WriteReg(VMADDH, reg_BG2SC & 0xFC); WriteReg(VMAIN, 0x80); static const StartDmaCopy unk_828DAE = { 1, 1, 0x18, LONGPTR(0x7edf5c), 0x1000 }; SetupDmaTransfer(&unk_828DAE); WriteReg(MDMAEN, 2u); } void BackupSomeGfxStateForPause(void) { // 0x828DBD pausemenu_bak_BG1SC = reg_BG1SC; pausemenu_bak_BG2SC = reg_BG2SC; pausemenu_bak_BG3SC = reg_BG3SC; pausemenu_bak_BG12NBA = reg_BG12NBA; pausemenu_bak_BG34NBA = reg_BG34NBA; pausemenu_bak_OBSEL = reg_OBSEL; pausemenu_bak_BG1HOFS = reg_BG1HOFS; pausemenu_bak_BG2HOFS = reg_BG2HOFS; pausemenu_bak_BG3HOFS = reg_BG3HOFS; pausemenu_bak_BG1VOFS = reg_BG1VOFS; pausemenu_bak_BG2VOFS = reg_BG2VOFS; pausemenu_bak_BG3VOFS = reg_BG3VOFS; pausemenu_bak_BGMODE = reg_BGMODE; pausemenu_bak_layer2_scroll_x = layer2_scroll_x; pausemenu_bak_layer2_scroll_y = layer2_scroll_y; pausemenu_bak_MOSAIC = reg_MOSAIC; pausemenu_bak_CGADSUB = next_gameplay_CGADSUB; } void RestoreSomeGfxStateForPause(void) { // 0x828E19 layer2_scroll_x = pausemenu_bak_layer2_scroll_x; layer2_scroll_y = pausemenu_bak_layer2_scroll_y; reg_BGMODE = pausemenu_bak_BGMODE; LOBYTE(reg_BG3VOFS) = pausemenu_bak_BG3VOFS; LOBYTE(reg_BG2VOFS) = pausemenu_bak_BG2VOFS; LOBYTE(reg_BG1VOFS) = pausemenu_bak_BG1VOFS; LOBYTE(reg_BG3HOFS) = pausemenu_bak_BG3HOFS; LOBYTE(reg_BG2HOFS) = pausemenu_bak_BG2HOFS; LOBYTE(reg_BG1HOFS) = pausemenu_bak_BG1HOFS; reg_OBSEL = pausemenu_bak_OBSEL; reg_BG34NBA = pausemenu_bak_BG34NBA; reg_BG12NBA = pausemenu_bak_BG12NBA; reg_BG3SC = pausemenu_bak_BG3SC; reg_BG2SC = pausemenu_bak_BG2SC; reg_BG1SC = pausemenu_bak_BG1SC; reg_MOSAIC = pausemenu_bak_MOSAIC; next_gameplay_CGADSUB = pausemenu_bak_CGADSUB; } void LoadPauseMenuTilesAndClearBG2(void) { // 0x828E75 WriteReg(VMADDL, 0); WriteReg(VMADDH, 0); WriteReg(VMAIN, 0x80); static const StartDmaCopy unk_828E8B = { 1, 1, 0x18, LONGPTR(0xb68000), 0x4000 }; SetupDmaTransfer(&unk_828E8B); WriteReg(MDMAEN, 2u); WriteReg(VMADDL, 0); WriteReg(VMADDH, 0x20u); WriteReg(VMAIN, 0x80); static const StartDmaCopy unk_828EAB = { 1, 1, 0x18, LONGPTR(0xb6c000), 0x2000 }; SetupDmaTransfer(&unk_828EAB); WriteReg(MDMAEN, 2u); WriteReg(VMADDL, 0); WriteReg(VMADDH, 0x40u); WriteReg(VMAIN, 0x80); static const StartDmaCopy unk_828ECB = { 1, 1, 0x18, LONGPTR(0x9ab200), 0x2000 }; SetupDmaTransfer(&unk_828ECB); WriteReg(MDMAEN, 2u); } void LoadPauseScreenBaseTilemaps(void) { // 0x828EDA WriteReg(VMADDL, 0); WriteReg(VMADDH, 0x38u); WriteReg(VMAIN, 0x80); static const StartDmaCopy unk_828EF0 = { 1, 1, 0x18, LONGPTR(0xb6e000), 0x0800 }; SetupDmaTransfer(&unk_828EF0); WriteReg(MDMAEN, 2u); WriteReg(WMADDL, 0); WriteReg(WMADDM, 0x34u); WriteReg(WMADDH, 0x7Eu); static const StartDmaCopy unk_828F10 = { 1, 0, 0x80, LONGPTR(0xb6e400), 0x0400 }; SetupDmaTransfer(&unk_828F10); WriteReg(MDMAEN, 2u); WriteReg(WMADDL, 0); WriteReg(WMADDM, 0x38u); WriteReg(WMADDH, 0x7Eu); static const StartDmaCopy unk_828F30 = { 1, 0, 0x80, LONGPTR(0xb6e800), 0x0800 }; SetupDmaTransfer(&unk_828F30); WriteReg(MDMAEN, 2u); uint16 v0 = addr_kDummySamusWireframeTilemap; uint16 v1 = 236; R20_ = 17; do { R18_ = 8; do { ram3000.pause_menu_map_tilemap[v1++] = *(uint16 *)RomPtr_82(v0); v0 += 2; --R18_; } while (R18_); v1 += 8; --R20_; } while (R20_); WriteSamusWireframeTilemap(); LoadEqupmentScreenReserveHealthTilemap(); } void LoadEqupmentScreenReserveHealthTilemap(void) { // 0x828F70 if (samus_max_reserve_health) { R42 = samus_reserve_health / 100; int rest = samus_reserve_health % 100; int div10 = rest / 10; int mod10 = rest % 10; ram3800.cinematic_bg_tilemap[394] = mod10 + 2052; ram3800.cinematic_bg_tilemap[393] = div10 + 2052; ram3800.cinematic_bg_tilemap[392] = R42 + 2052; } } #define kPauseScreenPalettes ((uint16*)RomPtr(0xb6f000)) void BackupGameplayPalettesAndLoadForPause(void) { // 0x828FD4 int16 v0; int16 v2; v0 = 512; uint16 v1 = 0; do { ram3000.pause_menu_map_tilemap[v1 + 384] = palette_buffer[v1]; ++v1; v0 -= 2; } while (v0); v2 = 512; uint16 v3 = 0; do { palette_buffer[v3 >> 1] = kPauseScreenPalettes[v3 >> 1]; v3 += 2; v2 -= 2; } while (v2); } void ContinueInitPauseMenu(void) { // 0x829009 SetupPpuForPauseMenu(); ResetPauseMenuAnimations(); LoadEquipmentScreenEquipmentTilemaps(); SetPauseScreenButtonLabelPalettes_0(); UpdatePauseMenuLRStartVramTilemap(); DetermineMapScrollLimits(); SetupMapScrollingForPauseMenu(0x80); } void SetupMapScrollingForFileSelectMap(void) { // 0x829028 int16 v0; int16 v1; ResetPauseMenuAnimations(); DetermineMapScrollLimits(); reg_BG1HOFS = map_min_x_scroll + ((uint16)(map_max_x_scroll - map_min_x_scroll) >> 1) - 128; R18_ = 8 * (room_x_coordinate_on_map + (uint8)((uint16)(samus_x_pos & 0xFF00) >> 8)) - reg_BG1HOFS; v0 = 224 - R18_; if ((int16)(224 - R18_) >= 0) { R18_ = 32 - R18_; if ((R18_ & 0x8000u) == 0) reg_BG1HOFS -= R18_; } else { R18_ = 224 - R18_; reg_BG1HOFS -= v0; } R18_ = map_min_y_scroll + ((uint16)(map_max_y_scroll - map_min_y_scroll) >> 1) + 16; reg_BG1VOFS = -((112 - R18_) & 0xFFF8); R18_ = 8 * (room_y_coordinate_on_map + HIBYTE(samus_y_pos) + 1) + ((112 - R18_) & 0xFFF8); v1 = 64 - R18_; if ((int16)(64 - R18_) >= 0) { R18_ = 64 - R18_; reg_BG1VOFS -= v1; if (sign16(reg_BG1VOFS + 40)) reg_BG1VOFS = -40; } } CoroutineRet GameState_14_Paused_Async(void) { // 0x8290C8 DrawPauseMenuDuringFadeIn(); HandleFadeIn(); if (reg_INIDISP == 15) { screen_fade_delay = 0; screen_fade_counter = 0; ++game_state; } return kCoroutineNone; } CoroutineRet GameState_15_Paused_Async(void) { // 0x8290E8 ReleaseButtonsFilter(3); MainPauseRoutine(); HandleHudTilemap(); HandlePauseScreenPaletteAnimation(); return kCoroutineNone; } static Func_V *const kPauseMenuFuncs[8] = { // 0x8290FF PauseMenu_0_MapScreen, PauseMenu_1_EquipmentScreen, PauseMenu_2, PauseMenu_3_MapToEquipment_Load, PauseMenu_4_MapToEquipment_FadeIn, PauseMenu_5, PauseMenu_6_EquipmentToMap_Load, PauseMenu_7_EquipmentToMap_FadeIn, }; void MainPauseRoutine(void) { kPauseMenuFuncs[menu_index](); } void PauseMenu_0_MapScreen(void) { // 0x829120 HandlePauseScreenLR(); HandlePauseScreenStart(); HandleMapScrollArrows(); MapScrolling(); MapScreenDrawSamusPositionIndicator(); DrawMapIcons(); DisplayMapElevatorDestinations(); pause_screen_mode = 0; } void PauseMenu_1_EquipmentScreen(void) { // 0x829142 reg_BG1HOFS = 0; reg_BG1VOFS = 0; EquipmentScreenMain(); HandlePauseScreenLR(); HandlePauseScreenStart(); pause_screen_mode = 1; } void PauseMenu_2(void) { // 0x829156 DisplayMapElevatorDestinations(); MapScreenDrawSamusPositionIndicator(); DrawMapIcons(); HandlePauseMenuLRPressHighlight(); pause_screen_mode = 0; HandleFadeOut(); if (reg_INIDISP == 0x80) { EnableNMI(); screen_fade_delay = 0; screen_fade_counter = 0; ++menu_index; } } void PauseMenu_5(void) { // 0x829186 EquipmentScreenDrawItemSelector(); EquipmentScreenDisplayReserveTankAmount(); HandlePauseMenuLRPressHighlight(); HandleFadeOut(); if (reg_INIDISP == 0x80) { EnableNMI(); screen_fade_delay = 0; screen_fade_counter = 0; ++menu_index; } } #define kPauseLrHighlightAnimData ((uint8*)RomPtr(0x82c10c)) void PauseMenu_3_MapToEquipment_Load(void) { // 0x8291AB DisplayMapElevatorDestinations(); EquipmentScreenSetupReserveMode(); EquipmentScreenTransferBG1Tilemap(); pause_screen_mode = 1; SetPauseScreenButtonLabelPalettes(); pausemenu_lr_animation_frame = 0; pausemenu_lr_animation_timer = *(uint16 *)kPauseLrHighlightAnimData; screen_fade_delay = 1; screen_fade_counter = 1; ++menu_index; } void PauseMenu_6_EquipmentToMap_Load(void) { // 0x8291D7 DisplayMapElevatorDestinations(); LoadPauseMenuMapTilemapAndAreaLabel(); SetPauseScreenButtonLabelPalettes(); pausemenu_lr_animation_frame = 0; pausemenu_lr_animation_timer = *(uint16 *)kPauseLrHighlightAnimData; screen_fade_delay = 1; screen_fade_counter = 1; pause_screen_mode = 0; ++menu_index; } void PauseMenu_7_EquipmentToMap_FadeIn(void) { // 0x829200 MapScreenDrawSamusPositionIndicator(); DrawMapIcons(); DisplayMapElevatorDestinations(); pause_screen_mode = 0; HandleFadeIn(); if (reg_INIDISP == 15) { screen_fade_delay = 0; screen_fade_counter = 0; uint16 v0 = pausemenu_button_label_mode; if (pausemenu_button_label_mode) v0 = 1; menu_index = v0; } } void PauseMenu_4_MapToEquipment_FadeIn(void) { // 0x829231 EquipmentScreenDrawItemSelector(); EquipmentScreenDisplayReserveTankAmount(); pause_screen_mode = 1; HandleFadeIn(); if (reg_INIDISP == 15) { screen_fade_delay = 0; screen_fade_counter = 0; uint16 v0 = pausemenu_button_label_mode; if (pausemenu_button_label_mode) v0 = 1; menu_index = v0; } } static Func_V *const kMapScrollingFuncs[5] = { // 0x82925D MapScrolling_0_None, MapScrolling_1_Left, MapScrolling_2_Right, MapScrolling_3_Up, MapScrolling_4_Down, }; void MapScrolling(void) { kMapScrollingFuncs[map_scrolling_direction](); } void MapScrolling_0_None(void) { // 0x829278 map_scrolling_gear_switch_timer = 4; } uint16 MapScrolling_GetSpeedIndex(void) { // 0x82927F uint16 result = map_scrolling_speed_index; if (!map_scrolling_gear_switch_timer) return map_scrolling_speed_index + 32; return result; } static const uint16 kMapScrollingSpeedTable[32] = { // 0x82928E 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; void MapScrolling_1_Left(void) { reg_BG1HOFS -= kMapScrollingSpeedTable[MapScrolling_GetSpeedIndex() >> 1]; MapScrolling_Common(); } void MapScrolling_Common(void) { // 0x829299 ++map_scrolling_speed_index; if ((++map_scrolling_speed_index & 0xF) == 0) { QueueSfx1_Max6(0x36u); map_scrolling_direction = 0; map_scrolling_speed_index = 0; if (map_scrolling_gear_switch_timer) --map_scrolling_gear_switch_timer; } } void MapScrolling_2_Right(void) { // 0x8292BD reg_BG1HOFS += kMapScrollingSpeedTable[MapScrolling_GetSpeedIndex() >> 1]; MapScrolling_Common(); } void MapScrolling_3_Up(void) { // 0x8292CA reg_BG1VOFS -= kMapScrollingSpeedTable[MapScrolling_GetSpeedIndex() >> 1]; MapScrolling_Common(); } void MapScrolling_4_Down(void) { // 0x8292D7 reg_BG1VOFS += kMapScrollingSpeedTable[MapScrolling_GetSpeedIndex() >> 1]; MapScrolling_Common(); } CoroutineRet GameState_16_Unpausing_Async(void) { // 0x829324 HighlightPauseScreenButton(); DrawPauseMenuDuringFadeout(); HandleFadeOut(); if (reg_INIDISP == 0x80) { EnableNMI(); screen_fade_delay = 0; screen_fade_counter = 0; ++game_state; } return kCoroutineNone; } void DrawPauseMenuDuringFadeout(void) { // 0x82934B if (pause_screen_mode == 1) { EquipmentScreenDrawItemSelector(); EquipmentScreenDisplayReserveTankAmount(); HandlePauseMenuLRPressHighlight(); } else { DisplayMapElevatorDestinations(); DrawMapIcons(); MapScreenDrawSamusPositionIndicator(); } } CoroutineRet GameState_17_Unpausing_Async(void) { // 0x829367 ClearSamusBeamTiles(); ContinueInitGameplayResume(); ResumeGameplay(); RestoreSomeGfxStateForPause(); RestoreBG2TilemapFromPauseScreen(); screen_fade_delay = 1; screen_fade_counter = 1; CallPauseHook(Load24(&unpause_hook)); EnableHdmaObjects(); EnableAnimtiles(); QueueSamusMovementSfx(); ++game_state; return kCoroutineNone; } CoroutineRet GameState_18_Unpausing(void) { // 0x8293A1 GameState_8_MainGameplay(); HandleFadeIn(); if (reg_INIDISP == 15) { screen_fade_delay = 0; screen_fade_counter = 0; game_state = kGameState_8_MainGameplay; } return kCoroutineNone; } #define kPauseAreaLabelTilemap ((uint16*)RomPtr(0x82965f)) void LoadPauseMenuMapTilemapAndAreaLabel(void) { // 0x8293C3 reg_BG1HOFS = reg_BG4HOFS; reg_BG1VOFS = reg_BG4VOFS; WriteReg(VMADDL, 0); WriteReg(VMADDH, 0x30u); WriteReg(VMAIN, 0x80); LoadPauseMenuMapTilemap(); static const StartDmaCopy unk_8293E9 = { 1, 1, 0x18, LONGPTR(0x7e4000), 0x1000 }; SetupDmaTransfer(&unk_8293E9); WriteReg(MDMAEN, 2u); WriteReg(VMADDL, 0xAAu); WriteReg(VMADDH, 0x38u); WriteReg(VMAIN, 0x80); WriteReg(DMAP1, 1u); WriteReg(BBAD1, 0x18u); WriteReg(DAS1L, 0x18u); WriteReg(DAS1H, 0); uint16 v0 = area_index; if (!sign16(area_index - 7)) v0 = 0; WriteRegWord(A1T1L, kPauseAreaLabelTilemap[v0]); WriteReg(A1B1, 0x82u); WriteReg(MDMAEN, 2u); } #define kPauseMenuMapTilemaps ((LongPtr*)RomPtr(0x82964a)) #define kPauseMenuMapData ((uint16*)RomPtr(0x829717)) void LoadPauseMenuMapTilemap(void) { // 0x82943D uint16 v5; uint16 v6; int16 v9; uint16 v13; uint16 v0 = area_index; if (!sign16(area_index - 7)) v0 = 0; R18_ = v0; R0_.addr = *(VoidP *)((char *)&kPauseMenuMapTilemaps[0].addr + (uint16)(3 * v0)); *(uint16 *)&R0_.bank = *(uint16 *)(&kPauseMenuMapTilemaps[0].bank + (uint16)(3 * v0)); R3_.addr = ADDR16_OF_RAM(ram4000); *(uint16 *)&R3_.bank = 126; R8_ = 130; R6_ = kPauseMenuMapData[v0]; if (map_station_byte_array[area_index]) { uint8 *v4 = IndirPtr(&R6_, 0); LOBYTE(v5) = HIBYTE(*(uint16 *)v4); HIBYTE(v5) = *(uint16 *)v4; R38 = v5; ++R6_; ++R6_; v6 = ADDR16_OF_RAM(*map_tiles_explored); *(uint16 *)((char *)&R10_ + 1) = 0; *(uint16 *)((char *)&R8_ + 1) = v6; uint8 *v7 = IndirPtr((char *)&R8_ + 1, 0); LOBYTE(v5) = HIBYTE(*(uint16 *)v7); HIBYTE(v5) = *(uint16 *)v7; R40 = v5; ++ *(uint16 *)((char *)&R8_ + 1); ++ *(uint16 *)((char *)&R8_ + 1); uint16 v8 = 0; v9 = 16; do { uint16 v10 = *(uint16 *)IndirPtr(&R0_, v8); bool v11 = R40 >> 15; R40 *= 2; if (v11) { v10 &= ~0x400u; R38 *= 2; } else { v11 = R38 >> 15; R38 *= 2; if (!v11) v10 = 31; } IndirWriteWord(&R3_, v8, v10); if (!--v9) { v9 = 16; uint8 *v12 = IndirPtr(&R6_, 0); LOBYTE(v13) = HIBYTE(*(uint16 *)v12); HIBYTE(v13) = *(uint16 *)v12; R38 = v13; ++R6_; ++R6_; uint8 *v14 = IndirPtr((char *)&R8_ + 1, 0); LOBYTE(v13) = HIBYTE(*(uint16 *)v14); HIBYTE(v13) = *(uint16 *)v14; R40 = v13; ++ *(uint16 *)((char *)&R8_ + 1); ++ *(uint16 *)((char *)&R8_ + 1); } v8 += 2; } while ((int16)(v8 - 4096) < 0); } else { uint16 v1 = 0; uint16 v2 = 0; LOBYTE(R18_) = 0; while (1) { uint8 t = map_tiles_explored[v2]; map_tiles_explored[v2] <<= 1; if (!(t & 0x80)) { IndirWriteWord(&R3_, v1, 0x1Fu); } else { ++map_tiles_explored[v2]; uint8 *v3 = IndirPtr(&R0_, v1); IndirWriteWord(&R3_, v1, *(uint16 *)v3 & 0xFBFF); } v1 += 2; LOBYTE(R18_) = R18_ + 1; if (!sign8(R18_ - 8)) { LOBYTE(R18_) = 0; if ((int16)(++v2 - 256) >= 0) break; } } } } void DrawRoomSelectMap(void) { // 0x829517 uint16 v3; // r8 uint16 v6; unsigned int v7; // kr00_4 int16 v10; uint16 v14; VramWriteEntry *v17; reg_BG12NBA = 51; reg_TM = 19; reg_BG1VOFS = -40; uint16 v0 = area_index; if (!sign16(area_index - 7)) v0 = 0; R18_ = v0; R0_.addr = *(VoidP *)((char *)&kPauseMenuMapTilemaps[0].addr + (uint16)(3 * v0)); *(uint16 *)&R0_.bank = *(uint16 *)(&kPauseMenuMapTilemaps[0].bank + (uint16)(3 * v0)); R3_.addr = ADDR16_OF_RAM(ram3000); R3_.bank = 126; R8_ = 130; R6_ = kPauseMenuMapData[v0]; if (map_station_byte_array[area_index]) { uint8 *v5 = IndirPtr(&R6_, 0); LOBYTE(v6) = HIBYTE(*(uint16 *)v5); HIBYTE(v6) = *(uint16 *)v5; R38 = v6; ++R6_; ++R6_; v7 = 2039; *(uint16 *)((char *)&R10_ + 1) = HIWORD(v7); *(uint16 *)((char *)&R8_ + 1) = v7; uint8 *v8 = IndirPtr((char *)&R8_ + 1, 0); LOBYTE(v6) = HIBYTE(*(uint16 *)v8); HIBYTE(v6) = *(uint16 *)v8; R40 = v6; ++ *(uint16 *)((char *)&R8_ + 1); ++ *(uint16 *)((char *)&R8_ + 1); uint16 v9 = 0; v10 = 16; do { uint16 v11 = *(uint16 *)IndirPtr(&R0_, v9); bool v12 = R40 >> 15; R40 *= 2; if (v12) { v11 &= ~0x400u; R38 *= 2; } else { v12 = R38 >> 15; R38 *= 2; if (!v12) v11 = 31; } IndirWriteWord(&R3_, v9, v11); if (!--v10) { v10 = 16; uint8 *v13 = IndirPtr(&R6_, 0); LOBYTE(v14) = HIBYTE(*(uint16 *)v13); HIBYTE(v14) = *(uint16 *)v13; R38 = v14; ++R6_; ++R6_; uint8 *v15 = IndirPtr((char *)&R8_ + 1, 0); LOBYTE(v14) = HIBYTE(*(uint16 *)v15); HIBYTE(v14) = *(uint16 *)v15; R40 = v14; ++ *(uint16 *)((char *)&R8_ + 1); ++ *(uint16 *)((char *)&R8_ + 1); } v9 += 2; } while ((int16)(v9 - 4096) < 0); } else { uint16 v1 = 0; uint16 v2 = 0; LOBYTE(R18_) = 0; while (1) { uint8 what = map_tiles_explored[v2]; map_tiles_explored[v2] <<= 1; if (!(what & 0x80)) { IndirWriteWord(&R3_, v1, 0xFu); } else { ++map_tiles_explored[v2]; IndirWriteWord(&R3_, v1, *(uint16 *)IndirPtr(&R0_, v1) & ~0x400); } v1 += 2; LOBYTE(R18_) = R18_ + 1; LOBYTE(v3) = R18_ - 8; if (!(uint8)sign8(v3)) { LOBYTE(R18_) = 0; if ((__int16)(++v2 - 256) >= 0) break; } } } uint16 v16 = vram_write_queue_tail; v17 = gVramWriteEntry(vram_write_queue_tail); v17->size = 4096; v17->src.addr = ADDR16_OF_RAM(ram3000); *(uint16 *)&v17->src.bank = 126; v17->vram_dst = (reg_BG1SC & 0xFC) << 8; vram_write_queue_tail = v16 + 7; } void DrawRoomSelectMapAreaLabel(void) { // 0x829628 uint16 v0 = kPauseAreaLabelTilemap[area_index]; uint16 v1 = 0; do { uint8 *v2 = RomPtr_82(v0); IndirWriteWord(&R0_, v1, *(uint16 *)v2 & 0xEFFF); v0 += 2; v1 += 2; } while ((int16)(v1 - 24) < 0); } void SetupMapScrollingForPauseMenu(uint16 a) { // 0x829E27 int16 v1; int16 v2; R20_ = a; reg_BG1HOFS = map_min_x_scroll + ((uint16)(map_max_x_scroll - map_min_x_scroll) >> 1) - 128; R18_ = 8 * (room_x_coordinate_on_map + (uint8)((uint16)(samus_x_pos & 0xFF00) >> 8)) - reg_BG1HOFS; v1 = 224 - R18_; if ((int16)(224 - R18_) >= 0) { R18_ = 32 - R18_; if ((R18_ & 0x8000u) == 0) reg_BG1HOFS -= R18_; } else { R18_ = 224 - R18_; reg_BG1HOFS -= v1; } R18_ = map_min_y_scroll + ((uint16)(map_max_y_scroll - map_min_y_scroll) >> 1) + 16; reg_BG1VOFS = -((R20_ - R18_) & 0xFFF8); R18_ = 8 * (room_y_coordinate_on_map + HIBYTE(samus_y_pos) + 1) + ((R20_ - R18_) & 0xFFF8); v2 = 64 - R18_; if ((int16)(64 - R18_) >= 0) { R18_ = 64 - R18_; reg_BG1VOFS -= v2; if (sign16(reg_BG1VOFS + 40)) reg_BG1VOFS = -40; } } void DetermineMapScrollLimits(void) { // 0x829EC4 if (has_area_map) { R8_ = 130; R6_ = addr_kPauseMenuMapData; R6_ = *(uint16 *)IndirPtr(&R6_, 2 * area_index); } else { R8_ = 0; R6_ = 2039; } R0_.bank = R8_; R0_.addr = R6_; uint16 v0 = DetermineLeftmostMapColumn(); map_min_x_scroll = MultiplyBy8(v0); if (area_index == 4) map_min_x_scroll -= 24; R0_.addr = R6_ + 131; uint16 v1 = DetermineRightmostMapColumn(); map_max_x_scroll = MultiplyBy8(v1); R0_.addr = R6_; uint16 v2 = DetermineTopmostMapColumn(); map_min_y_scroll = MultiplyBy8(v2); R0_.addr = R6_ + 124; uint16 v3 = DetermineBottommostMapColumn(); map_max_y_scroll = MultiplyBy8(v3); } uint16 MultiplyBy8(uint16 k) { // 0x829F45 return 8 * k; } static const uint8 k0x80Shr[8] = { // 0x829F4A 0x80, 0x40, 0x20, 0x10, 8, 4, 2, 1, }; static const uint8 k0x80Shr_0[8] = { 0x80, 0x40, 0x20, 0x10, 8, 4, 2, 1 }; uint16 DetermineLeftmostMapColumn(void) { uint16 v0; HIBYTE(v0) = 0; uint16 result = 0; LABEL_2: LOBYTE(v0) = result & 7; LOBYTE(R18_) = k0x80Shr[v0]; uint16 v2 = 0; while (((uint8)R18_ & *IndirPtr(&R0_, v2)) == 0) { v2 += 4; if ((int16)(v2 - 128) >= 0) { if ((int16)(++result - 64) >= 0) return 26; if ((result & 7) == 0) { R0_.addr += 1; } if (result == 32) { R0_.addr += 123; } goto LABEL_2; } } return result; } uint16 DetermineRightmostMapColumn(void) { // 0x829FA9 uint16 result = 63; LABEL_2: LOBYTE(R18_) = k0x80Shr_0[result & 7]; uint16 v1 = 0; while (((uint8)R18_ & *IndirPtr(&R0_, v1)) == 0) { v1 += 4; if ((int16)(v1 - 128) >= 0) { if ((--result & 0x8000u) != 0) return 28; if ((result & 7) == 7) { bool v2 = LOBYTE(R0_.addr)-- != 0; HIBYTE(R0_.addr) -= !v2; } if (result == 31) R0_.addr -= 124; goto LABEL_2; } } return result; } uint16 DetermineTopmostMapColumn(void) { // 0x82A009 R3_.addr = R0_.addr + 128; R3_.bank = R0_.bank; uint16 result = 0; uint16 v1 = 0; while (!*IndirPtr(&R0_, v1) && !*IndirPtr(&R3_, v1)) { if ((int16)(++v1 - 4) >= 0) { v1 = 0; R0_.addr += 4; R3_.addr += 4; if ((int16)(++result - 31) >= 0) return 1; } } return result; } uint16 DetermineBottommostMapColumn(void) { // 0x82A053 R3_.addr = R0_.addr + 128; R3_.bank = R0_.bank; uint16 result = 31; uint16 v1 = 0; while (!*IndirPtr(&R0_, v1) && !*IndirPtr(&R3_, v1)) { if ((int16)(++v1 - 4) >= 0) { v1 = 0; R0_.addr -= 4; R3_.addr -= 4; if (!--result) return 11; } } return result; } void SetupPpuForPauseMenu(void) { // 0x82A09A WriteReg(OBSEL, 1u); reg_OBSEL = 1; WriteReg(BGMODE, 9u); reg_BGMODE = 9; reg_BG12NBA = 0; WriteReg(BG12NBA, 0); reg_BG34NBA = 4; WriteReg(BG34NBA, 4u); reg_BG1SC = 49; WriteReg(BG1SC, 0x31u); reg_BG2SC = 56; WriteReg(BG2SC, 0x38u); reg_BG3SC = 88; WriteReg(BG3SC, 0x58u); reg_BG4SC = 0; WriteReg(BG4SC, 0); WriteReg(TM, 0x17u); reg_TM = 23; WriteReg(MOSAIC, 0); reg_MOSAIC = 0; reg_COLDATA[0] &= 0xE0u; reg_COLDATA[1] &= 0xE0u; reg_COLDATA[2] &= 0xE0u; next_gameplay_CGADSUB = 0; } void ResetPauseMenuAnimations(void) { // 0x82A0F7 pausemenu_reserve_tank_delay_ctr = 0; reg_BG1HOFS = 0; reg_BG2HOFS = 0; reg_BG3HOFS = 0; reg_BG2VOFS = 0; reg_BG3VOFS = 0; pausemenu_button_label_mode = 0; pausemenu_lr_animation_frame = 0; UNUSED_word_7E0745 = 0; samus_position_indicator_animation_frame = 0; samus_position_indicator_animation_timer = 0; samus_position_indicator_animation_loop_counter = 0; pausemenu_lr_animation_timer = *(uint16 *)kPauseLrHighlightAnimData; pausemenu_palette_animation_timer = 1; pausemenu_palette_animation_frame = 0; } #define kEquipmentTilemaps_Tanks ((uint16*)RomPtr(0x82c088)) #define kEquipmentTilemaps_Weapons ((uint16*)RomPtr(0x82c08c)) #define kEquipmentTilemaps_Suits ((uint16*)RomPtr(0x82c096)) #define kEquipmentTilemaps_Boots ((uint16*)RomPtr(0x82c0a2)) #define kHyperBeamWeaponsTilemaps ((uint16*)RomPtr(0x82c0a8)) #define kEquipmentBitmasks_Weapons ((uint16*)RomPtr(0x82c04c)) #define kEquipmentBitmasks_Suits ((uint16*)RomPtr(0x82c056)) #define kEquipmentBitmasks_Boots ((uint16*)RomPtr(0x82c062)) void LoadEquipmentScreenEquipmentTilemaps(void) { // 0x82A12B if (samus_max_reserve_health) { R3_.addr = addr_kEquipmentTilemapOffs_Tanks; *(uint16 *)&R3_.bank = 130; R0_.addr = *(uint16 *)IndirPtr(&R3_, 0); R22_ = 14; Copy_R22_Bytes(kEquipmentTilemaps_Tanks[0]); R3_.addr = addr_kEquipmentTilemapOffs_Tanks; *(uint16 *)&R3_.bank = 130; R0_.addr = *(uint16 *)IndirPtr(&R3_, 2u); R22_ = 14; Copy_R22_Bytes(kEquipmentTilemaps_Tanks[1]); } uint16 v0 = 0; R3_.addr = addr_kEquipmentTilemapOffs_Weapons; *(uint16 *)&R3_.bank = 130; R0_.addr = *(uint16 *)IndirPtr(&R3_, 0); if (hyper_beam_flag) { uint16 v3 = 0; do { uint16 v4 = kHyperBeamWeaponsTilemaps[v3 >> 1]; R22_ = 10; Copy_R22_Bytes(v4); v3 += 2; R0_.addr = *(uint16 *)IndirPtr(&R3_, v3); } while ((int16)(v3 - 10) < 0); } else { do { int v1 = v0 >> 1; if ((collected_beams & kEquipmentBitmasks_Weapons[v1]) != 0) { uint16 v2 = kEquipmentTilemaps_Weapons[v1]; R22_ = 10; Copy_R22_Bytes(v2); if ((equipped_beams & kEquipmentBitmasks_Weapons[v1]) == 0) { R18_ = 3072; R22_ = 10; SetPaletteOfR22TilemapBytesToR18(); } } else { R22_ = 10; Copy_R22_Bytes(addr_kEquipmentScreenTilemap_Blank); } v0 += 2; R0_.addr = *(uint16 *)IndirPtr(&R3_, v0); } while ((int16)(v0 - 12) < 0); } uint16 v5 = 0; R3_.addr = addr_kEquipmentTilemapOffs_Suits; *(uint16 *)&R3_.bank = 130; R0_.addr = *(uint16 *)IndirPtr(&R3_, 0); do { int v6 = v5 >> 1; if ((collected_items & kEquipmentBitmasks_Suits[v6]) != 0) { uint16 v7 = kEquipmentTilemaps_Suits[v6]; R22_ = 18; Copy_R22_Bytes(v7); if ((equipped_items & kEquipmentBitmasks_Suits[v6]) == 0) { R18_ = 3072; R22_ = 18; SetPaletteOfR22TilemapBytesToR18(); } } else { R22_ = 18; Copy_R22_Bytes(addr_kEquipmentScreenTilemap_Blank); } v5 += 2; R0_.addr = *(uint16 *)IndirPtr(&R3_, v5); } while ((int16)(v5 - 12) < 0); uint16 v8 = 0; R3_.addr = addr_kEquipmentTilemapOffs_Boots; *(uint16 *)&R3_.bank = 130; R0_.addr = *(uint16 *)IndirPtr(&R3_, 0); do { int v9 = v8 >> 1; if ((collected_items & kEquipmentBitmasks_Boots[v9]) != 0) { R22_ = 18; Copy_R22_Bytes(kEquipmentTilemaps_Boots[v9]); if ((equipped_items & kEquipmentBitmasks_Boots[v9]) == 0) { R18_ = 3072; R22_ = 18; SetPaletteOfR22TilemapBytesToR18(); } } else { R22_ = 18; Copy_R22_Bytes(addr_kEquipmentScreenTilemap_Blank); } v8 += 2; R0_.addr = *(uint16 *)IndirPtr(&R3_, v8); } while ((int16)(v8 - 6) < 0); } void Copy_R22_Bytes(uint16 k) { // 0x82A27E R0_.bank = 126; uint16 v1 = 0; do { uint16 *v2 = (uint16 *)RomPtr_82(k); IndirWriteWord(&R0_, v1, *v2); k += 2; v1 += 2; --R22_; --R22_; } while (R22_); } void SetPaletteOfR22TilemapBytesToR18(void) { // 0x82A29D R0_.bank = 126; uint16 v0 = 0; do { uint8 *v1 = IndirPtr(&R0_, v0); IndirWriteWord(&R0_, v0, R18_ | *(uint16 *)v1 & 0xE3FF); v0 += 2; --R22_; --R22_; } while (R22_); } void ClearSamusBeamTiles(void) { // 0x82A2BE WriteReg(VMADDL, 0); WriteReg(VMADDH, 0x60u); WriteReg(VMAIN, 0x80); static const StartDmaCopy unk_82A2D4 = { 1, 1, 0x18, LONGPTR(0x9ad200), 0x1000 }; SetupDmaTransfer(&unk_82A2D4); WriteReg(MDMAEN, 2u); } void ContinueInitGameplayResume(void) { // 0x82A2E3 int16 v0; v0 = 512; uint16 v1 = 0; do { palette_buffer[v1] = ram3000.pause_menu_map_tilemap[v1 + 384]; ++v1; v0 -= 2; } while (v0); SetupPpuForGameplayResume(); CalculateBgScrolls_Unpause(); UpdateBeamTilesAndPalette_Unpause(); ClearPauseMenuData(); CallSomeSamusCode(0xCu); } void SetupPpuForGameplayResume(void) { // 0x82A313 WriteReg(OBSEL, 3u); reg_OBSEL = 3; WriteReg(BGMODE, 9u); reg_BGMODE = 9; reg_BG12NBA = 0; WriteReg(BG12NBA, 0); reg_BG34NBA = 4; WriteReg(BG34NBA, 4u); reg_BG1SC = 81; WriteReg(BG1SC, 0x51u); reg_BG2SC = 73; WriteReg(BG2SC, 0x49u); reg_BG3SC = 90; WriteReg(BG3SC, 0x5Au); reg_BG4SC = 0; WriteReg(BG4SC, 0); } void CalculateBgScrolls_Unpause(void) { // 0x82A34E reg_BG1HOFS = bg1_x_offset + layer1_x_pos; reg_BG1VOFS = bg1_y_offset + layer1_y_pos; reg_BG2HOFS = bg2_x_scroll + layer2_x_pos; reg_BG2VOFS = bg2_y_scroll + layer2_y_pos; } void UpdateBeamTilesAndPalette_Unpause(void) { // 0x82A377 UpdateBeamTilesAndPalette(); } void ClearPauseMenuData(void) { // 0x82A380 menu_index = 0; pausemenu_start_lr_pressed_highlight_timer = 0; pausemenu_lr_animation_timer = 0; pausemenu_item_selector_animation_timer = 0; pausemenu_reserve_tank_animation_timer = 0; UNUSED_word_7E0731 = 0; pausemenu_uparrow_animation_timer = 0; pausemenu_downarrow_animation_timer = 0; pausemenu_rightarrow_animation_timer = 0; pausemenu_leftarrow_animation_timer = 0; UNUSED_word_7E073D = 0; pausemenu_lr_animation_frame = 0; pausemenu_item_selector_animation_frame = 0; pausemenu_reserve_tank_animation_frame = 0; UNUSED_word_7E0745 = 0; pausemenu_uparrow_animation_frame = 0; pausemenu_downarrow_animation_frame = 0; pausemenu_rightarrow_animation_frame = 0; pausemenu_leftarrow_animation_frame = 0; pausemenu_shoulder_button_highlight = 0; pausemenu_button_label_mode = 0; pausemenu_equipment_category_item = 0; pausemenu_reserve_tank_delay_ctr = 0; UNUSED_word_7E0759 = 0; UNUSED_word_7E075B = 0; UNUSED_word_7E075D = 0; UNUSED_word_7E075F = 0; UNUSED_word_7E0761 = 0; } void sub_82A425(void) { // 0x82A425 ; } void sub_82A42A(void) { // 0x82A42A if (samus_pose == kPose_81_FaceR_Screwattack || samus_pose == kPose_82_FaceL_Screwattack) { if ((equipped_items & 8) != 0) return; goto LABEL_8; } if ((samus_pose == kPose_1B_FaceR_SpaceJump || samus_pose == kPose_1C_FaceL_SpaceJump) && (equipped_items & 0x20) == 0) { LABEL_8: if (samus_pose_x_dir == 4) samus_pose = kPose_1A_FaceL_SpinJump; else samus_pose = kPose_19_FaceR_SpinJump; SamusFunc_F433(); Samus_SetAnimationFrameIfPoseChanged(); } } void sub_82A47B(void) { // 0x82A47B if ((equipped_items & 4) == 0) { if (samus_pose_x_dir == 4) samus_pose = kPose_41_FaceL_Morphball_Ground; else samus_pose = kPose_1D_FaceR_Morphball_Ground; SamusFunc_F433(); Samus_SetAnimationFrameIfPoseChanged(); } } void sub_82A4A9(void) { // 0x82A4A9 if ((equipped_items & 2) != 0) { if (samus_pose_x_dir == 4) samus_pose = kPose_7A_FaceL_Springball_Ground; else samus_pose = kPose_79_FaceR_Springball_Ground; SamusFunc_F433(); Samus_SetAnimationFrameIfPoseChanged(); } } void HandlePauseScreenLR(void) { // 0x82A505 HandlePauseScreenLrInput(); DrawLrHighlight(); } void HandlePauseScreenLrInput(void) { // 0x82A50C if ((newly_held_down_timed_held_input & kButton_L) != 0) { if (!pausemenu_button_label_mode) return; pausemenu_start_lr_pressed_highlight_timer = 5; menu_index = 5; pausemenu_shoulder_button_highlight = 1; pausemenu_button_label_mode = 0; SetPauseScreenButtonLabelPalettes(); goto LABEL_7; } if ((newly_held_down_timed_held_input & kButton_R) != 0 && pausemenu_button_label_mode != 2) { pausemenu_start_lr_pressed_highlight_timer = 5; menu_index = 2; pausemenu_shoulder_button_highlight = 2; pausemenu_button_label_mode = 2; SetPauseScreenButtonLabelPalettes(); LABEL_7: QueueSfx1_Max6(0x38u); } } static const uint16 kPauseLrButtonPressedHighlight_Spritemap[2] = { 0x28, 0x29 }; static const uint16 kPauseLrButtonPressedHighlight_Y[2] = { 0x18, 0xe8 }; static const uint16 kPauseLrButtonPressedHighlight_X[2] = { 0xd0, 0xd0 }; void HandlePauseMenuLRPressHighlight(void) { // 0x82A56D if (pausemenu_start_lr_pressed_highlight_timer) { --pausemenu_start_lr_pressed_highlight_timer; if (pausemenu_shoulder_button_highlight) { R3_.addr = 0; int v0 = pausemenu_shoulder_button_highlight - 1; DrawMenuSpritemap( kPauseLrButtonPressedHighlight_Spritemap[v0], kPauseLrButtonPressedHighlight_Y[v0], kPauseLrButtonPressedHighlight_X[v0] - 1); } } } void DrawLrHighlight(void) { // 0x82A59A DrawPauseScreenSpriteAnim(2u, 0x18u, 0xD0u); DrawPauseScreenSpriteAnim(2u, 0xE8u, 0xD0u); } void HandlePauseScreenStart(void) { // 0x82A5B7 if ((newly_held_down_timed_held_input & kButton_Start) != 0) { QueueSfx1_Max6(0x38u); screen_fade_delay = 1; screen_fade_counter = 1; uint16 v0 = pausemenu_button_label_mode; pausemenu_button_label_mode = 1; SetPauseScreenButtonLabelPalettes(); pausemenu_button_label_mode = v0; pausemenu_start_lr_pressed_highlight_timer = 11; ++game_state; } UpdatePauseMenuLRStartVramTilemap(); } void HighlightPauseScreenButton(void) { // 0x82A5F1 if (pausemenu_start_lr_pressed_highlight_timer) { --pausemenu_start_lr_pressed_highlight_timer; R3_.addr = 0; DrawMenuSpritemap(0x2Bu, 0x90u, 0xD0u); } } static Func_V *const kSetPauseScreenButtonLabelPalettes_Funcs[3] = { // 0x82A615 SetPauseScreenButtonLabelPalettes_0, SetPauseScreenButtonLabelPalettes_1, SetPauseScreenButtonLabelPalettes_2, }; void SetPauseScreenButtonLabelPalettes(void) { kSetPauseScreenButtonLabelPalettes_Funcs[pausemenu_button_label_mode](); } void SetPauseScreenButtonLabelPalettes_2(void) { // 0x82A628 int16 v0; int16 v2; int16 v4; int16 v6; int16 v8; int16 v10; v0 = 10; uint16 v1 = 0; do { ram3000.pause_menu_map_tilemap[v1 + 805] = ram3000.pause_menu_map_tilemap[v1 + 805] & 0xE3FF | 0x800; ++v1; v0 -= 2; } while (v0); v2 = 10; uint16 v3 = 0; do { ram3000.pause_menu_map_tilemap[v3 + 837] = ram3000.pause_menu_map_tilemap[v3 + 837] & 0xE3FF | 0x800; ++v3; v2 -= 2; } while (v2); v4 = 8; uint16 v5 = 0; do { ram3000.pause_menu_map_tilemap[v5 + 812] = ram3000.pause_menu_map_tilemap[v5 + 812] & 0xE3FF | 0x800; ++v5; v4 -= 2; } while (v4); v6 = 8; uint16 v7 = 0; do { ram3000.pause_menu_map_tilemap[v7 + 844] = ram3000.pause_menu_map_tilemap[v7 + 844] & 0xE3FF | 0x800; ++v7; v6 -= 2; } while (v6); v8 = 10; uint16 v9 = 0; do { ram3000.pause_menu_map_tilemap[v9 + 822] = ram3000.pause_menu_map_tilemap[v9 + 822] & 0xE3FF | 0x1400; ++v9; v8 -= 2; } while (v8); v10 = 10; uint16 v11 = 0; do { ram3000.pause_menu_map_tilemap[v11 + 854] = ram3000.pause_menu_map_tilemap[v11 + 854] & 0xE3FF | 0x1400; ++v11; v10 -= 2; } while (v10); } void SetPauseScreenButtonLabelPalettes_1(void) { // 0x82A6DF int16 v0; int16 v2; int16 v4; int16 v6; int16 v8; int16 v10; v0 = 8; uint16 v1 = 0; do { ram3000.pause_menu_map_tilemap[v1 + 812] = ram3000.pause_menu_map_tilemap[v1 + 812] & 0xE3FF | 0x800; ++v1; v0 -= 2; } while (v0); v2 = 8; uint16 v3 = 0; do { ram3000.pause_menu_map_tilemap[v3 + 844] = ram3000.pause_menu_map_tilemap[v3 + 844] & 0xE3FF | 0x800; ++v3; v2 -= 2; } while (v2); v4 = 10; uint16 v5 = 0; do { ram3000.pause_menu_map_tilemap[v5 + 805] = ram3000.pause_menu_map_tilemap[v5 + 805] & 0xE3FF | 0x1400; ++v5; v4 -= 2; } while (v4); v6 = 10; uint16 v7 = 0; do { ram3000.pause_menu_map_tilemap[v7 + 837] = ram3000.pause_menu_map_tilemap[v7 + 837] & 0xE3FF | 0x1400; ++v7; v6 -= 2; } while (v6); v8 = 10; uint16 v9 = 0; do { ram3000.pause_menu_map_tilemap[v9 + 822] = ram3000.pause_menu_map_tilemap[v9 + 822] & 0xE3FF | 0x1400; ++v9; v8 -= 2; } while (v8); v10 = 10; uint16 v11 = 0; do { ram3000.pause_menu_map_tilemap[v11 + 854] = ram3000.pause_menu_map_tilemap[v11 + 854] & 0xE3FF | 0x1400; ++v11; v10 -= 2; } while (v10); } void SetPauseScreenButtonLabelPalettes_0(void) { // 0x82A796 int16 v0; int16 v2; int16 v4; int16 v6; int16 v8; int16 v10; v0 = 10; uint16 v1 = 0; do { ram3000.pause_menu_map_tilemap[v1 + 822] = ram3000.pause_menu_map_tilemap[v1 + 822] & 0xE3FF | 0x800; ++v1; v0 -= 2; } while (v0); v2 = 10; uint16 v3 = 0; do { ram3000.pause_menu_map_tilemap[v3 + 854] = ram3000.pause_menu_map_tilemap[v3 + 854] & 0xE3FF | 0x800; ++v3; v2 -= 2; } while (v2); v4 = 8; uint16 v5 = 0; do { ram3000.pause_menu_map_tilemap[v5 + 812] = ram3000.pause_menu_map_tilemap[v5 + 812] & 0xE3FF | 0x800; ++v5; v4 -= 2; } while (v4); v6 = 8; uint16 v7 = 0; do { ram3000.pause_menu_map_tilemap[v7 + 844] = ram3000.pause_menu_map_tilemap[v7 + 844] & 0xE3FF | 0x800; ++v7; v6 -= 2; } while (v6); v8 = 10; uint16 v9 = 0; do { ram3000.pause_menu_map_tilemap[v9 + 805] = ram3000.pause_menu_map_tilemap[v9 + 805] & 0xE3FF | 0x1400; ++v9; v8 -= 2; } while (v8); v10 = 10; uint16 v11 = 0; do { ram3000.pause_menu_map_tilemap[v11 + 837] = ram3000.pause_menu_map_tilemap[v11 + 837] & 0xE3FF | 0x1400; ++v11; v10 -= 2; } while (v10); } void UpdatePauseMenuLRStartVramTilemap(void) { // 0x82A84D uint16 v0 = vram_write_queue_tail; gVramWriteEntry(vram_write_queue_tail)->size = 128; v0 += 2; gVramWriteEntry(v0)->size = 0x3640; v0 += 2; LOBYTE(gVramWriteEntry(v0++)->size) = 126; gVramWriteEntry(v0)->size = ((reg_BG2SC & 0xFC) << 8) + 800; vram_write_queue_tail = v0 + 2; } #define kPauseScreenSpriteAnimationData_0 (*(PauseScreenSpriteAnimationData*)RomPtr(0x82c0b2)) #define kPauseScreenSpriteAnimationData_1 (*(PauseScreenSpriteAnimationData*)RomPtr(0x82c0c4)) #define kPauseScreenSpriteAnimationData_2 (*(PauseScreenSpriteAnimationData*)RomPtr(0x82c0d6)) #define kPauseScreenSpriteAnimationData_3 (*(PauseScreenSpriteAnimationData*)RomPtr(0x82c0e8)) #define kPAuseSpritePaletteIndexValues ((uint16*)RomPtr(0x82c0fa)) #define kPausePtsToAnimationSpritemapBaseIds ((uint16*)RomPtr(0x82c1e4)) void DrawPauseScreenSpriteAnim(uint16 a, uint16 k, uint16 j) { // 0x82A881 int16 v9; int16 v10; int16 v12; R18_ = k; R20_ = j; uint16 v3 = 2 * (a - 1); uint16 v4 = *(VoidP *)((char *)&kPauseScreenSpriteAnimationData_0.unused + v3); uint8 *v5 = RomPtr_RAM(v4); bool v6 = *(uint16 *)v5 == 1; bool v7 = (int16)-- * (uint16 *)v5 < 0; if (v6 || v7) { R24_ = v4; uint8 *v8 = RomPtr_RAM(*(VoidP *)((char *)&kPauseScreenSpriteAnimationData_1.unused + v3)); v9 = *(uint16 *)v8 + 1; *(uint16 *)v8 = v9; R22_ = *(uint16 *)v8 + 2 * v9; v10 = *RomPtr_82(R22_ + *(VoidP *)((char *)&kPauseScreenSpriteAnimationData_3.unused + v3)); if (v10 == 255) { *(uint16 *)RomPtr_RAM(*(VoidP *)((char *)&kPauseScreenSpriteAnimationData_1.unused + v3)) = 0; v10 = *RomPtr_82(*(VoidP *)((char *)&kPauseScreenSpriteAnimationData_3.unused + v3)); } *(uint16 *)RomPtr_RAM(R24_) = v10; } R24_ = 3 * *(uint16 *)RomPtr_RAM(*(VoidP *)((char *)&kPauseScreenSpriteAnimationData_1.unused + v3)); v12 = R24_ + *(VoidP *)((char *)&kPauseScreenSpriteAnimationData_3.unused + v3) + 1; R3_.addr = kPAuseSpritePaletteIndexValues[3]; R24_ = *RomPtr_82(v12 + 1); R26_ = 2 * *RomPtr_RAM(*(VoidP *)((char *)&kPauseScreenSpriteAnimationData_2.unused + v3)); uint8 *v11 = RomPtr_82(R26_ + kPausePtsToAnimationSpritemapBaseIds[v3 >> 1]); DrawMenuSpritemap(R24_ + *(uint16 *)v11, R18_, R20_ - 1); } #define kPauseAnimatedPalette ((uint16*)RomPtr(0x82a987)) void HandlePauseScreenPaletteAnimation(void) { // 0x82A92B uint16 v2; uint16 j; uint8 v1; if ((uint8)pausemenu_palette_animation_timer) { LOBYTE(pausemenu_palette_animation_timer) = pausemenu_palette_animation_timer - 1; if (!(uint8)pausemenu_palette_animation_timer) { for (int i = pausemenu_palette_animation_frame + 1; ; i = 0) { LOBYTE(pausemenu_palette_animation_frame) = i; v1 = kPauseLrHighlightAnimData[(uint8)(3 * i)]; if (v1 != 0xFF) break; QueueSfx3_Max6(0x2Au); } LOBYTE(pausemenu_palette_animation_timer) = v1; LOBYTE(v2) = 0; HIBYTE(v2) = pausemenu_palette_animation_frame; uint16 v3 = (v2 >> 3) + 30; for (j = 30; (j & 0x8000u) == 0; j -= 2) { palette_buffer[(j >> 1) + 176] = kPauseAnimatedPalette[v3 >> 1]; v3 -= 2; } } } } #define kPauseReserveTankAnimationData ((uint8*)RomPtr(0x82c165)) void EquipmentScreenSetupReserveMode(void) { // 0x82AB47 VoidP v0; int16 v3; int16 v5; int16 v7; int16 v8; reg_BG4HOFS = reg_BG1HOFS; reg_BG4VOFS = reg_BG1VOFS; reg_BG1HOFS = 0; reg_BG1VOFS = 0; if (samus_max_reserve_health && reserve_health_mode) { v0 = addr_kEquipmentScreenTilemap_AUTO; if (reserve_health_mode != 1) v0 = addr_kEquipmentScreenTilemap_MANUAL; *(uint16 *)&R0_.bank = 130; R0_.addr = v0; R18_ = 4; uint16 v1 = 0; uint16 v2 = 0; do { v3 = ram3800.cinematic_bg_tilemap[v1 + 327] & 0xFC00; ram3800.cinematic_bg_tilemap[v1 + 327] = *(uint16 *)IndirPtr(&R0_, v2) | v3; v2 += 2; ++v1; --R18_; } while (R18_); } pausemenu_item_selector_animation_frame = 0; pausemenu_item_selector_animation_timer = kPauseLrHighlightAnimData[0]; pausemenu_reserve_tank_animation_frame = 0; pausemenu_reserve_tank_animation_timer = kPauseReserveTankAnimationData[0]; if (samus_max_reserve_health) { pausemenu_equipment_category_item = 0; } else if (hyper_beam_flag) { LABEL_15:; uint16 v6 = 0; do { if ((kEquipmentBitmasks_Suits[v6 >> 1] & collected_items) != 0) { LOBYTE(v7) = (uint16)(v6 >> 1) >> 8; HIBYTE(v7) = v6 >> 1; pausemenu_equipment_category_item = v7 | 2; goto LABEL_21; } v6 += 2; } while ((int16)(v6 - 12) < 0); v8 = 0; do v8 += 2; while ((int16)(v8 - 6) < 0); } else { uint16 v4 = 0; while ((kEquipmentBitmasks_Weapons[v4 >> 1] & collected_beams) == 0) { v4 += 2; if ((int16)(v4 - 10) >= 0) goto LABEL_15; } LOBYTE(v5) = (uint16)(v4 >> 1) >> 8; HIBYTE(v5) = v4 >> 1; pausemenu_equipment_category_item = v5 | 1; } LABEL_21: if (samus_reserve_health) { EquipmentScreenGlowingArrowSolidOn(); WriteSamusWireframeTilemapAndQueue(); } } void EquipmentScreenTransferBG1Tilemap(void) { // 0x82AC22 WriteReg(VMADDL, 0); WriteReg(VMADDH, 0x30u); WriteReg(VMAIN, 0x80); static const StartDmaCopy unk_82AC3B = { 1, 1, 0x18, LONGPTR(0x7e3800), 0x0800 }; SetupDmaTransfer(&unk_82AC3B); WriteReg(MDMAEN, 2u); reg_BG1VOFS = 0; } static Func_V *const kEquipmentScreenCategories[4] = { // 0x82AC4F EquipmentScreenCategory_Tanks, EquipmentScreenCategory_Weapons, EquipmentScreenCategory_Suit, EquipmentScreenCategory_Boots, }; void EquipmentScreenMain(void) { kEquipmentScreenCategories[(uint16)(2 * (uint8)pausemenu_equipment_category_item) >> 1](); EquipmentScreenDrawItemSelector(); EquipmentScreenDisplayReserveTankAmount(); WriteSamusWireframeTilemapAndQueue(); } static Func_V *const kEquipmentScreenCategory_TanksFuncs[2] = { // 0x82AC70 EquipmentScreenCategory_Tanks_0, EquipmentScreenCategory_Tanks_1, }; void EquipmentScreenCategory_Tanks(void) { kEquipmentScreenCategory_TanksFuncs[(uint16)(2 * HIBYTE(pausemenu_equipment_category_item)) >> 1](); EquipmentScreenHandleDpad(); EquipmentScreenGlowingArrow(); } void EquipmentScreenHandleDpad(void) { // 0x82AC8B R18_ = pausemenu_equipment_category_item; if ((joypad1_newkeys & kButton_Right) != 0) { if ((joypad1_newkeys & kButton_Down) != 0 || EquipmentScreenMoveLowerOnSuitsMisc(0) == 0xFFFF) EquipmentScreenMoveToHighJumpOrLowerInBoots(0); } else if ((joypad1_newkeys & kButton_Up) != 0) { if ((pausemenu_equipment_category_item & 0xFF00) != 0) { QueueSfx1_Max6(0x37u); pausemenu_equipment_category_item -= 256; } } else if ((joypad1_newkeys & kButton_Down) != 0) { if ((pausemenu_equipment_category_item & 0xFF00) == 256 || reserve_health_mode == 1 || (pausemenu_equipment_category_item += 256, !samus_reserve_health)) { EquipmentScreenMoveToBeams(0); } else { QueueSfx1_Max6(0x37u); } } } static Func_V *const kEquipmentScreenGlowingArrowFuncs[2] = { // 0x82AD0A EquipmentScreenGlowingArrowAnimated, EquipmentScreenGlowingArrowSolidOn, }; void EquipmentScreenGlowingArrow(void) { if ((uint8)pausemenu_equipment_category_item) EquipmentScreenGlowingArrowSolidOff(); else kEquipmentScreenGlowingArrowFuncs[0](); } static const uint16 kEquipmentScreenGlowingArrowPalettes0[32] = { 0x39e, 0x77d, 0xb5c, 0xf5b, 0x133a, 0x171a, 0x1f19, 0x22f8, 0x26d7, 0x2ad6, 0x2eb6, 0x3695, 0x3a94, 0x3e73, 0x4253, 0x4a52, 0x4a52, 0x4253, 0x3e73, 0x3a94, 0x3695, 0x2eb6, 0x2ad6, 0x26d7, 0x22f8, 0x1f19, 0x171a, 0x133a, 0xf5b, 0xb5c, 0x77d, 0x39e }; static const uint16 kEquipmentScreenGlowingArrowPalettes1[32] = { 0x156, 0x155, 0x554, 0x954, 0xd53, 0xd52, 0x1152, 0x1551, 0x1970, 0x1d70, 0x1d6f, 0x216e, 0x256e, 0x296d, 0x296c, 0x318c, 0x318c, 0x296c, 0x296d, 0x256e, 0x216e, 0x1d6f, 0x1d70, 0x1970, 0x1551, 0x1152, 0xd52, 0xd53, 0x954, 0x554, 0x155, 0x156 }; void EquipmentScreenGlowingArrowAnimated(void) { // 0x82AD29 if (reserve_health_mode == 1) { int v0 = nmi_frame_counter_byte & 0x1F; palette_buffer[102] = kEquipmentScreenGlowingArrowPalettes0[v0]; palette_buffer[107] = kEquipmentScreenGlowingArrowPalettes1[v0]; EquipmentScreenEnergyArrowGlow_On(); } else { palette_buffer[107] = 926; palette_buffer[102] = 342; EquipmentScreenEnergyArrowGlow_Off(); } } void EquipmentScreenGlowingArrowSolidOn(void) { // 0x82ADDD palette_buffer[107] = 926; palette_buffer[102] = 342; EquipmentScreenEnergyArrowGlow_On(); } void EquipmentScreenGlowingArrowSolidOff(void) { // 0x82ADEF palette_buffer[107] = 926; palette_buffer[102] = 342; EquipmentScreenEnergyArrowGlow_Off(); } void EquipmentScreenEnergyArrowGlow_On(void) { // 0x82AE01 int16 v0; int16 v2; v0 = 16; uint16 v1 = 0; do { ram3800.cinematic_bg_tilemap[v1 + 129] = ram3800.cinematic_bg_tilemap[v1 + 129] & 0xE3FF | 0x1800; v1 += 32; v0 -= 2; } while (v0); v2 = 4; uint16 v3 = 0; do { ram3800.cinematic_bg_tilemap[v3 + 385] = ram3800.cinematic_bg_tilemap[v3 + 385] & 0xE3FF | 0x1800; ++v3; v2 -= 2; } while (v2); } void EquipmentScreenEnergyArrowGlow_Off(void) { // 0x82AE46 int16 v0; int16 v2; v0 = 16; uint16 v1 = 0; do { ram3800.cinematic_bg_tilemap[v1 + 129] = ram3800.cinematic_bg_tilemap[v1 + 129] & 0xE3FF | 0x1C00; v1 += 32; v0 -= 2; } while (v0); v2 = 4; uint16 v3 = 0; do { ram3800.cinematic_bg_tilemap[v3 + 385] = ram3800.cinematic_bg_tilemap[v3 + 385] & 0xE3FF | 0x1C00; ++v3; v2 -= 2; } while (v2); } static const uint16 kEquipmentScreenTilemap_MODE_MANUAL[7] = { 0x2519, 0x251a, 0x251b, 0x3d46, 0x3d47, 0x3d48, 0x3d49 }; static const uint16 kEquipmentScreenTilemap_RESERVE_TANK[7] = { 0x3c80, 0x3c81, 0x3c82, 0x3c83, 0x3c84, 0x3c85, 0x3c86 }; static const uint16 kEquipmentScreenTilemap_MANUAL[4] = { 0x3d46, 0x3d47, 0x3d48, 0x3d49 }; static const uint16 kEquipmentScreenTilemap_AUTO[4] = { 0x3d56, 0x3d57, 0x3d58, 0x3d59 }; static const uint16 kEquipmentScreenTilemap_CHARGE[5] = { 0x8ff, 0x8d8, 0x8d9, 0x8da, 0x8e7 }; static const uint16 kEquipmentScreenTilemap_ICE[5] = { 0x8ff, 0x8db, 0x8dc, 0x8d4, 0x8d4 }; static const uint16 kEquipmentScreenTilemap_WAVE[5] = { 0x8ff, 0x8dd, 0x8de, 0x8df, 0x8d4 }; static const uint16 kEquipmentScreenTilemap_SPAZER[5] = { 0x8ff, 0x8e8, 0x8e9, 0x8ea, 0x8eb }; static const uint16 kEquipmentScreenTilemap_PLASMA[5] = { 0x8ff, 0x8ec, 0x8ed, 0x8ee, 0x8ef }; static const uint16 kEquipmentScreenTilemap_VARIASUIT[9] = { // 0x82AE8B 0x8ff, 0x900, 0x901, 0x902, 0x903, 0x904, 0x905, 0x8d4, 0x8d4, }; static const uint16 kEquipmentScreenTilemap_GRAVITYSUIT[9] = { 0x8ff, 0x8d0, 0x8d1, 0x8d2, 0x8d3, 0x903, 0x904, 0x905, 0x8d4, }; static const uint16 kEquipmentScreenTilemap_MORPHINGBALL[9] = { 0x8ff, 0x920, 0x921, 0x922, 0x923, 0x917, 0x918, 0x90f, 0x91f, }; static const uint16 kEquipmentScreenTilemap_BOMBS[9] = { 0x8ff, 0x8d5, 0x8d6, 0x8d7, 0x8d4, 0x8d4, 0x8d4, 0x8d4, 0x8d4, }; static const uint16 kEquipmentScreenTilemap_SPRING_BALL[9] = { 0x8ff, 0x910, 0x911, 0x912, 0x913, 0x914, 0x915, 0x916, 0x8d4, }; static const uint16 kEquipmentScreenTilemap_SCREW_ATTACK[9] = { 0x8ff, 0x8e0, 0x8e1, 0x8e2, 0x8e3, 0x8e4, 0x8e5, 0x8e6, 0x8d4, }; static const uint16 kEquipmentScreenTilemap_HIJUMP_BOOTS[9] = { 0x8ff, 0x930, 0x931, 0x932, 0x933, 0x934, 0x935, 0x936, 0x8d4, }; static const uint16 kEquipmentScreenTilemap_SPACE_JUMP[9] = { 0x8ff, 0x8f0, 0x8f1, 0x8f2, 0x8f3, 0x8f4, 0x8f5, 0x8d4, 0x8d4, }; static const uint16 kEquipmentScreenTilemap_SPEED_BOOSTER[9] = { 0x8ff, 0x924, 0x925, 0x926, 0x927, 0x928, 0x929, 0x92a, 0x92b, }; static const uint16 kEquipmentScreenTilemap_HYPER[9] = { 0x8ff, 0x937, 0x938, 0x939, 0x92f, 0x8d4, 0x8d4, 0x8d4, 0x8d4, }; static const uint16 kEquipmentScreenTilemap_Blank[9] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, }; void EquipmentScreenCategory_Tanks_0(void) { int16 v0; int16 v2; if ((joypad1_newkeys & kButton_A) != 0 && samus_max_reserve_health) { QueueSfx1_Max6(0x37u); if (reserve_health_mode == 1) { reserve_health_mode = 2; EquipmentScreenHudReserveAutoTilemap_Off(); v0 = 8; uint16 v1 = 0; do { ram3800.cinematic_bg_tilemap[v1 + 327] = kEquipmentScreenTilemap_MANUAL[v1] | ram3800.cinematic_bg_tilemap[v1 + 327] & 0xFC00; ++v1; v0 -= 2; } while (v0); } else { reserve_health_mode = 1; EquipmentScreenHudReserveAutoTilemap_On_BUGGY(); v2 = 8; uint16 v3 = 0; do { ram3800.cinematic_bg_tilemap[v3 + 327] = kEquipmentScreenTilemap_AUTO[v3] | ram3800.cinematic_bg_tilemap[v3 + 327] & 0xFC00; ++v3; v2 -= 2; } while (v2); } } } void EquipmentScreenHudReserveAutoTilemap_On_BUGGY(void) { // 0x82AEFD uint16 v0 = -26229; if (!samus_reserve_health) v0 = -26217; uint16 *v1 = (uint16 *)RomPtr_82(v0); hud_tilemap[8] = *v1; hud_tilemap[9] = v1[1]; hud_tilemap[40] = v1[2]; hud_tilemap[41] = v1[3]; hud_tilemap[72] = v1[4]; hud_tilemap[73] = v1[5]; } void EquipmentScreenHudReserveAutoTilemap_Off(void) { // 0x82AF33 hud_tilemap[8] = 11279; hud_tilemap[9] = 11279; hud_tilemap[40] = 11279; hud_tilemap[41] = 11279; hud_tilemap[72] = 11279; hud_tilemap[73] = 11279; } static const uint16 kReserveTankEnergyTransferPerFrame = 1; void EquipmentScreenCategory_Tanks_1(void) { // 0x82AF4F if (!pausemenu_reserve_tank_delay_ctr) { if ((joypad1_newkeys & kButton_A) == 0) return; pausemenu_reserve_tank_delay_ctr = (samus_reserve_health + 7) & 0xFFF8; } if ((--pausemenu_reserve_tank_delay_ctr & 7) == 7) QueueSfx3_Max6(0x2Du); samus_health += kReserveTankEnergyTransferPerFrame; if ((int16)(samus_health - samus_max_health) < 0) { bool v0 = (int16)(samus_reserve_health - kReserveTankEnergyTransferPerFrame) < 0; samus_reserve_health -= kReserveTankEnergyTransferPerFrame; if (samus_reserve_health) { if (!v0) return; samus_health += samus_reserve_health; } } else { samus_health = samus_max_health; } samus_reserve_health = 0; pausemenu_reserve_tank_delay_ctr = 0; EquipmentScreenEnergyArrowGlow_Off(); pausemenu_equipment_category_item = 0; } void EquipmentScreenCategory_Weapons(void) { // 0x82AFBE EquipmentScreenCategory_Weapons_MoveButtons(); R36 = equipped_beams; if (collected_beams) { R24_ = 10; EquipmentScreenCategory_ButtonResponse(); EquipmentScreenCategory_Weapons_PlazmaSpazerCheck(); } } void EquipmentScreenCategory_Weapons_MoveButtons(void) { // 0x82AFDB R18_ = pausemenu_equipment_category_item; if ((joypad1_newkeys & 0x100) != 0) { if ((joypad1_newkeys & 0x800) != 0) { EquipmentScreenMoveLowerOnSuitsMisc(0); } else if (EquipmentScreenMoveLowerOnSuitsMisc(4u)) { EquipmentScreenMoveToHighJumpOrLowerInBoots(0); } } else if ((joypad1_newkeys & 0x400) != 0) { if (!hyper_beam_flag && pausemenu_equipment_category_item != 1025) { pausemenu_equipment_category_item += 256; EquipmentScreenMoveToBeams(2 * HIBYTE(pausemenu_equipment_category_item)); } } else if ((joypad1_newkeys & 0x800) != 0) { if ((pausemenu_equipment_category_item & 0xFF00) == 0 || (pausemenu_equipment_category_item -= 256, EquipmentScreenMoveToBottomOfBeams(2 * HIBYTE(pausemenu_equipment_category_item)) == 0xFFFF)) { if (!EquipmentScreenMoveToReserveTanks()) pausemenu_equipment_category_item = R18_; } } } #define kEquipmentTilemapOffs_Tanks ((uint16*)RomPtr(0x82c068)) #define kEquipmentTilemapOffs_Weapons ((uint16*)RomPtr(0x82c06c)) #define kEquipmentTilemapOffs_Suits ((uint16*)RomPtr(0x82c076)) #define kEquipmentTilemapOffs_Boots ((uint16*)RomPtr(0x82c082)) #define kEquipmentTilemaps_Tanks ((uint16*)RomPtr(0x82c088)) #define kEquipmentTilemaps_Weapons ((uint16*)RomPtr(0x82c08c)) #define kEquipmentTilemaps_Suits ((uint16*)RomPtr(0x82c096)) #define kEquipmentTilemaps_Boots ((uint16*)RomPtr(0x82c0a2)) void EquipmentScreenCategory_Weapons_PlazmaSpazerCheck(void) { // 0x82B068 if (((uint8)equipped_beams & (uint8)~(uint8)R36 & 4) != 0) { if ((R36 & 4) == 0 && (equipped_beams & 8) != 0) { equipped_beams &= ~8; R0_.addr = kEquipmentTilemapOffs_Weapons[4]; goto LABEL_9; } } else if (((uint8)equipped_beams & (uint8)~(uint8)R36 & 8) != 0 && (R36 & 8) == 0 && (equipped_beams & 4) != 0) { equipped_beams &= ~4; R0_.addr = kEquipmentTilemapOffs_Weapons[3]; LABEL_9: R18_ = 3072; R22_ = 10; SetPaletteOfR22TilemapBytesToR18(); } } void EquipmentScreenCategory_Suit(void) { // 0x82B0C2 EquipmentScreenCategory_Suit_MoveResponse(); R24_ = 18; EquipmentScreenCategory_ButtonResponse(); } void EquipmentScreenCategory_Suit_MoveResponse(void) { // 0x82B0D2 R18_ = pausemenu_equipment_category_item; if ((joypad1_newkeys & kButton_Left) != 0) { if ((joypad1_newkeys & kButton_Down) == 0) { if (EquipmentScreenMoveToReserveTanks()) return; pausemenu_equipment_category_item = R18_; } EquipmentScreenMoveToBeams(0); } else if ((joypad1_newkeys & kButton_Up) != 0) { if ((pausemenu_equipment_category_item & 0xFF00) != 0) { pausemenu_equipment_category_item -= 256; EquipmentScreenMoveToScrewOrHigherOnSuits(2 * HIBYTE(pausemenu_equipment_category_item)); } } else if ((joypad1_newkeys & kButton_Down) != 0) { if ((pausemenu_equipment_category_item & 0xFF00) == 1280 || (pausemenu_equipment_category_item += 256, EquipmentScreenMoveLowerOnSuitsMisc(2 * HIBYTE(pausemenu_equipment_category_item)) == 0xFFFF)) { EquipmentScreenMoveToHighJumpOrLowerInBoots(0); } } } void EquipmentScreenCategory_Boots(void) { // 0x82B150 EquipmentScreenCategory_Boots_MoveResponse(); R24_ = 18; EquipmentScreenCategory_ButtonResponse(); } void EquipmentScreenCategory_Boots_MoveResponse(void) { // 0x82B160 R18_ = pausemenu_equipment_category_item; if ((joypad1_newkeys & kButton_Left) != 0) { if (((joypad1_newkeys & kButton_Up) != 0 || EquipmentScreenMoveToBottomOfBeams(8u) == 0xFFFF) && !EquipmentScreenMoveToReserveTanks()) { pausemenu_equipment_category_item = R18_; } } else if ((joypad1_newkeys & kButton_Down) != 0) { if (pausemenu_equipment_category_item != 515) { pausemenu_equipment_category_item += 256; EquipmentScreenMoveToHighJumpOrLowerInBoots(2 * HIBYTE(pausemenu_equipment_category_item)); } } else if ((joypad1_newkeys & kButton_Up) != 0) { if ((pausemenu_equipment_category_item & 0xFF00) == 0 || (pausemenu_equipment_category_item -= 256, EquipmentScreenCategory_Boots_MoveUpInBoots(2 * HIBYTE(pausemenu_equipment_category_item)) == 0xFFFF)) { EquipmentScreenMoveToScrewOrHigherOnSuits(0xAu); } } } void WriteSamusWireframeTilemapAndQueue(void) { // 0x82B1E0 WriteSamusWireframeTilemap(); uint16 v0 = vram_write_queue_tail; gVramWriteEntry(vram_write_queue_tail)->size = 1280; v0 += 2; gVramWriteEntry(v0)->size = ADDR16_OF_RAM(ram3800) + 256; v0 += 2; LOBYTE(gVramWriteEntry(v0++)->size) = 126; gVramWriteEntry(v0)->size = 0x3080; vram_write_queue_tail = v0 + 2; } #define kEquipmentScreenWireframeCmp ((uint16*)RomPtr(0x82b257)) #define kEquipmentScreenWireframePtrs ((uint16*)RomPtr(0x82b25f)) void WriteSamusWireframeTilemap(void) { // 0x82B20C uint16 i; for (i = 0; (equipped_items & 0x101) != kEquipmentScreenWireframeCmp[i >> 1]; i += 2) ; R0_.addr = kEquipmentScreenWireframePtrs[i >> 1]; *(uint16 *)&R0_.bank = 130; R20_ = 17; uint16 v1 = 0; uint16 v2 = 472; do { uint16 v3 = v2; R18_ = 8; do { *(uint16 *)((char *)ram3800.cinematic_bg_tilemap + v2) = *(uint16 *)IndirPtr(&R0_, v1); v2 += 2; v1 += 2; --R18_; } while (R18_); v2 = v3 + 64; --R20_; } while (R20_); } #define kEquipmentScreenPtrsToItemXYpos ((uint16*)RomPtr(0x82c18e)) void EquipmentScreenDrawItemSelector(void) { // 0x82B267 if (samus_max_reserve_health | (uint16)(collected_items | collected_beams)) { R18_ = kEquipmentScreenPtrsToItemXYpos[(uint16)(2 * (uint8)pausemenu_equipment_category_item) >> 1]; uint16 v0 = *(uint16 *)RomPtr_82(R18_ + 4 * HIBYTE(pausemenu_equipment_category_item)) - 1; uint16 v1 = *(uint16 *)RomPtr_82(R18_ + 4 * HIBYTE(pausemenu_equipment_category_item) + 2); DrawPauseScreenSpriteAnim(3u, v0, v1); } } void EquipmentScreenDisplayReserveTankAmount(void) { // 0x82B2A2 EquipmentScreenDisplayReserveTankAmount_(); } static const uint16 kEquipmentScreenReserveTank_X[6] = { // 0x82B2AA 0x18, 0x20, 0x28, 0x30, 0x38, 0x40, }; static const uint16 kEquipmentScreenReserveTank_Y = 0x60; static const uint16 kPartialReserveTankSpritemapIds[16] = { 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27 }; void EquipmentScreenDisplayReserveTankAmount_(void) { uint16 a; R3_.addr = 0; EquipmentScreenDisplayReserves_PaletteSetup(); bg3_tilemap_offset = 0; if (samus_max_reserve_health) { R44 = samus_max_reserve_health / 100; int mod_value = samus_reserve_health % 100; R50 = mod_value; R42 = samus_reserve_health / 100; R48 = R42; R46 = R42; if (R42) { uint16 v0 = 0; do { a = v0; DrawMenuSpritemap(0x1Bu, kEquipmentScreenReserveTank_X[v0 >> 1], kEquipmentScreenReserveTank_Y - 1); v0 += 2; --R46; } while (R46); bg3_tilemap_offset = a + 2; } uint16 RegWord = mod_value; if (RegWord) { uint16 v2 = 2 * (RegWord / 14); if (sign16(v2 - 7) && RegWord % 14 && (nmi_frame_counter_byte & 4) == 0) v2 += 2; if (!sign16(samus_reserve_health - 100)) v2 += 16; DrawMenuSpritemap( kPartialReserveTankSpritemapIds[v2 >> 1], kEquipmentScreenReserveTank_X[bg3_tilemap_offset >> 1], kEquipmentScreenReserveTank_Y - 1); ++R48; ++bg3_tilemap_offset; ++bg3_tilemap_offset; } while (sign16(R48 - R44)) { DrawMenuSpritemap( 0x20u, kEquipmentScreenReserveTank_X[bg3_tilemap_offset >> 1], kEquipmentScreenReserveTank_Y - 1); ++bg3_tilemap_offset; ++bg3_tilemap_offset; ++R48; } DrawMenuSpritemap( 0x1Fu, kEquipmentScreenReserveTank_X[bg3_tilemap_offset >> 1], kEquipmentScreenReserveTank_Y - 1); int div_val = R50 / 10; int mod_val = R50 % 10; ram3800.cinematic_bg_tilemap[394] = mod_val + 2052; ram3800.cinematic_bg_tilemap[393] = div_val + 2052; ram3800.cinematic_bg_tilemap[392] = R42 + 2052; } } void EquipmentScreenDisplayReserves_PaletteSetup(void) { // 0x82B3F9 R3_.addr = 1536; if (samus_reserve_health) { bool v0 = (--pausemenu_reserve_tank_animation_timer & 0x8000u) != 0; if (!pausemenu_reserve_tank_animation_timer || v0) { ++pausemenu_reserve_tank_animation_frame; uint16 v1 = kPauseReserveTankAnimationData[(uint16)(2 * pausemenu_reserve_tank_animation_frame)]; if (v1 == 255) { pausemenu_reserve_tank_animation_frame = 0; v1 = kPauseReserveTankAnimationData[0]; } pausemenu_reserve_tank_animation_timer = v1; } R3_.addr = kPAuseSpritePaletteIndexValues[3]; } } uint16 EquipmentScreenMoveToReserveTanks(void) { // 0x82B43F uint16 result = samus_max_reserve_health; if (samus_max_reserve_health) { pausemenu_equipment_category_item = 0; QueueSfx1_Max6(0x37u); return 1; } return result; } void EquipmentScreenMoveToBeams(uint16 v0) { // 0x82B456 int16 v1; if (hyper_beam_flag) { LABEL_4: pausemenu_equipment_category_item = R18_; } else { while ((kEquipmentBitmasks_Weapons[v0 >> 1] & collected_beams) == 0) { v0 += 2; if ((int16)(v0 - 10) >= 0) goto LABEL_4; } LOBYTE(v1) = (uint16)(v0 >> 1) >> 8; HIBYTE(v1) = v0 >> 1; pausemenu_equipment_category_item = v1 & 0xFF00 | 1; QueueSfx1_Max6(0x37u); } } uint16 EquipmentScreenMoveToBottomOfBeams(uint16 k) { // 0x82B489 int16 v2; if (hyper_beam_flag) return -1; while ((kEquipmentBitmasks_Weapons[k >> 1] & collected_beams) == 0) { k -= 2; if ((k & 0x8000u) != 0) return -1; } QueueSfx1_Max6(0x37u); LOBYTE(v2) = (uint16)(k >> 1) >> 8; HIBYTE(v2) = k >> 1; uint16 result = v2 & 0xFF00 | 1; pausemenu_equipment_category_item = result; return result; } uint16 EquipmentScreenMoveLowerOnSuitsMisc(uint16 v0) { // 0x82B4B7 int16 v1; while ((kEquipmentBitmasks_Suits[v0 >> 1] & collected_items) == 0) { v0 += 2; if ((int16)(v0 - 10) >= 0) return -1; } QueueSfx1_Max6(0x37u); LOBYTE(v1) = (uint16)(v0 >> 1) >> 8; HIBYTE(v1) = v0 >> 1; pausemenu_equipment_category_item = v1 & 0xFF00 | 2; return 0; } void EquipmentScreenMoveToScrewOrHigherOnSuits(uint16 v0) { // 0x82B4E6 int16 v1; while ((kEquipmentBitmasks_Suits[v0 >> 1] & collected_items) == 0) { v0 -= 2; if ((v0 & 0x8000u) != 0) { pausemenu_equipment_category_item = R18_; return; } } QueueSfx1_Max6(0x37u); LOBYTE(v1) = (uint16)(v0 >> 1) >> 8; HIBYTE(v1) = v0 >> 1; pausemenu_equipment_category_item = v1 & 0xFF00 | 2; } void EquipmentScreenMoveToHighJumpOrLowerInBoots(uint16 v0) { // 0x82B511 int16 v1; while ((kEquipmentBitmasks_Boots[v0 >> 1] & collected_items) == 0) { v0 += 2; if ((int16)(v0 - 6) >= 0) { pausemenu_equipment_category_item = R18_; return; } } QueueSfx1_Max6(0x37u); LOBYTE(v1) = (uint16)(v0 >> 1) >> 8; HIBYTE(v1) = v0 >> 1; pausemenu_equipment_category_item = v1 & 0xFF00 | 3; } uint16 EquipmentScreenCategory_Boots_MoveUpInBoots(uint16 k) { // 0x82B53F int16 v2; while ((kEquipmentBitmasks_Boots[k >> 1] & collected_items) == 0) { k -= 2; if ((k & 0x8000u) != 0) return -1; } QueueSfx1_Max6(0x37u); LOBYTE(v2) = (uint16)(k >> 1) >> 8; HIBYTE(v2) = k >> 1; uint16 result = v2 & 0xFF00 | 3; pausemenu_equipment_category_item = result; return result; } #define kEquipmentPtrsToRamTilemapOffsets ((uint16*)RomPtr(0x82c02c)) #define kEquipmentPtrsToBitmasks ((uint16*)RomPtr(0x82c034)) #define kEquipmentPtrsToBitsets ((uint16*)RomPtr(0x82c03c)) #define kEquipmentPtrsToEquipmentTilemaps ((uint16*)RomPtr(0x82c044)) void EquipmentScreenCategory_ButtonResponse(void) { // 0x82B568 if ((joypad1_newkeys & kButton_A) != 0) { QueueSfx1_Max6(0x38u); R26_ = 2 * (uint8)pausemenu_equipment_category_item; R18_ = 2 * HIBYTE(pausemenu_equipment_category_item); int v0 = R26_ >> 1; R0_.addr = *(uint16 *)RomPtr_82(R18_ + kEquipmentPtrsToRamTilemapOffsets[v0]); uint16 v1 = kEquipmentPtrsToBitsets[v0]; uint16 v2 = R18_ + kEquipmentPtrsToBitmasks[v0]; uint8 *v3 = RomPtr_RAM(v1); uint8 *v4 = RomPtr_82(v2); if ((*(uint16 *)v4 & *(uint16 *)v3) != 0) { R18_ = ~*(uint16 *)RomPtr_82(v2); uint8 *v6 = RomPtr_RAM(v1); *(uint16 *)v6 &= R18_; R18_ = 3072; R22_ = R24_; SetPaletteOfR22TilemapBytesToR18(); } else { *(uint16 *)v3 |= *(uint16 *)v4; R22_ = R24_; uint16 v5 = *(uint16 *)RomPtr_82(R18_ + kEquipmentPtrsToEquipmentTilemaps[R26_ >> 1]); Copy_R22_Bytes(v5); } } } void DrawPauseMenuDuringFadeIn(void) { // 0x82B62B if (menu_index) { EquipmentScreenDrawItemSelector(); EquipmentScreenDisplayReserveTankAmount(); } else { MapScreenDrawSamusPositionIndicator(); DrawMapIcons(); DisplayMapElevatorDestinations(); } } void UNKNOWN_sub_82B650(void) { // 0x82B650 if (pausemenu_button_label_mode) { DisplayMapElevatorDestinations(); MapScreenDrawSamusPositionIndicator(); DrawMapIcons(); } else { EquipmentScreenDrawItemSelector(); EquipmentScreenDisplayReserveTankAmount(); } } static const uint16 kMap_Criteria_SavePoints[16] = { 0xd8, 0x28, 0x90, 0x38, 0xfffe, 0xfffe, 0xfffe, 0xfffe, 0xfffe, 0xfffe, 0xfffe, 0xfffe, 0xfffe, 0xfffe, 0xfffe, 0xfffe }; void DrawMapIcons(void) { // 0x82B672 DrawBossMapIcons(9u, addr_kMapIconDataPointers); R3_.addr = 3584; DrawSimpleMapIcons(0xBu, addr_kMapIconDataPointers + 0x10); DrawSimpleMapIcons(0xAu, addr_kMapIconDataPointers + 0x20); DrawSimpleMapIcons(0x4Eu, addr_kMapIconDataPointers + 0x30); R3_.addr = 1024; DrawSaveStationMapIcon(8u, 0xC80B); if (enable_debug) DrawSimpleMapIcons(8u, 0xC82B); if (!area_index) { R3_.addr = 3584; DrawMenuSpritemap( 0x63u, kMap_Criteria_SavePoints[0] - reg_BG1HOFS, kMap_Criteria_SavePoints[1] - reg_BG1VOFS); } } #define kMapIconDataPointers ((MapIconDataPointers*)RomPtr(0x82c7cb)) void DrawFileSelectMapIcons(void) { // 0x82B6DD int16 v0; HandlePauseScreenPaletteAnimation(); DrawBossMapIcons(9u, 0xC7CBu); R3_.addr = 3584; DrawSimpleMapIcons(0xBu, 0xC7DBu); DrawSimpleMapIcons(0xAu, 0xC7EBu); DrawSimpleMapIcons(0x4Eu, 0xC7FBu); R3_.addr = 3584; uint16 a = UpdateSamusPositionIndicatorAnimation(); *(uint16 *)&R0_.bank = 130; R0_.addr = *(VoidP *)((char *)&kMapIconDataPointers[4].crateria + (uint16)(2 * area_index)); v0 = 4 * load_station_index; uint16 v1 = *(uint16 *)IndirPtr(&R0_, 4 * load_station_index) - reg_BG1HOFS; uint16 v2 = *(uint16 *)IndirPtr(&R0_, v0 + 2) - reg_BG1VOFS; if ((samus_position_indicator_animation_loop_counter & 1) == 0) DrawMenuSpritemap(0x12u, v1, v2); DrawMenuSpritemap(a, v1, v2); if (enable_debug) { R3_.addr = 1536; DrawDebugSaveMapIcons(0xCu, 0xC80B); DrawDebugElevatorMapIcons(0x17u, 0xC81B); DrawSimpleMapIcons(0xCu, 0xC82B); } if (!area_index) { R3_.addr = 3584; DrawMenuSpritemap( 0x63u, kMap_Criteria_SavePoints[0] - reg_BG1HOFS, kMap_Criteria_SavePoints[1] - reg_BG1VOFS); } } void DrawSaveStationMapIcon(uint16 a, uint16 k) { // 0x82B798 static const uint8 kShlBit[8] = { 1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80 }; R32 = k; R34 = a; if (area_index == sram_area_index) { R36 = *(uint16 *)&used_save_stations_and_elevators[(uint16)(2 * area_index)]; LOBYTE(R36) = R36 & kShlBit[load_station_index]; uint16 v2 = *(uint16 *)RomPtr_82(R32 + 2 * area_index); if (v2) DrawMapIconsOfType(v2); } } void DrawDebugSaveMapIcons(uint16 a, uint16 k) { // 0x82B7D1 R32 = k; R34 = a; R36 = *(uint16 *)&used_save_stations_and_elevators[(uint16)(2 * area_index)]; uint16 v2 = *(uint16 *)RomPtr_82(k + 2 * area_index); if (v2) DrawMapIconsOfType(v2); } void DrawDebugElevatorMapIcons(uint16 a, uint16 k) { // 0x82B7EB R32 = k; R34 = a; R36 = *(uint16 *)&used_save_stations_and_elevators[(uint16)(2 * area_index) + 1]; uint16 v2 = *(uint16 *)RomPtr_82(k + 2 * area_index); if (v2) DrawMapIconsOfType(v2); } void DrawSimpleMapIcons(uint16 a, uint16 k) { // 0x82B805 R32 = k; R34 = a; R36 = -1; uint16 v2 = *(uint16 *)RomPtr_82(k + 2 * area_index); if (v2) DrawMapIconsOfType(v2); } void DrawMapIconsOfType(uint16 a) { // 0x82B81C char v3; // cf int16 v4; while (1) { uint16 *v2 = (uint16 *)RomPtr_82(a); if ((*v2 & 0x8000u) != 0) break; v3 = R36 & 1; R36 >>= 1; if (v3) { v4 = CheckIfMapPositionIsExplored(*v2, v2[1]); if (v4) { uint8 *v5 = RomPtr_82(a); DrawMenuSpritemap(R34, *(uint16 *)v5 - reg_BG1HOFS, *((uint16 *)v5 + 1) - reg_BG1VOFS); } } a += 4; } } uint16 CheckIfMapPositionIsExplored(uint16 k, uint16 j) { // 0x82B855 static const uint8 kBits0x80Shr[8] = { 0x80, 0x40, 0x20, 0x10, 8, 4, 2, 1 }; uint16 v2; uint16 v4; // dx R18_ = (uint16)(k & 0xFF00) >> 1; R18_ += (uint8)k >> 6; R18_ += (uint16)(j & 0xFFF8) >> 1; uint16 v3 = (k >> 3) & 7; HIBYTE(v2) = HIBYTE(v3); LOBYTE(v2) = map_tiles_explored[R18_]; HIBYTE(v4) = HIBYTE(v3); LOBYTE(v4) = kBits0x80Shr[v3]; return (v4 & v2) != 0; } void DrawBossMapIcons(uint16 a, uint16 k) { // 0x82B892 int16 v4; char v5; // cf R32 = k; R34 = a; R36 = boss_bits_for_area[area_index]; uint8 *v2 = RomPtr_82(k + 2 * area_index); if (*(uint16 *)v2) { for (int i = *(uint16 *)v2; ; i += 4) { v4 = *(uint16 *)RomPtr_82(i); if (v4 == -1) return; if (v4 != -2) { R3_.addr = 3584; v5 = R36 & 1; R36 >>= 1; if (v5) { { uint8 *v7 = RomPtr_82(i); DrawMenuSpritemap(0x62u, *(uint16 *)v7 - reg_BG1HOFS, *((uint16 *)v7 + 1) - reg_BG1VOFS); R3_.addr = 3072; } LABEL_7:; uint8 *v6 = RomPtr_82(i); DrawMenuSpritemap(R34, *(uint16 *)v6 - reg_BG1HOFS, *((uint16 *)v6 + 1) - reg_BG1VOFS); continue; } if (has_area_map) goto LABEL_7; } R36 >>= 1; } } } void DrawMapScrollArrowAndCheckToScroll(uint8 db, uint16 k) { // 0x82B90A uint16 *v1 = (uint16 *)RomPtrWithBank(db, k); DrawPauseScreenSpriteAnim(v1[2], *v1, v1[1]); uint8 *v2 = RomPtrWithBank(db, k); if ((joypad1_lastkeys & *((uint16 *)v2 + 3)) != 0 && !map_scrolling_direction) map_scrolling_direction = *((uint16 *)v2 + 4); } void sub_82B932(void) { // 0x82B932 HandleMapScrollArrows(); } #define g_stru_82B9A0 ((MapScrollArrowData*)RomPtr(0x82b9a0)) #define g_stru_82B9AA ((MapScrollArrowData*)RomPtr(0x82b9aa)) #define g_stru_82B9B4 ((MapScrollArrowData*)RomPtr(0x82b9b4)) #define g_stru_82B9BE (*(MapScrollArrowData*)RomPtr(0x82b9be)) void HandleMapScrollArrows(void) { // 0x82B934 if (sign16(map_min_x_scroll - 24 - reg_BG1HOFS)) DrawMapScrollArrowAndCheckToScroll(0x82, addr_stru_82B9A0); if (!sign16(map_max_x_scroll - 232 - reg_BG1HOFS)) DrawMapScrollArrowAndCheckToScroll(0x82, addr_stru_82B9AA); if (sign16(map_min_y_scroll - 56 - reg_BG1VOFS)) DrawMapScrollArrowAndCheckToScroll(0x82, addr_stru_82B9B4); if (sign16(map_max_y_scroll - 177 - reg_BG1VOFS)) { if (map_scrolling_direction == g_stru_82B9BE.map_scroll_dir) { map_scrolling_gear_switch_timer = 0; map_scrolling_direction = 0; map_scrolling_speed_index = 0; } } else { DrawMapScrollArrowAndCheckToScroll(0x82, addr_stru_82B9BE); } } void MapScreenDrawSamusPositionIndicator(void) { // 0x82B9C8 R3_.addr = 3584; uint16 a = UpdateSamusPositionIndicatorAnimation(); DrawMenuSpritemap( a, 8 * (room_x_coordinate_on_map + HIBYTE(samus_x_pos)) - reg_BG1HOFS, 8 * (room_y_coordinate_on_map + HIBYTE(samus_y_pos) + 1) - reg_BG1VOFS); } static const uint16 kMap_SamusPositionIndicator_Delays[4] = { 8, 4, 8, 4 }; static const uint16 kMap_SamusPositionIndicator_SpritemapIds[4] = { 0x5f, 0x60, 0x61, 0x60 }; uint16 UpdateSamusPositionIndicatorAnimation(void) { // 0x82B9FC uint16 v0 = samus_position_indicator_animation_timer; if (!v0) { uint16 v1 = samus_position_indicator_animation_frame + 2; if ((int16)(v1 - 8) >= 0) { ++samus_position_indicator_animation_loop_counter; v1 = 0; } samus_position_indicator_animation_frame = v1; v0 = kMap_SamusPositionIndicator_Delays[v1 >> 1]; samus_position_indicator_animation_timer = v0; } samus_position_indicator_animation_timer = v0 - 1; return kMap_SamusPositionIndicator_SpritemapIds[samus_position_indicator_animation_frame >> 1]; } void DrawBorderAroundSamusData(void) { // 0x82BA35 R3_.addr = 3584; DrawMenuSpritemap(0x48u, 0x80, 0x10u); } void DrawBorderAroundDataCopyMode(void) { // 0x82BA48 R3_.addr = 3584; DrawMenuSpritemap(0x49u, 0x80, 0x10u); } void DrawBorderAroundDataClearMode(void) { // 0x82BA5B R3_.addr = 3584; DrawMenuSpritemap(0x4Au, 0x7Cu, 0x10u); } static const uint16 kDrawMenuSelectionMissile_Enable[4] = { 8, 8, 8, 8 }; static const uint16 kDrawMenuSelectionMissile_SpriteMap[4] = { 0x37, 0x36, 0x35, 0x34 }; void DrawMenuSelectionMissile(void) { // 0x82BA6E if (enemy_projectile_enable_flag) { if (!--enemy_projectile_enable_flag) { enemy_projectile_id[0] = (LOBYTE(enemy_projectile_id[0]) + 1) & 3; enemy_projectile_enable_flag = kDrawMenuSelectionMissile_Enable[enemy_projectile_id[0]]; } } R3_.addr = 3584; DrawMenuSpritemap( kDrawMenuSelectionMissile_SpriteMap[enemy_projectile_id[0]], enemy_projectile_id[5], enemy_projectile_id[10]); } #define file_copy_arrow_stuff ((FileCopyArrowStuff*)RomPtr(0x82bb0c)) void DrawFileCopyArrow(void) { // 0x82BABA uint16 v0; if ((int16)(enemy_projectile_id[16] - enemy_projectile_id[17]) >= 0) { v0 = 3; if (sign16(enemy_projectile_id[16] - enemy_projectile_id[17] - 2)) { v0 = 4; if (enemy_projectile_id[16] != 1) v0 = 5; } } else { v0 = 0; if (sign16(enemy_projectile_id[17] - enemy_projectile_id[16] - 2)) { v0 = 1; if (enemy_projectile_id[16]) v0 = 2; } } R3_.addr = 512; DrawMenuSpritemap( file_copy_arrow_stuff[v0].spritemap, file_copy_arrow_stuff[v0].xpos, file_copy_arrow_stuff[v0].ypos); } #define kMapElevatorDests ((uint16*)RomPtr(0x82c74d)) void DisplayMapElevatorDestinations(void) { // 0x82BB30 R3_.addr = 0; if (map_station_byte_array[area_index]) { for (int i = kMapElevatorDests[area_index]; ; i += 6) { uint8 *v1 = RomPtr_82(i); if (*(uint16 *)v1 == 0xFFFF) break; DrawMenuSpritemap(*((uint16 *)v1 + 2), *(uint16 *)v1 - reg_BG1HOFS, *((uint16 *)v1 + 1) - reg_BG1VOFS); } } } void HandleGameOverBabyMetroid(void) { // 0x82BB75 if (enemy_data[0].instruction_timer) sub_82BB7F(enemy_data[0].instruction_timer); else sub_82BBDD(); } void CallBabyMetroidPlaySfx(uint32 ea) { switch (ea) { case fnBabyMetroidPlaySfx0x23: BabyMetroidPlaySfx0x23(); return; case fnBabyMetroidPlaySfx0x26: BabyMetroidPlaySfx0x26(); return; case fnBabyMetroidPlaySfx0x27: BabyMetroidPlaySfx0x27(); return; default: Unreachable(); } } void sub_82BB7F(uint16 a) { // 0x82BB7F uint16 current_instruction = enemy_data[0].current_instruction; enemy_data[0].instruction_timer = a - 1; if (a == 1) { uint8 *v2 = RomPtr_82(enemy_data[0].current_instruction); if (*((uint16 *)v2 + 3) == 0xFFFF) { sub_82BBDD(); } else if ((int16)(*((uint16 *)v2 + 3) + 1) >= 0) { enemy_data[0].instruction_timer = *((uint16 *)v2 + 3); enemy_data[0].current_instruction += 6; DrawBabyMetroid(current_instruction + 6); } else { R18_ = *((uint16 *)v2 + 3); CallBabyMetroidPlaySfx(R18_ | 0x820000); } } else { DrawBabyMetroid(enemy_data[0].current_instruction); } } void sub_82BBDD(void) { // 0x82BBDD enemy_data[0].current_instruction = addr_kgameOverBabyMetridInstructionList; enemy_data[0].instruction_timer = 10; sub_82BB7F(0xAu); } void DrawBabyMetroid(uint16 k) { // 0x82BB9E uint16 v1 = *((uint16 *)RomPtr_82(k) + 2); uint16 v2 = 0; do { palette_buffer[(v2 >> 1) + 192] = *(uint16 *)RomPtr_82(v1); v1 += 2; v2 += 2; } while ((int16)(v2 - 32) < 0); R3_.addr = 2048; uint8 *v3 = RomPtr_82(k); DrawMenuSpritemap(*((uint16 *)v3 + 1), 0x7Cu, 0x50u); R3_.addr = 2560; DrawMenuSpritemap(0x64u, 0x7Cu, 0x50u); } void FinishProcessingGameOverBabyMetroidAsm(void) { // 0x82BBF0 uint16 current_instruction = enemy_data[0].current_instruction; enemy_data[0].instruction_timer = *((uint16 *)RomPtr_82(enemy_data[0].current_instruction) + 4); enemy_data[0].current_instruction += 8; if (*(uint16 *)RomPtr_82(current_instruction + 8) == 0xFFFF) sub_82BBDD(); else DrawBabyMetroid(enemy_data[0].current_instruction); } void BabyMetroidPlaySfx0x23(void) { // 0x82BC0C QueueSfx3_Max6(0x23u); FinishProcessingGameOverBabyMetroidAsm(); } void BabyMetroidPlaySfx0x26(void) { // 0x82BC15 QueueSfx3_Max6(0x26u); FinishProcessingGameOverBabyMetroidAsm(); } void BabyMetroidPlaySfx0x27(void) { // 0x82BC1E QueueSfx3_Max6(0x27u); FinishProcessingGameOverBabyMetroidAsm(); } void CancelSoundEffects(void) { // 0x82BE17 QueueSfx1_Max6(2u); QueueSfx2_Max6(0x71u); QueueSfx3_Max6(1u); } void QueueSamusMovementSfx(void) { // 0x82BE2F if ((speed_boost_counter & 0xFF00) == 1024) QueueSfx3_Max6(0x2Bu); if (!sign16(flare_counter - 16)) QueueSfx1_Max6(0x41u); CallSomeSamusCode(0x14u); } uint8 AdvancePaletteFadeForAllPalettes_0xc(void) { // 0x82D961 palette_change_denom = 12; return AdvancePaletteFadeForAllPalettes(); } uint8 AdvancePaletteFade_BgPalette6(void) { // 0x82D96C palette_change_denom = 12; if (palette_change_num <= 0xDu) { for (int i = 192; i < 0xE0u; i += 2) palette_buffer[i >> 1] = CalculateNthTransitionColorFromXtoY( palette_change_num, palette_buffer[i >> 1], target_palettes[i >> 1]); ++palette_change_num; return 0; } else { palette_change_num = 0; return 1; } } uint8 AdvanceGradualColorChangeOfPalette(uint16 k, uint16 j) { // 0x82D9B8 palette_change_denom = 15; if ((int16)(15 - palette_change_num) >= 0) { R34 = j; do { palette_buffer[k >> 1] = CalculateNthTransitionColorFromXtoY( palette_change_num + 1, palette_buffer[k >> 1], target_palettes[k >> 1]); k += 2; } while (k < R34); ++palette_change_num; return 0; } else { palette_change_num = 0; return 1; } } uint8 AdvancePaletteFadeForAllPalettes(void) { // 0x82DA02 if ((uint16)(palette_change_denom + 1) >= palette_change_num) { for (int i = 0; i < 0x200u; i += 2) { g_word_7EC404 = i; int v2 = i >> 1; if (target_palettes[v2] != palette_buffer[v2]) { uint16 v3 = CalculateNthTransitionColorFromXtoY(palette_change_num, palette_buffer[v2], target_palettes[v2]); i = g_word_7EC404; palette_buffer[g_word_7EC404 >> 1] = v3; } } ++palette_change_num; return 0; } else { palette_change_num = 0; return 1; } } uint16 CalculateNthTransitionColorFromXtoY(uint16 a, uint16 k, uint16 j) { // 0x82DA4A int16 v3; char v4; // t0 int16 v8; uint16 v7 = CalculateNthTransitionColorComponentFromXtoY(a, k & 0x1F, j & 0x1F); v8 = v7 | (32 * CalculateNthTransitionColorComponentFromXtoY(a, (k >> 5) & 0x1F, (j >> 5) & 0x1F)); v3 = 4 * CalculateNthTransitionColorComponentFromXtoY( a, ((uint16)(k >> 2) >> 8) & 0x1F, ((uint16)(j >> 2) >> 8) & 0x1F); v4 = v3; LOBYTE(v3) = HIBYTE(v3); HIBYTE(v3) = v4; return v8 | v3; } uint16 CalculateNthTransitionColorComponentFromXtoY(uint16 a, uint16 k, uint16 j) { // 0x82DAA6 int16 v4; char v6; // t0 int16 v8; if (!a) return k; v4 = a - 1; if (v4 == palette_change_denom) return j; R20_ = v4 + 1; R18_ = j - k; uint16 v5 = abs16(j - k); v6 = v5; LOBYTE(v5) = HIBYTE(v5); HIBYTE(v5) = v6; uint16 RegWord = SnesDivide(v5 & 0xFF00, palette_change_denom - R20_ + 1); R18_ = sign16(R18_) ? -RegWord : RegWord; LOBYTE(v8) = HIBYTE(k); HIBYTE(v8) = k; return (uint16)(R18_ + v8) >> 8; } uint8 sub_82DAF7(uint16 a) { // 0x82DAF7 palette_change_denom = 12; return sub_82DB0C(a); } uint8 sub_82DB0C(uint16 a) { // 0x82DB0C if ((uint16)(palette_change_denom + 1) >= palette_change_num) { g_word_7EC404 = 0; while (a) { if (!(a & 1)) g_word_7EC404 += 32; else sub_82DB41(); a >>= 1; } ++palette_change_num; return 0; } else { palette_change_num = 0; return 1; } } void sub_82DB41(void) { // 0x82DB41 uint16 v0 = g_word_7EC404; do { int v1 = v0 >> 1; if (target_palettes[v1] != palette_buffer[v1]) { uint16 v2 = CalculateNthTransitionColorFromXtoY(palette_change_num, palette_buffer[v1], target_palettes[v1]); v0 = g_word_7EC404; palette_buffer[g_word_7EC404 >> 1] = v2; } v0 += 2; g_word_7EC404 = v0; } while ((v0 & 0x1F) != 0); } void HandleSamusOutOfHealthAndGameTile(void) { // 0x82DB69 if ((int16)samus_health <= 0) { if ((reserve_health_mode & 1) != 0 && samus_reserve_health) { time_is_frozen_flag = 0x8000; game_state = kGameState_27_ReserveTanksAuto; CallSomeSamusCode(0x1Bu); } else { if (game_state != kGameState_8_MainGameplay) return; time_is_frozen_flag = 0x8000; CallSomeSamusCode(0x11u); game_state = kGameState_19_SamusNoHealth; } } if (!sign16(++game_time_frames - 60)) { game_time_frames = 0; if (!sign16(++game_time_seconds - 60)) { game_time_seconds = 0; if (!sign16(++game_time_minutes - 60)) { game_time_minutes = 0; ++game_time_hours; } } } if (!sign16(game_time_hours - 100)) { game_time_frames = 59; game_time_seconds = 59; game_time_minutes = 59; game_time_hours = 99; } } CoroutineRet GameState_27_ReserveTanksAuto(void) { // 0x82DC10 if (RefillHealthFromReserveTanks()) { time_is_frozen_flag = 0; game_state = kGameState_8_MainGameplay; CallSomeSamusCode(0x10u); } GameState_8_MainGameplay(); Samus_LowHealthCheck_0(); return kCoroutineNone; } uint8 RefillHealthFromReserveTanks(void) { // 0x82DC31 if (samus_reserve_health) { if ((nmi_frame_counter_word & 7) == 0) QueueSfx3_Max3(0x2Du); if ((int16)(++samus_health - samus_max_health) >= 0) { samus_health = samus_max_health; LABEL_9: samus_reserve_health = 0; return samus_reserve_health == 0; } bool v0 = (--samus_reserve_health & 0x8000u) != 0; if (!samus_reserve_health) goto LABEL_9; if (v0) { samus_health += samus_reserve_health; goto LABEL_9; } } return samus_reserve_health == 0; } CoroutineRet GameState_19_SamusNoHealth(void) { // 0x82DC80 uint16 j; uint16 k; uint16 m; GameState_8_MainGameplay(); for (int i = 255; i >= 0; --i) ram3000.pause_menu_map_tilemap[i + 384] = palette_buffer[i]; for (j = 382; (j & 0x8000u) == 0; j -= 2) target_palettes[j >> 1] = 0; for (k = 94; (k & 0x8000u) == 0; k -= 2) target_palettes[(k >> 1) + 208] = 0; for (m = 30; (m & 0x8000u) == 0; m -= 2) target_palettes[(m >> 1) + 192] = palette_buffer[(m >> 1) + 192]; game_options_screen_index = 3; g_word_7E0DE4 = 0; g_word_7E0DE6 = 0; g_word_7E0DE8 = 0; hud_item_index = 0; samus_auto_cancel_hud_item_index = 0; samus_invincibility_timer = 0; samus_knockback_timer = 0; ++game_state; return kCoroutineNone; } CoroutineRet GameState_20_SamusNoHealth_BlackOut(void) { // 0x82DCE0 GameState_8_MainGameplay(); palette_change_denom = 6; if (AdvancePaletteFadeForAllPalettes()) { WaitUntilEndOfVblankAndClearHdma(); DisableIrqInterrupts(); fx_layer_blending_config_a = 0; cur_irq_handler = 0; next_gameplay_CGWSEL = 0; next_gameplay_CGADSUB = 0; reg_TM = 16; reg_TS = 0; reg_TMW = 0; reg_TSW = 0; reg_BGMODE = 9; game_options_screen_index = 0; screen_fade_delay = 0; screen_fade_counter = 0; for (int i = 254; i >= 0; i -= 2) enemy_projectile_y_subpos[(i >> 1) + 15] = 0; g_word_7E0DE8 = 16; game_options_screen_index = 3; g_word_7E0DE4 = 0; g_word_7E0DE6 = 0; ++game_state; power_bomb_explosion_status = 0; QueueSfx1_Max15(2u); QueueSfx2_Max15(0x71u); QueueSfx3_Max15(1u); QueueMusic_Delayed8(0); QueueMusic_Delayed8(0xFF39u); QueueMusic_DelayedY(5u, 0xEu); } return kCoroutineNone; } CoroutineRet GameState_21_SamusNoHealth(void) { // 0x82DD71 Samus_DrawWhenNotAnimatingOrDying(); if (!HasQueuedMusic()) { StartSamusDeathAnimation(); ++game_state; } return kCoroutineNone; } CoroutineRet GameState_22_SamusNoHealth_Dying(void) { // 0x82DD87 DrawSamusStartingDeathAnim_(); bool v0 = (--g_word_7E0DE8 & 0x8000u) != 0; if (!g_word_7E0DE8 || v0) ++game_state; return kCoroutineNone; } CoroutineRet GameState_23_SamusNoHealth_Flashing(void) { // 0x82DD9A if (HandleSamusDeathSequence()) ++game_state; else Samus_DrawDuringDeathAnim(); return kCoroutineNone; } CoroutineRet GameState_24_SamusNoHealth_Explosion(void) { // 0x82DDAF if (GameState_24_SamusNoHealth_Explosion_Helper()) { screen_fade_delay = 1; screen_fade_counter = 1; ++game_state; } return kCoroutineNone; } CoroutineRet GameState_25_SamusNoHealth_BlackOut(void) { // 0x82DDC7 HandleFadeOut(); if (reg_INIDISP == 0x80) { EnableNMI(); screen_fade_delay = 0; screen_fade_counter = 0; ++game_state; menu_index = 0; debug_disable_sounds = 0; } return kCoroutineNone; } void LoaadDesinationRoomCreBitset(void) { // 0x82DDF1 uint16 room_definition_ptr = get_DoorDef(door_def_ptr)->room_definition_ptr; previous_cre_bitset = cre_bitset; cre_bitset = get_RoomDefHeader(room_definition_ptr)->cre_bitset_; } void LoadDoorHeader(void) { // 0x82DE12 DoorDef *DoorDef; int16 samus_distance_from_door; DoorDef = get_DoorDef(door_def_ptr); room_ptr = DoorDef->room_definition_ptr; elevator_door_properties_orientation = *(uint16 *)&DoorDef->door_bitflags; elevator_flags = elevator_door_properties_orientation & 0x80; door_direction = DoorDef->door_orientation; door_destination_x_pos = DoorDef->x_pos_in_room << 8; door_destination_y_pos = DoorDef->y_pos_in_room << 8; R18_ = 0; R20_ = 0; samus_distance_from_door = DoorDef->samus_distance_from_door; if (samus_distance_from_door < 0) { if ((door_direction & 2) != 0) samus_distance_from_door = 384; else samus_distance_from_door = 200; } *(uint16 *)((char *)&R18_ + 1) = samus_distance_from_door; samus_door_transition_subspeed = R18_; samus_door_transition_speed = R20_; } void LoadRoomHeader(void) { // 0x82DE6F RoomDefHeader *RoomDefHeader; RoomDefHeader = get_RoomDefHeader(room_ptr); room_index = RoomDefHeader->semiunique_room_number; area_index = RoomDefHeader->area_index_; room_x_coordinate_on_map = RoomDefHeader->x_coordinate_on_map; room_y_coordinate_on_map = RoomDefHeader->y_coordinate_on_map; room_width_in_scrolls = RoomDefHeader->width; room_width_in_blocks = 16 * room_width_in_scrolls; room_height_in_scrolls = RoomDefHeader->height; room_height_in_blocks = 16 * room_height_in_scrolls; up_scroller = RoomDefHeader->up_scroller_; down_scroller = RoomDefHeader->down_scroller_; door_list_pointer = RoomDefHeader->ptr_to_doorout; HandleRoomDefStateSelect(room_ptr); uint16 prod = Mult8x8(room_width_in_blocks, room_height_in_blocks); room_size_in_blocks = 2 * prod; } #define kStateHeaderGraphicsSets ((uint16*)RomPtr(0x8fe7a7)) void LoadStateHeader(void) { // 0x82DEF2 StateHeaderTiles *StateHeaderTiles; // r10 RoomDefRoomstate *RoomDefRoomstate; // r11 int v0 = (uint16)(2 * get_RoomDefRoomstate(roomdefroomstate_ptr)->graphics_set) >> 1; StateHeaderTiles = get_StateHeaderTiles(kStateHeaderGraphicsSets[v0]); copy24(&tileset_tile_table_pointer, &StateHeaderTiles->tile_table_ptr); copy24(&tileset_tiles_pointer, &StateHeaderTiles->tiles_ptr); copy24(&tileset_compr_palette_ptr, &StateHeaderTiles->palette_ptr); RoomDefRoomstate = get_RoomDefRoomstate(roomdefroomstate_ptr); copy24(&room_compr_level_data_ptr, &RoomDefRoomstate->compressed_room_map_ptr); room_music_data_index = RoomDefRoomstate->music_track; room_music_track_index = RoomDefRoomstate->music_control; room_layer3_asm_ptr = RoomDefRoomstate->room_layer3_fx_ptr; room_enemy_population_ptr = RoomDefRoomstate->enemy_population_ptr_; room_enemy_tilesets_ptr = RoomDefRoomstate->enemy_tilesets_ptr; *(uint16 *)&layer2_scroll_x = RoomDefRoomstate->vertical_screen_nudge_limit; room_main_code_ptr = RoomDefRoomstate->main_code_ptr; } void WaitUntilEndOfVblankAndEnableIrq(void) { // 0x82DF69 if ((reg_NMITIMEN & 0x30) != 0x30) EnableIrqInterruptsNow(); } void PointlessFunctionStupidToo(void) { // 0x82DF80 } void SaveMapExploredifElevator(void) { // 0x82DF99 if ((elevator_door_properties_orientation & 0xF) != 0) SetElevatorsAsUsed(); if ((get_DoorDef(door_def_ptr)->door_bitflags & 0x40) != 0) SaveExploredMapTilesToSaved(); } void LoadMapExploredIfElevator(void) { // 0x82DFB6 if ((get_DoorDef(door_def_ptr)->door_bitflags & 0x40) != 0) LoadMirrorOfExploredMapTiles(); } void EnsureSamusDrawnEachFrame(void) { // 0x82DFC7 if (!elevator_flags) Samus_DrawWhenNotAnimatingOrDying(); } void LoadEnemyGfxToVram(void) { // 0x82DFD1 EnemyDef_A2 *EnemyDef_A2; R18_ = 28672; uint16 v0 = room_enemy_tilesets_ptr; if (room_enemy_tilesets_ptr) { for (int i = room_enemy_tilesets_ptr; ; v0 = i) { uint16 enemy_def = get_EnemyTileset(v0)->enemy_def; if (enemy_def == 0xFFFF) break; EnemyDef_A2 = get_EnemyDef_A2(enemy_def); copy24(&door_transition_vram_update_src, &EnemyDef_A2->tile_data); if ((EnemyDef_A2->tile_data_size & 0x8000u) != 0) { door_transition_vram_update_size = EnemyDef_A2->tile_data_size & 0x7FFF; door_transition_vram_update_dst = ((uint16)(get_EnemyTileset(i)->vram_dst & 0xF000) >> 4) | 0x6000; } else { door_transition_vram_update_size = EnemyDef_A2->tile_data_size; door_transition_vram_update_dst = R18_; R18_ += EnemyDef_A2->tile_data_size >> 1; } WaitForIrqDoorTransitionVramUpdate(); i += 4; } } } void CopyToVramAtNextInterrupt(const void *p) { // 0x82E039 const CopyToVramAtNextInterruptArgs *pp = (const CopyToVramAtNextInterruptArgs *)p; door_transition_vram_update_src = pp->source; door_transition_vram_update_dst = pp->dest; door_transition_vram_update_size = pp->size; WaitForIrqDoorTransitionVramUpdate(); } void LoadRoomMusic(void) { // 0x82E071 if (game_state < kGameState_40_TransitionToDemo && room_music_data_index && room_music_data_index != music_data_index) { QueueMusic_Delayed8(0); QueueMusic_Delayed8((uint8)room_music_data_index | 0xFF00); } } void UpdateMusicTrackIndex(void) { // 0x82E09B if (game_state < kGameState_40_TransitionToDemo && room_music_track_index) { R18_ = (uint8)room_music_data_index << 8; R18_ |= room_music_track_index; R20_ = (uint8)music_data_index << 8; R20_ |= music_track_index; if (R18_ != R20_) music_track_index = room_music_track_index; } } void LoadNewMusicTrackIfChanged(void) { // 0x82E0D5 if (game_state < 0x28u && room_music_track_index) { R18_ = (uint8)room_music_data_index << 8; R18_ |= room_music_track_index; R20_ = (uint8)music_data_index << 8; R20_ |= music_track_index; if (R18_ != R20_) QueueMusic_DelayedY(room_music_track_index, 6u); } } void NullFunc(void) { // 0x82E113 ; } void PlayRoomMusicTrackAfterAFrames(uint16 a) { // 0x82E118 if (game_state < kGameState_40_TransitionToDemo) { QueueMusic_DelayedY(0, a); QueueMusic_Delayed8(music_track_index); } } #define kCommonSpritesPalette1 ((uint16*)RomPtr(0x9afc00)) void LoadColorsForSpritesBeamsAndEnemies(void) { // 0x82E139 uint16 j; uint16 k; for (int i = 30; i >= 0; i -= 2) target_palettes[(i >> 1) + 208] = kInitialPalette[(i >> 1) + 208]; for (j = 30; (j & 0x8000u) == 0; j -= 2) target_palettes[(j >> 1) + 224] = palette_buffer[(j >> 1) + 224]; for (k = 30; (k & 0x8000u) == 0; k -= 2) target_palettes[(k >> 1) + 128] = kCommonSpritesPalette1[k >> 1]; } CoroutineRet CallDoorTransitionFunction_Async(uint32 ea) { switch (ea) { case fnDoorTransitionFunction_HandleElevator: return DoorTransitionFunction_HandleElevator(); case fnDoorTransitionFunction_Wait48frames: return DoorTransitionFunction_Wait48frames(); case fnDoorTransitionFunction_WaitForSoundsToFinish: return DoorTransitionFunction_WaitForSoundsToFinish(); case fnDoorTransitionFunction_FadeOutScreen: return DoorTransitionFunction_FadeOutScreen(); case fnDoorTransitionFunction_LoadDoorHeaderEtc: return DoorTransitionFunction_LoadDoorHeaderEtc(); case fnDoorTransitionFunction_ScrollScreenToAlignment: return DoorTransitionFunction_ScrollScreenToAlignment(); case fnDoorTransitionFunction_FixDoorsMovingUp: return DoorTransitionFunction_FixDoorsMovingUp(); case fnDoorTransitionFunction_SetupNewRoom: return DoorTransitionFunction_SetupNewRoom(); case fnDoorTransitionFunction_SetupScrolling: return DoorTransitionFunction_SetupScrolling(); case fnDoorTransitionFunction_PlaceSamusLoadTiles: return DoorTransitionFunction_PlaceSamusLoadTiles(); case fnDoorTransitionFunction_LoadMoreThings_Async: return DoorTransitionFunction_LoadMoreThings_Async(); case fnDoorTransition_C_HandleAnimTiles: return DoorTransition_C_HandleAnimTiles(); case fnDoorTransition_WaitForMusicToClear: return DoorTransition_WaitForMusicToClear(); case fnDoorTransition_HandleTransition: return DoorTransition_HandleTransition(); case fnDoorTransition_FadeInScreenAndFinish: return DoorTransition_FadeInScreenAndFinish(); default: return Unreachable(); } } CoroutineRet GameState_9_HitDoorBlock(void) { // 0x82E169 return CallDoorTransitionFunction_Async(door_transition_function | 0x820000); } CoroutineRet DoorTransitionFunction_HandleElevator(void) { // 0x82E17D if (!elevator_flags) { ++game_state; return GameState_10_LoadingNextRoom_Async(); } CallSomeSamusCode(0); if ((elevator_direction & 0x8000u) != 0) { ++game_state; return GameState_10_LoadingNextRoom_Async(); } downwards_elevator_delay_timer = 48; door_transition_function = FUNC16(DoorTransitionFunction_Wait48frames); return DoorTransitionFunction_Wait48frames(); } CoroutineRet DoorTransitionFunction_Wait48frames(void) { // 0x82E19F if ((--downwards_elevator_delay_timer & 0x8000u) != 0) { ++game_state; return GameState_10_LoadingNextRoom_Async(); } else { DetermineWhichEnemiesToProcess(); EnemyMain(); DrawSamusEnemiesAndProjectiles(); EnsureSamusDrawnEachFrame(); } return kCoroutineNone; } CoroutineRet GameState_10_LoadingNextRoom_Async(void) { // 0x82E1B7 door_transition_flag_enemies = 1; door_transition_flag_elevator_zebetites = 1; debug_disable_minimap = 0; save_station_lockout_flag = 0; DetermineWhichEnemiesToProcess(); EnemyMain(); DrawSamusEnemiesAndProjectiles(); EnsureSamusDrawnEachFrame(); LoaadDesinationRoomCreBitset(); for (int i = 254; i >= 0; i -= 2) { int v1 = i >> 1; target_palettes[v1] = 0; target_palettes[v1 + 128] = 0; } target_palettes[9] = palette_buffer[9]; target_palettes[10] = palette_buffer[10]; target_palettes[13] = palette_buffer[13]; target_palettes[14] = palette_buffer[14]; target_palettes[17] = palette_buffer[17]; target_palettes[18] = palette_buffer[18]; target_palettes[19] = palette_buffer[19]; target_palettes[29] = palette_buffer[29]; if (((previous_cre_bitset | cre_bitset) & 1) == 0) { target_palettes[20] = palette_buffer[20]; target_palettes[21] = palette_buffer[21]; target_palettes[22] = palette_buffer[22]; target_palettes[23] = palette_buffer[23]; target_palettes[28] = palette_buffer[28]; if (timer_status) { target_palettes[209] = palette_buffer[209]; target_palettes[210] = palette_buffer[210]; target_palettes[212] = palette_buffer[212]; target_palettes[221] = palette_buffer[221]; DrawTimer(); } } ClearSoundsWhenGoingThroughDoor(); QueueSfx2_Max15(0x71u); debug_disable_sounds = -1; door_transition_function = FUNC16(DoorTransitionFunction_WaitForSoundsToFinish); ++game_state; return kCoroutineNone; } CoroutineRet GameState_11_LoadingNextRoom_Async(void) { // 0x82E288 COROUTINE_AWAIT_ONLY(CallDoorTransitionFunction_Async(door_transition_function | 0x820000)); if (timer_status) DrawTimer(); return kCoroutineNone; } CoroutineRet DoorTransitionFunction_WaitForSoundsToFinish(void) { // 0x82E29E DetermineWhichEnemiesToProcess(); EnemyMain(); DrawSamusEnemiesAndProjectiles(); EnsureSamusDrawnEachFrame(); if (((sfx_writepos[0] - sfx_readpos[0]) & 0xF) == 0 && ((sfx_writepos[1] - sfx_readpos[1]) & 0xF) == 0 && ((sfx_writepos[2] - sfx_readpos[2]) & 0xF) == 0) { door_transition_function = FUNC16(DoorTransitionFunction_FadeOutScreen); } return kCoroutineNone; } CoroutineRet DoorTransitionFunction_FadeOutScreen(void) { // 0x82E2DB if (AdvancePaletteFadeForAllPalettes_0xc()) { door_transition_function = FUNC16(DoorTransitionFunction_LoadDoorHeaderEtc); } else { DetermineWhichEnemiesToProcess(); EnemyMain(); DrawSamusEnemiesAndProjectiles(); EnsureSamusDrawnEachFrame(); } return kCoroutineNone; } CoroutineRet DoorTransitionFunction_LoadDoorHeaderEtc(void) { // 0x82E2F7 LoadDoorHeader(); sub_8882AC(); hdma_objects_enable_flag &= ~0x8000u; irqhandler_next_handler = 8; door_transition_function = FUNC16(DoorTransitionFunction_ScrollScreenToAlignment); return kCoroutineNone; } CoroutineRet DoorTransitionFunction_ScrollScreenToAlignment(void) { // 0x82E310 if ((door_direction & 2) != 0) { if ((uint8)layer1_x_pos) { if ((layer1_x_pos & 0x80) != 0) ++layer1_x_pos; else --layer1_x_pos; goto LABEL_10; } } else if ((uint8)layer1_y_pos) { if ((layer1_y_pos & 0x80) != 0) ++layer1_y_pos; else --layer1_y_pos; LABEL_10: CalculateLayer2PosAndScrollsWhenScrolling(); return kCoroutineNone; } CalculateLayer2PosAndScrollsWhenScrolling(); door_transition_function = FUNC16(DoorTransitionFunction_FixDoorsMovingUp); return kCoroutineNone; } CoroutineRet DoorTransitionFunction_FixDoorsMovingUp(void) { // 0x82E353 if ((door_direction & 3) == 3) FixDoorsMovingUp(); door_transition_function = FUNC16(DoorTransitionFunction_SetupNewRoom); return kCoroutineNone; } CoroutineRet DoorTransitionFunction_SetupNewRoom(void) { // 0x82E36E SaveMapExploredifElevator(); LoadRoomHeader(); LoadStateHeader(); LoadMapExploredIfElevator(); InitializeSpecialEffectsForNewRoom(); LoadLevelScrollAndCre(); door_transition_function = FUNC16(DoorTransitionFunction_SetupScrolling); return kCoroutineNone; } CoroutineRet DoorTransitionFunction_SetupScrolling(void) { // 0x82E38E reg_BG2HOFS = 0; reg_BG2VOFS = 0; scrolling_finished_hook = 0; if ((door_direction & 3) == 2) ++reg_BG1VOFS; if ((door_direction & 3) != 3) door_transition_frame_counter = 0; DoorTransitionScrollingSetup(); door_transition_function = FUNC16(DoorTransitionFunction_PlaceSamusLoadTiles); return kCoroutineNone; } CoroutineRet DoorTransitionFunction_PlaceSamusLoadTiles(void) { // 0x82E3C0 static const LongPtr unk_82E421 = LONGPTR(0x7e7000); static const LongPtr unk_82E432 = LONGPTR(0x7e2000); static const LongPtr unk_82E443 = LONGPTR(0x7ec200); static const CopyToVramAtNextInterruptArgs unk_82E449 = { LONGPTR(0x7e2000), 0x0000, 0x2000 }; static const CopyToVramAtNextInterruptArgs unk_82E453 = { LONGPTR(0x7e4000), 0x1000, 0x2000 }; static const CopyToVramAtNextInterruptArgs unk_82E45D = { LONGPTR(0x7e6000), 0x2000, 0x1000 }; static const CopyToVramAtNextInterruptArgs unk_82E477 = { LONGPTR(0x7e7000), 0x2800, 0x1000 }; static const CopyToVramAtNextInterruptArgs unk_82E481 = { LONGPTR(0x7e8000), 0x3000, 0x2000 }; static const CopyToVramAtNextInterruptArgs unk_82E48B = { LONGPTR(0x9ab200), 0x4000, 0x1000 }; uint16 v0; samus_x_pos = layer1_x_pos + (uint8)samus_x_pos; samus_prev_x_pos = samus_x_pos; samus_y_pos = layer1_y_pos + (uint8)samus_y_pos; samus_prev_y_pos = samus_y_pos; door_transition_flag = 0; door_transition_vram_update_enabled = 0; if ((door_direction & 3) == 2) v0 = 16; else v0 = 22; irqhandler_next_handler = v0; WaitUntilEndOfVblankAndEnableIrq(); if ((cre_bitset & 2) != 0 && door_def_ptr != (uint16)addr_kDoorDef_947a) { mov24(&decompress_src, 0xb98000); DecompressToMem_IpArg(&unk_82E421); } copy24(&decompress_src, &tileset_tiles_pointer); DecompressToMem_IpArg(&unk_82E432); copy24(&decompress_src, &tileset_compr_palette_ptr); DecompressToMem_IpArg(&unk_82E443); CopyToVramAtNextInterrupt(&unk_82E449); CopyToVramAtNextInterrupt(&unk_82E453); CopyToVramAtNextInterrupt(&unk_82E45D); if ((cre_bitset & 6) != 0 && door_def_ptr != (uint16)addr_kDoorDef_947a) { CopyToVramAtNextInterrupt(&unk_82E477); CopyToVramAtNextInterrupt(&unk_82E481); CopyToVramAtNextInterrupt(&unk_82E48B); } if ((door_direction & 3) == 3) irqhandler_next_handler = 16; door_transition_function = FUNC16(DoorTransitionFunction_LoadMoreThings_Async); return kCoroutineNone; } static Func_Y_Y *const kUpdateBackgroundCommands[8] = { UpdateBackgroundCommand_0_Finish, UpdateBackgroundCommand_2_TransferToVram, UpdateBackgroundCommand_4_Decompression, UpdateBackgroundCommand_6_ClearFxTilemap, UpdateBackgroundCommand_8_TransferToVramAndSetBg3, UpdateBackgroundCommand_A_ClearBg2Tilemap, UpdateBackgroundCommand_C_ClearKraidBg2Tilemap, UpdateBackgroundCommand_E_DoorDependentTransferToVRAM, }; CoroutineRet DoorTransitionFunction_LoadMoreThings_Async(void) { int16 bg_data_ptr; COROUTINE_BEGIN(coroutine_state_1, 0); LoadEnemyGfxToVram(); LoadRoomMusic(); ClearEnemyProjectiles(); ClearAnimtiles(); ClearPaletteFXObjects(); ClearPLMs(); CreatePlmsExecuteDoorAsmRoomSetup(); LoadFXHeader(); SpawnDoorClosingPLM(); UpdateBeamTilesAndPalette(); LoadColorsForSpritesBeamsAndEnemies(); LoadEnemies(); InitializeEnemies(); ResetProjectileData(); Samus_LoadSuitTargetPalette(); ClearFxTilemap(); *(VoidP *)((char *)&door_transition_vram_update_src.addr + 1) = -30208; if (fx_tilemap_ptr) { door_transition_vram_update_src.addr = fx_tilemap_ptr; door_transition_vram_update_dst = addr_unk_605BE0; door_transition_vram_update_size = 2112; WaitForIrqDoorTransitionVramUpdate(); } bg_data_ptr = get_RoomDefRoomstate(roomdefroomstate_ptr)->bg_data_ptr; if (bg_data_ptr < 0) { do { int v1 = *(uint16 *)RomPtr_8F(bg_data_ptr) >> 1; bg_data_ptr = kUpdateBackgroundCommands[v1](bg_data_ptr + 2); } while (bg_data_ptr); } // Wait until the screen has finished scrolling as a result of the door opening while ((door_transition_flag & 0x8000u) == 0) { COROUTINE_AWAIT(1, WaitForNMI_Async()); } palette_buffer[196] = 15328; SpawnBG3ScrollHdmaObject(); hdma_objects_enable_flag |= 0x8000; COROUTINE_AWAIT(2, PlmHandler_Async()); if ((door_direction & 2) == 0) { if ((door_direction & 3) != 0) samus_x_pos &= 0xFFF8u; else samus_x_pos |= 7u; } door_transition_function = FUNC16(DoorTransition_C_HandleAnimTiles); COROUTINE_END(0); } static const CopyToVramAtNextInterruptArgs unk_82E5B5 = { LONGPTR(0x7e4000), 0x4000, 0x1000 }; static const CopyToVramAtNextInterruptArgs unk_82E5BF = { LONGPTR(0x7e4000), 0x4800, 0x1000 }; static const CopyToVramAtNextInterruptArgs unk_82E57B = { LONGPTR(0x7e4000), 0x5880, 0x0f00 }; static const CopyToVramAtNextInterruptArgs unk_82E598 = { LONGPTR(0x7e4000), 0x4800, 0x1000 }; void ClearFxTilemap(void) { // 0x82E566 for (int i = 959; i >= 0; --i) { ram4000.xray_tilemaps[i] = 6222; ram4000.xray_tilemaps[i + 960] = 6222; } CopyToVramAtNextInterrupt(&unk_82E57B); } void ClearBg2Tilemap(void) { // 0x82E583 for (int i = 1023; i >= 0; --i) { ram4000.xray_tilemaps[i] = 824; ram4000.xray_tilemaps[i + 1024] = 824; } CopyToVramAtNextInterrupt(&unk_82E598); } void ClearKraidBg2Tilemap(void) { // 0x82E5A0 for (int i = 1023; i >= 0; --i) { ram4000.xray_tilemaps[i] = 824; ram4000.xray_tilemaps[i + 1024] = 824; } CopyToVramAtNextInterrupt(&unk_82E5B5); CopyToVramAtNextInterrupt(&unk_82E5BF); } uint16 UpdateBackgroundCommand_0_Finish(uint16 y) { // 0x82E5D7 return 0; } uint16 UpdateBackgroundCommand_E_DoorDependentTransferToVRAM(uint16 j) { // 0x82E5D9 if (door_def_ptr == *(uint16 *)RomPtr_8F(j)) return UpdateBackgroundCommand_2_TransferToVram(j + 2); else return j + 9; } uint16 UpdateBackgroundCommand_2_TransferToVram(uint16 j) { // 0x82E5EB uint8 *v1 = RomPtr_8F(j); door_transition_vram_update_dst = *(uint16 *)(v1 + 3); copy24(&door_transition_vram_update_src, (LongPtr *)v1); door_transition_vram_update_size = *(uint16 *)(v1 + 5); WaitForIrqDoorTransitionVramUpdate(); return j + 7; } uint16 UpdateBackgroundCommand_4_Decompression(uint16 j) { // 0x82E616 LongPtr *v1; v1 = (LongPtr *)RomPtr_8F(j); copy24(&decompress_src, v1); *(VoidP *)((char *)&decompress_dst.addr + 1) = 32256; decompress_dst.addr = v1[1].addr; DecompressToMem(); return j + 5; } uint16 UpdateBackgroundCommand_6_ClearFxTilemap(uint16 j) { // 0x82E637 ClearFxTilemap(); return j; } uint16 UpdateBackgroundCommand_8_TransferToVramAndSetBg3(uint16 j) { // 0x82E63E j = UpdateBackgroundCommand_2_TransferToVram(j); reg_BG34NBA = 2; return j; } uint16 UpdateBackgroundCommand_A_ClearBg2Tilemap(uint16 j) { // 0x82E64B ClearBg2Tilemap(); return j; } uint16 UpdateBackgroundCommand_C_ClearKraidBg2Tilemap(uint16 j) { // 0x82E652 ClearKraidBg2Tilemap(); return j; } CoroutineRet DoorTransition_C_HandleAnimTiles(void) { // 0x82E659 AnimtilesHandler(); door_transition_function = FUNC16(DoorTransition_WaitForMusicToClear); return kCoroutineNone; } CoroutineRet DoorTransition_WaitForMusicToClear(void) { // 0x82E664 if (!HasQueuedMusic()) { door_transition_function = FUNC16(DoorTransition_HandleTransition); LoadNewMusicTrackIfChanged(); } return kCoroutineNone; } CoroutineRet DoorTransition_HandleTransition(void) { // 0x82E6A2 if ((samus_x_pos & 0xF0) == 16) { samus_x_pos = (samus_x_pos | 0xF) + 8; } else if ((samus_x_pos & 0xF0) == 224) { samus_x_pos = (samus_x_pos & 0xFFF0) - 8; } if ((samus_y_pos & 0xF0) == 16) samus_y_pos = (samus_y_pos | 0xF) + 8; for (int i = 510; i >= 0; i -= 2) { *(uint16 *)&mother_brain_indirect_hdma[i] = 0; *(uint16 *)(&hdma_window_1_left_pos[0].field_0 + i) = 0; } uint16 v1 = room_loading_irq_handler; if (!room_loading_irq_handler) v1 = 4; irqhandler_next_handler = v1; PointlessFunctionStupidToo(); if (elevator_flags) { if ((elevator_direction & 0x8000u) == 0) CallSomeSamusCode(7u); else CallSomeSamusCode(0); } SetLiquidPhysicsType(); door_transition_function = FUNC16(DoorTransition_FadeInScreenAndFinish); *(uint16 *)®_INIDISP |= 0x1Fu; return kCoroutineNone; } CoroutineRet DoorTransition_FadeInScreenAndFinish(void) { // 0x82E737 AnimtilesHandler(); DetermineWhichEnemiesToProcess(); EnemyMain(); EprojRunAll(); DrawSamusEnemiesAndProjectiles(); EnsureSamusDrawnEachFrame(); QueueEnemyBG2TilemapTransfers(); if (AdvancePaletteFadeForAllPalettes_0xc()) { debug_disable_sounds = 0; PlaySpinJumpSoundIfSpinJumping(); door_transition_flag_elevator_zebetites = 0; door_transition_flag_enemies = 0; game_state = kGameState_8_MainGameplay; } return kCoroutineNone; } void LoadDestinationRoomThings(void) { // 0x82E76B LoaadDesinationRoomCreBitset(); LoadDoorHeader(); LoadRoomHeader(); LoadStateHeader(); LoadCRETilesTilesetTilesAndPalette(); } void LoadCRETilesTilesetTilesAndPalette(void) { // 0x82E783 elevator_flags = 0; WriteRegWord(VMAIN, 0x80); mov24(&decompress_src, 0xb98000); decompress_dst.addr = addr_unk_605000; WriteRegWord(VMADDL, 0x2800u); DecompressToVRAM(); copy24(&decompress_src, &tileset_tiles_pointer); WriteRegWord(VMADDL, 0); decompress_dst.addr = 0; DecompressToVRAM(); *(VoidP *)((char *)&decompress_src.addr + 1) = *(VoidP *)((char *)&tileset_compr_palette_ptr.addr + 1); decompress_src.addr = tileset_compr_palette_ptr.addr; static const LongPtr unk_82E7CD = LONGPTR(0x7ec200); DecompressToMem_IpArg(&unk_82E7CD); } void LoadLevelDataAndOtherThings(void) { // 0x82E7D3 uint16 j; int16 v3; uint16 k; RoomDefRoomstate *v12; RoomDefRoomstate *RoomDefRoomstate; int16 rdf_scroll_ptr; uint16 m; char v10; char v11; uint16 n; char v14; static const LongPtr unk_82E849 = LONGPTR(0x7ea000); static const LongPtr unk_82E85A = LONGPTR(0x7ea800); static const LongPtr unk_82E86D = LONGPTR(0x7ea000); for (int i = 25598; i >= 0; i -= 2) level_data[i >> 1] = 0x8000; copy24(&decompress_src, &room_compr_level_data_ptr); static const DecompressToParams unk_82E7F8 = { LONGPTR(0x7f0000) }; DecompressToMem_IpArg(&unk_82E7F8); uint16 v1 = ram7F_start; for (j = ram7F_start + ram7F_start + (ram7F_start >> 1); ; custom_background[v1 >> 1] = level_data[j >> 1]) { j -= 2; v1 -= 2; if ((v1 & 0x8000u) != 0) break; } v3 = ram7F_start >> 1; for (k = ram7F_start + (ram7F_start >> 1); ; *(uint16 *)&BTS[(uint16)v3] = level_data[k >> 1]) { k -= 2; v3 -= 2; if (v3 < 0) break; } if (area_index == 6) { copy24(&decompress_src, &tileset_tile_table_pointer); DecompressToMem_IpArg(&unk_82E86D); } else { mov24(&decompress_src, 0xb9a09d); DecompressToMem_IpArg(&unk_82E849); copy24(&decompress_src, &tileset_tile_table_pointer); DecompressToMem_IpArg(&unk_82E85A); } RoomDefRoomstate = get_RoomDefRoomstate(roomdefroomstate_ptr); rdf_scroll_ptr = RoomDefRoomstate->rdf_scroll_ptr; if (rdf_scroll_ptr >= 0) { R18_ = RoomDefRoomstate->rdf_scroll_ptr; LOBYTE(R20_) = room_height_in_scrolls - 1; uint8 v8 = 2; uint8 v9 = 0; v10 = 0; do { if (v10 == (uint8)R20_) v8 = R18_ + 1; v14 = v10; v11 = 0; do { scrolls[v9++] = v8; ++v11; } while (v11 != (uint8)room_width_in_scrolls); v10 = v14 + 1; } while (v14 + 1 != (uint8)room_height_in_scrolls); } else { for (m = 0; m != 50; m += 2) { *(uint16 *)&scrolls[m] = *(uint16 *)RomPtr_8F(rdf_scroll_ptr); rdf_scroll_ptr += 2; } } v12 = get_RoomDefRoomstate(roomdefroomstate_ptr); if (v12->room_plm_header_ptr) { for (n = v12->room_plm_header_ptr; get_RoomPlmEntry(n)->plm_header_ptr_; n += 6) SpawnRoomPLM(n); } RunDoorSetupCode(); RunRoomSetupCode(); if (elevator_flags) elevator_status = 2; } void SpawnDoorClosingPLM(void) { // 0x82E8EB if (!CheckIfColoredDoorCapSpawned()) { uint16 *v0 = (uint16 *)RomPtr_8F(2 * door_direction - 6518); if (*v0) { R18_ = *v0; R20_ = *(uint16 *)&get_DoorDef(door_def_ptr)->x_pos_plm; //SpawnRoomPLM(0x12u); // WTF? } } } uint8 CheckIfColoredDoorCapSpawned(void) { // 0x82E91C DoorDef *DoorDef; int16 x_pos_plm; int16 v2; int16 v6; DoorDef = get_DoorDef(door_def_ptr); uint16 prod = Mult8x8(DoorDef->y_pos_plm, room_width_in_blocks); x_pos_plm = DoorDef->x_pos_plm; v2 = 2 * (prod + x_pos_plm); uint16 v3 = 78; while (v2 != plm_block_indices[v3 >> 1]) { v3 -= 2; if ((v3 & 0x8000u) != 0) return 0; } int v5 = v3 >> 1; if (!plm_header_ptr[v5]) return 0; v6 = plm_room_arguments[v5]; if (v6 >= 0) { int idx = PrepareBitAccess(v6); if ((bitmask & opened_door_bit_array[idx]) != 0) return 0; } int v7 = v3 >> 1; plm_instruction_timer[v7] = 1; uint16 v8 = plm_header_ptr[v7]; if (!v8) return 0; plm_instr_list_ptrs[v3 >> 1] = get_PlmHeader_Size4(v8)[1].func_ptr; return 1; } static Func_Y_Y *const kLoadLibraryBackgroundFuncs[8] = { // 0x82E97C LoadLibraryBackgroundFunc_0_DONE, LoadLibraryBackgroundFunc_2_TransferToVram, LoadLibraryBackgroundFunc_4_Decompress, LoadLibraryBackgroundFunc_6_ClearFxTilemap, LoadLibraryBackgroundFunc_8_TransferToVramAndSetBg3, LoadLibraryBackgroundFunc_A_ClearBG2Tilemap, LoadLibraryBackgroundFunc_C_ClearKraidLayer2, LoadLibraryBackgroundFunc_E_DoorDependentTransferToVram, }; void LoadLibraryBackground(void) { int16 bg_data_ptr; ClearFXTilemap(); if (fx_tilemap_ptr) { WriteRegWord(A1T1L, fx_tilemap_ptr); WriteRegWord(VMADDL, addr_unk_605BE0); WriteRegWord(DMAP1, 0x1801u); WriteRegWord(A1B1, 0x8Au); WriteRegWord(DAS1L, 0x840u); WriteReg(VMAIN, 0x80); WriteReg(MDMAEN, 2u); } bg_data_ptr = get_RoomDefRoomstate(roomdefroomstate_ptr)->bg_data_ptr; if (bg_data_ptr < 0) { do { uint16 v1 = *(uint16 *)RomPtr_8F(bg_data_ptr); bg_data_ptr += 2; bg_data_ptr = kLoadLibraryBackgroundFuncs[v1 >> 1](bg_data_ptr); } while (bg_data_ptr); } } uint16 LoadLibraryBackgroundFunc_0_DONE(uint16 j) { // 0x82E9E5 return 0; } uint16 LoadLibraryBackgroundFunc_E_DoorDependentTransferToVram(uint16 j) { // 0x82E9E7 if (door_def_ptr == get_LoadBg_E(j)->field_0) return LoadLibraryBackgroundFunc_2_TransferToVram(j + 2); else return j + 9; } uint16 LoadLibraryBackgroundFunc_2_TransferToVram(uint16 j) { // 0x82E9F9 uint16 *LoadBg_28 = (uint16 *)get_LoadBg_28(j); WriteRegWord(VMADDL, *(uint16 *)((char *)LoadBg_28 + 3)); WriteRegWord(DMAP1, 0x1801u); WriteRegWord(A1T1L, *LoadBg_28); WriteRegWord(A1B1, LoadBg_28[1]); WriteRegWord(DAS1L, *(uint16 *)((char *)LoadBg_28 + 5)); WriteReg(VMAIN, 0x80); WriteReg(MDMAEN, 2u); return j + 7; } uint16 LoadLibraryBackgroundFunc_4_Decompress(uint16 j) { // 0x82EA2D LongPtr *LoadBg_28; LoadBg_28 = (LongPtr *)get_LoadBg_28(j); copy24(&decompress_src, LoadBg_28); *(VoidP *)((char *)&decompress_dst.addr + 1) = 32256; decompress_dst.addr = LoadBg_28[1].addr; DecompressToMem(); return j + 5; } uint16 LoadLibraryBackgroundFunc_6_ClearFxTilemap(uint16 j) { // 0x82EA4E ClearFXTilemap(); return j; } uint16 LoadLibraryBackgroundFunc_A_ClearBG2Tilemap(uint16 j) { // 0x82EA56 ClearBG2Tilemap(); return j; } uint16 LoadLibraryBackgroundFunc_C_ClearKraidLayer2(uint16 j) { // 0x82EA5E ClearBG2Tilemap(); return j; } uint16 LoadLibraryBackgroundFunc_8_TransferToVramAndSetBg3(uint16 j) { // 0x82EA66 j = LoadLibraryBackgroundFunc_2_TransferToVram(j); reg_BG34NBA = 2; return j; } void LoadLevelScrollAndCre(void) { // 0x82EA73 uint16 j; int16 v3; uint16 k; RoomDefRoomstate *RoomDefRoomstate; int16 rdf_scroll_ptr; uint16 m; char v10; char v11; char v12; static const LongPtr unk_82EAA0 = LONGPTR(0x7f0000); static const LongPtr unk_82EAF9 = LONGPTR(0x7ea000); static const LongPtr unk_82EB0A = LONGPTR(0x7ea800); static const LongPtr unk_82EB1D = LONGPTR(0x7ea000); for (int i = 6398; i >= 0; i -= 2) { level_data[i >> 1] = 0x8000; level_data[(i >> 1) + 3200 * 1] = 0x8000; level_data[(i >> 1) + 3200 * 2] = 0x8000; level_data[(i >> 1) + 3200 * 3] = 0x8000; } copy24(&decompress_src, &room_compr_level_data_ptr); DecompressToMem_IpArg(&unk_82EAA0); uint16 v1 = ram7F_start; for (j = ram7F_start + ram7F_start + (ram7F_start >> 1); ; custom_background[v1 >> 1] = level_data[j >> 1]) { j -= 2; v1 -= 2; if ((v1 & 0x8000u) != 0) break; } v3 = ram7F_start >> 1; for (k = ram7F_start + (ram7F_start & 1) + (ram7F_start >> 1); ; *(uint16 *)&BTS[(uint16)v3] = level_data[k >> 1]) { k -= 2; v3 -= 2; if (v3 < 0) break; } if (area_index == 6) { copy24(&decompress_src, &tileset_tile_table_pointer); DecompressToMem_IpArg(&unk_82EB1D); } else { if ((cre_bitset & 2) != 0) { mov24(&decompress_src, 0xb9a09d); DecompressToMem_IpArg(&unk_82EAF9); } copy24(&decompress_src, &tileset_tile_table_pointer); DecompressToMem_IpArg(&unk_82EB0A); } RoomDefRoomstate = get_RoomDefRoomstate(roomdefroomstate_ptr); rdf_scroll_ptr = RoomDefRoomstate->rdf_scroll_ptr; if (rdf_scroll_ptr >= 0) { R18_ = RoomDefRoomstate->rdf_scroll_ptr; LOBYTE(R20_) = room_height_in_scrolls - 1; uint8 v8 = 2; uint8 v9 = 0; v10 = 0; do { if (v10 == (uint8)R20_) v8 = R18_ + 1; v12 = v10; v11 = 0; do { scrolls[v9++] = v8; ++v11; } while (v11 != (uint8)room_width_in_scrolls); v10 = v12 + 1; } while (v12 + 1 != (uint8)room_height_in_scrolls); } else { for (m = 0; m != 50; m += 2) { *(uint16 *)&scrolls[m] = *(uint16 *)RomPtr_8F(rdf_scroll_ptr); rdf_scroll_ptr += 2; } } } void CreatePlmsExecuteDoorAsmRoomSetup(void) { // 0x82EB6C RoomDefRoomstate *RoomDefRoomstate; RoomDefRoomstate = get_RoomDefRoomstate(roomdefroomstate_ptr); if (RoomDefRoomstate->room_plm_header_ptr) { for (int i = RoomDefRoomstate->room_plm_header_ptr; get_PlmHeader_Size6(i)->func_ptr; i += 6) SpawnRoomPLM(i); } RunDoorSetupCode(); RunRoomSetupCode(); if (elevator_flags) elevator_status = 2; } static Func_V *const kGameOptionsMenuFuncs[13] = { // 0x82EB9F GameOptionsMenuFunc_0, GameOptionsMenu_1_LoadingOptionsScreen, GameOptionsMenu_2_FadeInOptionsScreen, GameOptionsMenu_3_OptionsScreen, GameOptionsMenu_4_StartGame, GameOptionsMenu_5_DissolveOutScreen, GameOptionsMenu_6_DissolveInScreen, GameOptionsMenu_7_ControllerSettings, GameOptionsMenu_8_SpecialSettings, GameOptionsMenu_9_ScrollControllerSettingsDown, GameOptionsMenu_A_ScrollControllerSettingsUp, GameOptionsMenu_B_TransitionBackToFileSelect, GameOptionsMenu_C_FadeOutOptionsScreenToStart, }; CoroutineRet GameState_2_GameOptionsMenu(void) { kGameOptionsMenuFuncs[game_options_screen_index](); OptionsMenuFunc1(); DrawOptionsMenuSpritemaps(); if (!sign16(game_options_screen_index - 2)) OptionsMenu_AddToVramQueue(); return kCoroutineNone; } void GameOptionsMenuFunc_0(void) { // 0x82EBDB HandleFadeOut(); if (reg_INIDISP == 0x80) { EnableNMI(); screen_fade_delay = 0; screen_fade_counter = 0; ++game_options_screen_index; } else if (reg_INIDISP == 14) { uint16 v0 = reg_TS; if ((reg_TS & 4) == 0) CreateOptionsMenuObject_(v0, addr_stru_82F4D6); } } #define kMenuPalettes ((uint16*)RomPtr(0x8ee400)) void GameOptionsMenu_1_LoadingOptionsScreen(void) { // 0x82EC11 uint16 j; static const DecompressToParams unk_82EC74 = { LONGPTR(0x7fc000) }; static const DecompressToParams unk_82EC85 = { LONGPTR(0x7fc800) }; static const DecompressToParams unk_82EC96 = { LONGPTR(0x7fd000) }; static const DecompressToParams unk_82ECA7 = { LONGPTR(0x7fd800) }; static const DecompressToParams unk_82ECB8 = { LONGPTR(0x7fe000) }; reg_BG12NBA = 0; reg_TM = 19; reg_TS = 0; reg_TMW = 0; reg_TSW = 0; next_gameplay_CGWSEL = 0; next_gameplay_CGADSUB = 0; reg_CGWSEL = 0; reg_CGADSUB = 0; WriteReg(VMADDL, 0); WriteReg(VMADDH, 0x58u); WriteReg(VMAIN, 0x80); static const StartDmaCopy unk_82EC3D = { 1, 1, 0x18, LONGPTR(0x8edc00), 0x0800 }; SetupDmaTransfer(&unk_82EC3D); WriteReg(MDMAEN, 2u); reg_BG1HOFS = 0; reg_BG1VOFS = 0; reg_BG2HOFS = 0; reg_BG2VOFS = 0; debug_invincibility = 0; for (int i = 510; i >= 0; i -= 2) palette_buffer[i >> 1] = kMenuPalettes[i >> 1]; mov24(&decompress_src, 0x978DF4u); DecompressToMem_IpArg(&unk_82EC74); mov24(&decompress_src, 0x978FCDu); DecompressToMem_IpArg(&unk_82EC85); mov24(&decompress_src, 0x9791C4u); DecompressToMem_IpArg(&unk_82EC96); mov24(&decompress_src, 0x97938Du); DecompressToMem_IpArg(&unk_82ECA7); mov24(&decompress_src, 0x97953Au); DecompressToMem_IpArg(&unk_82ECB8); for (j = 1023; (j & 0x8000u) == 0; --j) ram3000.pause_menu_map_tilemap[j] = custom_background[j + 5375]; menu_option_index = 0; DeleteAllOptionsMenuObjects_(); CreateOptionsMenuObject_(0, addr_stru_82F4B8); CreateOptionsMenuObject_(0, addr_stru_82F4C4); ++game_options_screen_index; OptionsMenuFunc4(); } void GameOptionsMenu_2_FadeInOptionsScreen(void) { // 0x82ECE4 HandleFadeIn(); if (reg_INIDISP == 15) { screen_fade_delay = 0; screen_fade_counter = 0; ++game_options_screen_index; } } void OptionsMenu_AddToVramQueue(void) { // 0x82ECFF uint16 v0 = vram_write_queue_tail; gVramWriteEntry(vram_write_queue_tail)->size = 2048; v0 += 2; gVramWriteEntry(v0)->size = 12288; v0 += 2; LOBYTE(gVramWriteEntry(v0++)->size) = 126; gVramWriteEntry(v0)->size = 20480; vram_write_queue_tail = v0 + 2; } void OptionsMenuFunc5(uint16 a, uint16 k, uint16 j) { // 0x82ED28 R18_ = a; do { *(uint16 *)((char *)ram3000.pause_menu_map_tilemap + k) = R18_ | *(uint16 *)((uint8 *)ram3000.pause_menu_map_tilemap + k) & 0xE3FF; k += 2; j -= 2; } while (j); } static Func_V *const kGameOptionsMenuItemFuncs[5] = { // 0x82ED42 GameOptionsMenuItemFunc_0, GameOptionsMenuItemFunc_2_ToggleJapanese, GameOptionsMenuItemFunc_2_ToggleJapanese, GameOptionsMenuItemFunc_4, GameOptionsMenuItemFunc_4, }; void GameOptionsMenu_3_OptionsScreen(void) { if ((joypad1_newkeys & kButton_Up) != 0) { QueueSfx1_Max6(0x37u); if ((--menu_option_index & 0x8000u) != 0) menu_option_index = 4; } else if ((joypad1_newkeys & kButton_Down) != 0) { QueueSfx1_Max6(0x37u); if (++menu_option_index == 5) menu_option_index = 0; } if ((joypad1_newkeys & 0x8000u) != 0) { game_options_screen_index = 11; } else if ((joypad1_newkeys & kButton_A) != 0 || (joypad1_newkeys & kButton_Start) != 0) { QueueSfx1_Max6(0x38u); kGameOptionsMenuItemFuncs[menu_option_index](); } } void GameOptionsMenuItemFunc_0(void) { // 0x82EDB1 if (enable_debug && (joypad1_lastkeys & kButton_L) == 0 || loading_game_state == kGameState_5_FileSelectMap) { game_options_screen_index = 4; } else { screen_fade_delay = 0; screen_fade_counter = 0; game_options_screen_index = 12; } } void GameOptionsMenuItemFunc_2_ToggleJapanese(void) { // 0x82EDDA menu_option_index = 0; japanese_text_flag = japanese_text_flag == 0; OptionsMenuFunc4(); } void OptionsMenuFunc4(void) { // 0x82EDED if (japanese_text_flag) { OptionsMenuFunc5(0x400u, 0x288u, 0x18u); OptionsMenuFunc5(0x400u, 0x2C8u, 0x18u); OptionsMenuFunc5(0, 0x348u, 0x32u); OptionsMenuFunc5(0, 0x388u, 0x32u); } else { OptionsMenuFunc5(0, 0x288u, 0x18u); OptionsMenuFunc5(0, 0x2C8u, 0x18u); OptionsMenuFunc5(0x400u, 0x348u, 0x32u); OptionsMenuFunc5(0x400u, 0x388u, 0x32u); } } void GameOptionsMenuItemFunc_4(void) { // 0x82EE55 reg_MOSAIC = 3; screen_fade_delay = 0; screen_fade_counter = 0; game_options_screen_index = 5; } void GameOptionsMenu_B_TransitionBackToFileSelect(void) { // 0x82EE6A HandleFadeOut(); if (reg_INIDISP == 0x80) { EnableNMI(); screen_fade_delay = 0; screen_fade_counter = 0; game_state = kGameState_4_FileSelectMenus; menu_index = 0; game_options_screen_index = 0; } } void GameOptionsMenu_C_FadeOutOptionsScreenToStart(void) { // 0x82EE92 HandleFadeOut(); if (reg_INIDISP == 0x80) { EnableNMI(); screen_fade_delay = 0; screen_fade_counter = 0; game_options_screen_index = 4; } } void GameOptionsMenu_4_StartGame(void) { // 0x82EEB4 game_options_screen_index = 0; if (enable_debug && (joypad1_lastkeys & 0x20) == 0) { game_state = kGameState_5_FileSelectMap; if (loading_game_state != kLoadingGameState_5_Main) { loading_game_state = kGameState_5_FileSelectMap; SaveToSram(selected_save_slot); } } else if (loading_game_state) { game_state = loading_game_state; if (loading_game_state == kGameState_34_CeresGoesBoom) cinematic_function = FUNC16(CinematicFunctionBlackoutFromCeres); menu_option_index = 0; game_options_screen_index = 0; } else { game_state = kGameState_30_IntroCinematic; cinematic_function = FUNC16(CinematicFunction_Intro_Initial); menu_option_index = 0; screen_fade_delay = 0; screen_fade_counter = 0; } } void GameOptionsMenu_5_DissolveOutScreen(void) { // 0x82EF18 uint16 m; uint16 k; uint16 j; uint16 n; uint16 v1; HandleFadeOut(); if (reg_MOSAIC != 0xF3) reg_MOSAIC += 16; if (reg_INIDISP == 0x80) { EnableNMI(); screen_fade_delay = 0; screen_fade_counter = 0; reg_BG1VOFS = 0; ++game_options_screen_index; if (menu_option_index) { if ((menu_option_index & 4) != 0) { if (japanese_text_flag) { for (int i = 1023; i >= 0; --i) ram3000.pause_menu_map_tilemap[i] = custom_background[i + 9471]; } else { for (j = 1023; (j & 0x8000u) == 0; --j) ram3000.pause_menu_map_tilemap[j] = custom_background[j + 8447]; } menu_option_index = 0; OptionsMenuFunc7(); menu_option_index = 1; OptionsMenuFunc7(); menu_option_index = 4; CreateOptionsMenuObject_(4u, addr_stru_82F4D0); } else { if (japanese_text_flag) { for (k = 1023; (k & 0x8000u) == 0; --k) { v1 = custom_background[k + 7423]; ram3000.pause_menu_map_tilemap[k] = v1; } } else { for (m = 1023; (m & 0x8000u) == 0; --m) { v1 = custom_background[m + 6399]; ram3000.pause_menu_map_tilemap[m] = v1; } } CreateOptionsMenuObject_(v1, addr_stru_82F4CA); LoadControllerOptionsFromControllerBindings(); OptionsMenuFunc6(); } } else { for (n = 1023; (n & 0x8000u) == 0; --n) ram3000.pause_menu_map_tilemap[n] = custom_background[n + 5375]; OptionsMenuFunc4(); uint16 v6 = 0; // bug CreateOptionsMenuObject_(v6, addr_stru_82F4C4); } } } void GameOptionsMenu_6_DissolveInScreen(void) { // 0x82EFDB HandleFadeIn(); if (reg_MOSAIC != 3) reg_MOSAIC -= 16; if (reg_INIDISP == 15) { reg_MOSAIC = 0; screen_fade_delay = 0; screen_fade_counter = 0; if (menu_option_index) { if ((menu_option_index & 4) != 0) game_options_screen_index = 8; else game_options_screen_index = 7; menu_option_index = 0; } else { game_options_screen_index = 3; } } } static Func_V *const kGameOptionsMenuSpecialSettings[3] = { // 0x82F024 GameOptionsMenuSpecialSettings_0, GameOptionsMenuSpecialSettings_0, GameOptionsMenuSpecialSettings_2, }; void GameOptionsMenu_8_SpecialSettings(void) { if ((joypad1_newkeys & kButton_Up) != 0) { QueueSfx1_Max6(0x37u); if ((--menu_option_index & 0x8000u) != 0) menu_option_index = 2; } else if ((joypad1_newkeys & kButton_Down) != 0) { QueueSfx1_Max6(0x37u); if (++menu_option_index == 3) menu_option_index = 0; } if ((joypad1_newkeys & 0x8000u) == 0) { if ((joypad1_newkeys & (kButton_Start | kButton_Left | kButton_Right | kButton_A)) != 0) { QueueSfx1_Max6(0x38u); kGameOptionsMenuSpecialSettings[menu_option_index](); } } else { QueueSfx1_Max6(0x38u); menu_option_index = 0; GameOptionsMenuItemFunc_4(); } } #define kOptionsMenuSpecialPtrs ((uint16*)RomPtr(0x82f0ae)) void GameOptionsMenuSpecialSettings_0(void) { // 0x82F08E uint8 *v0 = RomPtr_RAM(kOptionsMenuSpecialPtrs[menu_option_index]); if (*(uint16 *)v0) *(uint16 *)v0 = 0; else *(uint16 *)v0 = 1; OptionsMenuFunc7(); } void GameOptionsMenuSpecialSettings_2(void) { // 0x82F0B2 menu_option_index = 0; GameOptionsMenuItemFunc_4(); } static const uint16 g_word_82F149[4] = { // 0x82F0B9 0x1e0, 0x220, 0x360, 0x3a0, }; static const uint16 g_word_82F151[4] = { 0x1ee, 0x22e, 0x36e, 0x3ae, }; void OptionsMenuFunc7(void) { uint16 v0 = 4 * menu_option_index; if (*(uint16 *)RomPtr_RAM(kOptionsMenuSpecialPtrs[menu_option_index])) { OptionsMenuFunc5(0, g_word_82F149[(uint16)(4 * menu_option_index) >> 1], 0xCu); OptionsMenuFunc5(0, g_word_82F149[(v0 >> 1) + 1], 0xCu); OptionsMenuFunc5(0x400u, g_word_82F151[v0 >> 1], 0xCu); OptionsMenuFunc5(0x400u, g_word_82F151[(v0 >> 1) + 1], 0xCu); } else { OptionsMenuFunc5(0x400u, g_word_82F149[(uint16)(4 * menu_option_index) >> 1], 0xCu); OptionsMenuFunc5(0x400u, g_word_82F149[(v0 >> 1) + 1], 0xCu); OptionsMenuFunc5(0, g_word_82F151[v0 >> 1], 0xCu); OptionsMenuFunc5(0, g_word_82F151[(v0 >> 1) + 1], 0xCu); } } static const uint16 word_82F204[16] = { // 0x82F159 0x20, 0x20, 0x20, 0x20, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x4000, 0x40, 0x40, 0x80, 0x80, 0x80, }; void GameOptionsMenu_7_ControllerSettings(void) { if ((joypad1_newkeys & kButton_Up) != 0) { QueueSfx1_Max6(0x37u); uint16 v0 = --menu_option_index; if ((menu_option_index & 0x8000u) == 0) { if (v0 != 6) return; game_options_screen_index = 10; return; } menu_option_index = 8; game_options_screen_index = 9; return; } if ((joypad1_newkeys & kButton_Down) != 0) { QueueSfx1_Max6(0x37u); uint16 v1 = menu_option_index + 1; menu_option_index = v1; if (v1 == 7) { game_options_screen_index = 9; return; } if (v1 == 9) { menu_option_index = 0; game_options_screen_index = 10; return; } } else if (joypad1_newkeys) { QueueSfx1_Max6(0x38u); static Func_V *const kOptionsMenuControllerFuncs[9] = { OptionsMenuControllerFunc_0, OptionsMenuControllerFunc_0, OptionsMenuControllerFunc_0, OptionsMenuControllerFunc_0, OptionsMenuControllerFunc_0, OptionsMenuControllerFunc_0, OptionsMenuControllerFunc_0, OptionsMenuControllerFunc_7, OptionsMenuControllerFunc_8, }; kOptionsMenuControllerFuncs[menu_option_index](); } else if (joypad2_new_keys && menu_option_index == 8 && sign16(debug_invincibility - 16)) { if ((word_82F204[debug_invincibility] & joypad2_new_keys) == word_82F204[debug_invincibility]) ++debug_invincibility; else debug_invincibility = 0; } } void OptionsMenuControllerFunc_8(void) { // 0x82F224 if ((joypad1_newkeys & (kButton_Start | kButton_A)) != 0) { button_config_shoot_x = 64; button_config_jump_a = 128; button_config_run_b = 0x8000; button_config_itemcancel_y = 0x4000; button_config_itemswitch = 0x2000; button_config_aim_up_R = 16; button_config_aim_down_L = 32; LoadControllerOptionsFromControllerBindings(); OptionsMenuFunc6(); } } void OptionsMenuControllerFunc_7(void) { // 0x82F25D if ((joypad1_newkeys & (kButton_Start | kButton_A)) != 0 && !OptionsMenuFunc8()) { menu_option_index = 0; GameOptionsMenuItemFunc_4(); } } void GameOptionsMenu_9_ScrollControllerSettingsDown(void) { // 0x82F271 reg_BG1VOFS += 2; if (reg_BG1VOFS == 32) game_options_screen_index = 7; } void GameOptionsMenu_A_ScrollControllerSettingsUp(void) { // 0x82F285 reg_BG1VOFS -= 2; if (!reg_BG1VOFS) game_options_screen_index = 7; } void sub_82F296(uint16 j) { // 0x82F296 int v1 = j >> 1; enemy_projectile_y_pos[v1 + 13] = 24; enemy_projectile_x_vel[v1 + 3] = 56; enemy_projectile_x_vel[v1 + 11] = 3584; } #define off_82F2ED ((uint16*)RomPtr(0x82f2ed)) void OptionsPreInstr_F2A9(uint16 v0) { // 0x82F2A9 if (game_state == kGameState_2_GameOptionsMenu) { int v2 = game_options_screen_index; uint16 v3 = off_82F2ED[v2]; if (v3) { R18_ = off_82F2ED[v2]; uint16 *v4 = (uint16 *)RomPtr_82(v3 + 4 * menu_option_index); int v5 = v0 >> 1; enemy_projectile_y_pos[v5 + 13] = *v4; enemy_projectile_x_vel[v5 + 3] = v4[1]; } else { int v6 = v0 >> 1; enemy_projectile_y_pos[v6 + 13] = 384; enemy_projectile_x_vel[v6 + 3] = 16; } } else { int v1 = v0 >> 1; enemy_projectile_E[v1 + 15] = 1; enemy_projectile_y_vel[v1 + 17] = addr_off_82F4B6; } } void sub_82F34B(uint16 j) { // 0x82F34B enemy_projectile_y_pos[(j >> 1) + 13] = 124; sub_82F369(j); } void sub_82F353(uint16 j) { // 0x82F353 enemy_projectile_y_pos[(j >> 1) + 13] = 132; sub_82F369(j); } void sub_82F35B(uint16 j) { // 0x82F35B enemy_projectile_y_pos[(j >> 1) + 13] = 128; sub_82F369(j); } void sub_82F363(uint16 j) { // 0x82F363 enemy_projectile_y_pos[(j >> 1) + 13] = 128; sub_82F369(j); } void sub_82F369(uint16 j) { // 0x82F369 int v1 = j >> 1; enemy_projectile_x_vel[v1 + 3] = 16; enemy_projectile_x_vel[v1 + 11] = 3584; } void OptionsPreInstr_F376(uint16 k) { // 0x82F376 if (game_state != kGameState_2_GameOptionsMenu || game_options_screen_index == 6 && reg_INIDISP == 0x80) { int v1 = k >> 1; enemy_projectile_E[v1 + 15] = 1; enemy_projectile_y_vel[v1 + 17] = addr_off_82F4B6; } } void OptionsPreInstr_F3A0(uint16 k) { // 0x82F3A0 switch (game_options_screen_index) { case 6u: if (reg_INIDISP == 0x80) { int v1 = k >> 1; enemy_projectile_E[v1 + 15] = 1; enemy_projectile_y_vel[v1 + 17] = -2890; } break; case 9u: enemy_projectile_x_vel[(k >> 1) + 3] -= 2; break; case 0xAu: enemy_projectile_x_vel[(k >> 1) + 3] += 2; break; } } void OptionsPreInstr_F3E2(uint16 k) { // 0x82F3E2 if (game_options_screen_index == 6 && reg_INIDISP == 0x80) { int v1 = k >> 1; enemy_projectile_E[v1 + 15] = 1; enemy_projectile_y_vel[v1 + 17] = -2890; } } void sub_82F404(uint16 k) { // 0x82F404 if (game_options_screen_index == 1) { int v1 = k >> 1; enemy_projectile_E[v1 + 15] = 1; enemy_projectile_y_vel[v1 + 17] = -2890; } } void sub_82F419(uint16 j) { // 0x82F419 int v1 = j >> 1; enemy_projectile_y_pos[v1 + 13] = 216; enemy_projectile_x_vel[v1 + 3] = 16; enemy_projectile_x_vel[v1 + 11] = 3584; } void OptionsPreInstr_F42C(uint16 k) { // 0x82F42C if (game_state != 2) { int v1 = k >> 1; enemy_projectile_E[v1 + 15] = 1; enemy_projectile_y_vel[v1 + 17] = addr_off_82F4B6; } } #define off_82F54A ((uint16*)RomPtr(0x82f54a)) void LoadControllerOptionsFromControllerBindings(void) { // 0x82F4DC int16 v2; uint16 v0 = 0; do { int v1 = v0 >> 1; v2 = *(uint16 *)RomPtr_7E(off_82F54A[v1]); if ((v2 & kButton_X) != 0) { LABEL_9: enemy_projectile_F[v1 + 13] = 0; goto LABEL_16; } if ((v2 & kButton_A) != 0) { enemy_projectile_F[v1 + 13] = 1; } else if (v2 < 0) { enemy_projectile_F[v1 + 13] = 2; } else if ((v2 & kButton_Select) != 0) { enemy_projectile_F[v1 + 13] = 3; } else if ((v2 & kButton_Y) != 0) { enemy_projectile_F[v1 + 13] = 4; } else if ((v2 & kButton_L) != 0) { enemy_projectile_F[v1 + 13] = 5; } else { if ((v2 & kButton_R) == 0) goto LABEL_9; enemy_projectile_F[v1 + 13] = 6; } LABEL_16: v0 += 2; } while ((int16)(v0 - 14) < 0); } static const Buttons word_82F575[9] = { // 0x82F558 kButton_X, kButton_A, kButton_B, kButton_Select, kButton_Y, kButton_L, kButton_R, kButton_Left, kButton_Right, }; uint8 OptionsMenuFunc8(void) { uint16 v0 = 0, v2; do { v2 = v0; *(uint16 *)RomPtr_7E(off_82F54A[v0 >> 1]) = word_82F575[(uint16)(2 * enemy_projectile_F[(v0 >> 1) + 13]) >> 1]; v0 += 2; } while ((int16)(v2 - 12) < 0); return 0; } #define g_word_82F639 ((uint16*)RomPtr(0x82f639)) #define g_off_82F647 ((uint16*)RomPtr(0x82f647)) static const uint16 g_word_82F6AD[6] = { // 0x82F587 0, 0xe, 0xe, 0x10, 0x1f, 0x1f, }; void OptionsMenuFunc6(void) { uint16 v0 = 0, v4; do { v4 = v0; int v1 = v0 >> 1; uint16 v2 = g_word_82F639[v1]; uint16 *v3 = (uint16 *)RomPtr_82(g_off_82F647[(uint16)(2 * enemy_projectile_F[v1 + 13]) >> 1]); *(uint16 *)((char *)ram3000.pause_menu_map_tilemap + v2) = *v3; *(uint16 *)((char *)&ram3000.pause_menu_map_tilemap[1] + v2) = v3[1]; *(uint16 *)((char *)&ram3000.pause_menu_map_tilemap[2] + v2) = v3[2]; *(uint16 *)((char *)&ram3000.pause_menu_map_tilemap[32] + v2) = v3[3]; *(uint16 *)((char *)&ram3000.pause_menu_map_tilemap[33] + v2) = v3[4]; *(uint16 *)((char *)&ram3000.pause_menu_map_tilemap[34] + v2) = v3[5]; v0 = v4 + 2; } while ((int16)(v4 - 12) < 0); if (enemy_projectile_instr_list_ptr[0] != 5 && enemy_projectile_instr_list_ptr[0] != 6) { *(uint32 *)&ram3000.menu.backup_of_io_registers_in_gameover[46] = *(uint32 *)g_word_82F6AD; ram3000.pause_menu_map_tilemap[665] = g_word_82F6AD[2]; *(uint32 *)&ram3000.menu.field_536[56] = *(uint32 *)&g_word_82F6AD[3]; ram3000.pause_menu_map_tilemap[697] = g_word_82F6AD[5]; } if (enemy_projectile_instr_list_ptr[1] != 5 && enemy_projectile_instr_list_ptr[1] != 6) { *(uint32 *)&ram3000.menu.field_536[184] = *(uint32 *)g_word_82F6AD; ram3000.pause_menu_map_tilemap[761] = g_word_82F6AD[2]; *(uint32 *)&ram3000.menu.menu_tilemap[46] = *(uint32 *)&g_word_82F6AD[3]; ram3000.pause_menu_map_tilemap[793] = g_word_82F6AD[5]; } } void OptionsMenuControllerFunc_0(void) { // 0x82F6B9 uint16 v0 = 12; while ((word_82F575[v0 >> 1] & joypad1_newkeys) == 0) { v0 -= 2; if ((v0 & 0x8000u) != 0) return; } R18_ = v0 >> 1; uint16 v1 = 2 * menu_option_index + 2; if (!sign16(2 * menu_option_index - 12)) v1 = 0; uint16 v2 = v1; for (int i = 5; i >= 0; --i) { if (enemy_projectile_F[(v2 >> 1) + 13] == R18_) break; v2 += 2; if ((int16)(v2 - 14) >= 0) v2 = 0; } int v4 = menu_option_index; R20_ = enemy_projectile_F[v4 + 13]; enemy_projectile_F[v4 + 13] = R18_; enemy_projectile_F[(v2 >> 1) + 13] = R20_; OptionsMenuFunc6(); }