From 5647ca687b92954dcf37a6ea6bfbc9a341c32de4 Mon Sep 17 00:00:00 2001 From: dannye <33dannye@gmail.com> Date: Wed, 4 Nov 2020 00:06:44 -0600 Subject: Sync with pokered --- engine/HoF_room_pc.asm | 323 -- engine/add_mon.asm | 522 ---- engine/bank3c.asm | 24 +- engine/bank3d.asm | 72 +- engine/bank3f.asm | 10 +- engine/battle/animations.asm | 794 ++--- engine/battle/bank3d_battle.asm | 111 +- engine/battle/bank_e_misc.asm | 103 - engine/battle/battle_transitions.asm | 263 +- engine/battle/common_text.asm | 110 +- engine/battle/core.asm | 2840 ++++------------- engine/battle/decrement_pp.asm | 2 +- engine/battle/display_effectiveness.asm | 8 +- engine/battle/draw_hud_pokeball_gfx.asm | 8 +- engine/battle/effects.asm | 1551 ++++++++++ engine/battle/end_of_battle.asm | 10 +- engine/battle/experience.asm | 64 +- engine/battle/get_trainer_name.asm | 8 +- engine/battle/ghost_marowak_anim.asm | 20 +- engine/battle/init_battle_variables.asm | 4 +- engine/battle/link_battle_versus_text.asm | 10 +- engine/battle/misc.asm | 103 + engine/battle/moveEffects/conversion_effect.asm | 35 - engine/battle/moveEffects/drain_hp_effect.asm | 104 - engine/battle/moveEffects/focus_energy_effect.asm | 22 - engine/battle/moveEffects/haze_effect.asm | 81 - engine/battle/moveEffects/heal_effect.asm | 120 - engine/battle/moveEffects/leech_seed_effect.asm | 40 - engine/battle/moveEffects/mist_effect.asm | 19 - engine/battle/moveEffects/one_hit_ko_effect.asm | 38 - engine/battle/moveEffects/paralyze_effect.asm | 47 - engine/battle/moveEffects/pay_day_effect.asm | 45 - engine/battle/moveEffects/recoil_effect.asm | 70 - .../moveEffects/reflect_light_screen_effect.asm | 45 - engine/battle/moveEffects/substitute_effect.asm | 77 - engine/battle/moveEffects/transform_effect.asm | 141 - engine/battle/move_effects/conversion.asm | 35 + engine/battle/move_effects/drain_hp.asm | 104 + engine/battle/move_effects/focus_energy.asm | 22 + engine/battle/move_effects/haze.asm | 81 + engine/battle/move_effects/heal.asm | 120 + engine/battle/move_effects/leech_seed.asm | 40 + engine/battle/move_effects/mist.asm | 19 + engine/battle/move_effects/one_hit_ko.asm | 38 + engine/battle/move_effects/paralyze.asm | 47 + engine/battle/move_effects/pay_day.asm | 45 + engine/battle/move_effects/recoil.asm | 70 + .../battle/move_effects/reflect_light_screen.asm | 45 + engine/battle/move_effects/substitute.asm | 77 + engine/battle/move_effects/transform.asm | 141 + engine/battle/print_type.asm | 2 +- engine/battle/read_trainer_party.asm | 2 +- engine/battle/safari_zone.asm | 8 +- engine/battle/save_trainer_name.asm | 95 +- engine/battle/scale_sprites.asm | 30 +- engine/battle/scroll_draw_trainer_pic.asm | 4 +- engine/battle/trainer_ai.asm | 157 +- engine/battle/trainer_pic_money_pointers.asm | 143 - engine/battle/unused_stats_functions.asm | 4 +- engine/battle/wild_encounters.asm | 32 +- engine/bcd.asm | 218 -- engine/bg_map_attributes.asm | 40 +- engine/black_out.asm | 48 - engine/cable_club.asm | 984 ------ engine/clear_save.asm | 27 - engine/debug/debug_menu.asm | 46 + engine/debug/debug_party.asm | 24 + engine/debug1.asm | 24 - engine/diploma_3a.asm | 46 +- engine/display_pokedex.asm | 19 - engine/display_text_id_init.asm | 75 - engine/events/black_out.asm | 48 + engine/events/card_key.asm | 102 + engine/events/cinnabar_lab.asm | 123 + engine/events/diploma.asm | 17 + engine/events/display_pokedex.asm | 19 + engine/events/elevator.asm | 54 + engine/events/give_pokemon.asm | 87 + engine/events/heal_party.asm | 99 + engine/events/hidden_items.asm | 172 ++ engine/events/hidden_objects/bench_guys.asm | 98 + engine/events/hidden_objects/bills_house_pc.asm | 131 + engine/events/hidden_objects/blues_room.asm | 13 + engine/events/hidden_objects/book_or_sculpture.asm | 21 + engine/events/hidden_objects/bookshelves.asm | 39 + engine/events/hidden_objects/cinnabar_gym_quiz.asm | 246 ++ engine/events/hidden_objects/elevator.asm | 3 + engine/events/hidden_objects/fanclub_pictures.asm | 23 + engine/events/hidden_objects/fighting_dojo.asm | 23 + engine/events/hidden_objects/gym_statues.asm | 39 + engine/events/hidden_objects/indigo_plateau_hq.asm | 10 + .../hidden_objects/indigo_plateau_statues.asm | 24 + engine/events/hidden_objects/magazines.asm | 8 + engine/events/hidden_objects/museum_fossils.asm | 23 + engine/events/hidden_objects/museum_fossils2.asm | 28 + engine/events/hidden_objects/new_bike.asm | 7 + engine/events/hidden_objects/oaks_lab_email.asm | 11 + engine/events/hidden_objects/oaks_lab_posters.asm | 29 + engine/events/hidden_objects/pokecenter_pc.asm | 11 + engine/events/hidden_objects/pokemon_stuff.asm | 3 + engine/events/hidden_objects/reds_room.asm | 14 + .../events/hidden_objects/route_15_binoculars.asm | 17 + engine/events/hidden_objects/safari_game.asm | 78 + engine/events/hidden_objects/school_blackboard.asm | 223 ++ engine/events/hidden_objects/school_notebooks.asm | 65 + engine/events/hidden_objects/town_map.asm | 22 + .../events/hidden_objects/vermilion_gym_trash.asm | 134 + engine/events/in_game_trades.asm | 350 +++ engine/events/oaks_aide.asm | 71 + engine/events/pewter_guys.asm | 102 + engine/events/pick_up_item.asm | 54 + engine/events/poison.asm | 151 + engine/events/pokecenter.asm | 149 + engine/events/pokedex_rating.asm | 138 + engine/events/pokemart.asm | 272 ++ engine/events/prize_menu.asm | 305 ++ engine/events/saffron_guards.asm | 15 + engine/events/set_blackout_map.asm | 25 + engine/events/starter_dex.asm | 9 + engine/events/vending_machine.asm | 132 + engine/evolution.asm | 156 - engine/evos_moves.asm | 668 ---- engine/experience.asm | 160 - engine/game_corner_slots.asm | 54 - engine/game_corner_slots2.asm | 31 - engine/gamefreak.asm | 263 -- engine/get_bag_item_quantity.asm | 18 - engine/gfx/hp_bar.asm | 268 ++ engine/gfx/load_pokedex_tiles.asm | 11 + engine/gfx/mon_icons.asm | 307 ++ engine/gfx/oam_dma.asm | 28 + engine/gfx/palettes.asm | 1117 +++++++ engine/gfx/screen_effects.asm | 73 + engine/gfx/sprite_oam.asm | 232 ++ engine/give_pokemon.asm | 87 - engine/hall_of_fame.asm | 303 -- engine/heal_party.asm | 99 - engine/hidden_object_functions14.asm | 100 - engine/hidden_object_functions17.asm | 466 --- engine/hidden_object_functions18.asm | 204 -- engine/hidden_object_functions3.asm | 153 - engine/hidden_object_functions7.asm | 510 --- engine/hp_bar.asm | 268 -- engine/in_game_trades.asm | 350 --- engine/init_player_data.asm | 60 - engine/intro.asm | 164 - engine/items/get_bag_item_quantity.asm | 18 + engine/items/inventory.asm | 8 +- engine/items/item_effects.asm | 3186 +++++++++++++++++++ engine/items/items.asm | 3235 -------------------- engine/items/subtract_paid_money.asm | 17 + engine/items/tm_prices.asm | 14 +- engine/items/tmhm.asm | 4 +- engine/items/tms.asm | 2 +- engine/items/town_map.asm | 629 ++++ engine/joypad.asm | 52 +- engine/learn_move.asm | 250 -- engine/link/cable_club.asm | 984 ++++++ engine/link/cable_club_npc.asm | 208 ++ engine/link/print_waiting_text.asm | 19 + engine/load_mon_data.asm | 68 - engine/load_pokedex_tiles.asm | 11 - engine/math/bcd.asm | 218 ++ engine/math/multiply_divide.asm | 143 + engine/math/random.asm | 13 + engine/menu/bills_pc.asm | 598 ---- engine/menu/diploma.asm | 17 - engine/menu/draw_badges.asm | 120 - engine/menu/draw_start_menu.asm | 87 - engine/menu/league_pc.asm | 119 - engine/menu/link_menu.asm | 910 ------ engine/menu/main_menu.asm | 297 -- engine/menu/naming_screen.asm | 526 ---- engine/menu/oaks_pc.asm | 28 - engine/menu/options.asm | 443 --- engine/menu/party_menu.asm | 333 -- engine/menu/pc.asm | 141 - engine/menu/players_pc.asm | 302 -- engine/menu/pokedex.asm | 747 ----- engine/menu/prize_menu.asm | 307 -- engine/menu/start_menu.asm | 84 - engine/menu/start_sub_menus.asm | 871 ------ engine/menu/status_screen.asm | 495 --- engine/menu/swap_items.asm | 149 - engine/menu/text_box.asm | 739 ----- engine/menu/vending_machine.asm | 138 - engine/menus/display_text_id_init.asm | 76 + engine/menus/draw_badges.asm | 120 + engine/menus/draw_start_menu.asm | 87 + engine/menus/league_pc.asm | 119 + engine/menus/link_menu.asm | 910 ++++++ engine/menus/main_menu.asm | 300 ++ engine/menus/naming_screen.asm | 508 +++ engine/menus/oaks_pc.asm | 28 + engine/menus/options.asm | 443 +++ engine/menus/party_menu.asm | 314 ++ engine/menus/pc.asm | 141 + engine/menus/players_pc.asm | 302 ++ engine/menus/pokedex.asm | 745 +++++ engine/menus/save.asm | 682 +++++ engine/menus/start_sub_menus.asm | 825 +++++ engine/menus/swap_items.asm | 149 + engine/menus/text_box.asm | 533 ++++ engine/mon_party_sprites.asm | 445 --- engine/movie/credits.asm | 322 ++ engine/movie/evolution.asm | 156 + engine/movie/hall_of_fame.asm | 303 ++ engine/movie/intro.asm | 157 + engine/movie/oak_speech/clear_save.asm | 27 + engine/movie/oak_speech/init_player_data.asm | 60 + engine/movie/oak_speech/oak_speech.asm | 244 ++ engine/movie/oak_speech/oak_speech2.asm | 219 ++ engine/movie/splash.asm | 259 ++ engine/movie/title.asm | 370 +++ engine/movie/title2.asm | 122 + engine/movie/trade.asm | 859 ++++++ engine/movie/trade2.asm | 49 + engine/multiply_divide.asm | 144 - engine/oak_speech.asm | 244 -- engine/oak_speech2.asm | 241 -- engine/oam_dma.asm | 26 - engine/overworld/advance_player_sprite.asm | 247 +- engine/overworld/auto_movement.asm | 270 ++ engine/overworld/cable_club_npc.asm | 208 -- engine/overworld/card_key.asm | 113 - engine/overworld/cinnabar_lab.asm | 123 - engine/overworld/clear_variables.asm | 16 +- engine/overworld/cut.asm | 66 +- engine/overworld/cut2.asm | 8 +- engine/overworld/doors.asm | 55 +- engine/overworld/dungeon_warps.asm | 2 +- engine/overworld/dust_smoke.asm | 95 + engine/overworld/elevator.asm | 10 +- engine/overworld/emotion_bubbles.asm | 19 +- engine/overworld/field_move_messages.asm | 23 +- engine/overworld/healing_machine.asm | 43 +- engine/overworld/hidden_items.asm | 172 -- engine/overworld/hidden_objects.asm | 20 +- engine/overworld/item.asm | 54 - engine/overworld/ledges.asm | 26 +- engine/overworld/map_sprite_functions1.asm | 390 --- engine/overworld/map_sprites.asm | 32 +- engine/overworld/missable_objects.asm | 36 +- engine/overworld/movement.asm | 459 +-- engine/overworld/npc_movement.asm | 270 -- engine/overworld/npc_movement_2.asm | 14 +- engine/overworld/oaks_aide.asm | 71 - engine/overworld/oam.asm | 232 -- engine/overworld/pathfinding.asm | 201 ++ engine/overworld/pewter_guys.asm | 102 - engine/overworld/player_animations.asm | 118 +- engine/overworld/player_state.asm | 122 +- engine/overworld/poison.asm | 151 - engine/overworld/pokecenter.asm | 149 - engine/overworld/pokemart.asm | 272 -- engine/overworld/push_boulder.asm | 34 +- engine/overworld/saffron_guards.asm | 16 - engine/overworld/set_blackout_map.asm | 29 - engine/overworld/special_warps.asm | 149 + engine/overworld/spinners.asm | 65 + engine/overworld/sprite_collisions.asm | 392 +++ engine/overworld/ssanne.asm | 95 - engine/overworld/tileset_header.asm | 51 - engine/overworld/tilesets.asm | 51 + engine/overworld/trainer_sight.asm | 349 +++ engine/overworld/trainers.asm | 349 --- engine/overworld/update_map.asm | 32 +- engine/overworld/wild_mons.asm | 10 +- engine/palettes.asm | 1116 ------- engine/pathfinding.asm | 201 -- engine/pikachu_emotions.asm | 26 +- engine/pikachu_follow.asm | 16 +- engine/pikachu_movement.asm | 8 +- engine/pikachu_pcm.asm | 38 +- engine/pikachu_pic_animation.asm | 38 +- engine/pokedex_rating.asm | 154 - engine/pokemon/add_mon.asm | 522 ++++ engine/pokemon/bills_pc.asm | 593 ++++ engine/pokemon/evos_moves.asm | 668 ++++ engine/pokemon/experience.asm | 149 + engine/pokemon/learn_move.asm | 250 ++ engine/pokemon/load_mon_data.asm | 68 + engine/pokemon/remove_mon.asm | 95 + engine/pokemon/set_types.asm | 15 + engine/pokemon/status_ailments.asm | 46 + engine/pokemon/status_screen.asm | 496 +++ engine/predefs.asm | 113 +- engine/predefs17.asm | 9 - engine/predefs17_2.asm | 15 - engine/predefs7.asm | 54 - engine/predefsA.asm | 73 - engine/print_waiting_text.asm | 19 - engine/printer.asm | 208 +- engine/printer/serial.asm | 24 +- engine/random.asm | 13 - engine/remove_pokemon.asm | 95 - engine/save.asm | 682 ----- engine/slot_machine.asm | 891 ------ engine/slots/game_corner_slots.asm | 54 + engine/slots/game_corner_slots2.asm | 31 + engine/slots/slot_machine.asm | 892 ++++++ engine/special_warps.asm | 149 - engine/status_ailments.asm | 46 - engine/subtract_paid_money.asm | 17 - engine/surfing_minigame.asm | 218 +- engine/test_battle.asm | 45 - engine/titlescreen.asm | 370 --- engine/titlescreen2.asm | 122 - engine/town_map.asm | 628 ---- engine/trade.asm | 857 ------ engine/trade2.asm | 48 - engine/unknown_ea3ea.asm | 66 +- engine/vermilion_gym_trash_cans.asm | 2 +- engine/yellow_intro.asm | 164 +- 314 files changed, 31060 insertions(+), 32957 deletions(-) delete mode 100755 engine/HoF_room_pc.asm delete mode 100644 engine/add_mon.asm delete mode 100755 engine/battle/bank_e_misc.asm create mode 100644 engine/battle/effects.asm create mode 100755 engine/battle/misc.asm delete mode 100644 engine/battle/moveEffects/conversion_effect.asm delete mode 100644 engine/battle/moveEffects/drain_hp_effect.asm delete mode 100644 engine/battle/moveEffects/focus_energy_effect.asm delete mode 100644 engine/battle/moveEffects/haze_effect.asm delete mode 100644 engine/battle/moveEffects/heal_effect.asm delete mode 100644 engine/battle/moveEffects/leech_seed_effect.asm delete mode 100644 engine/battle/moveEffects/mist_effect.asm delete mode 100644 engine/battle/moveEffects/one_hit_ko_effect.asm delete mode 100644 engine/battle/moveEffects/paralyze_effect.asm delete mode 100644 engine/battle/moveEffects/pay_day_effect.asm delete mode 100644 engine/battle/moveEffects/recoil_effect.asm delete mode 100644 engine/battle/moveEffects/reflect_light_screen_effect.asm delete mode 100644 engine/battle/moveEffects/substitute_effect.asm delete mode 100644 engine/battle/moveEffects/transform_effect.asm create mode 100644 engine/battle/move_effects/conversion.asm create mode 100644 engine/battle/move_effects/drain_hp.asm create mode 100644 engine/battle/move_effects/focus_energy.asm create mode 100644 engine/battle/move_effects/haze.asm create mode 100644 engine/battle/move_effects/heal.asm create mode 100644 engine/battle/move_effects/leech_seed.asm create mode 100644 engine/battle/move_effects/mist.asm create mode 100644 engine/battle/move_effects/one_hit_ko.asm create mode 100644 engine/battle/move_effects/paralyze.asm create mode 100644 engine/battle/move_effects/pay_day.asm create mode 100644 engine/battle/move_effects/recoil.asm create mode 100644 engine/battle/move_effects/reflect_light_screen.asm create mode 100644 engine/battle/move_effects/substitute.asm create mode 100644 engine/battle/move_effects/transform.asm delete mode 100755 engine/battle/trainer_pic_money_pointers.asm delete mode 100644 engine/bcd.asm delete mode 100644 engine/black_out.asm delete mode 100755 engine/cable_club.asm delete mode 100755 engine/clear_save.asm create mode 100644 engine/debug/debug_menu.asm create mode 100644 engine/debug/debug_party.asm delete mode 100644 engine/debug1.asm delete mode 100644 engine/display_pokedex.asm delete mode 100644 engine/display_text_id_init.asm create mode 100644 engine/events/black_out.asm create mode 100755 engine/events/card_key.asm create mode 100755 engine/events/cinnabar_lab.asm create mode 100644 engine/events/diploma.asm create mode 100644 engine/events/display_pokedex.asm create mode 100755 engine/events/elevator.asm create mode 100755 engine/events/give_pokemon.asm create mode 100644 engine/events/heal_party.asm create mode 100755 engine/events/hidden_items.asm create mode 100644 engine/events/hidden_objects/bench_guys.asm create mode 100644 engine/events/hidden_objects/bills_house_pc.asm create mode 100644 engine/events/hidden_objects/blues_room.asm create mode 100644 engine/events/hidden_objects/book_or_sculpture.asm create mode 100644 engine/events/hidden_objects/bookshelves.asm create mode 100644 engine/events/hidden_objects/cinnabar_gym_quiz.asm create mode 100644 engine/events/hidden_objects/elevator.asm create mode 100644 engine/events/hidden_objects/fanclub_pictures.asm create mode 100644 engine/events/hidden_objects/fighting_dojo.asm create mode 100644 engine/events/hidden_objects/gym_statues.asm create mode 100644 engine/events/hidden_objects/indigo_plateau_hq.asm create mode 100644 engine/events/hidden_objects/indigo_plateau_statues.asm create mode 100644 engine/events/hidden_objects/magazines.asm create mode 100644 engine/events/hidden_objects/museum_fossils.asm create mode 100644 engine/events/hidden_objects/museum_fossils2.asm create mode 100644 engine/events/hidden_objects/new_bike.asm create mode 100644 engine/events/hidden_objects/oaks_lab_email.asm create mode 100644 engine/events/hidden_objects/oaks_lab_posters.asm create mode 100644 engine/events/hidden_objects/pokecenter_pc.asm create mode 100644 engine/events/hidden_objects/pokemon_stuff.asm create mode 100644 engine/events/hidden_objects/reds_room.asm create mode 100644 engine/events/hidden_objects/route_15_binoculars.asm create mode 100644 engine/events/hidden_objects/safari_game.asm create mode 100644 engine/events/hidden_objects/school_blackboard.asm create mode 100644 engine/events/hidden_objects/school_notebooks.asm create mode 100644 engine/events/hidden_objects/town_map.asm create mode 100644 engine/events/hidden_objects/vermilion_gym_trash.asm create mode 100755 engine/events/in_game_trades.asm create mode 100755 engine/events/oaks_aide.asm create mode 100755 engine/events/pewter_guys.asm create mode 100644 engine/events/pick_up_item.asm create mode 100644 engine/events/poison.asm create mode 100755 engine/events/pokecenter.asm create mode 100755 engine/events/pokedex_rating.asm create mode 100755 engine/events/pokemart.asm create mode 100755 engine/events/prize_menu.asm create mode 100755 engine/events/saffron_guards.asm create mode 100644 engine/events/set_blackout_map.asm create mode 100755 engine/events/starter_dex.asm create mode 100755 engine/events/vending_machine.asm delete mode 100755 engine/evolution.asm delete mode 100755 engine/evos_moves.asm delete mode 100755 engine/experience.asm delete mode 100755 engine/game_corner_slots.asm delete mode 100755 engine/game_corner_slots2.asm delete mode 100755 engine/gamefreak.asm delete mode 100644 engine/get_bag_item_quantity.asm create mode 100755 engine/gfx/hp_bar.asm create mode 100755 engine/gfx/load_pokedex_tiles.asm create mode 100755 engine/gfx/mon_icons.asm create mode 100644 engine/gfx/oam_dma.asm create mode 100755 engine/gfx/palettes.asm create mode 100644 engine/gfx/screen_effects.asm create mode 100644 engine/gfx/sprite_oam.asm delete mode 100755 engine/give_pokemon.asm delete mode 100755 engine/hall_of_fame.asm delete mode 100644 engine/heal_party.asm delete mode 100755 engine/hidden_object_functions14.asm delete mode 100755 engine/hidden_object_functions17.asm delete mode 100755 engine/hidden_object_functions18.asm delete mode 100755 engine/hidden_object_functions3.asm delete mode 100755 engine/hidden_object_functions7.asm delete mode 100755 engine/hp_bar.asm delete mode 100755 engine/in_game_trades.asm delete mode 100644 engine/init_player_data.asm delete mode 100755 engine/intro.asm create mode 100644 engine/items/get_bag_item_quantity.asm create mode 100755 engine/items/item_effects.asm delete mode 100755 engine/items/items.asm create mode 100644 engine/items/subtract_paid_money.asm create mode 100755 engine/items/town_map.asm delete mode 100755 engine/learn_move.asm create mode 100755 engine/link/cable_club.asm create mode 100755 engine/link/cable_club_npc.asm create mode 100644 engine/link/print_waiting_text.asm delete mode 100644 engine/load_mon_data.asm delete mode 100755 engine/load_pokedex_tiles.asm create mode 100644 engine/math/bcd.asm create mode 100755 engine/math/multiply_divide.asm create mode 100755 engine/math/random.asm delete mode 100644 engine/menu/bills_pc.asm delete mode 100644 engine/menu/diploma.asm delete mode 100644 engine/menu/draw_badges.asm delete mode 100644 engine/menu/draw_start_menu.asm delete mode 100755 engine/menu/league_pc.asm delete mode 100644 engine/menu/link_menu.asm delete mode 100755 engine/menu/main_menu.asm delete mode 100755 engine/menu/naming_screen.asm delete mode 100755 engine/menu/oaks_pc.asm delete mode 100644 engine/menu/options.asm delete mode 100755 engine/menu/party_menu.asm delete mode 100755 engine/menu/pc.asm delete mode 100755 engine/menu/players_pc.asm delete mode 100755 engine/menu/pokedex.asm delete mode 100755 engine/menu/prize_menu.asm delete mode 100755 engine/menu/start_menu.asm delete mode 100755 engine/menu/start_sub_menus.asm delete mode 100755 engine/menu/status_screen.asm delete mode 100644 engine/menu/swap_items.asm delete mode 100644 engine/menu/text_box.asm delete mode 100755 engine/menu/vending_machine.asm create mode 100644 engine/menus/display_text_id_init.asm create mode 100644 engine/menus/draw_badges.asm create mode 100644 engine/menus/draw_start_menu.asm create mode 100755 engine/menus/league_pc.asm create mode 100644 engine/menus/link_menu.asm create mode 100755 engine/menus/main_menu.asm create mode 100755 engine/menus/naming_screen.asm create mode 100755 engine/menus/oaks_pc.asm create mode 100644 engine/menus/options.asm create mode 100755 engine/menus/party_menu.asm create mode 100755 engine/menus/pc.asm create mode 100755 engine/menus/players_pc.asm create mode 100755 engine/menus/pokedex.asm create mode 100755 engine/menus/save.asm create mode 100755 engine/menus/start_sub_menus.asm create mode 100644 engine/menus/swap_items.asm create mode 100644 engine/menus/text_box.asm delete mode 100755 engine/mon_party_sprites.asm create mode 100755 engine/movie/credits.asm create mode 100755 engine/movie/evolution.asm create mode 100755 engine/movie/hall_of_fame.asm create mode 100755 engine/movie/intro.asm create mode 100755 engine/movie/oak_speech/clear_save.asm create mode 100644 engine/movie/oak_speech/init_player_data.asm create mode 100755 engine/movie/oak_speech/oak_speech.asm create mode 100755 engine/movie/oak_speech/oak_speech2.asm create mode 100755 engine/movie/splash.asm create mode 100755 engine/movie/title.asm create mode 100755 engine/movie/title2.asm create mode 100755 engine/movie/trade.asm create mode 100755 engine/movie/trade2.asm delete mode 100755 engine/multiply_divide.asm delete mode 100755 engine/oak_speech.asm delete mode 100755 engine/oak_speech2.asm delete mode 100644 engine/oam_dma.asm create mode 100755 engine/overworld/auto_movement.asm delete mode 100755 engine/overworld/cable_club_npc.asm delete mode 100755 engine/overworld/card_key.asm delete mode 100755 engine/overworld/cinnabar_lab.asm create mode 100755 engine/overworld/dust_smoke.asm delete mode 100755 engine/overworld/hidden_items.asm delete mode 100644 engine/overworld/item.asm delete mode 100644 engine/overworld/map_sprite_functions1.asm delete mode 100755 engine/overworld/npc_movement.asm delete mode 100755 engine/overworld/oaks_aide.asm delete mode 100644 engine/overworld/oam.asm create mode 100644 engine/overworld/pathfinding.asm delete mode 100755 engine/overworld/pewter_guys.asm delete mode 100644 engine/overworld/poison.asm delete mode 100755 engine/overworld/pokecenter.asm delete mode 100755 engine/overworld/pokemart.asm delete mode 100755 engine/overworld/saffron_guards.asm delete mode 100644 engine/overworld/set_blackout_map.asm create mode 100644 engine/overworld/special_warps.asm create mode 100644 engine/overworld/spinners.asm create mode 100644 engine/overworld/sprite_collisions.asm delete mode 100755 engine/overworld/ssanne.asm delete mode 100644 engine/overworld/tileset_header.asm create mode 100644 engine/overworld/tilesets.asm create mode 100755 engine/overworld/trainer_sight.asm delete mode 100755 engine/overworld/trainers.asm delete mode 100755 engine/palettes.asm delete mode 100644 engine/pathfinding.asm delete mode 100755 engine/pokedex_rating.asm create mode 100644 engine/pokemon/add_mon.asm create mode 100644 engine/pokemon/bills_pc.asm create mode 100755 engine/pokemon/evos_moves.asm create mode 100755 engine/pokemon/experience.asm create mode 100755 engine/pokemon/learn_move.asm create mode 100644 engine/pokemon/load_mon_data.asm create mode 100644 engine/pokemon/remove_mon.asm create mode 100755 engine/pokemon/set_types.asm create mode 100755 engine/pokemon/status_ailments.asm create mode 100755 engine/pokemon/status_screen.asm delete mode 100755 engine/predefs17.asm delete mode 100755 engine/predefs17_2.asm delete mode 100755 engine/predefs7.asm delete mode 100644 engine/predefsA.asm delete mode 100644 engine/print_waiting_text.asm delete mode 100755 engine/random.asm delete mode 100644 engine/remove_pokemon.asm delete mode 100755 engine/save.asm delete mode 100755 engine/slot_machine.asm create mode 100755 engine/slots/game_corner_slots.asm create mode 100755 engine/slots/game_corner_slots2.asm create mode 100755 engine/slots/slot_machine.asm delete mode 100644 engine/special_warps.asm delete mode 100755 engine/status_ailments.asm delete mode 100644 engine/subtract_paid_money.asm delete mode 100644 engine/test_battle.asm delete mode 100755 engine/titlescreen.asm delete mode 100755 engine/titlescreen2.asm delete mode 100755 engine/town_map.asm delete mode 100755 engine/trade.asm delete mode 100755 engine/trade2.asm (limited to 'engine') diff --git a/engine/HoF_room_pc.asm b/engine/HoF_room_pc.asm deleted file mode 100755 index 71a98c59..00000000 --- a/engine/HoF_room_pc.asm +++ /dev/null @@ -1,323 +0,0 @@ -HallOfFamePC: - callab AnimateHallOfFame - call ClearScreen - ld c, 100 - call DelayFrames - - call DisableLCD - ld a, $a7 - ld [rWX], a - xor a - ld [rSCX], a - ld [rSCY], a - ld [hSCX], a - ld [hSCY], a - ld [hWY], a - ld [rWY], a - call CreditsLoadFont - coord hl, 0, 0 - call FillFourRowsWithBlack - coord hl, 0, 14 - call FillFourRowsWithBlack - ld a, %11000000 - ld [rBGP], a - call UpdateGBCPal_BGP - call EnableLCD - call StopAllMusic - ld hl, vBGMap1 - call CreditsCopyTileMapToVRAM - ld hl, vBGMap0 - call CreditsCopyTileMapToVRAM - ld c, BANK(Music_Credits) - ld a, MUSIC_CREDITS - call PlayMusic - ld c, 128 - call DelayFrames - xor a - ld [wHoFMonSpecies], a - ld [wNumCreditsMonsDisplayed], a - jp Credits - -FadeInCreditsText: - ld a, 1 - ld [H_AUTOBGTRANSFERENABLED], a - ld hl, HoFGBPalettes - ld b, 4 -.loop - ld a, [hli] - ld [rBGP], a - call UpdateGBCPal_BGP - ld c, 5 - call DelayFrames - dec b - jr nz, .loop - ret - -HoFGBPalettes: - db %11000000 - db %11010000 - db %11100000 - db %11110000 - -DisplayCreditsMon: - ld hl, vBGMap1 - call CreditsCopyTileMapToVRAM - xor a - ld [H_AUTOBGTRANSFERENABLED], a - ld hl, rLCDC - set 3, [hl] - call SaveScreenTilesToBuffer2 - call FillMiddleOfScreenWithWhite - call GetNextCreditsMon - ld hl, vBGMap0 + 12 - call CreditsCopyTileMapToVRAM - xor a - ld [H_AUTOBGTRANSFERENABLED], a - call LoadScreenTilesFromBuffer2DisableBGTransfer - ld hl, vBGMap0 - call CreditsCopyTileMapToVRAM - ld a, %11111100 ; make the mon a black silhouette - ld [rBGP], a - call UpdateGBCPal_BGP - ld hl, rLCDC - res 3, [hl] - ld a, 1 - ld [H_AUTOBGTRANSFERENABLED], a - ld b, 0 - ld c, 10 - call ScrollCreditsMonLeft - call FillLeftHalfOfScreenWithWhite - ld c, 10 - call ScrollCreditsMonLeft - call FillRightHalfOfScreenWithWhite - ld c, 8 - call ScrollCreditsMonLeft - ld a, %11000000 - ld [rBGP], a - call UpdateGBCPal_BGP - xor a - ld [hSCX], a - ret - -ScrollCreditsMonLeft: - ld a, b - ld [hSCX], a - add 8 - ld b, a - call DelayFrame - dec c - jr nz, ScrollCreditsMonLeft - ret - -GetNextCreditsMon: - ld hl, wNumCreditsMonsDisplayed - ld c, [hl] - inc [hl] - ld b, 0 - ld hl, CreditsMons - add hl, bc - ld a, [hl] - ld [wcf91], a - ld [wd0b5], a - coord hl, 8, 6 - call GetMonHeader - call LoadFrontSpriteByMonIndex - ret - -INCLUDE "data/credit_mons.asm" - -CreditsCopyTileMapToVRAM: - ld a, l - ld [H_AUTOBGTRANSFERDEST], a - ld a, h - ld [H_AUTOBGTRANSFERDEST + 1], a - ld a, 1 - ld [H_AUTOBGTRANSFERENABLED], a - jp Delay3 - -CreditsLoadFont: - call LoadFontTilePatterns - ld hl, vChars1 - ld bc, $40 * $10 - call ZeroMemory - - call LoadTextBoxTilePatterns - ld hl, vChars2 + $60 * $10 - ld bc, $10 * $10 - call ZeroMemory - - ld hl, vChars2 + $7e * $10 - ld bc, $1 * $10 - ld a, $ff - call FillMemory - ret - -ZeroMemory: -; zero bc bytes at hl - ld [hl], 0 - inc hl - inc hl - dec bc - ld a, b - or c - jr nz, ZeroMemory - ret - -FillFourRowsWithBlack: - ld bc, SCREEN_WIDTH * 4 - ld a, $7e - jp FillMemory - -FillMiddleOfScreenWithWhite: - coord hl, 0, 4 - ld bc, SCREEN_WIDTH * 10 - ld a, " " - jp FillMemory - -FillLeftHalfOfScreenWithWhite: - coord hl, 0, 4 - push bc - call FillHalfOfScreenWithWhite - pop bc - ret - -FillRightHalfOfScreenWithWhite: - coord hl, 10, 4 - push bc - call FillHalfOfScreenWithWhite - pop bc - ret - -FillHalfOfScreenWithWhite: - ld b, 10 - ld c, 10 - ld a, " " -.loop - push bc - push hl -.innerLoop - ld [hli], a - dec c - jr nz, .innerLoop - pop hl - ld bc, SCREEN_WIDTH - add hl, bc - pop bc - dec b - jr nz, .loop - ret - -Credits: ; Roll credits - ld de, CreditsOrder - push de -.nextCreditsScreen - pop de - coord hl, 9, 6 - push hl - call FillMiddleOfScreenWithWhite - pop hl -.nextCreditsCommand - ld a, [de] - inc de - push de - cp $ff - jr z, .fadeInTextAndShowMon - cp $fe - jr z, .showTextAndShowMon - cp $fd - jr z, .fadeInText - cp $fc - jr z, .showText - cp $fb - jr z, .showCopyrightText - cp $fa - jr z, .showTheEnd - call PlaceCreditsText - pop de - jr .nextCreditsCommand - -.showCopyrightText - callba LoadCopyrightTiles - pop de - jr .nextCreditsCommand - - -.fadeInTextAndShowMon - call FadeInCreditsText - ld c, 102 - jr .next1 - -.showTextAndShowMon - ld c, 122 -.next1 - call DelayFrames - call DisplayCreditsMon - jr .nextCreditsScreen - -.fadeInText - call FadeInCreditsText - ld c, 132 - jr .next2 - -.showText - ld c, 152 -.next2 - call DelayFrames - jr .nextCreditsScreen - -.showTheEnd - call ShowTheEndGFX - pop de - ret - -ShowTheEndGFX: - ld c, 24 - call DelayFrames - call FillMiddleOfScreenWithWhite - ld de, TheEndGfx - ld hl, vChars2 + $600 - lb bc, BANK(TheEndGfx), (TheEndGfxEnd - TheEndGfx) / $10 - call CopyVideoData - coord hl, 4, 8 - ld de, TheEndTextString - call PlaceString - coord hl, 4, 9 - inc de - call PlaceString - jp FadeInCreditsText - -TheEndTextString: -; "T H E E N D" - db $60, " ", $62, " ", $64, " ", $64, " ", $66, " ", $68, "@" - db $61, " ", $63, " ", $65, " ", $65, " ", $67, " ", $69, "@" - -PlaceCreditsText: - push hl - push hl - ld hl, CreditsTextPointers - ld c, a - ld b, 0 - add hl, bc - add hl, bc - ld e, [hl] - inc hl - ld d, [hl] - pop hl - ld a, [de] - inc de - ld c, a - ld b, $ff - add hl, bc - call PlaceString - pop hl - ld bc, SCREEN_WIDTH * 2 - add hl, bc - ret - -INCLUDE "data/credits_order.asm" - -INCLUDE "text/credits_text.asm" - -TheEndGfx: - INCBIN "gfx/theend.2bpp" -TheEndGfxEnd: diff --git a/engine/add_mon.asm b/engine/add_mon.asm deleted file mode 100644 index 40b776d4..00000000 --- a/engine/add_mon.asm +++ /dev/null @@ -1,522 +0,0 @@ -_AddPartyMon: -; Adds a new mon to the player's or enemy's party. -; [wMonDataLocation] is used in an unusual way in this function. -; If the lower nybble is 0, the mon is added to the player's party, else the enemy's. -; If the entire value is 0, then the player is allowed to name the mon. - ld de, wPartyCount - ld a, [wMonDataLocation] - and $f - jr z, .next - ld de, wEnemyPartyCount -.next - ld a, [de] - inc a - cp PARTY_LENGTH + 1 - ret nc ; return if the party is already full - ld [de], a - ld a, [de] - ld [hNewPartyLength], a - add e - ld e, a - jr nc, .noCarry - inc d -.noCarry - ld a, [wcf91] - ld [de], a ; write species of new mon in party list - inc de - ld a, $ff ; terminator - ld [de], a - ld hl, wPartyMonOT - ld a, [wMonDataLocation] - and $f - jr z, .next2 - ld hl, wEnemyMonOT -.next2 - ld a, [hNewPartyLength] - dec a - call SkipFixedLengthTextEntries - ld d, h - ld e, l - ld hl, wPlayerName - ld bc, NAME_LENGTH - call CopyData - ld a, [wMonDataLocation] - and a - jr nz, .skipNaming - ld hl, wPartyMonNicks - ld a, [hNewPartyLength] - dec a - call SkipFixedLengthTextEntries - ld a, NAME_MON_SCREEN - ld [wNamingScreenType], a - predef AskName -.skipNaming - ld hl, wPartyMons - ld a, [wMonDataLocation] - and $f - jr z, .next3 - ld hl, wEnemyMons -.next3 - ld a, [hNewPartyLength] - dec a - ld bc, wPartyMon2 - wPartyMon1 - call AddNTimes - ld e, l - ld d, h - push hl - ld a, [wcf91] - ld [wd0b5], a - call GetMonHeader - ld hl, wMonHeader - ld a, [hli] - ld [de], a ; species - inc de - pop hl - push hl - ld a, [wMonDataLocation] - and $f - ld a, $98 ; set enemy trainer mon IVs to fixed average values - ld b, $88 - jr nz, .next4 - -; If the mon is being added to the player's party, update the pokedex. - ld a, [wcf91] - ld [wd11e], a - push de - predef IndexToPokedex - pop de - ld a, [wd11e] - dec a - ld c, a - ld b, FLAG_TEST - ld hl, wPokedexOwned - call FlagAction - ld a, c ; whether the mon was already flagged as owned - ld [wUnusedD153], a ; not read - ld a, [wd11e] - dec a - ld c, a - ld b, FLAG_SET - push bc - call FlagAction - pop bc - ld hl, wPokedexSeen - call FlagAction - - pop hl - push hl - - ld a, [wIsInBattle] - and a ; is this a wild mon caught in battle? - jr nz, .copyEnemyMonData - -; Not wild. - call Random ; generate random IVs - ld b, a - call Random - -.next4 - push bc - ld bc, wPartyMon1DVs - wPartyMon1 - add hl, bc - pop bc - ld [hli], a - ld [hl], b ; write IVs - ld bc, (wPartyMon1HPExp - 1) - (wPartyMon1DVs + 1) - add hl, bc - ld a, 1 - ld c, a - xor a - ld b, a - call CalcStat ; calc HP stat (set cur Hp to max HP) - ld a, [H_MULTIPLICAND+1] - ld [de], a - inc de - ld a, [H_MULTIPLICAND+2] - ld [de], a - inc de - xor a - ld [de], a ; box level - inc de - ld [de], a ; status ailments - inc de - jr .copyMonTypesAndMoves -.copyEnemyMonData - ld bc, wEnemyMon1DVs - wEnemyMon1 - add hl, bc - ld a, [wEnemyMonDVs] ; copy IVs from cur enemy mon - ld [hli], a - ld a, [wEnemyMonDVs + 1] - ld [hl], a - ld a, [wEnemyMonHP] ; copy HP from cur enemy mon - ld [de], a - inc de - ld a, [wEnemyMonHP+1] - ld [de], a - inc de - xor a - ld [de], a ; box level - inc de - ld a, [wEnemyMonStatus] ; copy status ailments from cur enemy mon - ld [de], a - inc de -.copyMonTypesAndMoves - ld hl, wMonHTypes - ld a, [hli] ; type 1 - ld [de], a - inc de - ld a, [hli] ; type 2 - ld [de], a - inc de - ld a, [hli] ; catch rate (held item in gen 2) - ld [de], a - ld a, [wcf91] - cp KADABRA - jr nz, .skipGivingTwistedSpoon - ld a, $60 ; twistedspoon in gen 2 - ld [de], a -.skipGivingTwistedSpoon - ld hl, wMonHMoves - ld a, [hli] - inc de - push de - ld [de], a - ld a, [hli] - inc de - ld [de], a - ld a, [hli] - inc de - ld [de], a - ld a, [hli] - inc de - ld [de], a - push de - dec de - dec de - dec de - xor a - ld [wLearningMovesFromDayCare], a - predef WriteMonMoves - pop de - ld a, [wPlayerID] ; set trainer ID to player ID - inc de - ld [de], a - ld a, [wPlayerID + 1] - inc de - ld [de], a - push de - ld a, [wCurEnemyLVL] - ld d, a - callab CalcExperience - pop de - inc de - ld a, [hExperience] ; write experience - ld [de], a - inc de - ld a, [hExperience + 1] - ld [de], a - inc de - ld a, [hExperience + 2] - ld [de], a - xor a - ld b, NUM_STATS * 2 -.writeEVsLoop ; set all EVs to 0 - inc de - ld [de], a - dec b - jr nz, .writeEVsLoop - inc de - inc de - pop hl - call AddPartyMon_WriteMovePP - inc de - ld a, [wCurEnemyLVL] - ld [de], a - inc de - ld a, [wIsInBattle] - dec a - jr nz, .calcFreshStats - ld hl, wEnemyMonMaxHP - ld bc, $a - call CopyData ; copy stats of cur enemy mon - pop hl - jr .done -.calcFreshStats - pop hl - ld bc, wPartyMon1HPExp - 1 - wPartyMon1 - add hl, bc - ld b, $0 - call CalcStats ; calculate fresh set of stats -.done - scf - ret - -LoadMovePPs: - call GetPredefRegisters - ; fallthrough -AddPartyMon_WriteMovePP: - ld b, NUM_MOVES -.pploop - ld a, [hli] ; read move ID - and a - jr z, .empty - dec a - push hl - push de - push bc - ld hl, Moves - ld bc, MoveEnd - Moves - call AddNTimes - ld de, wcd6d - ld a, BANK(Moves) - call FarCopyData - pop bc - pop de - pop hl - ld a, [wcd6d + 5] ; PP is byte 5 of move data -.empty - inc de - ld [de], a - dec b - jr nz, .pploop ; there are still moves to read - ret - -; adds enemy mon [wcf91] (at position [wWhichPokemon] in enemy list) to own party -; used in the cable club trade center -_AddEnemyMonToPlayerParty: - ld hl, wPartyCount - ld a, [hl] - cp PARTY_LENGTH - scf - ret z ; party full, return failure - inc a - ld [hl], a ; add 1 to party members - ld c, a - ld b, $0 - add hl, bc - ld a, [wcf91] - ld [hli], a ; add mon as last list entry - ld [hl], $ff ; write new sentinel - ld hl, wPartyMons - ld a, [wPartyCount] - dec a - ld bc, wPartyMon2 - wPartyMon1 - call AddNTimes - ld e, l - ld d, h - ld hl, wLoadedMon - call CopyData ; write new mon's data (from wLoadedMon) - ld hl, wPartyMonOT - ld a, [wPartyCount] - dec a - call SkipFixedLengthTextEntries - ld d, h - ld e, l - ld hl, wEnemyMonOT - ld a, [wWhichPokemon] - call SkipFixedLengthTextEntries - ld bc, NAME_LENGTH - call CopyData ; write new mon's OT name (from an enemy mon) - ld hl, wPartyMonNicks - ld a, [wPartyCount] - dec a - call SkipFixedLengthTextEntries - ld d, h - ld e, l - ld hl, wEnemyMonNicks - ld a, [wWhichPokemon] - call SkipFixedLengthTextEntries - ld bc, NAME_LENGTH - call CopyData ; write new mon's nickname (from an enemy mon) - ld a, [wcf91] - ld [wd11e], a - predef IndexToPokedex - ld a, [wd11e] - dec a - ld c, a - ld b, FLAG_SET - ld hl, wPokedexOwned - push bc - call FlagAction ; add to owned pokemon - pop bc - ld hl, wPokedexSeen - call FlagAction ; add to seen pokemon - and a - ret ; return success - -_MoveMon: - ld a, [wMoveMonType] - and a ; BOX_TO_PARTY - jr z, .checkPartyMonSlots - cp DAYCARE_TO_PARTY - jr z, .checkPartyMonSlots - cp PARTY_TO_DAYCARE - ld hl, wDayCareMon - jr z, .findMonDataSrc - ; else it's PARTY_TO_BOX - ld hl, wNumInBox - ld a, [hl] - cp MONS_PER_BOX - jr nz, .partyOrBoxNotFull - jr .boxFull -.checkPartyMonSlots - ld hl, wPartyCount - ld a, [hl] - cp PARTY_LENGTH - jr nz, .partyOrBoxNotFull -.boxFull - scf - ret -.partyOrBoxNotFull - inc a - ld [hl], a ; increment number of mons in party/box - ld c, a - ld b, 0 - add hl, bc - ld a, [wMoveMonType] - cp DAYCARE_TO_PARTY - ld a, [wDayCareMon] - jr z, .copySpecies - ld a, [wcf91] -.copySpecies - ld [hli], a ; write new mon ID - ld [hl], $ff ; write new sentinel -.findMonDataDest - ld a, [wMoveMonType] - dec a - ld hl, wPartyMons - ld bc, wPartyMon2 - wPartyMon1 ; $2c - ld a, [wPartyCount] - jr nz, .addMonOffset - ; if it's PARTY_TO_BOX - ld hl, wBoxMons - ld bc, wBoxMon2 - wBoxMon1 ; $21 - ld a, [wNumInBox] -.addMonOffset - dec a - call AddNTimes -.findMonDataSrc - push hl - ld e, l - ld d, h - ld a, [wMoveMonType] - and a - ld hl, wBoxMons - ld bc, wBoxMon2 - wBoxMon1 ; $21 - jr z, .addMonOffset2 - cp DAYCARE_TO_PARTY - ld hl, wDayCareMon - jr z, .copyMonData - ld hl, wPartyMons - ld bc, wPartyMon2 - wPartyMon1 ; $2c -.addMonOffset2 - ld a, [wWhichPokemon] - call AddNTimes -.copyMonData - push hl - push de - ld bc, wBoxMon2 - wBoxMon1 - call CopyData - pop de - pop hl - ld a, [wMoveMonType] - and a ; BOX_TO_PARTY - jr z, .findOTdest - cp DAYCARE_TO_PARTY - jr z, .findOTdest - ld bc, wBoxMon2 - wBoxMon1 - add hl, bc - ld a, [hl] ; hl = Level - inc de - inc de - inc de - ld [de], a ; de = BoxLevel -.findOTdest - ld a, [wMoveMonType] - cp PARTY_TO_DAYCARE - ld de, wDayCareMonOT - jr z, .findOTsrc - dec a - ld hl, wPartyMonOT - ld a, [wPartyCount] - jr nz, .addOToffset - ld hl, wBoxMonOT - ld a, [wNumInBox] -.addOToffset - dec a - call SkipFixedLengthTextEntries - ld d, h - ld e, l -.findOTsrc - ld hl, wBoxMonOT - ld a, [wMoveMonType] - and a - jr z, .addOToffset2 - ld hl, wDayCareMonOT - cp DAYCARE_TO_PARTY - jr z, .copyOT - ld hl, wPartyMonOT -.addOToffset2 - ld a, [wWhichPokemon] - call SkipFixedLengthTextEntries -.copyOT - ld bc, NAME_LENGTH - call CopyData - ld a, [wMoveMonType] -.findNickDest - cp PARTY_TO_DAYCARE - ld de, wDayCareMonName - jr z, .findNickSrc - dec a - ld hl, wPartyMonNicks - ld a, [wPartyCount] - jr nz, .addNickOffset - ld hl, wBoxMonNicks - ld a, [wNumInBox] -.addNickOffset - dec a - call SkipFixedLengthTextEntries - ld d, h - ld e, l -.findNickSrc - ld hl, wBoxMonNicks - ld a, [wMoveMonType] - and a - jr z, .addNickOffset2 - ld hl, wDayCareMonName - cp DAYCARE_TO_PARTY - jr z, .copyNick - ld hl, wPartyMonNicks -.addNickOffset2 - ld a, [wWhichPokemon] - call SkipFixedLengthTextEntries -.copyNick - ld bc, NAME_LENGTH - call CopyData - pop hl - ld a, [wMoveMonType] - cp PARTY_TO_BOX - jr z, .done - cp PARTY_TO_DAYCARE - jr z, .done - push hl - srl a - add $2 - ld [wMonDataLocation], a - call LoadMonData - callba CalcLevelFromExperience - ld a, d - ld [wCurEnemyLVL], a - pop hl - ld bc, wBoxMon2 - wBoxMon1 - add hl, bc - ld [hli], a - ld d, h - ld e, l - ld bc, -18 - add hl, bc - ld b, $1 - call CalcStats -.done - and a - ret diff --git a/engine/bank3c.asm b/engine/bank3c.asm index 9c0e281f..8eb32837 100644 --- a/engine/bank3c.asm +++ b/engine/bank3c.asm @@ -1,9 +1,9 @@ INCLUDE "engine/pikachu_pcm.asm" INCLUDE "engine/overworld/advance_player_sprite.asm" -INCLUDE "engine/black_out.asm" +INCLUDE "engine/events/black_out.asm" -SetMapSpecificScriptFlagsOnMapReload: +SetMapSpecificScriptFlagsOnMapReload:: ld a, [wCurMap] cp VERMILION_GYM ; ??? new thing about verm gym? jr z, .verm_gym @@ -65,7 +65,7 @@ BeachHouse_Block: Func_f0a54: ret -LoadUnusedBluesHouseMissableObjectData: +LoadUnusedBluesHouseMissableObjectData:: ; referenced in an unused function ld hl, .MissableObjectsMaps .loop @@ -112,7 +112,7 @@ TryApplyPikachuMovementData: ret nz push hl push bc - callab GetPikachuFacingDirectionAndReturnToE + callfar GetPikachuFacingDirectionAndReturnToE pop bc pop hl ld a, b @@ -123,12 +123,12 @@ TryApplyPikachuMovementData: push af ld a, $ff ld [wUpdateSpritesEnabled], a - callab LoadPikachuShadowIntoVRAM + callfar LoadPikachuShadowIntoVRAM pop af ld [wUpdateSpritesEnabled], a pop hl call ApplyPikachuMovementData - callab RefreshPikachuFollow + callfar RefreshPikachuFollow ret Pic_f0abf: @@ -140,7 +140,7 @@ INCBIN "gfx/pikachu/unknown_f0cf4.pic" GFX_f0d82: INCBIN "gfx/pikachu/unknown_f0d82.2bpp" -PokecenterChanseyText: +PokecenterChanseyText:: ld hl, NurseChanseyText call PrintText ld a, CHANSEY @@ -149,10 +149,10 @@ PokecenterChanseyText: ret NurseChanseyText: - TX_FAR _NurseChanseyText - db "@" + text_far _NurseChanseyText + text_end -INCLUDE "engine/HoF_room_pc.asm" +INCLUDE "engine/movie/credits.asm" INCLUDE "scripts/ViridianCity2.asm" INCLUDE "scripts/VermilionCity2.asm" INCLUDE "scripts/CeladonCity2.asm" @@ -173,11 +173,11 @@ INCLUDE "scripts/SafariZoneGate2.asm" INCLUDE "scripts/CinnabarGym3.asm" INCLUDE "scripts/MtMoonPokecenter2.asm" -INCLUDE "data/mapHeaders/BeachHouse.asm" +INCLUDE "data/maps/headers/BeachHouse.asm" INCLUDE "scripts/BeachHouse.asm" BeachHouse_Blocks: INCBIN "maps/BeachHouse.blk" -INCLUDE "data/mapObjects/BeachHouse.asm" +INCLUDE "data/maps/objects/BeachHouse.asm" INCLUDE "scripts/BeachHouse2.asm" INCLUDE "scripts/BillsHouse2.asm" diff --git a/engine/bank3d.asm b/engine/bank3d.asm index 6d0b3a50..e929e44e 100644 --- a/engine/bank3d.asm +++ b/engine/bank3d.asm @@ -4,7 +4,7 @@ INCLUDE "engine/battle/unused_stats_functions.asm" INCLUDE "engine/battle/scroll_draw_trainer_pic.asm" StarterPikachuBattleEntranceAnimation: - coord hl, 0, 5 + hlcoord 0, 5 ld c, 0 .loop1 inc c @@ -60,14 +60,14 @@ ModifyPikachuHappiness:: cp PIKAHAPPY_WALKING jr z, .checkanywhereinparty push de - callab IsThisPartymonStarterPikachu_Party + callfar IsThisPartymonStarterPikachu_Party pop de ret nc jr .proceed .checkanywhereinparty push de - callab IsStarterPikachuInOurParty + callfar IsStarterPikachuInOurParty pop de ret nc @@ -172,9 +172,9 @@ PikachuMoods: db $6c ; Unknown (d = 10) db $00 ; Unknown (d = 11) -RedPicBack: INCBIN "pic/trainer/redb.pic" -OldManPic: INCBIN "pic/trainer/oldman.pic" -ProfOakPicBack: INCBIN "pic/ytrainer/prof.oakb.pic" +RedPicBack: INCBIN "gfx/player/redb.pic" +OldManPic: INCBIN "gfx/battle/oldman.pic" +ProfOakPicBack: INCBIN "gfx/battle/prof.oakb.pic" LoadYellowTitleScreenGFX: ld hl, PokemonLogoGraphics @@ -200,35 +200,35 @@ LoadYellowTitleScreenGFX: ret TitleScreen_PlacePokemonLogo: - coord hl, 2, 1 + hlcoord 2, 1 ld de, TitleScreenPokemonLogoTilemap lb bc, 7, 16 call Bank3D_CopyBox ret TitleScreen_PlacePikaSpeechBubble: - coord hl, 6, 4 + hlcoord 6, 4 ld de, TitleScreenPikaBubbleTilemap lb bc, 4, 7 call Bank3D_CopyBox - coord hl, 9, 8 + hlcoord 9, 8 ld [hl], $64 inc hl ld [hl], $65 ret TitleScreen_PlacePikachu: - coord hl, 4, 8 + hlcoord 4, 8 ld de, TitleScreenPikachuTilemap lb bc, 9, 12 call Bank3D_CopyBox - coord hl, 16, 10 + hlcoord 16, 10 ld [hl], $96 - coord hl, 16, 11 + hlcoord 16, 11 ld [hl], $9d - coord hl, 16, 12 + hlcoord 16, 12 ld [hl], $a7 - coord hl, 16, 13 + hlcoord 16, 13 ld [hl], $b1 ld hl, TitleScreenPikachuEyesOAMData ld de, wOAMBuffer @@ -298,45 +298,45 @@ TitleScreenPikachuTilemap: db $00, $b9, $ba, $8a, $8a, $8a, $8a, $8a, $8a, $bb, $bc, $00 db $00, $00, $bd, $8a, $8a, $8a, $8a, $8a, $8a, $be, $bf, $00 -PokemonLogoGraphics: INCBIN "gfx/pokemon_logo.2bpp" +PokemonLogoGraphics: INCBIN "gfx/title/pokemon_logo.2bpp" PokemonLogoGraphicsEnd: YellowLogoGraphics: INCBIN "gfx/yellow_titlescreen.2bpp" YellowLogoGraphicsEnd: -INCLUDE "engine/menu/link_menu.asm" +INCLUDE "engine/menus/link_menu.asm" HandleMenuInputDouble: xor a ld [wPartyMenuAnimMonEnabled], a HandleMenuInputPokemonSelectionDouble: - ld a, [H_DOWNARROWBLINKCNT1] + ldh a, [hDownArrowBlinkCount1] push af - ld a, [H_DOWNARROWBLINKCNT2] + ldh a, [hDownArrowBlinkCount2] push af ; save existing values on stack xor a - ld [H_DOWNARROWBLINKCNT1], a ; blinking down arrow timing value 1 + ldh [hDownArrowBlinkCount1], a ; blinking down arrow timing value 1 ld a, $06 - ld [H_DOWNARROWBLINKCNT2], a ; blinking down arrow timing value 2 + ldh [hDownArrowBlinkCount2], a ; blinking down arrow timing value 2 .loop1 xor a ld [wAnimCounter], a ; counter for pokemon shaking animation call .UpdateCursorTile call JoypadLowSensitivity - ld a, [hJoy5] + ldh a, [hJoy5] and a ; was a key pressed? jr nz, .keyPressed pop af - ld [H_DOWNARROWBLINKCNT2], a + ldh [hDownArrowBlinkCount2], a pop af - ld [H_DOWNARROWBLINKCNT1], a ; restore previous values + ldh [hDownArrowBlinkCount1], a ; restore previous values xor a ld [wMenuWrappingEnabled], a ; disable menu wrapping ret .keyPressed xor a ld [wCheckFor180DegreeTurn], a - ld a, [hJoy5] + ldh a, [hJoy5] ld b, a bit 6, a ; pressed Up key? jr z, .checkIfDownPressed @@ -365,7 +365,7 @@ HandleMenuInputPokemonSelectionDouble: and b ; does the menu care about any of the pressed keys? jp z, .loop1 .checkIfAButtonOrBButtonPressed - ld a, [hJoy5] + ldh a, [hJoy5] and A_BUTTON | B_BUTTON jr z, .skipPlayingSound .AButtonOrBButtonPressed @@ -373,17 +373,17 @@ HandleMenuInputPokemonSelectionDouble: call PlaySound ; play sound .skipPlayingSound pop af - ld [H_DOWNARROWBLINKCNT2], a + ldh [hDownArrowBlinkCount2], a pop af - ld [H_DOWNARROWBLINKCNT1], a ; restore previous values - ld a, [hJoy5] + ldh [hDownArrowBlinkCount1], a ; restore previous values + ldh a, [hJoy5] ret .UpdateCursorTile: ld a, [wTopMenuItemY] and a jr z, .asm_f5ac0 - coord hl, 0, 0 + hlcoord 0, 0 ld bc, SCREEN_WIDTH .loop add hl, bc @@ -439,11 +439,7 @@ INCLUDE "engine/overworld/field_move_messages.asm" INCLUDE "engine/items/inventory.asm" -TrainerInfoTextBoxTileGraphics: INCBIN "gfx/trainer_info.2bpp" -TrainerInfoTextBoxTileGraphicsEnd: -BlankLeaderNames: INCBIN "gfx/blank_leader_names.2bpp" -CircleTile: INCBIN "gfx/circle_tile.2bpp" -BadgeNumbersTileGraphics: INCBIN "gfx/badge_numbers.2bpp" +INCLUDE "gfx/trainer_card.asm" ReadSuperRodData: ld a, [wCurMap] @@ -485,11 +481,11 @@ GenerateRandomFishingEncounter: ld d, [hl] ret -INCLUDE "data/super_rod.asm" +INCLUDE "data/wild/super_rod.asm" INCLUDE "engine/battle/bank3d_battle.asm" INCLUDE "engine/items/tm_prices.asm" -INCLUDE "engine/multiply_divide.asm" -INCLUDE "engine/give_pokemon.asm" +INCLUDE "engine/math/multiply_divide.asm" +INCLUDE "engine/events/give_pokemon.asm" INCLUDE "engine/battle/get_trainer_name.asm" -INCLUDE "engine/random.asm" +INCLUDE "engine/math/random.asm" INCLUDE "engine/predefs.asm" diff --git a/engine/bank3f.asm b/engine/bank3f.asm index 23eadbb1..c26e9834 100644 --- a/engine/bank3f.asm +++ b/engine/bank3f.asm @@ -1,6 +1,6 @@ -INCLUDE "data/map_songs.asm" -INCLUDE "data/map_header_pointers.asm" -INCLUDE "data/map_header_banks.asm" +INCLUDE "data/maps/songs.asm" +INCLUDE "data/maps/map_header_pointers.asm" +INCLUDE "data/maps/map_header_banks.asm" INCLUDE "engine/pikachu_follow.asm" INCLUDE "engine/pikachu_status.asm" INCLUDE "engine/pikachu_emotions.asm" @@ -16,8 +16,8 @@ SandshrewSprite: INCBIN "gfx/sprites/sandshrew.2bpp" OddishSprite: INCBIN "gfx/sprites/oddish.2bpp" BulbasaurSprite: INCBIN "gfx/sprites/bulbasaur.2bpp" JigglypuffSprite: INCBIN "gfx/sprites/jigglypuff.2bpp" -Clefairy2Sprite: INCBIN "gfx/sprites/clefairy2.2bpp" +ClefairySprite: INCBIN "gfx/sprites/clefairy.2bpp" ChanseySprite: INCBIN "gfx/sprites/chansey.2bpp" -SurfingPikachuSprite: INCBIN "gfx/sprites/surfing_pikachu.2bpp" +SurfingPikachuSprite:: INCBIN "gfx/sprites/surfing_pikachu.2bpp" JessieSprite: INCBIN "gfx/sprites/jessie.2bpp" JamesSprite: INCBIN "gfx/sprites/james.2bpp" diff --git a/engine/battle/animations.asm b/engine/battle/animations.asm index de1e67b9..4508dbaa 100755 --- a/engine/battle/animations.asm +++ b/engine/battle/animations.asm @@ -19,11 +19,11 @@ DrawFrameBlock: ld [wdef5], a ld a, [wSubAnimTransform] dec a - jr z, .flipHorizontalAndVertical ; 1 + jr z, .flipHorizontalAndVertical ; SUBANIMTYPE_HVFLIP dec a - jp z, .flipHorizontalTranslateDown ; 2 + jp z, .flipHorizontalTranslateDown ; SUBANIMTYPE_HFLIP dec a - jr z, .flipBaseCoords ; 3 + jr z, .flipBaseCoords ; SUBANIMTYPE_COORDFLIP .noTransformation ld a, [wBaseCoordY] add [hl] @@ -45,7 +45,7 @@ DrawFrameBlock: ld b, a ld a, 168 sub b ; flip X base coordinate -.finishCopying ; finish copying values to OAM (when [wSubAnimTransform] not 1 or 2) +.finishCopying ; finish copying values to OAM (when subanimation not transformed) add [hl] ; X offset ld [de], a ; store X cp 88 @@ -159,15 +159,15 @@ DrawFrameBlock: jp nz, .loop ; go back up if there are more tiles to draw .afterDrawingTiles ld a, [wFBMode] - cp 2 + cp FRAMEBLOCKMODE_02 jr z, .advanceFrameBlockDestAddr; skip delay and don't clean OAM buffer ld a, [wSubAnimFrameDelay] ld c, a call DelayFrames ld a, [wFBMode] - cp 3 + cp FRAMEBLOCKMODE_03 jr z, .advanceFrameBlockDestAddr ; skip cleaning OAM buffer - cp 4 + cp FRAMEBLOCKMODE_04 jr z, .done ; skip cleaning OAM buffer and don't advance the frame block destination address ld a, [wAnimationID] cp GROWL @@ -190,7 +190,7 @@ DrawFrameBlock: PlayAnimation: xor a - ld [$FF8B], a ; it looks like nothing reads this + ldh [hROMBankTemp], a ; it looks like nothing reads this ld [wSubAnimTransform], a ld a, [wAnimationID] ; get animation number dec a @@ -204,9 +204,9 @@ PlayAnimation: ld l, a .animationLoop ld a, [hli] - cp $FF + cp -1 jr z, .AnimationOver - cp $C0 ; is this subanimation or a special effect? + cp FIRST_SE_ID ; is this subanimation or a special effect? jr c, .playSubanimation .doSpecialEffect ld c, a @@ -221,7 +221,7 @@ PlayAnimation: jr .searchSpecialEffectTableLoop .foundMatch ld a, [hli] - cp $FF ; is there a sound to play? + cp NO_MOVE - 1 ; is there a sound to play? jr z, .skipPlayingSound ld [wAnimSoundID], a ; store sound push hl @@ -268,16 +268,16 @@ PlayAnimation: ld l, c ld h, b push hl - ld a, [rOBP0] + ldh a, [rOBP0] push af ld a, [wAnimPalette] - ld [rOBP0], a + ldh [rOBP0], a call UpdateGBCPal_OBP0 call LoadAnimationTileset call LoadSubanimation call PlaySubanimation pop af - ld [rOBP0], a + ldh [rOBP0], a call UpdateGBCPal_OBP0 .nextAnimationCommand pop hl @@ -296,11 +296,11 @@ LoadSubanimation: ld d, a ; de = address of subanimation ld a, [de] ld b, a - and 31 + and %00011111 ld [wSubAnimCounter], a ; number of frame blocks ld a, b and %11100000 - cp 5 << 5 ; is subanimation type 5? + cp SUBANIMTYPE_ENEMY << 5 jr nz, .isNotType5 .isType5 call GetSubanimationTransform2 @@ -312,7 +312,7 @@ LoadSubanimation: srl a swap a ld [wSubAnimTransform], a - cp 4 ; is the animation reversed? + cp SUBANIMTYPE_REVERSE ld hl, 0 jr nz, .storeSubentryAddr ; if the animation is reversed, then place the initial subentry address at the end of the list of subentries @@ -332,27 +332,27 @@ LoadSubanimation: ld [wSubAnimSubEntryAddr + 1], a ret -; called if the subanimation type is not 5 -; sets the transform to 0 (i.e. no transform) if it's the player's turn +; called if the subanimation type is not SUBANIMTYPE_ENEMY +; sets the transform to SUBANIMTYPE_NORMAL if it's the player's turn ; sets the transform to the subanimation type if it's the enemy's turn GetSubanimationTransform1: ld b, a - ld a, [H_WHOSETURN] + ldh a, [hWhoseTurn] and a ld a, b ret nz - xor a + xor a ; SUBANIMTYPE_NORMAL << 5 ret -; called if the subanimation type is 5 -; sets the transform to 2 (i.e. horizontal and vertical flip) if it's the player's turn -; sets the transform to 0 (i.e. no transform) if it's the enemy's turn +; called if the subanimation type is SUBANIMTYPE_ENEMY +; sets the transform to SUBANIMTYPE_HFLIP if it's the player's turn +; sets the transform to SUBANIMTYPE_NORMAL if it's the enemy's turn GetSubanimationTransform2: - ld a, [H_WHOSETURN] + ldh a, [hWhoseTurn] and a - ld a, 2 << 5 + ld a, SUBANIMTYPE_HFLIP << 5 ret z - xor a + xor a ; SUBANIMTYPE_NORMAL << 5 ret ; loads tile patterns for battle animations @@ -370,33 +370,33 @@ LoadAnimationTileset: ld e, a ld a, [hl] ld d, a ; de = address of tileset - ld hl, vSprites + $310 + ld hl, vSprites tile $31 ld b, BANK(AnimationTileset1) ; ROM bank ld a, [wTempTilesetNumTiles] ld c, a ; number of tiles jp CopyVideoData ; load tileset -AnimationTilesetPointers: - db 79 ; number of tiles - dw AnimationTileset1 - db $FF - - db 79 ; number of tiles - dw AnimationTileset2 - db $FF +anim_tileset: MACRO + db \1 + dw \2 + db -1 ; padding +ENDM - db 64 ; number of tiles - dw AnimationTileset1 - db $FF +AnimationTilesetPointers: + ; number of tiles, gfx pointer + anim_tileset 79, AnimationTileset1 + anim_tileset 79, AnimationTileset2 + anim_tileset 64, AnimationTileset1 AnimationTileset1: - INCBIN "gfx/attack_anim_1.2bpp" + INCBIN "gfx/battle/attack_anim_1.2bpp" AnimationTileset2: - INCBIN "gfx/attack_anim_2.2bpp" + INCBIN "gfx/battle/attack_anim_2.2bpp" SlotMachineTiles2: - INCBIN "gfx/slotmachine2.2bpp" + INCBIN "gfx/slots/slots_2.2bpp" +SlotMachineTiles2End: MoveAnimation: push hl @@ -435,7 +435,7 @@ MoveAnimation: ld [wSubAnimSubEntryAddr], a ld [wUnusedD09B], a ld [wSubAnimTransform], a - dec a + dec a ; NO_MOVE - 1 ld [wAnimSoundID], a pop af pop bc @@ -445,11 +445,11 @@ MoveAnimation: ShareMoveAnimations: ; some moves just reuse animations from status conditions - ld a, [H_WHOSETURN] + ldh a, [hWhoseTurn] and a ret z - ; opponent’s turn + ; opponent's turn ld a, [wAnimationID] @@ -484,10 +484,10 @@ PlayApplyingAttackAnimation: jp hl AnimationTypePointerTable: - dw ShakeScreenVertically ; enemy mon has used a damaging move without a side effect + dw ShakeScreenVertically ; enemy mon has used a damaging move without a side effect dw ShakeScreenHorizontallyHeavy ; enemy mon has used a damaging move with a side effect - dw ShakeScreenHorizontallySlow ; enemy mon has used a non-damaging move - dw BlinkEnemyMonSprite ; player mon has used a damaging move without a side effect + dw ShakeScreenHorizontallySlow ; enemy mon has used a non-damaging move + dw BlinkEnemyMonSprite ; player mon has used a damaging move without a side effect dw ShakeScreenHorizontallyLight ; player mon has used a damaging move with a side effect dw ShakeScreenHorizontallySlow2 ; player mon has used a non-damaging move @@ -521,18 +521,18 @@ AnimationShakeScreenHorizontallySlow: push bc push bc .loop1 - ld a, [rWX] + ldh a, [rWX] inc a - ld [rWX], a + ldh [rWX], a ld c, 2 call DelayFrames dec b jr nz, .loop1 pop bc .loop2 - ld a, [rWX] + ldh a, [rWX] dec a - ld [rWX], a + ldh [rWX], a ld c, 2 call DelayFrames dec b @@ -558,18 +558,18 @@ SetAnimationPalette: ld b, $f0 .next ld a, b - ld [rOBP0], a + ldh [rOBP0], a ld a, $6c - ld [rOBP1], a + ldh [rOBP1], a call UpdateGBCPal_OBP0 call UpdateGBCPal_OBP1 ret .notSGB ld a, $e4 ld [wAnimPalette], a - ld [rOBP0], a + ldh [rOBP0], a ld a, $6c - ld [rOBP1], a + ldh [rOBP1], a call UpdateGBCPal_OBP0 call UpdateGBCPal_OBP1 ret @@ -577,13 +577,13 @@ SetAnimationPalette: Func_78e98: call SaveScreenTilesToBuffer2 xor a - ld [H_AUTOBGTRANSFERENABLED], a + ldh [hAutoBGTransferEnabled], a call ClearScreen ld h, vBGMap0 / $100 call WriteLowerByteOfBGMapAndEnableBGTransfer call Delay3 xor a - ld [H_AUTOBGTRANSFERENABLED], a + ldh [hAutoBGTransferEnabled], a call LoadScreenTilesFromBuffer2 ld h, vBGMap1 / $100 @@ -591,12 +591,12 @@ WriteLowerByteOfBGMapAndEnableBGTransfer: ld l, vBGMap0 & $ff call BattleAnimCopyTileMapToVRAM ld a, $1 - ld [H_AUTOBGTRANSFERENABLED], a + ldh [hAutoBGTransferEnabled], a ret PlaySubanimation: ld a, [wAnimSoundID] - cp $FF + cp NO_MOVE - 1 jr z, .skipPlayingSound call GetMoveSound call PlaySound @@ -648,7 +648,7 @@ PlaySubanimation: ld a, [wSubAnimSubEntryAddr] ld l, a ld a, [wSubAnimTransform] - cp 4 ; is the animation reversed? + cp SUBANIMTYPE_REVERSE ld bc, 3 jr nz, .nextSubanimationSubentry ld bc, -3 @@ -697,90 +697,16 @@ DoSpecialEffectByAnimationId: pop hl ret -; Format: Animation ID (1 byte), Address (2 bytes) -AnimationIdSpecialEffects: - db MEGA_PUNCH - dw AnimationFlashScreen - - db GUILLOTINE - dw AnimationFlashScreen - - db MEGA_KICK - dw AnimationFlashScreen - - db HEADBUTT - dw AnimationFlashScreen - - db TAIL_WHIP - dw TailWhipAnimationUnused - - db GROWL - dw DoGrowlSpecialEffects - - db DISABLE - dw AnimationFlashScreen - - db BLIZZARD - dw DoBlizzardSpecialEffects - - db BUBBLEBEAM - dw AnimationFlashScreen - - db HYPER_BEAM - dw FlashScreenEveryFourFrameBlocks - - db THUNDERBOLT - dw FlashScreenEveryEightFrameBlocks - - db REFLECT - dw AnimationFlashScreen - - db SELFDESTRUCT - dw DoExplodeSpecialEffects - - db SPORE - dw FlashScreenEveryFourFrameBlocks - - db EXPLOSION - dw DoExplodeSpecialEffects - - db ROCK_SLIDE - dw DoRockSlideSpecialEffects - - db TRADE_BALL_DROP_ANIM - dw TradeHidePokemon - - db TRADE_BALL_SHAKE_ANIM - dw TradeShakePokeball - - db TRADE_BALL_TILT_ANIM - dw TradeJumpPokeball - - db TOSS_ANIM - dw DoBallTossSpecialEffects - - db SHAKE_ANIM - dw DoBallShakeSpecialEffects - - db POOF_ANIM - dw DoPoofSpecialEffects - - db GREATTOSS_ANIM - dw DoBallTossSpecialEffects - - db ULTRATOSS_ANIM - dw DoBallTossSpecialEffects - - db $FF ; terminator +INCLUDE "data/battle_anims/special_effects.asm" DoBallTossSpecialEffects: ld a, [wcf91] cp 3 ; is it a Master Ball or Ultra Ball? jr nc, .skipFlashingEffect .flashingEffect ; do a flashing effect if it's Master Ball or Ultra Ball - ld a, [rOBP0] + ldh a, [rOBP0] xor %00111100 ; complement colors 1 and 2 - ld [rOBP0], a + ldh [rOBP0], a call UpdateGBCPal_OBP0 .skipFlashingEffect ld a, [wSubAnimCounter] @@ -805,7 +731,7 @@ DoBallTossSpecialEffects: cp 1 ret nz .moveGhostMarowakLeft - coord hl, 17, 0 + hlcoord 17, 0 ld de, 20 lb bc, 7, 7 .loop @@ -818,7 +744,7 @@ DoBallTossSpecialEffects: dec b jr nz, .loop ld a, %00001000 - ld [rNR10], a ; Channel 1 sweep register + ldh [rNR10], a ; Channel 1 sweep register ret .isTrainerBattle ; if it's a trainer battle, shorten the animation by one frame ld a, [wSubAnimCounter] @@ -904,7 +830,7 @@ DoExplodeSpecialEffects: cp 1 ; is it the end of the subanimation? jr nz, FlashScreenEveryFourFrameBlocks ; if it's the end of the subanimation, make the attacking pokemon disappear - coord hl, 1, 5 + hlcoord 1, 5 jp AnimationHideMonPic ; make pokemon disappear ; flashes the screen when subanimation counter is 1 modulo 4 @@ -972,7 +898,7 @@ TradeShakePokeball: BallMoveDistances1: db -12, -12, -8 - db $ff ; terminator + db -1 ; end ; function to make the pokeball jump up TradeJumpPokeball: @@ -1005,15 +931,15 @@ TradeJumpPokeball: ld c, 5 call DelayFrames pop bc - ld a, [hSCX] ; background scroll X + ldh a, [hSCX] ; background scroll X sub 8 ; scroll to the left - ld [hSCX], a + ldh [hSCX], a pop de jr .loop BallMoveDistances2: db 11, 12, -12, -7, 7, 12, -8, 8 - db $ff ; terminator + db -1 ; end ; this function copies the current musical note graphic ; so that there are two musical notes flying towards the defending pokemon @@ -1034,87 +960,7 @@ TailWhipAnimationUnused: ld c, 20 jp DelayFrames -; Format: Special Effect ID (1 byte), Address (2 bytes) -SpecialEffectPointers: - db SE_DARK_SCREEN_FLASH ; $FE - dw AnimationFlashScreen - db SE_DARK_SCREEN_PALETTE ; $FD - dw AnimationDarkScreenPalette - db SE_RESET_SCREEN_PALETTE ; $FC - dw AnimationResetScreenPalette - db SE_SHAKE_SCREEN ; $FB - dw AnimationShakeScreen - db SE_WATER_DROPLETS_EVERYWHERE ; $FA - dw AnimationWaterDropletsEverywhere - db SE_DARKEN_MON_PALETTE ; $F9 - dw AnimationDarkenMonPalette - db SE_FLASH_SCREEN_LONG ; $F8 - dw AnimationFlashScreenLong - db SE_SLIDE_MON_UP ; $F7 - dw AnimationSlideMonUp - db SE_SLIDE_MON_DOWN ; $F6 - dw AnimationSlideMonDown - db SE_FLASH_MON_PIC ; $F5 - dw AnimationFlashMonPic - db SE_SLIDE_MON_OFF ; $F4 - dw AnimationSlideMonOff - db SE_BLINK_MON ; $F3 - dw AnimationBlinkMon - db SE_MOVE_MON_HORIZONTALLY ; $F2 - dw AnimationMoveMonHorizontally - db SE_RESET_MON_POSITION ; $F1 - dw AnimationResetMonPosition - db SE_LIGHT_SCREEN_PALETTE ; $F0 - dw AnimationLightScreenPalette - db SE_HIDE_MON_PIC ; $EF - dw AnimationHideMonPic - db SE_SQUISH_MON_PIC ; $EE - dw AnimationSquishMonPic - db SE_SHOOT_BALLS_UPWARD ; $ED - dw AnimationShootBallsUpward - db SE_SHOOT_MANY_BALLS_UPWARD ; $EC - dw AnimationShootManyBallsUpward - db SE_BOUNCE_UP_AND_DOWN ; $EB - dw AnimationBoundUpAndDown - db SE_MINIMIZE_MON ; $EA - dw AnimationMinimizeMon - db SE_SLIDE_MON_DOWN_AND_HIDE ; $E9 - dw AnimationSlideMonDownAndHide - db SE_TRANSFORM_MON ; $E8 - dw AnimationTransformMon - db SE_LEAVES_FALLING ; $E7 - dw AnimationLeavesFalling - db SE_PETALS_FALLING ; $E6 - dw AnimationPetalsFalling - db SE_SLIDE_MON_HALF_OFF ; $E5 - dw AnimationSlideMonHalfOff - db SE_SHAKE_ENEMY_HUD ; $E4 - dw AnimationShakeEnemyHUD - db SE_SHAKE_ENEMY_HUD_2 ; unused--same pointer as SE_SHAKE_ENEMY_HUD ($E4) - dw AnimationShakeEnemyHUD - db SE_SPIRAL_BALLS_INWARD ; $E2 - dw AnimationSpiralBallsInward - db SE_DELAY_ANIMATION_10 ; $E1 - dw AnimationDelay10 - db SE_FLASH_ENEMY_MON_PIC ; unused--same as SE_FLASH_MON_PIC ($F5), but for the enemy mon - dw AnimationFlashEnemyMonPic - db SE_HIDE_ENEMY_MON_PIC ; $DF - dw AnimationHideEnemyMonPic - db SE_BLINK_ENEMY_MON ; $DE - dw AnimationBlinkEnemyMon - db SE_SHOW_MON_PIC ; $DD - dw AnimationShowMonPic - db SE_SHOW_ENEMY_MON_PIC ; $DC - dw AnimationShowEnemyMonPic - db SE_SLIDE_ENEMY_MON_OFF ; $DB - dw AnimationSlideEnemyMonOff - db SE_SHAKE_BACK_AND_FORTH ; $DA - dw AnimationShakeBackAndForth - db SE_SUBSTITUTE_MON ; $D9 - dw AnimationSubstitute - db SE_WAVY_SCREEN ; $D8 - dw AnimationWavyScreen - db $FF +INCLUDE "data/battle_anims/special_effect_pointers.asm" AnimationDelay10: ld c, 10 @@ -1123,16 +969,16 @@ AnimationDelay10: ; calls a function with the turn flipped from player to enemy or vice versa ; input - hl - address of function to call CallWithTurnFlipped: - ld a, [H_WHOSETURN] + ldh a, [hWhoseTurn] push af xor 1 - ld [H_WHOSETURN], a + ldh [hWhoseTurn], a ld de, .returnAddress push de jp hl .returnAddress pop af - ld [H_WHOSETURN], a + ldh [hWhoseTurn], a ret ; flashes the screen for an extended period (48 frames) @@ -1150,7 +996,7 @@ AnimationFlashScreenLong: ld a, [hli] cp $01 ; is it the end of the palettes? jr z, .endOfPalettes - ld [rBGP], a + ldh [rBGP], a call UpdateGBCPal_BGP call FlashScreenLongDelay jr .innerLoop @@ -1210,20 +1056,20 @@ FlashScreenLongDelay: jp DelayFrames AnimationFlashScreen: - ld a, [rBGP] + ldh a, [rBGP] push af ; save initial palette ld a, %00011011 ; 0, 1, 2, 3 (inverted colors) - ld [rBGP], a + ldh [rBGP], a call UpdateGBCPal_BGP ld c, 2 call DelayFrames xor a ; white out background - ld [rBGP], a + ldh [rBGP], a call UpdateGBCPal_BGP ld c, 2 call DelayFrames pop af - ld [rBGP], a ; restore initial palette + ldh [rBGP], a ; restore initial palette call UpdateGBCPal_BGP ret @@ -1269,7 +1115,7 @@ SetAnimationBGPalette: jr z, .next ld a, c .next - ld [rBGP], a + ldh [rBGP], a call UpdateGBCPal_BGP ret @@ -1356,14 +1202,14 @@ _AnimationWaterDroplets: AnimationSlideMonUp: ; Slides the mon's sprite upwards. ld c, 7 - ld a, [H_WHOSETURN] + ldh a, [hWhoseTurn] and a - coord hl, 1, 6 - coord de, 1, 5 + hlcoord 1, 6 + decoord 1, 5 ld a, $30 jr z, .next - coord hl, 12, 1 - coord de, 12, 0 + hlcoord 12, 1 + decoord 12, 0 ld a, $ff .next ld [wSlideMonUpBottomRowLeftTile], a @@ -1371,7 +1217,7 @@ AnimationSlideMonUp: AnimationSlideMonDown: ; Slides the mon's sprite down out of the screen. - xor a + xor a ; TILEMAP_MON_PIC call GetTileIDList .loop call GetMonSpriteTileMapPointerFromRowCount @@ -1424,11 +1270,11 @@ _AnimationSlideMonUp: jr nz, .slideLoop ; Fill in the bottom row of the mon pic with the next row's tile IDs. - ld a, [H_WHOSETURN] + ldh a, [hWhoseTurn] and a - coord hl, 1, 11 + hlcoord 1, 11 jr z, .next - coord hl, 12, 6 + hlcoord 12, 6 .next ld a, [wSlideMonUpBottomRowLeftTile] inc a @@ -1592,7 +1438,7 @@ AnimationFlashEnemyMonPic: jp CallWithTurnFlipped AnimationShowMonPic: - xor a + xor a ; TILEMAP_MON_PIC call GetTileIDList call GetMonSpriteTileMapPointerFromRowCount call CopyPicTiles @@ -1607,16 +1453,16 @@ AnimationShowEnemyMonPic: AnimationShakeBackAndForth: ; Shakes the mon's sprite back and forth rapidly. This is used in Double Team. ; The mon's sprite disappears after this animation. - ld a, [H_WHOSETURN] + ldh a, [hWhoseTurn] and a - coord hl, 0, 5 - coord de, 2, 5 + hlcoord 0, 5 + decoord 2, 5 jr z, .next - coord hl, 11, 0 - coord de, 13, 0 + hlcoord 11, 0 + decoord 13, 0 .next - xor a + xor a ; TILEMAP_MON_PIC ld c, $10 .loop push af @@ -1655,13 +1501,13 @@ AnimationMoveMonHorizontally: ; Shifts the mon's sprite horizontally to a fixed location. Used by lots of ; animations like Tackle/Body Slam. call AnimationHideMonPic - ld a, [H_WHOSETURN] + ldh a, [hWhoseTurn] and a - coord hl, 2, 5 + hlcoord 2, 5 jr z, .next - coord hl, 11, 0 + hlcoord 11, 0 .next - xor a + xor a ; TILEMAP_MON_PIC push hl call GetTileIDList pop hl @@ -1671,7 +1517,7 @@ AnimationMoveMonHorizontally: AnimationResetMonPosition: ; Resets the mon's sprites to be located at the normal coordinates. - ld a, [H_WHOSETURN] + ldh a, [hWhoseTurn] and a ld a, 5 * SCREEN_WIDTH + 2 jr z, .next @@ -1683,7 +1529,7 @@ AnimationResetMonPosition: AnimationSpiralBallsInward: ; Creates an effect that looks like energy balls spiralling into the ; player mon's sprite. Used in Focus Energy, for example. - ld a, [H_WHOSETURN] + ldh a, [hWhoseTurn] and a jr z, .playerTurn ld a, -40 @@ -1772,7 +1618,7 @@ SpiralBallAnimationCoordinates: db $58, $28 db $50, $30 db $50, $28 - db $FF ; list terminator + db -1 ; end AnimationSquishMonPic: ; Squishes the mon's sprite horizontally making it @@ -1780,15 +1626,15 @@ AnimationSquishMonPic: ld c, 4 .loop push bc - ld a, [H_WHOSETURN] + ldh a, [hWhoseTurn] and a jr z, .playerTurn - coord hl, 16, 0 - coord de, 14, 0 + hlcoord 16, 0 + decoord 14, 0 jr .next .playerTurn - coord hl, 5, 5 - coord de, 3, 5 + hlcoord 5, 5 + decoord 3, 5 .next push de xor a ; left @@ -1833,7 +1679,7 @@ _AnimationSquishMonPic: AnimationShootBallsUpward: ; Shoots one pillar of "energy" balls upwards. Used in Teleport/Sky Attack ; animations. - ld a, [H_WHOSETURN] + ldh a, [hWhoseTurn] and a jr z, .playerTurn lb bc, 0, 16 * 8 @@ -1901,7 +1747,7 @@ _AnimationShootBallsUpward: AnimationShootManyBallsUpward: ; Shoots several pillars of "energy" balls upward. - ld a, [H_WHOSETURN] + ldh a, [hWhoseTurn] and a ld hl, UpwardBallsAnimXCoordinatesPlayerTurn ld a, $50 ; y coordinate for "energy" ball pillar @@ -1927,13 +1773,13 @@ UpwardBallsAnimXCoordinatesPlayerTurn: ; List of x coordinates for each pillar of "energy" balls in the ; AnimationShootManyBallsUpward animation. It's unused in the game. db $10, $40, $28, $18, $38, $30 - db $FF ; list terminator + db -1 ; end UpwardBallsAnimXCoordinatesEnemyTurn: ; List of x coordinates for each pillar of "energy" balls in the ; AnimationShootManyBallsUpward animation. It's unused in the game. db $60, $90, $78, $68, $88, $80 - db $FF ; list terminator + db -1 ; end AnimationMinimizeMon: ; Changes the mon's sprite to a mini black sprite. Used by the @@ -1960,13 +1806,13 @@ AnimationMinimizeMon: jp AnimationShowMonPic MinimizedMonSprite: - INCBIN "gfx/minimized_mon_sprite.1bpp" + INCBIN "gfx/battle/minimize.1bpp" MinimizedMonSpriteEnd: AnimationSlideMonDownAndHide: ; Slides the mon's sprite down and disappears. Used in Acid Armor. - ld a, $1 - ld c, $2 + ld a, TILEMAP_SLIDE_DOWN_MON_PIC_7X5 + ld c, 2 .loop push bc push af @@ -1985,7 +1831,7 @@ AnimationSlideMonDownAndHide: jr nz, .loop call AnimationHideMonPic ld hl, wTempPic - ld bc, $0310 + ld bc, 7 * 7 tiles xor a call FillMemory jp CopyTempPicToMonPic @@ -1993,13 +1839,13 @@ AnimationSlideMonDownAndHide: _AnimationSlideMonOff: ; Slides the mon's sprite off the screen horizontally by e tiles and waits ; [wSlideMonDelay] V-blanks each time the pic is slid by one tile. - ld a, [H_WHOSETURN] + ldh a, [hWhoseTurn] and a jr z, .playerTurn - coord hl, 12, 0 + hlcoord 12, 0 jr .next .playerTurn - coord hl, 0, 5 + hlcoord 0, 5 .next ld d, 8 ; d's value is unused .slideLoop ; iterates once for each time the pic slides by one tile @@ -2008,7 +1854,7 @@ _AnimationSlideMonOff: .rowLoop ; iterates once for each row ld c, 8 .tileLoop ; iterates once for each tile in the row - ld a, [H_WHOSETURN] + ldh a, [hWhoseTurn] and a jr z, .playerTurn2 call .EnemyNextTile @@ -2069,7 +1915,7 @@ AnimationSlideMonHalfOff: jp Delay3 CopyTempPicToMonPic: - ld a, [H_WHOSETURN] + ldh a, [hWhoseTurn] and a ld hl, vBackPic ; player turn jr z, .next @@ -2085,18 +1931,18 @@ AnimationWavyScreen: call BattleAnimCopyTileMapToVRAM call Delay3 xor a - ld [H_AUTOBGTRANSFERENABLED], a - ld a, SCREEN_HEIGHT_PIXELS - ld [hWY], a + ldh [hAutoBGTransferEnabled], a + ld a, SCREEN_HEIGHT_PX + ldh [hWY], a ld d, $80 ; terminator - ld e, SCREEN_HEIGHT_PIXELS - 1 + ld e, SCREEN_HEIGHT_PX - 1 ld c, $ff ld hl, WavyScreenLineOffsets .loop push hl .innerLoop call WavyScreen_SetSCX - ld a, [rLY] + ldh a, [rLY] cp e ; is it the last visible line in the frame? jr nz, .innerLoop ; keep going if not pop hl @@ -2109,11 +1955,11 @@ AnimationWavyScreen: dec c jr nz, .loop xor a - ld [hWY], a + ldh [hWY], a call SaveScreenTilesToBuffer2 call ClearScreen ld a, 1 - ld [H_AUTOBGTRANSFERENABLED], a + ldh [hAutoBGTransferEnabled], a call Delay3 call LoadScreenTilesFromBuffer2 ld hl, vBGMap1 @@ -2121,11 +1967,11 @@ AnimationWavyScreen: ret WavyScreen_SetSCX: - ld a, [rSTAT] + ldh a, [rSTAT] and $3 ; is it H-blank? jr nz, WavyScreen_SetSCX ; wait until it's H-blank ld a, [hl] - ld [rSCX], a + ldh [rSCX], a inc hl ld a, [hl] cp d ; have we reached the end? @@ -2144,48 +1990,48 @@ AnimationSubstitute: ; Changes the pokemon's sprite to the mini sprite ld hl, wTempPic xor a - ld bc, $0310 + ld bc, $310 call FillMemory - ld a, [H_WHOSETURN] + ldh a, [hWhoseTurn] and a jr z, .playerTurn - ld hl, SlowbroSprite ; facing down sprite + ld hl, MonsterSprite tile 0 ; facing down sprite ld de, wTempPic + $120 - call CopySlowbroSpriteData - ld hl, SlowbroSprite + $10 + call CopyMonsterSpriteData + ld hl, MonsterSprite tile 1 ld de, wTempPic + $120 + $70 - call CopySlowbroSpriteData - ld hl, SlowbroSprite + $20 + call CopyMonsterSpriteData + ld hl, MonsterSprite tile 2 ld de, wTempPic + $120 + $10 - call CopySlowbroSpriteData - ld hl, SlowbroSprite + $30 + call CopyMonsterSpriteData + ld hl, MonsterSprite tile 3 ld de, wTempPic + $120 + $10 + $70 - call CopySlowbroSpriteData + call CopyMonsterSpriteData jr .next .playerTurn - ld hl, SlowbroSprite + $40 ; facing up sprite + ld hl, MonsterSprite tile 4 ; facing up sprite ld de, wTempPic + $120 + $70 - call CopySlowbroSpriteData - ld hl, SlowbroSprite + $50 + call CopyMonsterSpriteData + ld hl, MonsterSprite tile 5 ld de, wTempPic + $120 + $e0 - call CopySlowbroSpriteData - ld hl, SlowbroSprite + $60 + call CopyMonsterSpriteData + ld hl, MonsterSprite tile 6 ld de, wTempPic + $120 + $80 - call CopySlowbroSpriteData - ld hl, SlowbroSprite + $70 + call CopyMonsterSpriteData + ld hl, MonsterSprite tile 7 ld de, wTempPic + $120 + $f0 - call CopySlowbroSpriteData + call CopyMonsterSpriteData .next call CopyTempPicToMonPic jp AnimationShowMonPic -CopySlowbroSpriteData: - ld bc, $0010 - ld a, BANK(SlowbroSprite) +CopyMonsterSpriteData: + ld bc, 1 tiles + ld a, BANK(MonsterSprite) jp FarCopyData HideSubstituteShowMonAnim: - ld a, [H_WHOSETURN] + ldh a, [hWhoseTurn] and a ld hl, wPlayerMonMinimized ld de, wPlayerBattleStatus1 @@ -2226,7 +2072,7 @@ HideSubstituteShowMonAnim: call AnimationFlashMonPic jp AnimationShowMonPic .flyOrDig - ld a, [H_WHOSETURN] + ldh a, [hWhoseTurn] and a jr nz, .enemy ld a, [wPlayerMonMinimized] @@ -2294,7 +2140,7 @@ AnimationTransformMon: ld [wChangeMonPicEnemyTurnSpecies], a ChangeMonPic: - ld a, [H_WHOSETURN] + ldh a, [hWhoseTurn] and a jr z, .playerTurn ld a, [wChangeMonPicEnemyTurnSpecies] @@ -2303,7 +2149,7 @@ ChangeMonPic: xor a ld [wSpriteFlipped], a call GetMonHeader - coord hl, 12, 0 + hlcoord 12, 0 call LoadFrontSpriteByMonIndex jr .done .playerTurn @@ -2314,7 +2160,7 @@ ChangeMonPic: ld [wd0b5], a call GetMonHeader predef LoadMonBackPic - xor a + xor a ; TILEMAP_MON_PIC call GetTileIDList call GetMonSpriteTileMapPointerFromRowCount call CopyPicTiles @@ -2327,16 +2173,16 @@ ChangeMonPic: AnimationHideEnemyMonPic: ; Hides the enemy mon's sprite xor a - ld [H_AUTOBGTRANSFERENABLED], a + ldh [hAutoBGTransferEnabled], a ld hl, AnimationHideMonPic call CallWithTurnFlipped ld a, $1 - ld [H_AUTOBGTRANSFERENABLED], a + ldh [hAutoBGTransferEnabled], a jp Delay3 Func_79929: ld hl, wPlayerMonMinimized - ld a, [H_WHOSETURN] + ldh a, [hWhoseTurn] and a jr z, .playerTurn ld hl, wEnemyMonMinimized @@ -2376,7 +2222,7 @@ InitMultipleObjectsOAM: AnimationHideMonPic: ; Hides the mon's sprite. - ld a, [H_WHOSETURN] + ldh a, [hWhoseTurn] and a jr z, .playerTurn ld a, 12 @@ -2390,7 +2236,7 @@ ClearMonPicFromTileMap: push bc ld e, a ld d, 0 - coord hl, 0, 0 + hlcoord 0, 0 add hl, de lb bc, 7, 7 call ClearScreenArea @@ -2404,7 +2250,7 @@ ClearMonPicFromTileMap: ; in order to show only a portion of the mon sprite. GetMonSpriteTileMapPointerFromRowCount: push de - ld a, [H_WHOSETURN] + ldh a, [hWhoseTurn] and a jr nz, .enemyTurn ld a, 20 * 5 + 1 @@ -2412,7 +2258,7 @@ GetMonSpriteTileMapPointerFromRowCount: .enemyTurn ld a, 12 .next - coord hl, 0, 0 + hlcoord 0, 0 ld e, a ld d, 0 add hl, de @@ -2492,7 +2338,7 @@ GetMoveSound: ld b, a call IsCryMove jr nc, .NotCryMove - ld a, [H_WHOSETURN] + ldh a, [hWhoseTurn] and a jr nz, .next ld a, [wBattleMonSpecies] ; get number of current monster @@ -2534,184 +2380,17 @@ IsCryMove: scf ret -MoveSoundTable: - ; ID, pitch mod, tempo mod - db SFX_POUND, $00, $80 ; POUND - db SFX_BATTLE_0C, $10, $80 ; KARATE_CHOP - db SFX_DOUBLESLAP, $00, $80 ; DOUBLESLAP - db SFX_BATTLE_0B, $01, $80 ; COMET_PUNCH - db SFX_BATTLE_0D, $00, $40 ; MEGA_PUNCH - db SFX_SILPH_SCOPE, $00, $ff ; PAY_DAY - db SFX_BATTLE_0D, $10, $60 ; FIRE_PUNCH - db SFX_BATTLE_0D, $20, $80 ; ICE_PUNCH - db SFX_BATTLE_0D, $00, $a0 ; THUNDERPUNCH - db SFX_DAMAGE, $00, $80 ; SCRATCH - db SFX_BATTLE_0F, $20, $40 ; VICEGRIP - db SFX_BATTLE_0F, $00, $80 ; GUILLOTINE - db SFX_BATTLE_0E, $00, $a0 ; RAZOR_WIND - db SFX_NOT_VERY_EFFECTIVE, $10, $c0 ; SWORDS_DANCE - db SFX_NOT_VERY_EFFECTIVE, $00, $a0 ; CUT - db SFX_BATTLE_12, $00, $c0 ; GUST - db SFX_BATTLE_12, $10, $a0 ; WING_ATTACK - db SFX_BATTLE_13, $00, $e0 ; WHIRLWIND - db SFX_NOT_VERY_EFFECTIVE, $20, $c0 ; FLY - db SFX_BATTLE_14, $00, $80 ; BIND - db SFX_BATTLE_22, $00, $80 ; SLAM - db SFX_VINE_WHIP, $01, $80 ; VINE_WHIP - db SFX_BATTLE_20, $00, $80 ; STOMP - db SFX_BATTLE_17, $f0, $40 ; DOUBLE_KICK - db SFX_SUPER_EFFECTIVE, $00, $80 ; MEGA_KICK - db SFX_BATTLE_17, $00, $80 ; JUMP_KICK - db SFX_BATTLE_21, $10, $80 ; ROLLING_KICK - db SFX_BATTLE_1B, $01, $a0 ; SAND_ATTACK - db SFX_BATTLE_18, $00, $80 ; HEADBUTT - db SFX_BATTLE_1E, $00, $60 ; HORN_ATTACK - db SFX_BATTLE_1E, $01, $40 ; FURY_ATTACK - db SFX_HORN_DRILL, $00, $a0 ; HORN_DRILL - db SFX_SUPER_EFFECTIVE, $10, $a0 ; TACKLE - db SFX_BATTLE_20, $00, $c0 ; BODY_SLAM - db SFX_BATTLE_14, $10, $60 ; WRAP - db SFX_SUPER_EFFECTIVE, $00, $a0 ; TAKE_DOWN - db SFX_BATTLE_22, $11, $c0 ; THRASH - db SFX_SUPER_EFFECTIVE, $20, $c0 ; DOUBLE_EDGE - db SFX_BATTLE_21, $00, $80 ; TAIL_WHIP - db SFX_BATTLE_1B, $00, $80 ; POISON_STING - db SFX_BATTLE_1B, $20, $c0 ; TWINEEDLE - db SFX_BATTLE_19, $00, $80 ; PIN_MISSILE - db SFX_BATTLE_31, $ff, $40 ; LEER - db SFX_BATTLE_1E, $00, $80 ; BITE - db SFX_BATTLE_0B, $00, $c0 ; GROWL - db SFX_BATTLE_0B, $00, $40 ; ROAR - db SFX_BATTLE_35, $00, $80 ; SING - db SFX_BATTLE_27, $40, $60 ; SUPERSONIC - db SFX_BATTLE_27, $00, $80 ; SONICBOOM - db SFX_BATTLE_27, $ff, $40 ; DISABLE - db SFX_BATTLE_2A, $80, $c0 ; ACID - db SFX_BATTLE_19, $10, $a0 ; EMBER - db SFX_BATTLE_19, $21, $e0 ; FLAMETHROWER - db SFX_BATTLE_29, $00, $80 ; MIST - db SFX_BATTLE_24, $20, $60 ; WATER_GUN - db SFX_BATTLE_2A, $00, $80 ; HYDRO_PUMP - db SFX_BATTLE_2C, $00, $80 ; SURF - db SFX_BATTLE_28, $40, $80 ; ICE_BEAM - db SFX_BATTLE_29, $f0, $e0 ; BLIZZARD - db SFX_PSYBEAM, $00, $80 ; PSYBEAM - db SFX_BATTLE_2A, $f0, $60 ; BUBBLEBEAM - db SFX_BATTLE_28, $00, $80 ; AURORA_BEAM - db SFX_BATTLE_36, $00, $80 ; HYPER_BEAM - db SFX_PECK, $01, $a0 ; PECK - db SFX_BATTLE_13, $f0, $20 ; DRILL_PECK - db SFX_BATTLE_23, $01, $c0 ; SUBMISSION - db SFX_BATTLE_23, $00, $80 ; LOW_KICK - db SFX_SUPER_EFFECTIVE, $00, $e0 ; COUNTER - db SFX_BATTLE_26, $01, $60 ; SEISMIC_TOSS - db SFX_BATTLE_26, $20, $40 ; STRENGTH - db SFX_BATTLE_24, $00, $80 ; ABSORB - db SFX_BATTLE_24, $40, $c0 ; MEGA_DRAIN - db SFX_BATTLE_1B, $03, $60 ; LEECH_SEED - db SFX_BATTLE_25, $11, $e0 ; GROWTH - db SFX_BATTLE_12, $20, $e0 ; RAZOR_LEAF - db SFX_BATTLE_2E, $00, $80 ; SOLARBEAM - db SFX_BATTLE_1C, $00, $80 ; POISONPOWDER - db SFX_BATTLE_1C, $11, $a0 ; STUN_SPORE - db SFX_BATTLE_1C, $01, $c0 ; SLEEP_POWDER - db SFX_BATTLE_13, $14, $c0 ; PETAL_DANCE - db SFX_BATTLE_1B, $02, $a0 ; STRING_SHOT - db SFX_BATTLE_29, $f0, $80 ; DRAGON_RAGE - db SFX_BATTLE_29, $20, $c0 ; FIRE_SPIN - db SFX_BATTLE_2F, $00, $20 ; THUNDERSHOCK - db SFX_BATTLE_2F, $20, $80 ; THUNDERBOLT - db SFX_BATTLE_2E, $12, $60 ; THUNDER_WAVE - db SFX_BATTLE_26, $00, $80 ; THUNDER - db SFX_BATTLE_14, $01, $e0 ; ROCK_THROW - db SFX_BATTLE_29, $0f, $e0 ; EARTHQUAKE - db SFX_BATTLE_29, $11, $20 ; FISSURE - db SFX_DAMAGE, $10, $40 ; DIG - db SFX_BATTLE_0F, $10, $c0 ; TOXIC - db SFX_BATTLE_14, $00, $20 ; CONFUSION - db SFX_PSYCHIC_M, $00, $80 ; PSYCHIC_M - db SFX_BATTLE_35, $11, $18 ; HYPNOSIS - db SFX_BATTLE_09, $20, $c0 ; MEDITATE - db SFX_FAINT_FALL, $20, $c0 ; AGILITY - db SFX_BATTLE_25, $00, $10 ; QUICK_ATTACK - db SFX_BATTLE_26, $f0, $20 ; RAGE - db SFX_BATTLE_33, $f0, $c0 ; TELEPORT - db SFX_NOT_VERY_EFFECTIVE, $f0, $e0 ; NIGHT_SHADE - db SFX_BATTLE_09, $f0, $40 ; MIMIC - db SFX_BATTLE_31, $00, $80 ; SCREECH - db SFX_BATTLE_33, $80, $40 ; DOUBLE_TEAM - db SFX_BATTLE_33, $00, $80 ; RECOVER - db SFX_BATTLE_14, $11, $20 ; HARDEN - db SFX_BATTLE_14, $22, $10 ; MINIMIZE - db SFX_BATTLE_1B, $f1, $ff ; SMOKESCREEN - db SFX_BATTLE_13, $f1, $ff ; CONFUSE_RAY - db SFX_BATTLE_14, $33, $30 ; WITHDRAW - db SFX_BATTLE_32, $40, $c0 ; DEFENSE_CURL - db SFX_BATTLE_0E, $20, $20 ; BARRIER - db SFX_BATTLE_0E, $f0, $10 ; LIGHT_SCREEN - db SFX_BATTLE_0F, $f8, $10 ; HAZE - db SFX_NOT_VERY_EFFECTIVE, $f0, $10 ; REFLECT - db SFX_BATTLE_25, $00, $80 ; FOCUS_ENERGY - db SFX_BATTLE_18, $00, $c0 ; BIDE - db SFX_BATTLE_32, $c0, $ff ; METRONOME - db SFX_BATTLE_09, $f2, $20 ; MIRROR_MOVE - db SFX_BATTLE_34, $00, $80 ; SELFDESTRUCT - db SFX_BATTLE_34, $00, $40 ; EGG_BOMB - db SFX_BATTLE_09, $00, $40 ; LICK - db SFX_NOT_VERY_EFFECTIVE, $10, $ff ; SMOG - db SFX_BATTLE_2A, $20, $20 ; SLUDGE - db SFX_BATTLE_32, $00, $80 ; BONE_CLUB - db SFX_BATTLE_29, $1f, $20 ; FIRE_BLAST - db SFX_BATTLE_25, $2f, $80 ; WATERFALL - db SFX_BATTLE_0F, $1f, $ff ; CLAMP - db SFX_BATTLE_2B, $1f, $60 ; SWIFT - db SFX_BATTLE_26, $1e, $20 ; SKULL_BASH - db SFX_BATTLE_26, $1f, $18 ; SPIKE_CANNON - db SFX_BATTLE_14, $0f, $80 ; CONSTRICT - db SFX_BATTLE_09, $f8, $10 ; AMNESIA - db SFX_FAINT_FALL, $18, $20 ; KINESIS - db SFX_BATTLE_32, $08, $40 ; SOFTBOILED - db SFX_BATTLE_17, $01, $e0 ; HI_JUMP_KICK - db SFX_NOT_VERY_EFFECTIVE, $09, $ff ; GLARE - db SFX_BATTLE_35, $42, $01 ; DREAM_EATER - db SFX_BATTLE_1C, $00, $ff ; POISON_GAS - db SFX_BATTLE_32, $08, $e0 ; BARRAGE - db SFX_BATTLE_24, $00, $80 ; LEECH_LIFE - db SFX_BATTLE_09, $88, $10 ; LOVELY_KISS - db SFX_BATTLE_25, $48, $ff ; SKY_ATTACK - db SFX_FAINT_FALL, $ff, $ff ; TRANSFORM - db SFX_BATTLE_24, $ff, $10 ; BUBBLE - db SFX_FAINT_FALL, $ff, $04 ; DIZZY_PUNCH - db SFX_BATTLE_1C, $01, $ff ; SPORE - db SFX_BATTLE_13, $f8, $ff ; FLASH - db SFX_BATTLE_0C, $f0, $f0 ; PSYWAVE - db SFX_BATTLE_0F, $08, $10 ; SPLASH - db SFX_BATTLE_0D, $f0, $ff ; ACID_ARMOR - db SFX_SUPER_EFFECTIVE, $f0, $ff ; CRABHAMMER - db SFX_BATTLE_34, $10, $ff ; EXPLOSION - db SFX_BATTLE_0E, $f0, $20 ; FURY_SWIPES - db SFX_BATTLE_2B, $f0, $60 ; BONEMERANG - db SFX_BATTLE_21, $12, $10 ; REST - db SFX_BATTLE_36, $f0, $20 ; ROCK_SLIDE - db SFX_BATTLE_1E, $12, $ff ; HYPER_FANG - db SFX_BATTLE_31, $80, $04 ; SHARPEN - db SFX_BATTLE_33, $f0, $10 ; CONVERSION - db SFX_BATTLE_29, $f8, $ff ; TRI_ATTACK - db SFX_BATTLE_26, $f0, $ff ; SUPER_FANG - db SFX_NOT_VERY_EFFECTIVE, $01, $ff ; SLASH - db SFX_BATTLE_2C, $d8, $04 ; SUBSTITUTE - db SFX_BATTLE_0B, $00, $80 ; STRUGGLE - db SFX_BATTLE_0B, $00, $80 +INCLUDE "data/moves/sfx.asm" CopyPicTiles: - ld a, [H_WHOSETURN] + ldh a, [hWhoseTurn] and a ld a, $31 ; base tile ID of player mon sprite jr z, .next ; enemy turn xor a ; base tile ID of enemy mon sprite .next - ld [hBaseTileID], a + ldh [hBaseTileID], a jr CopyTileIDs_NoBGTransfer ; copy the tiles used when a mon is being sent out of or into a pokeball @@ -2728,7 +2407,7 @@ CopyDownscaledMonTiles: CopyTileIDs_NoBGTransfer: xor a - ld [H_AUTOBGTRANSFERENABLED], a + ldh [hAutoBGTransferEnabled], a ; fall through ; b = number of rows @@ -2738,7 +2417,7 @@ CopyTileIDs: .rowLoop push bc push hl - ld a, [hBaseTileID] + ldh a, [hBaseTileID] ld b, a .columnLoop ld a, [de] @@ -2754,108 +2433,17 @@ CopyTileIDs: dec b jr nz, .rowLoop ld a, $1 - ld [H_AUTOBGTRANSFERENABLED], a + ldh [hAutoBGTransferEnabled], a pop hl ret -TileIDListPointerTable: - dw DownscaledMonTiles_7x7 - dn 7, 7 - dw DownscaledMonTiles_5x7 - dn 5, 7 - dw DownscaledMonTiles_3x7 - dn 3, 7 - dw GengarIntroTiles1 - dn 7, 7 - dw GengarIntroTiles2 - dn 7, 7 - dw GengarIntroTiles3 - dn 7, 7 - dw DownscaledMonTiles_79d7c - dn 8, 6 - dw DownscaledMonTiles_79dac - dn 3, 12 - -DownscaledMonTiles_5x5: - db $31, $38, $46, $54, $5B - db $32, $39, $47, $55, $5C - db $34, $3B, $49, $57, $5E - db $36, $3D, $4B, $59, $60 - db $37, $3E, $4C, $5A, $61 - -DownscaledMonTiles_3x3: - db $31, $46, $5B - db $34, $49, $5E - db $37, $4C, $61 - -DownscaledMonTiles_7x7: - db $00, $07, $0E, $15, $1C, $23, $2A - db $01, $08, $0F, $16, $1D, $24, $2B - db $02, $09, $10, $17, $1E, $25, $2C - db $03, $0A, $11, $18, $1F, $26, $2D - db $04, $0B, $12, $19, $20, $27, $2E - db $05, $0C, $13, $1A, $21, $28, $2F - db $06, $0D, $14, $1B, $22, $29, $30 - -DownscaledMonTiles_5x7: - db $00, $07, $0E, $15, $1C, $23, $2A - db $01, $08, $0F, $16, $1D, $24, $2B - db $03, $0A, $11, $18, $1F, $26, $2D - db $04, $0B, $12, $19, $20, $27, $2E - db $05, $0C, $13, $1A, $21, $28, $2F - -DownscaledMonTiles_3x7: - db $00, $07, $0E, $15, $1C, $23, $2A - db $02, $09, $10, $17, $1E, $25, $2C - db $04, $0B, $12, $19, $20, $27, $2E - -GengarIntroTiles1: - db $00, $00, $00, $00, $00, $00, $00 - db $00, $00, $00, $00, $00, $19, $00 - db $02, $06, $0B, $10, $14, $1A, $00 - db $00, $07, $0C, $11, $15, $1B, $00 - db $03, $08, $0D, $12, $16, $1C, $00 - db $04, $09, $0E, $13, $17, $1D, $1F - db $05, $0A, $0F, $01, $18, $1E, $20 - -GengarIntroTiles2: - db $00, $00, $00, $30, $00, $37, $00 - db $00, $00, $2B, $31, $34, $38, $3D - db $21, $26, $2C, $01, $35, $39, $3E - db $22, $27, $2D, $32, $36, $01, $00 - db $23, $28, $2E, $33, $01, $3A, $00 - db $24, $29, $2F, $01, $01, $3B, $00 - db $25, $2A, $01, $01, $01, $3C, $00 - -GengarIntroTiles3: - db $00, $00, $00, $00, $00, $00, $00 - db $00, $00, $47, $4D, $00, $00, $00 - db $00, $00, $48, $4E, $52, $56, $5B - db $3F, $43, $49, $4F, $53, $57, $5C - db $40, $44, $4A, $50, $54, $58, $00 - db $41, $45, $4B, $51, $4C, $59, $5D - db $42, $46, $4C, $4C, $55, $5A, $5E - -DownscaledMonTiles_79d7c: - db $31, $32, $32, $32, $32, $33 - db $34, $35, $36, $36, $37, $38 - db $34, $39, $3A, $3A, $3B, $38 - db $3C, $3D, $3E, $3E, $3F, $40 - db $41, $42, $43, $43, $44, $45 - db $46, $47, $43, $48, $49, $4A - db $41, $43, $4B, $4C, $4D, $4E - db $4F, $50, $50, $50, $51, $52 - -DownscaledMonTiles_79dac: - db $43, $55, $56, $53, $53, $53, $53, $53, $53, $53, $53, $53 - db $43, $57, $58, $54, $54, $54, $54, $54, $54, $54, $54, $54 - db $43, $59, $5A, $43, $43, $43, $43, $43, $43, $43, $43, $43 +INCLUDE "data/tilemaps.asm" AnimationLeavesFalling: ; Makes leaves float down from the top of the screen. This is used ; in Razor Leaf's animation. ld a, [wAnimPalette] - ld [rOBP0], a + ldh [rOBP0], a call UpdateGBCPal_OBP0 ld d, $37 ; leaf tile ld a, 3 ; number of leaves @@ -3043,7 +2631,7 @@ AnimationShakeEnemyHUD: call CopyVideoData xor a - ld [hSCX], a + ldh [hSCX], a ; Copy wTileMap to BG map 0. The regular BG (not the window) is set to use ; map 0 and can be scrolled with SCX, which allows a shaking effect. @@ -3052,8 +2640,8 @@ AnimationShakeEnemyHUD: ; Now that the regular BG is showing the same thing the window was, move the ; window off the screen so that we can modify its contents below. - ld a, SCREEN_HEIGHT_PIXELS - ld [hWY], a + ld a, SCREEN_HEIGHT_PX + ldh [hWY], a ; Copy wTileMap to VRAM such that the row below the enemy HUD (in wTileMap) is ; lined up with row 0 of the window. @@ -3061,11 +2649,11 @@ AnimationShakeEnemyHUD: call BattleAnimCopyTileMapToVRAM ; update BGMap attributes - ld a, [hGBC] + ldh a, [hGBC] and a jr z, .notGBC ld c, 13 - callba LoadBGMapAttributes + farcall LoadBGMapAttributes .notGBC ; Move the window so that the row below the enemy HUD (in BG map 0) lines up @@ -3073,7 +2661,7 @@ AnimationShakeEnemyHUD: ; covers everything below the enemy HD with a copy that looks just like what ; was there before. ld a, 7 * 8 - ld [hWY], a + ldh [hWY], a ; Write OAM entries so that the copy of the back pic from the top of this ; function shows up on screen. We need this because the back pic's Y coordinates @@ -3097,19 +2685,19 @@ AnimationShakeEnemyHUD: ; Restore the original graphics. call AnimationShowMonPic call ClearSprites - ld a, SCREEN_HEIGHT_PIXELS - ld [hWY], a + ld a, SCREEN_HEIGHT_PX + ldh [hWY], a ld hl, vBGMap1 call BattleAnimCopyTileMapToVRAM ; update BGMap attributes - ld a, [hGBC] + ldh a, [hGBC] and a jr z, .notGBC2 ld c, 11 - callba LoadBGMapAttributes + farcall LoadBGMapAttributes .notGBC2 xor a - ld [hWY], a + ldh [hWY], a call SaveScreenTilesToBuffer1 ld hl, vBGMap0 call BattleAnimCopyTileMapToVRAM @@ -3122,7 +2710,7 @@ AnimationShakeEnemyHUD: CopyTileIDsFromList: call GetPredefRegisters ld a, c - ld [hBaseTileID], a + ldh [hBaseTileID], a ld a, b push hl call GetTileIDList @@ -3130,30 +2718,30 @@ CopyTileIDsFromList: jp CopyTileIDs ShakeEnemyHUD_ShakeBG: - ld a, [hSCX] + ldh a, [hSCX] ld [wTempSCX], a .loop ld a, [wTempSCX] add d - ld [hSCX], a + ldh [hSCX], a ld c, 2 call DelayFrames ld a, [wTempSCX] sub d - ld [hSCX], a + ldh [hSCX], a ld c, 2 call DelayFrames dec e jr nz, .loop ld a, [wTempSCX] - ld [hSCX], a + ldh [hSCX], a ret BattleAnimCopyTileMapToVRAM: ld a, h - ld [H_AUTOBGTRANSFERDEST + 1], a + ldh [hAutoBGTransferDest + 1], a ld a, l - ld [H_AUTOBGTRANSFERDEST], a + ldh [hAutoBGTransferDest], a jp Delay3 TossBallAnimation: diff --git a/engine/battle/bank3d_battle.asm b/engine/battle/bank3d_battle.asm index 5edc4571..48c3cde3 100644 --- a/engine/battle/bank3d_battle.asm +++ b/engine/battle/bank3d_battle.asm @@ -1,27 +1,28 @@ -InitBattle: +InitBattle:: ld a, [wCurOpponent] and a - jr z, asm_f6003 + jr z, DetermineWildOpponent InitOpponent: ld a, [wCurOpponent] ld [wcf91], a ld [wEnemyMonSpecies2], a - jr asm_f601d -asm_f6003: + jr InitBattleCommon + +DetermineWildOpponent: ld a, [wd732] bit 1, a - jr z, .asm_f600f - ld a, [hJoyHeld] + jr z, .asm_3ef2f + ldh a, [hJoyHeld] bit 1, a ; B button pressed? ret nz -.asm_f600f +.asm_3ef2f ld a, [wNumberOfNoRandomBattleStepsLeft] and a ret nz - callab TryDoWildEncounter + callfar TryDoWildEncounter ret nz -asm_f601d: +InitBattleCommon: ld a, [wMapPalOffset] push af ld hl, wLetterPrintingDelayFlags @@ -34,37 +35,37 @@ asm_f601d: jp c, InitWildBattle ld [wTrainerClass], a call GetTrainerInformation - callab ReadTrainer - callab DoBattleTransitionAndInitBattleVariables + callfar ReadTrainer + callfar DoBattleTransitionAndInitBattleVariables call _LoadTrainerPic xor a ld [wEnemyMonSpecies2], a - ld [$ffe1], a + ldh [hStartTileID], a dec a ld [wAICount], a - coord hl, 12, 0 + hlcoord 12, 0 predef CopyUncompressedPicToTilemap ld a, $ff ld [wEnemyMonPartyPos], a ld a, $2 ld [wIsInBattle], a - ; Is this a major story battle? - ld a,[wLoneAttackNo] +; Is this a major story battle? + ld a, [wLoneAttackNo] and a - jp z,InitBattle_Common + jp z, _InitBattleCommon callabd_ModifyPikachuHappiness PIKAHAPPY_GYMLEADER ; useless since already in bank3d - jp InitBattle_Common + jp _InitBattleCommon InitWildBattle: ld a, $1 ld [wIsInBattle], a - callab LoadEnemyMonData - callab DoBattleTransitionAndInitBattleVariables + callfar LoadEnemyMonData + callfar DoBattleTransitionAndInitBattleVariables ld a, [wCurOpponent] cp RESTLESS_SOUL jr z, .isGhost - callab IsGhostBattle + callfar IsGhostBattle jr nz, .isNoGhost .isGhost ld hl, wMonHSpriteDim @@ -101,49 +102,49 @@ InitWildBattle: .spriteLoaded xor a ld [wTrainerClass], a - ld [$ffe1], a - coord hl, 12, 0 + ldh [hStartTileID], a + hlcoord 12, 0 predef CopyUncompressedPicToTilemap ; common code that executes after init battle code specific to trainer or wild battles -InitBattle_Common: - ld b, $0 +_InitBattleCommon: + ld b, SET_PAL_BATTLE_BLACK call RunPaletteCommand - callab SlidePlayerAndEnemySilhouettesOnScreen + callfar SlidePlayerAndEnemySilhouettesOnScreen xor a - ld [H_AUTOBGTRANSFERENABLED], a + ldh [hAutoBGTransferEnabled], a ld hl, .emptyString call PrintText call SaveScreenTilesToBuffer1 call ClearScreen ld a, $98 - ld [$ffbd], a + ldh [hAutoBGTransferDest + 1], a ld a, $1 - ld [H_AUTOBGTRANSFERENABLED], a + ldh [hAutoBGTransferEnabled], a call Delay3 ld a, $9c - ld [$ffbd], a + ldh [hAutoBGTransferDest + 1], a call LoadScreenTilesFromBuffer1 - coord hl, 9, 7 - ld bc, $50a + hlcoord 9, 7 + lb bc, 5, 10 call ClearScreenArea - coord hl, 1, 0 - ld bc, $40a + hlcoord 1, 0 + lb bc, 4, 10 call ClearScreenArea call ClearSprites ld a, [wIsInBattle] dec a ; is it a wild battle? ld hl, DrawEnemyHUDAndHPBar - ld b,BANK(DrawEnemyHUDAndHPBar) + ld b, BANK(DrawEnemyHUDAndHPBar) call z, Bankswitch ; draw enemy HUD and HP bar if it's a wild battle - callab StartBattle - callab EndOfBattle + callfar StartBattle + callfar EndOfBattle pop af ld [wLetterPrintingDelayFlags], a pop af ld [wMapPalOffset], a ld a, [wSavedTilesetType] - ld [hTilesetType], a + ldh [hTilesetType], a scf ret .emptyString @@ -157,9 +158,9 @@ _LoadTrainerPic: ld d, a ; de contains pointer to trainer pic ld a, [wLinkState] and a - ld a, Bank(TrainerPics) ; this is where all the trainer pics are (not counting Red's) + ld a, BANK(TrainerPics) ; this is where all the trainer pics are (not counting Red's) jr z, .loadSprite - ld a, Bank(RedPicFront) + ld a, BANK(RedPicFront) .loadSprite call UncompressSpriteFromDE ld de, vFrontPic @@ -172,8 +173,8 @@ LoadMonBackPic: ; been loaded with GetMonHeader. ld a, [wBattleMonSpecies2] ld [wcf91], a - coord hl, 1, 5 - ld bc,$708 + hlcoord 1, 5 + lb bc, 7, 8 call ClearScreenArea ld hl, wMonHBackSprite - wMonHeader call UncompressMonSprite @@ -183,7 +184,7 @@ LoadMonBackPic: ld hl, vSprites ld de, vBackPic ld c, (2*SPRITEBUFFERSIZE)/16 ; count of 16-byte chunks to be copied - ld a, [H_LOADEDROMBANK] + ldh a, [hLoadedROMBank] ld b, a jp CopyVideoData @@ -192,8 +193,8 @@ AnimateSendingOutMon: ld h, a ld a, [wPredefRegisters + 1] ld l, a - ld a, [$ffe1] - ld [H_DOWNARROWBLINKCNT1], a + ldh a, [hStartTileID] + ldh [hDownArrowBlinkCount1], a ld b, $4c ld a, [wIsInBattle] and a @@ -223,7 +224,7 @@ AnimateSendingOutMon: ld bc, -123 .asm_f61f2 add hl, bc - ld a, [H_DOWNARROWBLINKCNT1] + ldh a, [hDownArrowBlinkCount1] add $31 jr CopyUncompressedPicToHL @@ -232,8 +233,8 @@ CopyUncompressedPicToTilemap: ld h, a ld a, [wPredefRegisters + 1] ld l, a - ld a, [$ffe1] -CopyUncompressedPicToHL: + ldh a, [hStartTileID] +CopyUncompressedPicToHL:: ld bc, $707 ld de, $14 push af @@ -281,11 +282,11 @@ CopyUncompressedPicToHL: ret INCLUDE "engine/battle/init_battle_variables.asm" -INCLUDE "engine/battle/moveEffects/focus_energy_effect.asm" -INCLUDE "engine/battle/moveEffects/heal_effect.asm" -INCLUDE "engine/battle/moveEffects/transform_effect.asm" -INCLUDE "engine/battle/moveEffects/reflect_light_screen_effect.asm" -INCLUDE "engine/battle/moveEffects/mist_effect.asm" -INCLUDE "engine/battle/moveEffects/one_hit_ko_effect.asm" -INCLUDE "engine/battle/moveEffects/pay_day_effect.asm" -INCLUDE "engine/battle/moveEffects/paralyze_effect.asm" +INCLUDE "engine/battle/move_effects/focus_energy.asm" +INCLUDE "engine/battle/move_effects/heal.asm" +INCLUDE "engine/battle/move_effects/transform.asm" +INCLUDE "engine/battle/move_effects/reflect_light_screen.asm" +INCLUDE "engine/battle/move_effects/mist.asm" +INCLUDE "engine/battle/move_effects/one_hit_ko.asm" +INCLUDE "engine/battle/move_effects/pay_day.asm" +INCLUDE "engine/battle/move_effects/paralyze.asm" diff --git a/engine/battle/bank_e_misc.asm b/engine/battle/bank_e_misc.asm deleted file mode 100755 index df9145f2..00000000 --- a/engine/battle/bank_e_misc.asm +++ /dev/null @@ -1,103 +0,0 @@ -; formats a string at wMovesString that lists the moves at wMoves -FormatMovesString: - ld hl, wMoves - ld de, wMovesString - ld b, $0 -.printMoveNameLoop - ld a, [hli] - and a ; end of move list? - jr z, .printDashLoop ; print dashes when no moves are left - push hl - ld [wd0b5], a - ld a, BANK(MoveNames) - ld [wPredefBank], a - ld a, MOVE_NAME - ld [wNameListType], a - call GetName - ld hl, wcd6d -.copyNameLoop - ld a, [hli] - cp $50 - jr z, .doneCopyingName - ld [de], a - inc de - jr .copyNameLoop -.doneCopyingName - ld a, b - ld [wNumMovesMinusOne], a - inc b - ld a, $4e ; line break - ld [de], a - inc de - pop hl - ld a, b - cp NUM_MOVES - jr z, .done - jr .printMoveNameLoop -.printDashLoop - ld a, "-" - ld [de], a - inc de - inc b - ld a, b - cp NUM_MOVES - jr z, .done - ld a, $4e ; line break - ld [de], a - inc de - jr .printDashLoop -.done - ld a, "@" - ld [de], a - ret - -; XXX this is called in a few places, but it doesn't appear to do anything useful -InitList: - ld a, [wInitListType] - cp INIT_ENEMYOT_LIST - jr nz, .notEnemy - ld hl, wEnemyPartyCount - ld de, wEnemyMonOT - ld a, ENEMYOT_NAME - jr .done -.notEnemy - cp INIT_PLAYEROT_LIST - jr nz, .notPlayer - ld hl, wPartyCount - ld de, wPartyMonOT - ld a, PLAYEROT_NAME - jr .done -.notPlayer - cp INIT_MON_LIST - jr nz, .notMonster - ld hl, wItemList - ld de, MonsterNames - ld a, MONSTER_NAME - jr .done -.notMonster - cp INIT_BAG_ITEM_LIST - jr nz, .notBag - ld hl, wNumBagItems - ld de, ItemNames - ld a, ITEM_NAME - jr .done -.notBag - ld hl, wItemList - ld de, ItemNames - ld a, ITEM_NAME -.done - ld [wNameListType], a - ld a, l - ld [wListPointer], a - ld a, h - ld [wListPointer + 1], a - ld a, e - ld [wUnusedCF8D], a - ld a, d - ld [wUnusedCF8D + 1], a - ld bc, ItemPrices - ld a, c - ld [wItemPrices], a - ld a, b - ld [wItemPrices + 1], a - ret diff --git a/engine/battle/battle_transitions.asm b/engine/battle/battle_transitions.asm index e4392a01..82c3318c 100644 --- a/engine/battle/battle_transitions.asm +++ b/engine/battle/battle_transitions.asm @@ -1,17 +1,17 @@ BattleTransition: ld a, 1 - ld [H_AUTOBGTRANSFERENABLED], a + ldh [hAutoBGTransferEnabled], a call Delay3 xor a - ld [hWY], a + ldh [hWY], a dec a ld [wUpdateSpritesEnabled], a call DelayFrame ; Determine which OAM block is being used by the enemy trainer sprite (if there ; is one). - ld hl, wSpriteStateData1 + 2 - ld a, [hSpriteIndexOrTextID] ; enemy trainer sprite index (0 if wild battle) + ld hl, wSpritePlayerStateData1ImageIndex + ldh a, [hSpriteIndexOrTextID] ; enemy trainer sprite index (0 if wild battle) ld c, a ld b, 0 ld de, $10 @@ -118,9 +118,6 @@ GetBattleTransitionID_CompareLevels: ld [wBattleTransitionSpiralDirection], a ret -; fails to recognize VICTORY_ROAD_2F, VICTORY_ROAD_3F, all ROCKET_HIDEOUT maps, -; POKEMON_MANSION_1F, SEAFOAM_ISLANDS_[B1F-B4F], POWER_PLANT, DIGLETTS_CAVE -; and SILPH_CO_[9-11]F as dungeon maps GetBattleTransitionID_IsDungeonMap: ld a, [wCurMap] ld e, a @@ -151,51 +148,21 @@ GetBattleTransitionID_IsDungeonMap: res 2, c ret -; GetBattleTransitionID_IsDungeonMap checks if wCurMap -; is equal to one of these maps -DungeonMaps1: - db VIRIDIAN_FOREST - db ROCK_TUNNEL_1F - db SEAFOAM_ISLANDS_1F - db ROCK_TUNNEL_B1F - db $FF - -; GetBattleTransitionID_IsDungeonMap checks if wCurMap -; is in between or equal to each pair of maps -DungeonMaps2: - ; all MT_MOON maps - db MT_MOON_1F - db MT_MOON_B2F - - ; all SS_ANNE maps, VICTORY_ROAD_1F, LANCES_ROOM, and HALL_OF_FAME - db SS_ANNE_1F - db HALL_OF_FAME - - ; all POKEMON_TOWER maps and Lavender Town buildings - db LAVENDER_POKECENTER - db LAVENDER_CUBONE_HOUSE - - ; SILPH_CO_[2-8]F, POKEMON_MANSION[2F-B1F], SAFARI_ZONE, and - ; CERULEAN_CAVE maps, except for SILPH_CO_1F - db SILPH_CO_2F - db CERULEAN_CAVE_1F - db $FF +INCLUDE "data/maps/dungeon_maps.asm" LoadBattleTransitionTile: - ld hl, vChars1 + $7f0 + ld hl, vChars1 tile $7f ld de, BattleTransitionTile - lb bc, BANK(BattleTransitionTile), (BattleTransitionTileEnd - BattleTransitionTile) / $10 + lb bc, BANK(BattleTransitionTile), 1 jp CopyVideoData -BattleTransitionTile: - INCBIN "gfx/battle_transition.2bpp" -BattleTransitionTileEnd: +BattleTransitionTile: INCBIN "gfx/overworld/battle_transition.2bpp" BattleTransition_BlackScreen: ld a, $ff - ld [rBGP], a - ld [rOBP0], a - ld [rOBP1], a + ldh [rBGP], a + ldh [rOBP0], a + ldh [rOBP1], a call UpdateGBCPal_BGP call UpdateGBCPal_OBP0 call UpdateGBCPal_OBP1 @@ -212,7 +179,7 @@ BattleTransition_Spiral: call BattleTransition_InwardSpiral jr .done .outwardSpiral - coord hl, 10, 10 + hlcoord 10, 10 ld a, $3 ld [wOutwardSpiralCurrentDirection], a ld a, l @@ -241,7 +208,7 @@ BattleTransition_Spiral: BattleTransition_InwardSpiral: ld a, 7 ld [wInwardSpiralUpdateScreenCounter], a - coord hl, 0, 0 + hlcoord 0, 0 ld c, SCREEN_HEIGHT - 1 ld de, SCREEN_WIDTH call BattleTransition_InwardSpiral_ @@ -359,9 +326,9 @@ BattleTransition_FlashScreen_: ld hl, BattleTransition_FlashScreenPalettes .loop ld a, [hli] - cp $1 + cp 1 jr z, .done - ld [rBGP], a + ldh [rBGP], a call UpdateGBCPal_BGP ld c, 2 call DelayFrames @@ -372,8 +339,19 @@ BattleTransition_FlashScreen_: ret BattleTransition_FlashScreenPalettes: - db $F9,$FE,$FF,$FE,$F9,$E4,$90,$40,$00,$40,$90,$E4 - db $01 ; terminator + db %11111001 + db %11111110 + db %11111111 + db %11111110 + db %11111001 + db %11100100 + db %10010000 + db %01000000 + db %00000000 + db %01000000 + db %10010000 + db %11100100 + db 1 ; end ; used for low level trainer dungeon battles BattleTransition_Shrink: @@ -381,25 +359,25 @@ BattleTransition_Shrink: .loop push bc xor a - ld [H_AUTOBGTRANSFERENABLED], a - coord hl, 0, 7 - coord de, 0, 8 + ldh [hAutoBGTransferEnabled], a + hlcoord 0, 7 + decoord 0, 8 ld bc, -SCREEN_WIDTH * 2 call BattleTransition_CopyTiles1 - coord hl, 0, 10 - coord de, 0, 9 + hlcoord 0, 10 + decoord 0, 9 ld bc, SCREEN_WIDTH * 2 call BattleTransition_CopyTiles1 - coord hl, 8, 0 - coord de, 9, 0 + hlcoord 8, 0 + decoord 9, 0 ld bc, -2 call BattleTransition_CopyTiles2 - coord hl, 11, 0 - coord de, 10, 0 + hlcoord 11, 0 + decoord 10, 0 ld bc, 2 call BattleTransition_CopyTiles2 ld a, $1 - ld [H_AUTOBGTRANSFERENABLED], a + ldh [hAutoBGTransferEnabled], a ld c, 6 call DelayFrames pop bc @@ -413,23 +391,23 @@ BattleTransition_Shrink: BattleTransition_Split: ld c, 9 xor a - ld [H_AUTOBGTRANSFERENABLED], a + ldh [hAutoBGTransferEnabled], a .loop push bc - coord hl, 0, 16 - coord de, 0, 17 + hlcoord 0, 16 + decoord 0, 17 ld bc, -SCREEN_WIDTH * 2 call BattleTransition_CopyTiles1 - coord hl, 0, 1 - coord de, 0, 0 + hlcoord 0, 1 + decoord 0, 0 ld bc, SCREEN_WIDTH * 2 call BattleTransition_CopyTiles1 - coord hl, 18, 0 - coord de, 19, 0 + hlcoord 18, 0 + decoord 19, 0 ld bc, -2 call BattleTransition_CopyTiles2 - coord hl, 1, 0 - coord de, 0, 0 + hlcoord 1, 0 + decoord 0, 0 ld bc, 2 call BattleTransition_CopyTiles2 call BattleTransition_TransferDelay3 @@ -525,10 +503,10 @@ BattleTransition_CopyTiles2: ; used for high level wild dungeon battles BattleTransition_VerticalStripes: ld c, SCREEN_HEIGHT - coord hl, 0, 0 - coord de, 1, 17 + hlcoord 0, 0 + decoord 1, 17 xor a - ld [H_AUTOBGTRANSFERENABLED], a + ldh [hAutoBGTransferEnabled], a .loop push bc push hl @@ -564,10 +542,10 @@ BattleTransition_VerticalStripes_: ; used for low level wild dungeon battles BattleTransition_HorizontalStripes: ld c, SCREEN_WIDTH - coord hl, 0, 0 - coord de, 19, 1 + hlcoord 0, 0 + decoord 19, 1 xor a - ld [H_AUTOBGTRANSFERENABLED], a + ldh [hAutoBGTransferEnabled], a .loop push bc push hl @@ -614,7 +592,7 @@ BattleTransition_FlashScreen: ld b, $3 call BattleTransition_FlashScreen_ xor a - ld [H_AUTOBGTRANSFERENABLED], a + ldh [hAutoBGTransferEnabled], a ret BattleTransition_Circle_Sub1: @@ -633,10 +611,10 @@ BattleTransition_Circle_Sub1: BattleTransition_TransferDelay3: ld a, 1 - ld [H_AUTOBGTRANSFERENABLED], a + ldh [hAutoBGTransferEnabled], a call Delay3 xor a - ld [H_AUTOBGTRANSFERENABLED], a + ldh [hAutoBGTransferEnabled], a ret ; used for low level wild non-dungeon battles @@ -683,87 +661,41 @@ BattleTransition_Circle_Sub2: ld l, a jp BattleTransition_Circle_Sub3 -BattleTransition_HalfCircle1: - db $01 - dw BattleTransition_CircleData1 - dwCoord 18, 6 - - db $01 - dw BattleTransition_CircleData2 - dwCoord 19, 3 - - db $01 - dw BattleTransition_CircleData3 - dwCoord 18, 0 - - db $01 - dw BattleTransition_CircleData4 - dwCoord 14, 0 - - db $01 - dw BattleTransition_CircleData5 - dwCoord 10, 0 +; halves + const_def + const CIRCLE_LEFT + const CIRCLE_RIGHT - db $00 - dw BattleTransition_CircleData5 - dwCoord 9, 0 +half_circle: MACRO + ; quadrant x, circle data, target coord + db \1 + dw \2 + dwcoord \3, \4 +ENDM - db $00 - dw BattleTransition_CircleData4 - dwCoord 5, 0 - - db $00 - dw BattleTransition_CircleData3 - dwCoord 1, 0 - - db $00 - dw BattleTransition_CircleData2 - dwCoord 0, 3 - - db $00 - dw BattleTransition_CircleData1 - dwCoord 1, 6 +BattleTransition_HalfCircle1: + half_circle CIRCLE_RIGHT, BattleTransition_CircleData1, 18, 6 + half_circle CIRCLE_RIGHT, BattleTransition_CircleData2, 19, 3 + half_circle CIRCLE_RIGHT, BattleTransition_CircleData3, 18, 0 + half_circle CIRCLE_RIGHT, BattleTransition_CircleData4, 14, 0 + half_circle CIRCLE_RIGHT, BattleTransition_CircleData5, 10, 0 + half_circle CIRCLE_LEFT, BattleTransition_CircleData5, 9, 0 + half_circle CIRCLE_LEFT, BattleTransition_CircleData4, 5, 0 + half_circle CIRCLE_LEFT, BattleTransition_CircleData3, 1, 0 + half_circle CIRCLE_LEFT, BattleTransition_CircleData2, 0, 3 + half_circle CIRCLE_LEFT, BattleTransition_CircleData1, 1, 6 BattleTransition_HalfCircle2: - db $00 - dw BattleTransition_CircleData1 - dwCoord 1, 11 - - db $00 - dw BattleTransition_CircleData2 - dwCoord 0, 14 - - db $00 - dw BattleTransition_CircleData3 - dwCoord 1, 17 - - db $00 - dw BattleTransition_CircleData4 - dwCoord 5, 17 - - db $00 - dw BattleTransition_CircleData5 - dwCoord 9, 17 - - db $01 - dw BattleTransition_CircleData5 - dwCoord 10, 17 - - db $01 - dw BattleTransition_CircleData4 - dwCoord 14, 17 - - db $01 - dw BattleTransition_CircleData3 - dwCoord 18, 17 - - db $01 - dw BattleTransition_CircleData2 - dwCoord 19, 14 - - db $01 - dw BattleTransition_CircleData1 - dwCoord 18, 11 + half_circle CIRCLE_LEFT, BattleTransition_CircleData1, 1, 11 + half_circle CIRCLE_LEFT, BattleTransition_CircleData2, 0, 14 + half_circle CIRCLE_LEFT, BattleTransition_CircleData3, 1, 17 + half_circle CIRCLE_LEFT, BattleTransition_CircleData4, 5, 17 + half_circle CIRCLE_LEFT, BattleTransition_CircleData5, 9, 17 + half_circle CIRCLE_RIGHT, BattleTransition_CircleData5, 10, 17 + half_circle CIRCLE_RIGHT, BattleTransition_CircleData4, 14, 17 + half_circle CIRCLE_RIGHT, BattleTransition_CircleData3, 18, 17 + half_circle CIRCLE_RIGHT, BattleTransition_CircleData2, 19, 14 + half_circle CIRCLE_RIGHT, BattleTransition_CircleData1, 18, 11 BattleTransition_Circle_Sub3: push hl @@ -792,7 +724,7 @@ BattleTransition_Circle_Sub3: add hl, bc ld a, [de] inc de - cp $ff + cp -1 ret z and a jr z, BattleTransition_Circle_Sub3 @@ -810,17 +742,8 @@ BattleTransition_Circle_Sub3: jr nz, .loop2 jr BattleTransition_Circle_Sub3 -BattleTransition_CircleData1: - db $02,$03,$05,$04,$09,$FF - -BattleTransition_CircleData2: - db $01,$01,$02,$02,$04,$02,$04,$02,$03,$FF - -BattleTransition_CircleData3: - db $02,$01,$03,$01,$04,$01,$04,$01,$04,$01,$03,$01,$02,$01,$01,$01,$01,$FF - -BattleTransition_CircleData4: - db $04,$01,$04,$00,$03,$01,$03,$00,$02,$01,$02,$00,$01,$FF - -BattleTransition_CircleData5: - db $04,$00,$03,$00,$03,$00,$02,$00,$02,$00,$01,$00,$01,$00,$01,$FF +BattleTransition_CircleData1: db 2, 3, 5, 4, 9, -1 +BattleTransition_CircleData2: db 1, 1, 2, 2, 4, 2, 4, 2, 3, -1 +BattleTransition_CircleData3: db 2, 1, 3, 1, 4, 1, 4, 1, 4, 1, 3, 1, 2, 1, 1, 1, 1, -1 +BattleTransition_CircleData4: db 4, 1, 4, 0, 3, 1, 3, 0, 2, 1, 2, 0, 1, -1 +BattleTransition_CircleData5: db 4, 0, 3, 0, 3, 0, 2, 0, 2, 0, 1, 0, 1, 0, 1, -1 diff --git a/engine/battle/common_text.asm b/engine/battle/common_text.asm index 1c85efe9..95c06bf5 100644 --- a/engine/battle/common_text.asm +++ b/engine/battle/common_text.asm @@ -5,18 +5,18 @@ PrintBeginningBattleText: ld a, [wCurMap] cp POKEMON_TOWER_3F jr c, .notPokemonTower - cp MR_FUJIS_HOUSE + cp POKEMON_TOWER_7F + 1 jr c, .pokemonTower .notPokemonTower - ld a,[wBattleType] + ld a, [wBattleType] cp BATTLE_TYPE_PIKACHU - jr nz,.notPikachuBattle - callab IsPlayerPikachuAsleepInParty - ld e,$24 - jr c,.asm_f4026 - ld e,$a + jr nz, .notPikachuBattle + callfar IsPlayerPikachuAsleepInParty + ld e, $24 + jr c, .asm_f4026 + ld e, $a .asm_f4026 - callab PlayPikachuSoundClip + callfar PlayPikachuSoundClip jr .continue .notPikachuBattle ld a, [wEnemyMonSpecies2] @@ -39,7 +39,7 @@ PrintBeginningBattleText: and a jr nz, .doNotDrawPokeballs push hl - callab DrawAllPokeballs + callfar DrawAllPokeballs pop hl .doNotDrawPokeballs call PrintText @@ -54,7 +54,7 @@ PrintBeginningBattleText: ld a, b and a jr z, .noSilphScope - callab LoadEnemyMonData + callfar LoadEnemyMonData jr .notPokemonTower .noSilphScope ld hl, EnemyAppearedText @@ -70,8 +70,8 @@ PrintBeginningBattleText: call PrintText ld hl, UnveiledGhostText call PrintText - callab LoadEnemyMonData - callab MarowakAnim + callfar LoadEnemyMonData + callfar MarowakAnim ld hl, WildMonAppearedText call PrintText @@ -87,28 +87,28 @@ PrintBeginningBattleText: ret WildMonAppearedText: - TX_FAR _WildMonAppearedText - db "@" + text_far _WildMonAppearedText + text_end HookedMonAttackedText: - TX_FAR _HookedMonAttackedText - db "@" + text_far _HookedMonAttackedText + text_end EnemyAppearedText: - TX_FAR _EnemyAppearedText - db "@" + text_far _EnemyAppearedText + text_end TrainerWantsToFightText: - TX_FAR _TrainerWantsToFightText - db "@" + text_far _TrainerWantsToFightText + text_end UnveiledGhostText: - TX_FAR _UnveiledGhostText - db "@" + text_far _UnveiledGhostText + text_end GhostCantBeIDdText: - TX_FAR _GhostCantBeIDdText - db "@" + text_far _GhostCantBeIDdText + text_end PrintSendOutMonMessage: ld hl, wEnemyMonHP @@ -117,16 +117,16 @@ PrintSendOutMonMessage: ld hl, GoText jr z, .printText xor a - ld [H_MULTIPLICAND], a + ldh [hMultiplicand], a ld hl, wEnemyMonHP ld a, [hli] ld [wLastSwitchInEnemyMonHP], a - ld [H_MULTIPLICAND + 1], a + ldh [hMultiplicand + 1], a ld a, [hl] ld [wLastSwitchInEnemyMonHP + 1], a - ld [H_MULTIPLICAND + 2], a + ldh [hMultiplicand + 2], a ld a, 25 - ld [H_MULTIPLIER], a + ldh [hMultiplier], a call Multiply ld hl, wEnemyMonMaxHP ld a, [hli] @@ -137,9 +137,9 @@ PrintSendOutMonMessage: rr b ld a, b ld b, 4 - ld [H_DIVISOR], a ; enemy mon max HP divided by 4 + ldh [hDivisor], a ; enemy mon max HP divided by 4 call Divide - ld a, [H_QUOTIENT + 3] ; a = (enemy mon current HP * 25) / (enemy max HP / 4); this approximates the current percentage of max HP + ldh a, [hQuotient + 3] ; a = (enemy mon current HP * 25) / (enemy max HP / 4); this approximates the current percentage of max HP ld hl, GoText ; 70% or greater cp 70 jr nc, .printText @@ -154,39 +154,39 @@ PrintSendOutMonMessage: jp PrintText GoText: - TX_FAR _GoText - TX_ASM + text_far _GoText + text_asm jr PrintPlayerMon1Text DoItText: - TX_FAR _DoItText - TX_ASM + text_far _DoItText + text_asm jr PrintPlayerMon1Text GetmText: - TX_FAR _GetmText - TX_ASM + text_far _GetmText + text_asm jr PrintPlayerMon1Text EnemysWeakText: - TX_FAR _EnemysWeakText - TX_ASM + text_far _EnemysWeakText + text_asm PrintPlayerMon1Text: ld hl, PlayerMon1Text ret PlayerMon1Text: - TX_FAR _PlayerMon1Text - db "@" + text_far _PlayerMon1Text + text_end RetreatMon: ld hl, PlayerMon2Text jp PrintText PlayerMon2Text: - TX_FAR _PlayerMon2Text - TX_ASM + text_far _PlayerMon2Text + text_asm push de push bc ld hl, wEnemyMonHP + 1 @@ -195,14 +195,14 @@ PlayerMon2Text: dec hl ld a, [de] sub b - ld [H_MULTIPLICAND + 2], a + ldh [hMultiplicand + 2], a dec de ld b, [hl] ld a, [de] sbc b - ld [H_MULTIPLICAND + 1], a + ldh [hMultiplicand + 1], a ld a, 25 - ld [H_MULTIPLIER], a + ldh [hMultiplier], a call Multiply ld hl, wEnemyMonMaxHP ld a, [hli] @@ -213,11 +213,11 @@ PlayerMon2Text: rr b ld a, b ld b, 4 - ld [H_DIVISOR], a + ldh [hDivisor], a call Divide pop bc pop de - ld a, [H_QUOTIENT + 3] ; a = ((LastSwitchInEnemyMonHP - CurrentEnemyMonHP) / 25) / (EnemyMonMaxHP / 4) + ldh a, [hQuotient + 3] ; a = ((LastSwitchInEnemyMonHP - CurrentEnemyMonHP) / 25) / (EnemyMonMaxHP / 4) ; Assuming that the enemy mon hasn't gained HP since the last switch in, ; a approximates the percentage that the enemy mon's total HP has decreased ; since the last switch in. @@ -236,18 +236,18 @@ PlayerMon2Text: ret EnoughText: - TX_FAR _EnoughText - TX_ASM + text_far _EnoughText + text_asm jr PrintComeBackText OKExclamationText: - TX_FAR _OKExclamationText - TX_ASM + text_far _OKExclamationText + text_asm jr PrintComeBackText GoodText: - TX_FAR _GoodText - TX_ASM + text_far _GoodText + text_asm jr PrintComeBackText PrintComeBackText: @@ -255,5 +255,5 @@ PrintComeBackText: ret ComeBackText: - TX_FAR _ComeBackText - db "@" + text_far _ComeBackText + text_end diff --git a/engine/battle/core.asm b/engine/battle/core.asm index 60146902..f66f509f 100755 --- a/engine/battle/core.asm +++ b/engine/battle/core.asm @@ -1,107 +1,17 @@ BattleCore: -; These are move effects (second value from the Moves table in bank $E). -ResidualEffects1: -; most non-side effects - db CONVERSION_EFFECT - db HAZE_EFFECT - db SWITCH_AND_TELEPORT_EFFECT - db MIST_EFFECT - db FOCUS_ENERGY_EFFECT - db CONFUSION_EFFECT - db HEAL_EFFECT - db TRANSFORM_EFFECT - db LIGHT_SCREEN_EFFECT - db REFLECT_EFFECT - db POISON_EFFECT - db PARALYZE_EFFECT - db SUBSTITUTE_EFFECT - db MIMIC_EFFECT - db LEECH_SEED_EFFECT - db SPLASH_EFFECT - db -1 -SetDamageEffects: -; moves that do damage but not through normal calculations -; e.g., Super Fang, Psywave - db SUPER_FANG_EFFECT - db SPECIAL_DAMAGE_EFFECT - db -1 -ResidualEffects2: -; non-side effects not included in ResidualEffects1 -; stat-affecting moves, sleep-inflicting moves, and Bide -; e.g., Meditate, Bide, Hypnosis - db $01 - db ATTACK_UP1_EFFECT - db DEFENSE_UP1_EFFECT - db SPEED_UP1_EFFECT - db SPECIAL_UP1_EFFECT - db ACCURACY_UP1_EFFECT - db EVASION_UP1_EFFECT - db ATTACK_DOWN1_EFFECT - db DEFENSE_DOWN1_EFFECT - db SPEED_DOWN1_EFFECT - db SPECIAL_DOWN1_EFFECT - db ACCURACY_DOWN1_EFFECT - db EVASION_DOWN1_EFFECT - db BIDE_EFFECT - db SLEEP_EFFECT - db ATTACK_UP2_EFFECT - db DEFENSE_UP2_EFFECT - db SPEED_UP2_EFFECT - db SPECIAL_UP2_EFFECT - db ACCURACY_UP2_EFFECT - db EVASION_UP2_EFFECT - db ATTACK_DOWN2_EFFECT - db DEFENSE_DOWN2_EFFECT - db SPEED_DOWN2_EFFECT - db SPECIAL_DOWN2_EFFECT - db ACCURACY_DOWN2_EFFECT - db EVASION_DOWN2_EFFECT - db -1 -AlwaysHappenSideEffects: -; Attacks that aren't finished after they faint the opponent. - db DRAIN_HP_EFFECT - db EXPLODE_EFFECT - db DREAM_EATER_EFFECT - db PAY_DAY_EFFECT - db TWO_TO_FIVE_ATTACKS_EFFECT - db $1E - db ATTACK_TWICE_EFFECT - db RECOIL_EFFECT - db TWINEEDLE_EFFECT - db RAGE_EFFECT - db -1 -SpecialEffects: -; Effects from arrays 2, 4, and 5B, minus Twineedle and Rage. -; Includes all effects that do not need to be called at the end of -; ExecutePlayerMove (or ExecuteEnemyMove), because they have already been handled - db DRAIN_HP_EFFECT - db EXPLODE_EFFECT - db DREAM_EATER_EFFECT - db PAY_DAY_EFFECT - db SWIFT_EFFECT - db TWO_TO_FIVE_ATTACKS_EFFECT - db $1E - db CHARGE_EFFECT - db SUPER_FANG_EFFECT - db SPECIAL_DAMAGE_EFFECT - db FLY_EFFECT - db ATTACK_TWICE_EFFECT - db JUMP_KICK_EFFECT - db RECOIL_EFFECT - ; fallthrough to Next EffectsArray -SpecialEffectsCont: -; damaging moves whose effect is executed prior to damage calculation - db THRASH_PETAL_DANCE_EFFECT - db TRAPPING_EFFECT - db -1 +INCLUDE "data/battle/residual_effects_1.asm" +INCLUDE "data/battle/set_damage_effects.asm" +INCLUDE "data/battle/residual_effects_2.asm" +INCLUDE "data/battle/always_happen_effects.asm" +INCLUDE "data/battle/special_effects.asm" SlidePlayerAndEnemySilhouettesOnScreen: call LoadPlayerBackPic ld a, MESSAGE_BOX ; the usual text box at the bottom of the screen ld [wTextBoxID], a call DisplayTextBoxID - coord hl, 1, 5 + hlcoord 1, 5 lb bc, 3, 7 call ClearScreenArea call DisableLCD @@ -117,7 +27,7 @@ SlidePlayerAndEnemySilhouettesOnScreen: or c jr nz, .clearBackgroundLoop ; copy the work RAM tile map to VRAM - coord hl, 0, 0 + hlcoord 0, 0 ld de, vBGMap0 ld b, 18 ; number of rows .copyRowLoop @@ -138,25 +48,25 @@ SlidePlayerAndEnemySilhouettesOnScreen: jr nz, .copyRowLoop call EnableLCD ld a, $90 - ld [hWY], a - ld [rWY], a + ldh [hWY], a + ldh [rWY], a xor a - ld [hTilesetType], a - ld [hSCY], a + ldh [hTilesetType], a + ldh [hSCY], a dec a ld [wUpdateSpritesEnabled], a call Delay3 xor a - ld [H_AUTOBGTRANSFERENABLED], a + ldh [hAutoBGTransferEnabled], a ld b, $70 ld c, $90 ld a, c - ld [hSCX], a + ldh [hSCX], a call DelayFrame ld a, %11100100 ; inverted palette for silhouette effect - ld [rBGP], a - ld [rOBP0], a - ld [rOBP1], a + ldh [rBGP], a + ldh [rOBP0], a + ldh [rOBP1], a call UpdateGBCPal_BGP call UpdateGBCPal_OBP0 call UpdateGBCPal_OBP1 @@ -171,26 +81,26 @@ SlidePlayerAndEnemySilhouettesOnScreen: call SetScrollXForSlidingPlayerBodyLeft ; end background scrolling on line $60 call SlidePlayerHeadLeft ld a, c - ld [hSCX], a + ldh [hSCX], a dec c dec c jr nz, .slideSilhouettesLoop ld a, $1 - ld [H_AUTOBGTRANSFERENABLED], a + ldh [hAutoBGTransferEnabled], a ld a, $31 - ld [hStartTileID], a - coord hl, 1, 5 + ldh [hStartTileID], a + hlcoord 1, 5 predef CopyUncompressedPicToTilemap xor a - ld [hWY], a - ld [rWY], a + ldh [hWY], a + ldh [rWY], a inc a - ld [H_AUTOBGTRANSFERENABLED], a + ldh [hAutoBGTransferEnabled], a call Delay3 ld b, SET_PAL_BATTLE call RunPaletteCommand call HideSprites - jpab PrintBeginningBattleText + jpfar PrintBeginningBattleText ; when a battle is starting, silhouettes of the player's pic and the enemy's pic are slid onto the screen ; the lower of the player's pic (his body) is part of the background, but his head is a sprite @@ -211,13 +121,13 @@ SlidePlayerHeadLeft: ret SetScrollXForSlidingPlayerBodyLeft: - ld a, [rLY] + ldh a, [rLY] cp l jr nz, SetScrollXForSlidingPlayerBodyLeft ld a, h - ld [rSCX], a + ldh [rSCX], a .loop - ld a, [rLY] + ldh a, [rLY] cp h jr z, .loop ret @@ -277,7 +187,7 @@ StartBattle: ld hl, .outOfSafariBallsText jp PrintText .notOutOfSafariBalls - callab PrintSafariZoneBattleText + callfar PrintSafariZoneBattleText ld a, [wEnemyMonSpeed + 1] add a ld b, a ; init b (which is later compared with random value) to (enemy speed % 256) * 2 @@ -306,8 +216,8 @@ StartBattle: jr EnemyRan ; if b was greater than the random value, the enemy runs .outOfSafariBallsText - TX_FAR _OutOfSafariBallsText - db "@" + text_far _OutOfSafariBallsText + text_end .playerSendOutFirstMon xor a @@ -331,7 +241,7 @@ StartBattle: ld [wcf91], a ld [wBattleMonSpecies2], a call LoadScreenTilesFromBuffer1 - coord hl, 1, 5 + hlcoord 1, 5 ld a, $9 call SlideTrainerPicOffScreen call SaveScreenTilesToBuffer1 @@ -365,16 +275,16 @@ EnemyRan: ld a, SFX_RUN call PlaySoundWaitForCurrent xor a - ld [H_WHOSETURN], a - jpab AnimationSlideEnemyMonOff + ldh [hWhoseTurn], a + jpfar AnimationSlideEnemyMonOff WildRanText: - TX_FAR _WildRanText - db "@" + text_far _WildRanText + text_end EnemyRanText: - TX_FAR _EnemyRanText - db "@" + text_far _EnemyRanText + text_end MainInBattleLoop: call ReadPlayerMonCurHPAndStatus @@ -464,7 +374,7 @@ MainInBattleLoop: jr nz, .specialMoveNotUsed ld [wPlayerSelectedMove], a .specialMoveNotUsed - callab SwitchEnemyMon + callfar SwitchEnemyMon .noLinkBattle ld a, [wPlayerSelectedMove] cp QUICK_ATTACK @@ -497,7 +407,7 @@ MainInBattleLoop: jr nc, .playerMovesFirst ; if player is faster jr .enemyMovesFirst ; if enemy is faster .speedEqual ; 50/50 chance for both players - ld a, [hSerialConnectionStatus] + ldh a, [hSerialConnectionStatus] cp USING_INTERNAL_CLOCK jr z, .invertOutcome call BattleRandom @@ -511,8 +421,8 @@ MainInBattleLoop: jr .playerMovesFirst .enemyMovesFirst ld a, $1 - ld [H_WHOSETURN], a - callab TrainerAI + ldh [hWhoseTurn], a + callfar TrainerAI jr c, .AIActionUsedEnemyFirst call ExecuteEnemyMove ld a, [wEscapedFromBattle] @@ -549,8 +459,8 @@ MainInBattleLoop: jp z, HandlePlayerMonFainted call DrawHUDsAndHPBars ld a, $1 - ld [H_WHOSETURN], a - callab TrainerAI + ldh [hWhoseTurn], a + callfar TrainerAI jr c, .AIActionUsedPlayerFirst call ExecuteEnemyMove ld a, [wEscapedFromBattle] @@ -569,7 +479,7 @@ MainInBattleLoop: HandlePoisonBurnLeechSeed: ld hl, wBattleMonHP ld de, wBattleMonStatus - ld a, [H_WHOSETURN] + ldh a, [hWhoseTurn] and a jr z, .playersTurn ld hl, wEnemyMonHP @@ -594,7 +504,7 @@ HandlePoisonBurnLeechSeed: call HandlePoisonBurnLeechSeed_DecreaseOwnHP .notBurnedOrPoisoned ld de, wPlayerBattleStatus2 - ld a, [H_WHOSETURN] + ldh a, [hWhoseTurn] and a jr z, .playersTurn2 ld de, wEnemyBattleStatus2 @@ -603,16 +513,16 @@ HandlePoisonBurnLeechSeed: add a jr nc, .notLeechSeeded push hl - ld a, [H_WHOSETURN] + ldh a, [hWhoseTurn] push af xor $1 - ld [H_WHOSETURN], a + ldh [hWhoseTurn], a xor a ld [wAnimationType], a ld a, ABSORB call PlayMoveAnimation ; play leech seed animation (from opposing mon) pop af - ld [H_WHOSETURN], a + ldh [hWhoseTurn], a pop hl call HandlePoisonBurnLeechSeed_DecreaseOwnHP call HandlePoisonBurnLeechSeed_IncreaseEnemyHP @@ -631,16 +541,16 @@ HandlePoisonBurnLeechSeed: ret HurtByPoisonText: - TX_FAR _HurtByPoisonText - db "@" + text_far _HurtByPoisonText + text_end HurtByBurnText: - TX_FAR _HurtByBurnText - db "@" + text_far _HurtByBurnText + text_end HurtByLeechSeedText: - TX_FAR _HurtByLeechSeedText - db "@" + text_far _HurtByLeechSeedText + text_end ; decreases the mon's current HP by 1/16 of the Max HP (multiplied by number of toxic ticks if active) ; note that the toxic ticks are considered even if the damage is not poison (hence the Leech Seed glitch) @@ -670,7 +580,7 @@ HandlePoisonBurnLeechSeed_DecreaseOwnHP: .nonZeroDamage ld hl, wPlayerBattleStatus3 ld de, wPlayerToxicCounter - ld a, [H_WHOSETURN] + ldh a, [hWhoseTurn] and a jr z, .playersTurn ld hl, wEnemyBattleStatus3 @@ -681,7 +591,7 @@ HandlePoisonBurnLeechSeed_DecreaseOwnHP: ld a, [de] ; increment toxic counter inc a ld [de], a - ld hl, $0000 + ld hl, 0 .toxicTicksLoop add hl, bc dec a @@ -717,7 +627,7 @@ HandlePoisonBurnLeechSeed_DecreaseOwnHP: HandlePoisonBurnLeechSeed_IncreaseEnemyHP: push hl ld hl, wEnemyMonMaxHP - ld a, [H_WHOSETURN] + ldh a, [hWhoseTurn] and a jr z, .playersTurn ld hl, wBattleMonMaxHP @@ -754,23 +664,23 @@ HandlePoisonBurnLeechSeed_IncreaseEnemyHP: ld [hl], a ld [wHPBarNewHP], a .noOverfullHeal - ld a, [H_WHOSETURN] + ldh a, [hWhoseTurn] xor $1 - ld [H_WHOSETURN], a + ldh [hWhoseTurn], a call UpdateCurMonHPBar - ld a, [H_WHOSETURN] + ldh a, [hWhoseTurn] xor $1 - ld [H_WHOSETURN], a + ldh [hWhoseTurn], a pop hl ret UpdateCurMonHPBar: - coord hl, 10, 9 ; tile pointer to player HP bar - ld a, [H_WHOSETURN] + hlcoord 10, 9 ; tile pointer to player HP bar + ldh a, [hWhoseTurn] and a ld a, $1 jr z, .playersTurn - coord hl, 2, 2 ; tile pointer to enemy HP bar + hlcoord 2, 2 ; tile pointer to enemy HP bar xor a .playersTurn push bc @@ -866,10 +776,10 @@ FaintEnemyPokemon: ld hl, wPlayerUsedMove ld [hli], a ld [hl], a - coord hl, 12, 5 - coord de, 12, 6 + hlcoord 12, 5 + decoord 12, 6 call SlideDownFaintedMonPic - coord hl, 0, 0 + hlcoord 0, 0 lb bc, 4, 11 call ClearScreenArea ld a, [wIsInBattle] @@ -936,7 +846,7 @@ FaintEnemyPokemon: .giveExpToMonsThatFought xor a ld [wBoostExpByExpAll], a - callab GainExperience + callfar GainExperience pop af ret z ; return if no exp all @@ -954,11 +864,11 @@ FaintEnemyPokemon: jr nz, .gainExpFlagsLoop ld a, b ld [wPartyGainExpFlags], a - jpab GainExperience + jpfar GainExperience EnemyMonFaintedText: - TX_FAR _EnemyMonFaintedText - db "@" + text_far _EnemyMonFaintedText + text_end EndLowHealthAlarm: ; This function is called when the player has the won the battle. It turns off @@ -993,11 +903,11 @@ ReplaceFaintedEnemyMon: ld e, $30 call GetBattleHealthBarColor setpal SHADE_BLACK, SHADE_DARK, SHADE_LIGHT, SHADE_WHITE - ld [rOBP0], a - ld [rOBP1], a + ldh [rOBP0], a + ldh [rOBP1], a call UpdateGBCPal_OBP0 call UpdateGBCPal_OBP1 - callab DrawEnemyPokeballs + callfar DrawEnemyPokeballs ld a, [wLinkState] cp LINK_STATE_BATTLING jr nz, .notLinkBattle @@ -1025,7 +935,7 @@ TrainerBattleVictory: ld b, MUSIC_DEFEATED_TRAINER .gymleader ld a, [wTrainerClass] - cp SONY3 ; final battle against rival + cp RIVAL3 ; final battle against rival jr nz, .notrival ld b, MUSIC_DEFEATED_GYM_LEADER ld hl, wFlags_D733 @@ -1053,12 +963,12 @@ TrainerBattleVictory: predef_jump AddBCDPredef MoneyForWinningText: - TX_FAR _MoneyForWinningText - db "@" + text_far _MoneyForWinningText + text_end TrainerDefeatedText: - TX_FAR _TrainerDefeatedText - db "@" + text_far _TrainerDefeatedText + text_end PlayBattleVictoryMusic: push af @@ -1124,11 +1034,11 @@ RemoveFaintedPlayerMon: ld [hl], a ld [wBattleMonStatus], a call ReadPlayerMonCurHPAndStatus - coord hl, 9, 7 + hlcoord 9, 7 lb bc, 5, 11 call ClearScreenArea - coord hl, 1, 10 - coord de, 1, 11 + hlcoord 1, 10 + decoord 1, 11 call SlideDownFaintedMonPic ld a, $1 ld [wBattleResult], a @@ -1143,10 +1053,10 @@ RemoveFaintedPlayerMon: ld a, [wPlayerMonNumber] ld [wWhichPokemon], a - callab IsThisPartymonStarterPikachu_Party + callfar IsThisPartymonStarterPikachu_Party jr nc, .notPlayerPikachu ld e, $3 - callab PlayPikachuSoundClip + callfar PlayPikachuSoundClip jr .printText .notPlayerPikachu ld a, [wBattleMonSpecies] @@ -1173,8 +1083,8 @@ RemoveFaintedPlayerMon: ret PlayerMonFaintedText: - TX_FAR _PlayerMonFaintedText - db "@" + text_far _PlayerMonFaintedText + text_end ; asks if you want to use next mon ; stores whether you ran in C flag @@ -1188,7 +1098,7 @@ DoUseNextMonDialogue: ld hl, UseNextMonText call PrintText .displayYesNoBox - coord hl, 13, 9 + hlcoord 13, 9 lb bc, 10, 14 ld a, TWO_OPTION_MENU ld [wTextBoxID], a @@ -1207,8 +1117,8 @@ DoUseNextMonDialogue: jp TryRunningFromBattle UseNextMonText: - TX_FAR _UseNextMonText - db "@" + text_far _UseNextMonText + text_end ; choose next player mon to send out ; stores whether enemy mon has no HP left in Z flag @@ -1263,9 +1173,9 @@ HandlePlayerBlackOut: cp LINK_STATE_BATTLING jr z, .notSony1Battle ld a, [wCurOpponent] - cp OPP_SONY1 + cp OPP_RIVAL1 jr nz, .notSony1Battle - coord hl, 0, 0 ; sony 1 battle + hlcoord 0, 0 ; sony 1 battle lb bc, 8, 21 call ClearScreenArea call ScrollTrainerPicAfterBattle @@ -1294,19 +1204,19 @@ HandlePlayerBlackOut: ret Sony1WinText: - TX_FAR _Sony1WinText - db "@" + text_far _Sony1WinText + text_end PlayerBlackedOutText2: - TX_FAR _PlayerBlackedOutText2 - db "@" + text_far _PlayerBlackedOutText2 + text_end LinkBattleLostText: - TX_FAR _LinkBattleLostText - db "@" + text_far _LinkBattleLostText + text_end ; slides pic of fainted mon downwards until it disappears -; bug: when this is called, [H_AUTOBGTRANSFERENABLED] is non-zero, so there is screen tearing +; bug: when this is called, [hAutoBGTransferEnabled] is non-zero, so there is screen tearing SlideDownFaintedMonPic: ld a, [wd730] push af @@ -1359,9 +1269,9 @@ SevenSpacesText: ; slides the player or enemy trainer off screen ; a is the number of tiles to slide it horizontally (always 9 for the player trainer or 8 for the enemy trainer) ; if a is 8, the slide is to the right, else it is to the left -; bug: when this is called, [H_AUTOBGTRANSFERENABLED] is non-zero, so there is screen tearing +; bug: when this is called, [hAutoBGTransferEnabled] is non-zero, so there is screen tearing SlideTrainerPicOffScreen: - ld [hSlideAmount], a + ldh [hSlideAmount], a ld c, a .slideStepLoop ; each iteration, the trainer pic is slid one tile left/right push bc @@ -1369,10 +1279,10 @@ SlideTrainerPicOffScreen: ld b, 7 ; number of rows .rowLoop push hl - ld a, [hSlideAmount] + ldh a, [hSlideAmount] ld c, a .columnLoop - ld a, [hSlideAmount] + ldh a, [hSlideAmount] cp 8 jr z, .slideRight .slideLeft ; slide player sprite off screen @@ -1435,7 +1345,7 @@ EnemySendOutFirstMon: ld [wAICount], a ld hl, wPlayerBattleStatus1 res 5, [hl] - coord hl, 18, 0 + hlcoord 18, 0 ld a, 8 call SlideTrainerPicOffScreen call PrintEmptyString @@ -1505,7 +1415,7 @@ EnemySendOutFirstMon: jr nz, .next4 ld hl, TrainerAboutToUseText call PrintText - coord hl, 0, 7 + hlcoord 0, 7 lb bc, 8, 1 ld a, TWO_OPTION_MENU ld [wTextBoxID], a @@ -1540,7 +1450,7 @@ EnemySendOutFirstMon: call LoadScreenTilesFromBuffer1 .next4 call ClearSprites - coord hl, 0, 0 + hlcoord 0, 0 lb bc, 4, 11 call ClearScreenArea ld b, SET_PAL_BATTLE @@ -1555,8 +1465,8 @@ EnemySendOutFirstMon: ld de, vFrontPic call LoadMonFrontSprite ld a, -$31 - ld [hStartTileID], a - coord hl, 15, 6 + ldh [hStartTileID], a + hlcoord 15, 6 predef AnimateSendingOutMon ld a, [wEnemyMonSpecies2] call PlayCry @@ -1571,16 +1481,16 @@ EnemySendOutFirstMon: jp SwitchPlayerMon TrainerAboutToUseText: - TX_FAR _TrainerAboutToUseText - db "@" + text_far _TrainerAboutToUseText + text_end TrainerSentOutText: - TX_FAR _TrainerSentOutText - db "@" + text_far _TrainerSentOutText + text_end ; tests if the player has any pokemon that are not fainted ; sets d = 0 if all fainted, d != 0 if some mons are still alive -AnyPartyAlive: +AnyPartyAlive:: ld a, [wPartyCount] ld e, a xor a @@ -1616,8 +1526,8 @@ HasMonFainted: ret NoWillText: - TX_FAR _NoWillText - db "@" + text_far _NoWillText + text_end ; try to run from battle (hl = player speed, de = enemy speed) ; stores whether the attempt was successful in carry flag @@ -1639,32 +1549,32 @@ TryRunningFromBattle: inc a ld [wNumRunAttempts], a ld a, [hli] - ld [H_MULTIPLICAND + 1], a + ldh [hMultiplicand + 1], a ld a, [hl] - ld [H_MULTIPLICAND + 2], a + ldh [hMultiplicand + 2], a ld a, [de] - ld [hEnemySpeed], a + ldh [hEnemySpeed], a inc de ld a, [de] - ld [hEnemySpeed + 1], a + ldh [hEnemySpeed + 1], a call LoadScreenTilesFromBuffer1 - ld de, H_MULTIPLICAND + 1 + ld de, hMultiplicand + 1 ld hl, hEnemySpeed ld c, 2 call StringCmp jr nc, .canEscape ; jump if player speed greater than enemy speed xor a - ld [H_MULTIPLICAND], a + ldh [hMultiplicand], a ld a, 32 - ld [H_MULTIPLIER], a + ldh [hMultiplier], a call Multiply ; multiply player speed by 32 - ld a, [H_PRODUCT + 2] - ld [H_DIVIDEND], a - ld a, [H_PRODUCT + 3] - ld [H_DIVIDEND + 1], a - ld a, [hEnemySpeed] + ldh a, [hProduct + 2] + ldh [hDividend], a + ldh a, [hProduct + 3] + ldh [hDividend + 1], a + ldh a, [hEnemySpeed] ld b, a - ld a, [hEnemySpeed + 1] + ldh a, [hEnemySpeed + 1] ; divide enemy speed by 4 srl b rr a @@ -1672,10 +1582,10 @@ TryRunningFromBattle: rr a and a jr z, .canEscape ; jump if enemy speed divided by 4, mod 256 is 0 - ld [H_DIVISOR], a ; ((enemy speed / 4) % 256) + ldh [hDivisor], a ; ((enemy speed / 4) % 256) ld b, $2 call Divide ; divide (player speed * 32) by ((enemy speed / 4) % 256) - ld a, [H_QUOTIENT + 2] + ldh a, [hQuotient + 2] and a ; is the quotient greater than 256? jr nz, .canEscape ; if so, the player can escape ld a, [wNumRunAttempts] @@ -1685,15 +1595,15 @@ TryRunningFromBattle: dec c jr z, .compareWithRandomValue ld b, 30 - ld a, [H_QUOTIENT + 3] + ldh a, [hQuotient + 3] add b - ld [H_QUOTIENT + 3], a + ldh [hQuotient + 3], a jr c, .canEscape jr .loop .compareWithRandomValue call BattleRandom ld b, a - ld a, [H_QUOTIENT + 3] + ldh a, [hQuotient + 3] cp b jr nc, .canEscape ; if the random value was less than or equal to the quotient ; plus 30 times the number of attempts, the player can escape @@ -1741,16 +1651,16 @@ TryRunningFromBattle: ret CantEscapeText: - TX_FAR _CantEscapeText - db "@" + text_far _CantEscapeText + text_end NoRunningText: - TX_FAR _NoRunningText - db "@" + text_far _NoRunningText + text_end GotAwayText: - TX_FAR _GotAwayText - db "@" + text_far _GotAwayText + text_end ; copies from party data to battle mon data when sending out a new player mon LoadBattleMonFromParty: @@ -1851,7 +1761,7 @@ LoadEnemyMonFromParty: ret SendOutMon: - callab PrintSendOutMonMessage + callfar PrintSendOutMonMessage ld hl, wEnemyMonHP ld a, [hli] or [hl] ; is enemy mon HP zero? @@ -1861,7 +1771,7 @@ SendOutMon: call DrawPlayerHUDAndHPBar predef LoadMonBackPic xor a - ld [hStartTileID], a + ldh [hStartTileID], a ld hl, wBattleAndStartSavedMenuItem ld [hli], a ld [hl], a @@ -1884,27 +1794,27 @@ SendOutMon: call RunPaletteCommand ld hl, wEnemyBattleStatus1 res USING_TRAPPING_MOVE, [hl] - callab IsThisPartymonStarterPikachu + callfar IsThisPartymonStarterPikachu jr c, .starterPikachu ld a, $1 - ld [H_WHOSETURN], a + ldh [hWhoseTurn], a ld a, POOF_ANIM call PlayMoveAnimation - coord hl, 4, 11 + hlcoord 4, 11 predef AnimateSendingOutMon jr .playRegularCry .starterPikachu xor a - ld [H_WHOSETURN], a + ldh [hWhoseTurn], a ld a, $1 - ld [H_AUTOBGTRANSFERENABLED], a - callab StarterPikachuBattleEntranceAnimation - callab IsPlayerPikachuAsleepInParty + ldh [hAutoBGTransferEnabled], a + callfar StarterPikachuBattleEntranceAnimation + callfar IsPlayerPikachuAsleepInParty ld e, $24 jr c, .asm_3cd81 ld e, $a .asm_3cd81 - callab PlayPikachuSoundClip + callfar PlayPikachuSoundClip jr .done .playRegularCry ld a, [wcf91] @@ -1919,42 +1829,42 @@ AnimateRetreatingPlayerMon: push af ld a, [wPlayerMonNumber] ld [wWhichPokemon], a - callab IsThisPartymonStarterPikachu + callfar IsThisPartymonStarterPikachu pop bc ld a, b ld [wWhichPokemon], a jr c, .starterPikachu - coord hl, 1, 5 + hlcoord 1, 5 lb bc, 7, 7 call ClearScreenArea - coord hl, 3, 7 + hlcoord 3, 7 lb bc, 5, 5 xor a ld [wDownscaledMonSize], a - ld [hBaseTileID], a + ldh [hBaseTileID], a predef CopyDownscaledMonTiles ld c, 4 call DelayFrames call .clearScreenArea - coord hl, 4, 9 + hlcoord 4, 9 lb bc, 3, 3 ld a, 1 ld [wDownscaledMonSize], a xor a - ld [hBaseTileID], a + ldh [hBaseTileID], a predef CopyDownscaledMonTiles call Delay3 call .clearScreenArea ld a, $4c - Coorda 5, 11 + ldcoord_a 5, 11 jr .clearScreenArea .starterPikachu xor a - ld [H_WHOSETURN], a - callab AnimationSlideMonOff + ldh [hWhoseTurn], a + callfar AnimationSlideMonOff ret .clearScreenArea - coord hl, 1, 5 + hlcoord 1, 5 lb bc, 7, 7 call ClearScreenArea ret @@ -1977,15 +1887,15 @@ DrawHUDsAndHPBars: DrawPlayerHUDAndHPBar: xor a - ld [H_AUTOBGTRANSFERENABLED], a - coord hl, 9, 7 + ldh [hAutoBGTransferEnabled], a + hlcoord 9, 7 lb bc, 5, 11 call ClearScreenArea - callab PlacePlayerHUDTiles - coord hl, 18, 9 + callfar PlacePlayerHUDTiles + hlcoord 18, 9 ld [hl], $73 ld de, wBattleMonNick - coord hl, 10, 7 + hlcoord 10, 7 call CenterMonName call PlaceString ld hl, wBattleMonSpecies @@ -1996,7 +1906,7 @@ DrawPlayerHUDAndHPBar: ld de, wLoadedMonLevel ld bc, wBattleMonPP - wBattleMonLevel call CopyData - coord hl, 14, 8 + hlcoord 14, 8 push hl inc hl ld de, wLoadedMonStatus @@ -2007,10 +1917,10 @@ DrawPlayerHUDAndHPBar: .doNotPrintLevel ld a, [wLoadedMonSpecies] ld [wcf91], a - coord hl, 10, 9 + hlcoord 10, 9 predef DrawHP ld a, $1 - ld [H_AUTOBGTRANSFERENABLED], a + ldh [hAutoBGTransferEnabled], a ld hl, wPlayerHPBarColor call GetBattleHealthBarColor ld hl, wBattleMonHP @@ -2038,16 +1948,16 @@ DrawPlayerHUDAndHPBar: DrawEnemyHUDAndHPBar: xor a - ld [H_AUTOBGTRANSFERENABLED], a - coord hl, 0, 0 + ldh [hAutoBGTransferEnabled], a + hlcoord 0, 0 lb bc, 4, 12 call ClearScreenArea - callab PlaceEnemyHUDTiles + callfar PlaceEnemyHUDTiles ld de, wEnemyMonNick - coord hl, 1, 0 + hlcoord 1, 0 call CenterMonName call PlaceString - coord hl, 4, 1 + hlcoord 4, 1 push hl inc hl ld de, wEnemyMonStatus @@ -2060,9 +1970,9 @@ DrawEnemyHUDAndHPBar: .skipPrintLevel ld hl, wEnemyMonHP ld a, [hli] - ld [H_MULTIPLICAND + 1], a + ldh [hMultiplicand + 1], a ld a, [hld] - ld [H_MULTIPLICAND + 2], a + ldh [hMultiplicand + 2], a or [hl] ; is current HP zero? jr nz, .hpNonzero ; current HP is 0 @@ -2073,45 +1983,45 @@ DrawEnemyHUDAndHPBar: jp .drawHPBar .hpNonzero xor a - ld [H_MULTIPLICAND], a + ldh [hMultiplicand], a ld a, 48 - ld [H_MULTIPLIER], a + ldh [hMultiplier], a call Multiply ; multiply current HP by 48 ld hl, wEnemyMonMaxHP ld a, [hli] ld b, a ld a, [hl] - ld [H_DIVISOR], a + ldh [hDivisor], a ld a, b and a ; is max HP > 255? jr z, .doDivide ; if max HP > 255, scale both (current HP * 48) and max HP by dividing by 4 so that max HP fits in one byte ; (it needs to be one byte so it can be used as the divisor for the Divide function) - ld a, [H_DIVISOR] + ldh a, [hDivisor] srl b rr a srl b rr a - ld [H_DIVISOR], a - ld a, [H_PRODUCT + 2] + ldh [hDivisor], a + ldh a, [hProduct + 2] ld b, a srl b - ld a, [H_PRODUCT + 3] + ldh a, [hProduct + 3] rr a srl b rr a - ld [H_PRODUCT + 3], a + ldh [hProduct + 3], a ld a, b - ld [H_PRODUCT + 2], a + ldh [hProduct + 2], a .doDivide - ld a, [H_PRODUCT + 2] - ld [H_DIVIDEND], a - ld a, [H_PRODUCT + 3] - ld [H_DIVIDEND + 1], a + ldh a, [hProduct + 2] + ldh [hDividend], a + ldh a, [hProduct + 3] + ldh [hDividend + 1], a ld a, $2 ld b, a call Divide ; divide (current HP * 48) by max HP - ld a, [H_QUOTIENT + 3] + ldh a, [hQuotient + 3] ; set variables for DrawHPBar ld e, a ld a, $6 @@ -2120,10 +2030,10 @@ DrawEnemyHUDAndHPBar: .drawHPBar xor a ld [wHPBarType], a - coord hl, 2, 2 + hlcoord 2, 2 call DrawHPBar ld a, $1 - ld [H_AUTOBGTRANSFERENABLED], a + ldh [hAutoBGTransferEnabled], a ld hl, wEnemyHPBarColor GetBattleHealthBarColor: @@ -2161,7 +2071,7 @@ CenterMonName: pop de ret -DisplayBattleMenu: +DisplayBattleMenu:: call LoadScreenTilesFromBuffer1 ; restore saved screen ld a, [wBattleType] and a @@ -2206,12 +2116,12 @@ DisplayBattleMenu: ld bc, NAME_LENGTH call CopyData ; the following simulates the keystrokes by drawing menus on screen - coord hl, 9, 14 + hlcoord 9, 14 ld [hl], "▶" ld c, 20 call DelayFrames ld [hl], " " - coord hl, 9, 16 + hlcoord 9, 16 ld [hl], "▶" ld c, 20 call DelayFrames @@ -2238,14 +2148,14 @@ DisplayBattleMenu: ld a, " " jr z, .safariLeftColumn ; put cursor in left column for normal battle menu (i.e. when it's not a Safari battle) - Coorda 15, 14 ; clear upper cursor position in right column - Coorda 15, 16 ; clear lower cursor position in right column + ldcoord_a 15, 14 ; clear upper cursor position in right column + ldcoord_a 15, 16 ; clear lower cursor position in right column ld b, $9 ; top menu item X jr .leftColumn_WaitForInput .safariLeftColumn - Coorda 13, 14 - Coorda 13, 16 - coord hl, 7, 14 + ldcoord_a 13, 14 + ldcoord_a 13, 16 + hlcoord 7, 14 ld de, wNumSafariBalls lb bc, 1, 2 call PrintNumber @@ -2271,14 +2181,14 @@ DisplayBattleMenu: ld a, " " jr z, .safariRightColumn ; put cursor in right column for normal battle menu (i.e. when it's not a Safari battle) - Coorda 9, 14 ; clear upper cursor position in left column - Coorda 9, 16 ; clear lower cursor position in left column + ldcoord_a 9, 14 ; clear upper cursor position in left column + ldcoord_a 9, 16 ; clear lower cursor position in left column ld b, $f ; top menu item X jr .rightColumn_WaitForInput .safariRightColumn - Coorda 1, 14 ; clear upper cursor position in left column - Coorda 1, 16 ; clear lower cursor position in left column - coord hl, 7, 14 + ldcoord_a 1, 14 ; clear upper cursor position in left column + ldcoord_a 1, 16 ; clear lower cursor position in left column + hlcoord 7, 14 ld de, wNumSafariBalls lb bc, 1, 2 call PrintNumber @@ -2348,8 +2258,8 @@ DisplayBattleMenu: jp DisplayBattleMenu .RunAwayText - TX_FAR _RunAwayText - db "@" + text_far _RunAwayText + text_end .upperLeftMenuItemWasNotSelected ; a menu item other than the upper left item was selected cp $2 @@ -2485,8 +2395,8 @@ UseBagItem: ret ItemsCantBeUsedHereText: - TX_FAR _ItemsCantBeUsedHereText - db "@" + text_far _ItemsCantBeUsedHereText + text_end PartyMenuOrRockOrRun: dec a ; was Run selected? @@ -2517,7 +2427,7 @@ PartyMenuOrRockOrRun: call GBPalNormal jp DisplayBattleMenu .partyMonDeselected - coord hl, 11, 11 + hlcoord 11, 11 ld bc, 6 * SCREEN_WIDTH + 9 ld a, " " call FillMemory @@ -2562,7 +2472,7 @@ PartyMenuOrRockOrRun: predef StatusScreen2 ; now we need to reload the enemy mon pic ld a, 1 - ld [H_WHOSETURN], a + ldh [hWhoseTurn], a ld a, [wEnemyBattleStatus2] bit HAS_SUBSTITUTE_UP, a ; does the enemy mon have a substitute? ld hl, AnimationSubstitute @@ -2609,7 +2519,7 @@ PartyMenuOrRockOrRun: ; fall through to SwitchPlayerMon SwitchPlayerMon: - callab RetreatMon + callfar RetreatMon ld c, 50 call DelayFrames call AnimateRetreatingPlayerMon @@ -2632,8 +2542,8 @@ SwitchPlayerMon: ret AlreadyOutText: - TX_FAR _AlreadyOutText - db "@" + text_far _AlreadyOutText + text_end BattleMenu_RunWasSelected: call LoadScreenTilesFromBuffer1 @@ -2662,18 +2572,18 @@ MoveSelectionMenu: ld de, wMoves ld bc, NUM_MOVES call CopyData - callab FormatMovesString + callfar FormatMovesString ret .writemoves ld de, wMovesString - ld a, [hFlags_0xFFFA] + ldh a, [hFlagsFFFA] set 2, a - ld [hFlags_0xFFFA], a + ldh [hFlagsFFFA], a call PlaceString - ld a, [hFlags_0xFFFA] + ldh a, [hFlagsFFFA] res 2, a - ld [hFlags_0xFFFA], a + ldh [hFlagsFFFA], a ret .regularmenu @@ -2681,17 +2591,17 @@ MoveSelectionMenu: ret z ld hl, wBattleMonMoves call .loadmoves - coord hl, 4, 12 + hlcoord 4, 12 lb bc, 4, 14 di ; out of pure coincidence, it is possible for vblank to occur between the di and ei ; so it is necessary to put the di ei block to not cause tearing call TextBoxBorder - coord hl, 4, 12 + hlcoord 4, 12 ld [hl], $7a - coord hl, 10, 12 + hlcoord 10, 12 ld [hl], $7e ei - coord hl, 6, 13 + hlcoord 6, 13 call .writemoves ld b, $5 ld a, $c @@ -2699,10 +2609,10 @@ MoveSelectionMenu: .mimicmenu ld hl, wEnemyMonMoves call .loadmoves - coord hl, 0, 7 + hlcoord 0, 7 lb bc, 4, 14 call TextBoxBorder - coord hl, 2, 8 + hlcoord 2, 8 call .writemoves ld b, $1 ld a, $7 @@ -2713,10 +2623,10 @@ MoveSelectionMenu: ld bc, wPartyMon2 - wPartyMon1 call AddNTimes call .loadmoves - coord hl, 4, 7 + hlcoord 4, 7 lb bc, 4, 14 call TextBoxBorder - coord hl, 6, 8 + hlcoord 6, 8 call .writemoves ld b, $5 ld a, $7 @@ -2770,7 +2680,7 @@ SelectMenuItem: jr z, .battleselect dec a jr nz, .select - coord hl, 1, 14 + hlcoord 1, 14 ld de, WhichTechniqueString call PlaceString jr .select @@ -2782,16 +2692,16 @@ SelectMenuItem: ld a, [wMenuItemToSwap] and a jr z, .select - coord hl, 5, 13 + hlcoord 5, 13 dec a ld bc, SCREEN_WIDTH call AddNTimes ld [hl], "▷" .select - ld hl, hFlags_0xFFFA + ld hl, hFlagsFFFA set 1, [hl] call HandleMenuInput - ld hl, hFlags_0xFFFA + ld hl, hFlagsFFFA res 1, [hl] bit 6, a jp nz, SelectMenuItem_CursorUp ; up @@ -2860,12 +2770,12 @@ SelectMenuItem: jp MoveSelectionMenu MoveNoPPText: - TX_FAR _MoveNoPPText - db "@" + text_far _MoveNoPPText + text_end MoveDisabledText: - TX_FAR _MoveDisabledText - db "@" + text_far _MoveDisabledText + text_end WhichTechniqueString: db "WHICH TECHNIQUE?@" @@ -2899,7 +2809,7 @@ Func_3d4f5: jr nz, .asm_3d4fd ld a, $1 .asm_3d4fd - ld [H_WHOSETURN], a + ldh [hWhoseTurn], a call LoadScreenTilesFromBuffer1 call Func_3d536 ld a, [wTestBattlePlayerSelectedMove] @@ -2909,7 +2819,7 @@ Func_3d4f5: xor a ld [wAnimationType], a predef MoveAnimation - callab Func_78e98 + callfar Func_78e98 jp MoveSelectionMenu Func_3d523: @@ -2925,10 +2835,10 @@ asm_3d52d: jp MoveSelectionMenu Func_3d536: - coord hl, 10, 16 + hlcoord 10, 16 lb bc, 2, 10 call ClearScreenArea - coord hl, 10, 17 + hlcoord 10, 17 ld de, wTestBattlePlayerSelectedMove lb bc, LEADING_ZEROES | 1, 3 call PrintNumber @@ -2939,7 +2849,7 @@ Func_3d536: ret nc ld [wd11e], a call GetMoveName - coord hl, 13, 17 + hlcoord 13, 17 jp PlaceString AnyMoveToSelect: @@ -2989,8 +2899,8 @@ AnyMoveToSelect: ret NoMovesLeftText: - TX_FAR _NoMovesLeftText - db "@" + text_far _NoMovesLeftText + text_end SwapMovesInMenu: ld a, [wPlayerBattleStatus3] @@ -3073,8 +2983,8 @@ SwapMovesInMenu: PrintMenuItem: xor a - ld [H_AUTOBGTRANSFERENABLED], a - coord hl, 0, 8 + ldh [hAutoBGTransferEnabled], a + hlcoord 0, 8 lb bc, 3, 9 call TextBoxBorder ld a, [wPlayerDisabledMove] @@ -3086,7 +2996,7 @@ PrintMenuItem: ld a, [wCurrentMenuItem] cp b jr nz, .notDisabled - coord hl, 1, 10 + hlcoord 1, 10 ld de, DisabledText call PlaceString jr .moveDisabled @@ -3094,7 +3004,7 @@ PrintMenuItem: ld hl, wCurrentMenuItem dec [hl] xor a - ld [H_WHOSETURN], a + ldh [hWhoseTurn], a ld hl, wBattleMonMoves ld a, [wCurrentMenuItem] ld c, a @@ -3107,7 +3017,7 @@ PrintMenuItem: ld [wWhichPokemon], a ld a, BATTLE_MON_DATA ld [wMonDataLocation], a - callab GetMaxPP + callfar GetMaxPP ld hl, wCurrentMenuItem ld c, [hl] inc [hl] @@ -3118,27 +3028,27 @@ PrintMenuItem: and $3f ld [wcd6d], a ; print TYPE/ and / - coord hl, 1, 9 + hlcoord 1, 9 ld de, TypeText call PlaceString - coord hl, 7, 11 + hlcoord 7, 11 ld [hl], "/" - coord hl, 5, 9 + hlcoord 5, 9 ld [hl], "/" - coord hl, 5, 11 + hlcoord 5, 11 ld de, wcd6d lb bc, 1, 2 call PrintNumber - coord hl, 8, 11 + hlcoord 8, 11 ld de, wMaxPP lb bc, 1, 2 call PrintNumber call GetCurrentMove - coord hl, 2, 10 + hlcoord 2, 10 predef PrintMoveType .moveDisabled ld a, $1 - ld [H_AUTOBGTRANSFERENABLED], a + ldh [hAutoBGTransferEnabled], a jp Delay3 DisabledText: @@ -3202,7 +3112,7 @@ SelectEnemyMove: ld a, [wIsInBattle] dec a jr z, .chooseRandomMove ; wild encounter - callab AIEnemyTrainerChooseMoves + callfar AIEnemyTrainerChooseMoves .chooseRandomMove push hl call BattleRandom @@ -3267,7 +3177,7 @@ LinkBattleExchangeData: ld a, b .doExchange ld [wSerialExchangeNybbleSendData], a - callab PrintWaitingText + callfar PrintWaitingText .syncLoop1 call Serial_ExchangeNybble call DelayFrame @@ -3290,7 +3200,7 @@ LinkBattleExchangeData: ExecutePlayerMove: xor a - ld [H_WHOSETURN], a ; set player's turn + ldh [hWhoseTurn], a ; set player's turn ld a, [wPlayerSelectedMove] inc a jp z, ExecutePlayerMoveDone ; for selected move = FF, skip most of player's turn @@ -3443,7 +3353,7 @@ MirrorMoveCheck: .moveDidNotMiss call ApplyAttackToEnemyPokemon call PrintCriticalOHKOText - callab DisplayEffectiveness + callfar DisplayEffectiveness ld a, 1 ld [wMoveDidntMiss], a .notDone @@ -3486,8 +3396,8 @@ MirrorMoveCheck: jp ExecutePlayerMoveDone MultiHitText: - TX_FAR _MultiHitText - db "@" + text_far _MultiHitText + text_end ExecutePlayerMoveDone: xor a @@ -3499,29 +3409,29 @@ PrintGhostText: ; print the ghost battle messages call IsGhostBattle ret nz - ld a, [H_WHOSETURN] + ldh a, [hWhoseTurn] and a jr nz, .Ghost - ld a, [wBattleMonStatus] ; player’s turn + ld a, [wBattleMonStatus] ; player's turn and SLP | (1 << FRZ) ret nz ld hl, ScaredText call PrintText xor a ret -.Ghost ; ghost’s turn +.Ghost ; ghost's turn ld hl, GetOutText call PrintText xor a ret ScaredText: - TX_FAR _ScaredText - db "@" + text_far _ScaredText + text_end GetOutText: - TX_FAR _GetOutText - db "@" + text_far _GetOutText + text_end IsGhostBattle: ld a, [wIsInBattle] @@ -3804,69 +3714,69 @@ CheckPlayerStatusConditions: ret FastAsleepText: - TX_FAR _FastAsleepText - db "@" + text_far _FastAsleepText + text_end WokeUpText: - TX_FAR _WokeUpText - db "@" + text_far _WokeUpText + text_end IsFrozenText: - TX_FAR _IsFrozenText - db "@" + text_far _IsFrozenText + text_end FullyParalyzedText: - TX_FAR _FullyParalyzedText - db "@" + text_far _FullyParalyzedText + text_end FlinchedText: - TX_FAR _FlinchedText - db "@" + text_far _FlinchedText + text_end MustRechargeText: - TX_FAR _MustRechargeText - db "@" + text_far _MustRechargeText + text_end DisabledNoMoreText: - TX_FAR _DisabledNoMoreText - db "@" + text_far _DisabledNoMoreText + text_end IsConfusedText: - TX_FAR _IsConfusedText - db "@" + text_far _IsConfusedText + text_end HurtItselfText: - TX_FAR _HurtItselfText - db "@" + text_far _HurtItselfText + text_end ConfusedNoMoreText: - TX_FAR _ConfusedNoMoreText - db "@" + text_far _ConfusedNoMoreText + text_end SavingEnergyText: - TX_FAR _SavingEnergyText - db "@" + text_far _SavingEnergyText + text_end UnleashedEnergyText: - TX_FAR _UnleashedEnergyText - db "@" + text_far _UnleashedEnergyText + text_end ThrashingAboutText: - TX_FAR _ThrashingAboutText - db "@" + text_far _ThrashingAboutText + text_end AttackContinuesText: - TX_FAR _AttackContinuesText - db "@" + text_far _AttackContinuesText + text_end CantMoveText: - TX_FAR _CantMoveText - db "@" + text_far _CantMoveText + text_end PrintMoveIsDisabledText: ld hl, wPlayerSelectedMove ld de, wPlayerBattleStatus1 - ld a, [H_WHOSETURN] + ldh a, [hWhoseTurn] and a jr z, .removeChargingUp inc hl @@ -3882,8 +3792,8 @@ PrintMoveIsDisabledText: jp PrintText MoveIsDisabledText: - TX_FAR _MoveIsDisabledText - db "@" + text_far _MoveIsDisabledText + text_end HandleSelfConfusionDamage: ld hl, HurtItselfText @@ -3922,11 +3832,11 @@ HandleSelfConfusionDamage: xor a ld [wAnimationType], a inc a - ld [H_WHOSETURN], a + ldh [hWhoseTurn], a call PlayMoveAnimation call DrawPlayerHUDAndHPBar xor a - ld [H_WHOSETURN], a + ldh [hWhoseTurn], a jp ApplyDamageToPlayerPokemon PrintMonName1Text: @@ -3939,9 +3849,9 @@ PrintMonName1Text: ; this likely had to do with Japanese grammar that got translated, ; but the functionality didn't get removed MonName1Text: - TX_FAR _MonName1Text - TX_ASM - ld a, [H_WHOSETURN] + text_far _MonName1Text + text_asm + ldh a, [hWhoseTurn] and a ld a, [wPlayerMoveNum] ld hl, wPlayerUsedMove @@ -3964,13 +3874,13 @@ MonName1Text: ret Used1Text: - TX_FAR _Used1Text - TX_ASM + text_far _Used1Text + text_asm jr PrintInsteadText Used2Text: - TX_FAR _Used2Text - TX_ASM + text_far _Used2Text + text_asm ; fall through PrintInsteadText: @@ -3981,8 +3891,8 @@ PrintInsteadText: ret InsteadText: - TX_FAR _InsteadText - TX_ASM + text_far _InsteadText + text_asm ; fall through PrintMoveName: @@ -3990,8 +3900,8 @@ PrintMoveName: ret _PrintMoveName: - TX_FAR _CF4BText - TX_ASM + text_far _CF4BText + text_asm ld hl, ExclamationPointPointerTable ld a, [wd11e] ; exclamation point num add a @@ -4013,24 +3923,24 @@ ExclamationPointPointerTable: dw ExclamationPoint5Text ExclamationPoint1Text: - TX_FAR _ExclamationPoint1Text - db "@" + text_far _ExclamationPoint1Text + text_end ExclamationPoint2Text: - TX_FAR _ExclamationPoint2Text - db "@" + text_far _ExclamationPoint2Text + text_end ExclamationPoint3Text: - TX_FAR _ExclamationPoint3Text - db "@" + text_far _ExclamationPoint3Text + text_end ExclamationPoint4Text: - TX_FAR _ExclamationPoint4Text - db "@" + text_far _ExclamationPoint4Text + text_end ExclamationPoint5Text: - TX_FAR _ExclamationPoint5Text - db "@" + text_far _ExclamationPoint5Text + text_end ; this function does nothing useful ; if the move being used is in set [1-4] from ExclamationPointMoveSets, @@ -4061,26 +3971,11 @@ DetermineExclamationPointTextNum: pop bc ret -ExclamationPointMoveSets: -; a grammar mistake was fixed (only concerning japanese) -; BIDE is in category 3, moved from category 2 - db SWORDS_DANCE, GROWTH - db $00 - db RECOVER, SELFDESTRUCT, AMNESIA - db $00 - db MEDITATE, AGILITY, TELEPORT, MIMIC, DOUBLE_TEAM, BIDE, BARRAGE - db $00 - db POUND, SCRATCH, VICEGRIP, WING_ATTACK, FLY, BIND, SLAM, HORN_ATTACK, BODY_SLAM - db WRAP, THRASH, TAIL_WHIP, LEER, BITE, GROWL, ROAR, SING, PECK, COUNTER - db STRENGTH, ABSORB, STRING_SHOT, EARTHQUAKE, FISSURE, DIG, TOXIC, SCREECH, HARDEN - db MINIMIZE, WITHDRAW, DEFENSE_CURL, METRONOME, LICK, CLAMP, CONSTRICT, POISON_GAS - db LEECH_LIFE, BUBBLE, FLASH, SPLASH, ACID_ARMOR, FURY_SWIPES, REST, SHARPEN, SLASH, SUBSTITUTE - db $00 - db $FF ; terminator +INCLUDE "data/moves/grammar.asm" PrintMoveFailureText: ld de, wPlayerMoveEffect - ld a, [H_WHOSETURN] + ldh a, [hWhoseTurn] and a jr z, .playersTurn ld de, wEnemyMoveEffect @@ -4128,7 +4023,7 @@ PrintMoveFailureText: call PrintText ld b, $4 predef PredefShakeScreenHorizontally - ld a, [H_WHOSETURN] + ldh a, [hWhoseTurn] and a jr nz, .enemyTurn jp ApplyDamageToPlayerPokemon @@ -4136,24 +4031,24 @@ PrintMoveFailureText: jp ApplyDamageToEnemyPokemon AttackMissedText: - TX_FAR _AttackMissedText - db "@" + text_far _AttackMissedText + text_end KeptGoingAndCrashedText: - TX_FAR _KeptGoingAndCrashedText - db "@" + text_far _KeptGoingAndCrashedText + text_end UnaffectedText: - TX_FAR _UnaffectedText - db "@" + text_far _UnaffectedText + text_end PrintDoesntAffectText: ld hl, DoesntAffectMonText jp PrintText DoesntAffectMonText: - TX_FAR _DoesntAffectMonText - db "@" + text_far _DoesntAffectMonText + text_end ; if there was a critical hit or an OHKO was successful, print the corresponding text PrintCriticalOHKOText: @@ -4181,12 +4076,12 @@ CriticalOHKOTextPointers: dw OHKOText CriticalHitText: - TX_FAR _CriticalHitText - db "@" + text_far _CriticalHitText + text_end OHKOText: - TX_FAR _OHKOText - db "@" + text_far _OHKOText + text_end ; checks if a traded mon will disobey due to lack of badges ; stores whether the mon will use a move in Z flag @@ -4216,16 +4111,16 @@ CheckForDisobedience: .monIsTraded ; what level might disobey? ld hl, wObtainedBadges - bit 7, [hl] + bit BIT_EARTHBADGE, [hl] ld a, 101 jr nz, .next - bit 5, [hl] + bit BIT_MARSHBADGE, [hl] ld a, 70 jr nz, .next - bit 3, [hl] + bit BIT_RAINBOWBADGE, [hl] ld a, 50 jr nz, .next - bit 1, [hl] + bit BIT_CASCADEBADGE, [hl] ld a, 30 jr nz, .next ld a, 10 @@ -4370,24 +4265,24 @@ CheckForDisobedience: ret LoafingAroundText: - TX_FAR _LoafingAroundText - db "@" + text_far _LoafingAroundText + text_end BeganToNapText: - TX_FAR _BeganToNapText - db "@" + text_far _BeganToNapText + text_end WontObeyText: - TX_FAR _WontObeyText - db "@" + text_far _WontObeyText + text_end TurnedAwayText: - TX_FAR _TurnedAwayText - db "@" + text_far _TurnedAwayText + text_end IgnoredOrdersText: - TX_FAR _IgnoredOrdersText - db "@" + text_far _IgnoredOrdersText + text_end ; sets b, c, d, and e for the CalculateDamage routine in the case of an attack by the player mon GetDamageVarsForPlayerAttack: @@ -4401,7 +4296,7 @@ GetDamageVarsForPlayerAttack: ld d, a ; d = move power ret z ; return if move power is zero ld a, [hl] ; a = [wPlayerMoveType] - cp FIRE ; types >= FIRE are all special + cp SPECIAL ; types >= SPECIAL are all special jr nc, .specialAttack .physicalAttack ld hl, wEnemyMonDefense @@ -4422,9 +4317,9 @@ GetDamageVarsForPlayerAttack: ; in the case of a critical hit, reset the player's attack and the enemy's defense to their base values ld c, 3 ; defense stat call GetEnemyMonStat - ld a, [H_PRODUCT + 2] + ldh a, [hProduct + 2] ld b, a - ld a, [H_PRODUCT + 3] + ldh a, [hProduct + 3] ld c, a push bc ld hl, wPartyMon1Attack @@ -4444,8 +4339,8 @@ GetDamageVarsForPlayerAttack: ; if the enemy has used Light Screen, double the enemy's special sla c rl b -; reflect and light screen boosts do not cap the stat at 999, so weird things will happen during stats scaling if -; a Pokemon with 512 or more Defense has used Reflect, or if a Pokemon with 512 or more Special has used Light Screen +; reflect and light screen boosts do not cap the stat at MAX_STAT_VALUE, so weird things will happen during stats scaling +; if a Pokemon with 512 or more Defense has used Reflect, or if a Pokemon with 512 or more Special has used Light Screen .specialAttackCritCheck ld hl, wBattleMonSpecial ld a, [wCriticalHitOrOHKO] @@ -4454,9 +4349,9 @@ GetDamageVarsForPlayerAttack: ; in the case of a critical hit, reset the player's and enemy's specials to their base values ld c, 5 ; special stat call GetEnemyMonStat - ld a, [H_PRODUCT + 2] + ldh a, [hProduct + 2] ld b, a - ld a, [H_PRODUCT + 3] + ldh a, [hProduct + 3] ld c, a push bc ld hl, wPartyMon1Special @@ -4514,7 +4409,7 @@ GetDamageVarsForEnemyAttack: and a ret z ; return if move power is zero ld a, [hl] ; a = [wEnemyMoveType] - cp FIRE ; types >= FIRE are all special + cp SPECIAL ; types >= SPECIAL are all special jr nc, .specialAttack .physicalAttack ld hl, wBattleMonDefense @@ -4543,7 +4438,7 @@ GetDamageVarsForEnemyAttack: push bc ld c, 2 ; attack stat call GetEnemyMonStat - ld hl, H_PRODUCT + 2 + ld hl, hProduct + 2 pop bc jr .scaleStats .specialAttack @@ -4557,8 +4452,8 @@ GetDamageVarsForEnemyAttack: ; if the player has used Light Screen, double the player's special sla c rl b -; reflect and light screen boosts do not cap the stat at 999, so weird things will happen during stats scaling if -; a Pokemon with 512 or more Defense has used Reflect, or if a Pokemon with 512 or more Special has used Light Screen +; reflect and light screen boosts do not cap the stat at MAX_STAT_VALUE, so weird things will happen during stats scaling +; if a Pokemon with 512 or more Defense has used Reflect, or if a Pokemon with 512 or more Special has used Light Screen .specialAttackCritCheck ld hl, wEnemyMonSpecial ld a, [wCriticalHitOrOHKO] @@ -4575,7 +4470,7 @@ GetDamageVarsForEnemyAttack: push bc ld c, 5 ; special stat call GetEnemyMonStat - ld hl, H_PRODUCT + 2 + ld hl, hProduct + 2 pop bc ; if either the offensive or defensive stat is too large to store in a byte, scale both stats by dividing them by 4 ; this allows values with up to 10 bits (values up to 1023) to be handled @@ -4633,9 +4528,9 @@ GetEnemyMonStat: ld bc, wEnemyMon2 - wEnemyMon1 call AddNTimes ld a, [hli] - ld [H_MULTIPLICAND + 1], a + ldh [hMultiplicand + 1], a ld a, [hl] - ld [H_MULTIPLICAND + 2], a + ldh [hMultiplicand + 2], a pop bc pop de ret @@ -4666,7 +4561,7 @@ CalculateDamage: ; d: base power ; e: level - ld a, [H_WHOSETURN] ; whose turn? + ldh a, [hWhoseTurn] ; whose turn? and a ld a, [wPlayerMoveEffect] jr z, .effect @@ -4698,7 +4593,7 @@ CalculateDamage: .skipbp xor a - ld hl, H_DIVIDEND + ld hl, hDividend ldi [hl], a ldi [hl], a ld [hl], a @@ -4747,76 +4642,82 @@ CalculateDamage: ld b, 4 call Divide +; Update wCurDamage. +; Capped at MAX_NEUTRAL_DAMAGE - MIN_NEUTRAL_DAMAGE: 999 - 2 = 997. ld hl, wDamage ld b, [hl] - ld a, [H_QUOTIENT + 3] + ldh a, [hQuotient + 3] add b - ld [H_QUOTIENT + 3], a - jr nc, .asm_3e142 + ldh [hQuotient + 3], a + jr nc, .dont_cap_1 - ld a, [H_QUOTIENT + 2] + ldh a, [hQuotient + 2] inc a - ld [H_QUOTIENT + 2], a + ldh [hQuotient + 2], a and a - jr z, .asm_3e176 + jr z, .cap -.asm_3e142 - ld a, [H_QUOTIENT] +.dont_cap_1 + ldh a, [hQuotient] ld b, a - ld a, [H_QUOTIENT + 1] + ldh a, [hQuotient + 1] or a - jr nz, .asm_3e176 - - ld a, [H_QUOTIENT + 2] - cp 998 / $100 - jr c, .asm_3e15a - cp 998 / $100 + 1 - jr nc, .asm_3e176 - ld a, [H_QUOTIENT + 3] - cp 998 % $100 - jr nc, .asm_3e176 - -.asm_3e15a + jr nz, .cap + + ldh a, [hQuotient + 2] + cp HIGH(MAX_NEUTRAL_DAMAGE - MIN_NEUTRAL_DAMAGE + 1) + jr c, .dont_cap_2 + + cp HIGH(MAX_NEUTRAL_DAMAGE - MIN_NEUTRAL_DAMAGE + 1) + 1 + jr nc, .cap + + ldh a, [hQuotient + 3] + cp LOW(MAX_NEUTRAL_DAMAGE - MIN_NEUTRAL_DAMAGE + 1) + jr nc, .cap + +.dont_cap_2 inc hl - ld a, [H_QUOTIENT + 3] + + ldh a, [hQuotient + 3] ld b, [hl] add b ld [hld], a - ld a, [H_QUOTIENT + 2] + ldh a, [hQuotient + 2] ld b, [hl] adc b ld [hl], a - jr c, .asm_3e176 + jr c, .cap ld a, [hl] - cp 998 / $100 - jr c, .asm_3e17c - cp 998 / $100 + 1 - jr nc, .asm_3e176 + cp HIGH(MAX_NEUTRAL_DAMAGE - MIN_NEUTRAL_DAMAGE + 1) + jr c, .dont_cap_3 + + cp HIGH(MAX_NEUTRAL_DAMAGE - MIN_NEUTRAL_DAMAGE + 1) + 1 + jr nc, .cap + inc hl ld a, [hld] - cp 998 % $100 - jr c, .asm_3e17c + cp LOW(MAX_NEUTRAL_DAMAGE - MIN_NEUTRAL_DAMAGE + 1) + jr c, .dont_cap_3 -.asm_3e176 -; cap at 997 - ld a, 997 / $100 +.cap + ld a, HIGH(MAX_NEUTRAL_DAMAGE - MIN_NEUTRAL_DAMAGE) ld [hli], a - ld a, 997 % $100 + ld a, LOW(MAX_NEUTRAL_DAMAGE - MIN_NEUTRAL_DAMAGE) ld [hld], a -.asm_3e17c -; add 2 +.dont_cap_3 +; Add back MIN_NEUTRAL_DAMAGE (capping at 999). inc hl ld a, [hl] - add 2 + add MIN_NEUTRAL_DAMAGE ld [hld], a - jr nc, .done + jr nc, .dont_floor inc [hl] +.dont_floor -.done -; minimum damage is 1 +; Returns nz and nc. ld a, 1 and a ret @@ -4827,13 +4728,7 @@ JumpToOHKOMoveEffect: dec a ret - -UnusedHighCriticalMoves: - db KARATE_CHOP - db RAZOR_LEAF - db CRABHAMMER - db SLASH - db $FF +INCLUDE "data/battle/unused_critical_hit_moves.asm" ; determines if attack is a critical hit ; azure heights claims "the fastest pokémon (who are, not coincidentally, @@ -4841,7 +4736,7 @@ UnusedHighCriticalMoves: CriticalHitTest: xor a ld [wCriticalHitOrOHKO], a - ld a, [H_WHOSETURN] + ldh a, [hWhoseTurn] and a ld a, [wEnemyMonSpecies] jr nz, .handleEnemy @@ -4852,7 +4747,7 @@ CriticalHitTest: ld a, [wMonHBaseSpeed] ld b, a srl b ; (effective (base speed/2)) - ld a, [H_WHOSETURN] + ldh a, [hWhoseTurn] and a ld hl, wPlayerMovePower ld de, wPlayerBattleStatus2 @@ -4904,14 +4799,7 @@ CriticalHitTest: ld [wCriticalHitOrOHKO], a ; set critical hit flag ret -; high critical hit moves -HighCriticalMoves: - db KARATE_CHOP - db RAZOR_LEAF - db CRABHAMMER - db SLASH - db $FF - +INCLUDE "data/battle/critical_hit_moves.asm" ; function to determine if Counter hits and if so, how much damage it does HandleCounterMove: @@ -4921,7 +4809,7 @@ HandleCounterMove: ; the outcome may be affected by the player's actions in the move selection menu prior to switching the Pokemon. ; This might also lead to desync glitches in link battles. - ld a, [H_WHOSETURN] ; whose turn + ldh a, [hWhoseTurn] ; whose turn and a ; player's turn ld hl, wEnemySelectedMove @@ -5091,7 +4979,7 @@ ApplyDamageToEnemyPokemon: ld [wHPBarNewHP+1], a ld a, [hl] ld [wHPBarNewHP], a - coord hl, 2, 2 + hlcoord 2, 2 xor a ld [wHPBarType], a predef UpdateHPBar2 ; animate the HP bar shortening @@ -5209,7 +5097,7 @@ ApplyDamageToPlayerPokemon: ld [wHPBarMaxHP+1], a ld a, [hl] ld [wHPBarMaxHP], a - coord hl, 10, 9 + hlcoord 10, 9 ld a, $01 ld [wHPBarType], a predef UpdateHPBar2 ; animate the HP bar shortening @@ -5229,7 +5117,7 @@ AttackSubstitute: ; values for player turn ld de, wEnemySubstituteHP ld bc, wEnemyBattleStatus2 - ld a, [H_WHOSETURN] + ldh a, [hWhoseTurn] and a jr z, .applyDamageToSubstitute ; values for enemy turn @@ -5254,14 +5142,14 @@ AttackSubstitute: ld hl, SubstituteBrokeText call PrintText ; flip whose turn it is for the next function call - ld a, [H_WHOSETURN] + ldh a, [hWhoseTurn] xor $01 - ld [H_WHOSETURN], a - callab Func_79929 ; animate the substitute breaking + ldh [hWhoseTurn], a + callfar Func_79929 ; animate the substitute breaking ; flip the turn back to the way it was - ld a, [H_WHOSETURN] + ldh a, [hWhoseTurn] xor $01 - ld [H_WHOSETURN], a + ldh [hWhoseTurn], a ld hl, wPlayerMoveEffect ; value for player's turn and a jr z, .nullifyEffect @@ -5272,12 +5160,12 @@ AttackSubstitute: jp DrawHUDsAndHPBars SubstituteTookDamageText: - TX_FAR _SubstituteTookDamageText - db "@" + text_far _SubstituteTookDamageText + text_end SubstituteBrokeText: - TX_FAR _SubstituteBrokeText - db "@" + text_far _SubstituteBrokeText + text_end ; this function raises the attack modifier of a pokemon using Rage when that pokemon is attacked HandleBuildingRage: @@ -5285,7 +5173,7 @@ HandleBuildingRage: ld hl, wEnemyBattleStatus2 ld de, wEnemyMonStatMods ld bc, wEnemyMoveNum - ld a, [H_WHOSETURN] + ldh a, [hWhoseTurn] and a jr z, .next ; values for the enemy turn @@ -5298,9 +5186,9 @@ HandleBuildingRage: ld a, [de] cp $0d ; maximum stat modifier value ret z ; return if attack modifier is already maxed - ld a, [H_WHOSETURN] + ldh a, [hWhoseTurn] xor $01 ; flip turn for the stat modifier raising function - ld [H_WHOSETURN], a + ldh [hWhoseTurn], a ; temporarily change the target pokemon's move to $00 and the effect to the one ; that causes the attack modifier to go up one stage ld h, b @@ -5317,25 +5205,25 @@ HandleBuildingRage: ldd [hl], a ; null move effect ld a, RAGE ld [hl], a ; restore the target pokemon's move number to Rage - ld a, [H_WHOSETURN] + ldh a, [hWhoseTurn] xor $01 ; flip turn back to the way it was - ld [H_WHOSETURN], a + ldh [hWhoseTurn], a ret BuildingRageText: - TX_FAR _BuildingRageText - db "@" + text_far _BuildingRageText + text_end ; copy last move for Mirror Move ; sets zero flag on failure and unsets zero flag on success MirrorMoveCopyMove: -; Mirror Move makes use of ccf1 (wPlayerUsedMove) and ccf2 (wEnemyUsedMove) addresses, +; Mirror Move makes use of wPlayerUsedMove and wEnemyUsedMove, ; which are mainly used to print the "[Pokemon] used [Move]" text. ; Both are set to 0 whenever a new Pokemon is sent out -; ccf1 is also set to 0 whenever the player is fast asleep or frozen solid. -; ccf2 is also set to 0 whenever the enemy is fast asleep or frozen solid. +; wPlayerUsedMove is also set to 0 whenever the player is fast asleep or frozen solid. +; wEnemyUsedMove is also set to 0 whenever the enemy is fast asleep or frozen solid. - ld a, [H_WHOSETURN] + ldh a, [hWhoseTurn] and a ; values for player turn ld a, [wEnemyUsedMove] @@ -5359,8 +5247,8 @@ MirrorMoveCopyMove: ret MirrorMoveFailedText: - TX_FAR _MirrorMoveFailedText - db "@" + text_far _MirrorMoveFailedText + text_end ; function used to reload move data for moves like Mirror Move and Metronome ReloadMoveData: @@ -5388,7 +5276,7 @@ MetronomePickMove: ; values for player turn ld de, wPlayerMoveNum ld hl, wPlayerSelectedMove - ld a, [H_WHOSETURN] + ldh a, [hWhoseTurn] and a jr z, .pickMoveLoop ; values for enemy turn @@ -5410,7 +5298,7 @@ MetronomePickMove: ; it's used to prevent moves that run another move within the same turn ; (like Mirror Move and Metronome) from losing 2 PP IncrementMovePP: - ld a, [H_WHOSETURN] + ldh a, [hWhoseTurn] and a ; values for player turn ld hl, wBattleMonPP @@ -5429,7 +5317,7 @@ IncrementMovePP: ld h, d ld l, e add hl, bc - ld a, [H_WHOSETURN] + ldh a, [hWhoseTurn] and a ld a, [wPlayerMonNumber] ; value for player turn jr z, .updatePP @@ -5453,7 +5341,7 @@ AdjustDamageForMoveType: ld e, [hl] ; e = type 2 of defender ld a, [wPlayerMoveType] ld [wMoveType], a - ld a, [H_WHOSETURN] + ldh a, [hWhoseTurn] and a jr z, .next ; values for enemy turn @@ -5517,25 +5405,25 @@ AdjustDamageForMoveType: and $80 ld b, a ld a, [hl] ; a = damage multiplier - ld [H_MULTIPLIER], a + ldh [hMultiplier], a add b ld [wDamageMultipliers], a xor a - ld [H_MULTIPLICAND], a + ldh [hMultiplicand], a ld hl, wDamage ld a, [hli] - ld [H_MULTIPLICAND + 1], a + ldh [hMultiplicand + 1], a ld a, [hld] - ld [H_MULTIPLICAND + 2], a + ldh [hMultiplicand + 2], a call Multiply ld a, 10 - ld [H_DIVISOR], a + ldh [hDivisor], a ld b, $04 call Divide - ld a, [H_QUOTIENT + 2] + ldh a, [hQuotient + 2] ld [hli], a ld b, a - ld a, [H_QUOTIENT + 3] + ldh a, [hQuotient + 3] ld [hl], a or b ; is damage 0? jr nz, .skipTypeImmunity @@ -5598,7 +5486,7 @@ AIGetTypeEffectiveness: ld [wd11e], a ; store damage multiplier ret -INCLUDE "data/type_effects.asm" +INCLUDE "data/types/type_matchups.asm" ; some tests that need to pass for a move to hit MoveHitTest: @@ -5606,7 +5494,7 @@ MoveHitTest: ld hl, wEnemyBattleStatus1 ld de, wPlayerMoveEffect ld bc, wEnemyMonStatus - ld a, [H_WHOSETURN] + ldh a, [hWhoseTurn] and a jr z, .dreamEaterCheck ; enemy's turn @@ -5626,8 +5514,8 @@ MoveHitTest: ret z ; Swift never misses (interestingly, Azure Heights lists this is a myth, but it appears to be true) call CheckTargetSubstitute ; substitute check (note that this overwrites a) jr z, .checkForDigOrFlyStatus -; this code is buggy. it's supposed to prevent HP draining moves from working on substitutes. -; since $7b79 overwrites a with either $00 or $01, it never works. +; This code is buggy. It's supposed to prevent HP draining moves from working on substitutes. +; Since CheckTargetSubstitute overwrites a with either $00 or $01, it never works. cp DRAIN_HP_EFFECT jp z, .moveMissed cp DREAM_EATER_EFFECT @@ -5635,7 +5523,7 @@ MoveHitTest: .checkForDigOrFlyStatus bit INVULNERABLE, [hl] jp nz, .moveMissed - ld a, [H_WHOSETURN] + ldh a, [hWhoseTurn] and a jr nz, .enemyTurn .playerTurn @@ -5689,7 +5577,7 @@ MoveHitTest: call CalcHitChance ; scale the move accuracy according to attacker's accuracy and target's evasion ld a, [wPlayerMoveAccuracy] ld b, a - ld a, [H_WHOSETURN] + ldh a, [hWhoseTurn] and a jr z, .doAccuracyCheck ld a, [wEnemyMoveAccuracy] @@ -5708,7 +5596,7 @@ MoveHitTest: ld [hl], a inc a ld [wMoveMissed], a - ld a, [H_WHOSETURN] + ldh a, [hWhoseTurn] and a jr z, .playerTurn2 .enemyTurn2 @@ -5723,7 +5611,7 @@ MoveHitTest: ; values for player turn CalcHitChance: ld hl, wPlayerMoveAccuracy - ld a, [H_WHOSETURN] + ldh a, [hWhoseTurn] and a ld a, [wPlayerMonAccuracyMod] ld b, a @@ -5743,10 +5631,10 @@ CalcHitChance: ; decreases the hit chance instead of increasing the hit chance) ; zero the high bytes of the multiplicand xor a - ld [H_MULTIPLICAND], a - ld [H_MULTIPLICAND + 1], a + ldh [hMultiplicand], a + ldh [hMultiplicand + 1], a ld a, [hl] - ld [H_MULTIPLICAND + 2], a ; set multiplicand to move accuracy + ldh [hMultiplicand + 2], a ; set multiplicand to move accuracy push hl ld d, $02 ; loop has two iterations ; loop to do the calculations, the first iteration multiplies by the accuracy ratio and @@ -5761,29 +5649,29 @@ CalcHitChance: add hl, bc ; hl = address of stat modifier ratio pop bc ld a, [hli] - ld [H_MULTIPLIER], a ; set multiplier to the numerator of the ratio + ldh [hMultiplier], a ; set multiplier to the numerator of the ratio call Multiply ld a, [hl] - ld [H_DIVISOR], a ; set divisor to the the denominator of the ratio + ldh [hDivisor], a ; set divisor to the the denominator of the ratio ; (the dividend is the product of the previous multiplication) ld b, $04 ; number of bytes in the dividend call Divide - ld a, [H_QUOTIENT + 3] + ldh a, [hQuotient + 3] ld b, a - ld a, [H_QUOTIENT + 2] + ldh a, [hQuotient + 2] or b jp nz, .nextCalculation ; make sure the result is always at least one - ld [H_QUOTIENT + 2], a + ldh [hQuotient + 2], a ld a, $01 - ld [H_QUOTIENT + 3], a + ldh [hQuotient + 3], a .nextCalculation ld b, c dec d jr nz, .loop - ld a, [H_QUOTIENT + 2] + ldh a, [hQuotient + 2] and a ; is the calculated hit chance over 0xFF? - ld a, [H_QUOTIENT + 3] + ldh a, [hQuotient + 3] jr z, .storeAccuracy ; if calculated hit chance over 0xFF ld a, $ff ; set the hit chance to 0xFF @@ -5803,29 +5691,29 @@ RandomizeDamage: ret c ; return if damage is equal to 0 or 1 .DamageGreaterThanOne xor a - ld [H_MULTIPLICAND], a + ldh [hMultiplicand], a dec hl ld a, [hli] - ld [H_MULTIPLICAND + 1], a + ldh [hMultiplicand + 1], a ld a, [hl] - ld [H_MULTIPLICAND + 2], a + ldh [hMultiplicand + 2], a ; loop until a random number greater than or equal to 217 is generated .loop call BattleRandom rrca cp 217 jr c, .loop - ld [H_MULTIPLIER], a + ldh [hMultiplier], a call Multiply ; multiply damage by the random number, which is in the range [217, 255] ld a, 255 - ld [H_DIVISOR], a + ldh [hDivisor], a ld b, $4 call Divide ; divide the result by 255 ; store the modified damage - ld a, [H_QUOTIENT + 2] + ldh a, [hQuotient + 2] ld hl, wDamage ld [hli], a - ld a, [H_QUOTIENT + 3] + ldh a, [hQuotient + 3] ld [hl], a ret @@ -6001,7 +5889,7 @@ EnemyCheckIfMirrorMoveEffect: .moveDidNotMiss call ApplyAttackToPlayerPokemon call PrintCriticalOHKOText - callab DisplayEffectiveness + callfar DisplayEffectiveness ld a, 1 ld [wMoveDidntMiss], a .handleExplosionMiss @@ -6040,8 +5928,8 @@ EnemyCheckIfMirrorMoveEffect: jr ExecuteEnemyMoveDone HitXTimesText: - TX_FAR _HitXTimesText - db "@" + text_far _HitXTimesText + text_end ExecuteEnemyMoveDone: ld b, $1 @@ -6181,11 +6069,11 @@ CheckEnemyStatusConditions: ld [hl], a xor a ld [wAnimationType], a - ld [H_WHOSETURN], a + ldh [hWhoseTurn], a ld a, POUND call PlayMoveAnimation ld a, $1 - ld [H_WHOSETURN], a + ldh [hWhoseTurn], a call ApplyDamageToEnemyPokemon jr .monHurtItselfOrFullyParalysed .checkIfTriedToUseDisabledMove @@ -6332,7 +6220,7 @@ CheckEnemyStatusConditions: ret GetCurrentMove: - ld a, [H_WHOSETURN] + ldh a, [hWhoseTurn] and a jp z, .player ld de, wEnemyMoveNum @@ -6379,8 +6267,8 @@ LoadEnemyMonData: ld a, [wIsInBattle] cp $2 ; is it a trainer battle? ; fixed DVs for trainer mon - ld a, $98 - ld b, $88 + ld a, ATKDEFDV_TRAINER + ld b, SPDSPCDV_TRAINER jr z, .storeDVs ; random DVs for wild mon call BattleRandom @@ -6529,25 +6417,25 @@ DoBattleTransitionAndInitBattleVariables: ; link battle xor a ld [wMenuJoypadPollCount], a - callab DisplayLinkBattleVersusTextBox + callfar DisplayLinkBattleVersusTextBox ld a, $1 ld [wUpdateSpritesEnabled], a call ClearScreen .next call DelayFrame predef BattleTransition - callab LoadHudAndHpBarAndStatusTilePatterns + callfar LoadHudAndHpBarAndStatusTilePatterns ld a, $1 - ld [H_AUTOBGTRANSFERENABLED], a + ldh [hAutoBGTransferEnabled], a ld a, $ff ld [wUpdateSpritesEnabled], a call ClearSprites call ClearScreen xor a - ld [H_AUTOBGTRANSFERENABLED], a - ld [hWY], a - ld [rWY], a - ld [hTilesetType], a + ldh [hAutoBGTransferEnabled], a + ldh [hWY], a + ldh [rWY], a + ldh [hTilesetType], a ld hl, wPlayerStatsToDouble ld [hli], a ld [hli], a @@ -6587,7 +6475,7 @@ LoadPlayerBackPic: predef ScaleSpriteByTwo ld hl, wOAMBuffer xor a - ld [hOAMTile], a ; initial tile number + ldh [hOAMTile], a ; initial tile number ld b, $7 ; 7 columns ld e, $a0 ; X for the left-most column .loop ; each loop iteration writes 3 OAM entries in a vertical column @@ -6601,18 +6489,18 @@ LoadPlayerBackPic: add d ; increase Y by height of tile ld d, a inc hl - ld a, [hOAMTile] + ldh a, [hOAMTile] ld [hli], a ; OAM tile number inc a ; increment tile number - ld [hOAMTile], a + ldh [hOAMTile], a ld a, $2 ld [hl], a inc hl dec c jr nz, .innerLoop - ld a, [hOAMTile] + ldh a, [hOAMTile] add $4 ; increase tile number by 4 - ld [hOAMTile], a + ldh [hOAMTile], a ld a, $8 ; width of tile add e ; increase X by width of tile ld e, a @@ -6624,23 +6512,23 @@ LoadPlayerBackPic: call SwitchSRAMBankAndLatchClockData ld hl, vSprites ld de, sSpriteBuffer1 - ld a, [H_LOADEDROMBANK] + ldh a, [hLoadedROMBank] ld b, a ld c, 7 * 7 call CopyVideoData call PrepareRTCDataAndDisableSRAM ld a, $31 - ld [hStartTileID], a - coord hl, 1, 5 + ldh [hStartTileID], a + hlcoord 1, 5 predef_jump CopyUncompressedPicToTilemap ; does nothing since no stats are ever selected (barring glitches) DoubleOrHalveSelectedStats: - callab DoubleSelectedStats - jpab HalveSelectedStats + callfar DoubleSelectedStats + jpfar HalveSelectedStats ScrollTrainerPicAfterBattle: - jpab _ScrollTrainerPicAfterBattle + jpfar _ScrollTrainerPicAfterBattle ApplyBurnAndParalysisPenaltiesToPlayer: ld a, $1 @@ -6650,12 +6538,12 @@ ApplyBurnAndParalysisPenaltiesToEnemy: xor a ApplyBurnAndParalysisPenalties: - ld [H_WHOSETURN], a + ldh [hWhoseTurn], a call QuarterSpeedDueToParalysis jp HalveAttackDueToBurn QuarterSpeedDueToParalysis: - ld a, [H_WHOSETURN] + ldh a, [hWhoseTurn] and a jr z, .playerTurn .enemyTurn ; quarter the player's speed @@ -6698,7 +6586,7 @@ QuarterSpeedDueToParalysis: ret HalveAttackDueToBurn: - ld a, [H_WHOSETURN] + ldh a, [hWhoseTurn] and a jr z, .playerTurn .enemyTurn ; halve the player's attack @@ -6788,35 +6676,35 @@ CalculateModifiedStat: ld b, 0 add hl, bc xor a - ld [H_MULTIPLICAND], a + ldh [hMultiplicand], a ld a, [de] - ld [H_MULTIPLICAND + 1], a + ldh [hMultiplicand + 1], a inc de ld a, [de] - ld [H_MULTIPLICAND + 2], a + ldh [hMultiplicand + 2], a ld a, [hli] - ld [H_MULTIPLIER], a + ldh [hMultiplier], a call Multiply ld a, [hl] - ld [H_DIVISOR], a + ldh [hDivisor], a ld b, $4 call Divide pop hl - ld a, [H_DIVIDEND + 3] - sub 999 % $100 - ld a, [H_DIVIDEND + 2] - sbc 999 / $100 + ldh a, [hDividend + 3] + sub LOW(MAX_STAT_VALUE) + ldh a, [hDividend + 2] + sbc HIGH(MAX_STAT_VALUE) jp c, .storeNewStatValue -; cap the stat at 999 - ld a, 999 / $100 - ld [H_DIVIDEND + 2], a - ld a, 999 % $100 - ld [H_DIVIDEND + 3], a +; cap the stat at MAX_STAT_VALUE (999) + ld a, HIGH(MAX_STAT_VALUE) + ldh [hDividend + 2], a + ld a, LOW(MAX_STAT_VALUE) + ldh [hDividend + 3], a .storeNewStatValue - ld a, [H_DIVIDEND + 2] + ldh a, [hDividend + 2] ld [hli], a ld b, a - ld a, [H_DIVIDEND + 3] + ldh a, [hDividend + 3] ld [hl], a or b jr nz, .done @@ -6850,7 +6738,7 @@ ApplyBadgeStatBoosts: ret ; multiply stat at hl by 1.125 -; cap stat at 999 +; cap stat at MAX_STAT_VALUE .applyBoostToStat ld a, [hli] ld d, a @@ -6868,13 +6756,13 @@ ApplyBadgeStatBoosts: adc d ld [hli], a ld a, [hld] - sub 999 % $100 + sub LOW(MAX_STAT_VALUE) ld a, [hl] - sbc 999 / $100 + sbc HIGH(MAX_STAT_VALUE) ret c - ld a, 999 / $100 + ld a, HIGH(MAX_STAT_VALUE) ld [hli], a - ld a, 999 % $100 + ld a, LOW(MAX_STAT_VALUE) ld [hld], a ret @@ -6882,33 +6770,34 @@ LoadHudAndHpBarAndStatusTilePatterns: call LoadHpBarAndStatusTilePatterns LoadHudTilePatterns: - ld a, [rLCDC] + ldh a, [rLCDC] add a ; is LCD disabled? jr c, .lcdEnabled .lcdDisabled ld hl, BattleHudTiles1 - ld de, vChars2 + $6d0 + ld de, vChars2 tile $6d ld bc, BattleHudTiles1End - BattleHudTiles1 ld a, BANK(BattleHudTiles1) call FarCopyDataDouble ld hl, BattleHudTiles2 - ld de, vChars2 + $730 + ld de, vChars2 tile $73 ld bc, BattleHudTiles3End - BattleHudTiles2 ld a, BANK(BattleHudTiles2) jp FarCopyDataDouble .lcdEnabled ld de, BattleHudTiles1 - ld hl, vChars2 + $6d0 + ld hl, vChars2 tile $6d lb bc, BANK(BattleHudTiles1), (BattleHudTiles1End - BattleHudTiles1) / $8 call CopyVideoDataDouble ld de, BattleHudTiles2 - ld hl, vChars2 + $730 + ld hl, vChars2 tile $73 lb bc, BANK(BattleHudTiles2), (BattleHudTiles3End - BattleHudTiles2) / $8 jp CopyVideoDataDouble PrintEmptyString: ld hl, .emptyString jp PrintText + .emptyString db "@" @@ -6966,7 +6855,7 @@ BattleRandom: HandleExplodingAnimation: - ld a, [H_WHOSETURN] + ldh a, [hWhoseTurn] and a ld hl, wEnemyMonType1 ld de, wEnemyBattleStatus1 @@ -7000,1662 +6889,5 @@ PlayMoveAnimation: ld [wAnimationID], a call Delay3 predef MoveAnimation - callab Func_78e98 - ret - -JumpMoveEffect: - call _JumpMoveEffect - ld b, $1 - ret - -_JumpMoveEffect: - ld a, [H_WHOSETURN] - and a - ld a, [wPlayerMoveEffect] - jr z, .next1 - ld a, [wEnemyMoveEffect] -.next1 - dec a ; subtract 1, there is no special effect for 00 - add a ; x2, 16bit pointers - ld hl, MoveEffectPointerTable - ld b, 0 - ld c, a - add hl, bc - ld a, [hli] - ld h, [hl] - ld l, a - jp hl ; jump to special effect handler - -MoveEffectPointerTable: - dw SleepEffect ; unused effect - dw PoisonEffect ; POISON_SIDE_EFFECT1 - dw DrainHPEffect ; DRAIN_HP_EFFECT - dw FreezeBurnParalyzeEffect ; BURN_SIDE_EFFECT1 - dw FreezeBurnParalyzeEffect ; FREEZE_SIDE_EFFECT - dw FreezeBurnParalyzeEffect ; PARALYZE_SIDE_EFFECT1 - dw ExplodeEffect ; EXPLODE_EFFECT - dw DrainHPEffect ; DREAM_EATER_EFFECT - dw $0000 ; MIRROR_MOVE_EFFECT - dw StatModifierUpEffect ; ATTACK_UP1_EFFECT - dw StatModifierUpEffect ; DEFENSE_UP1_EFFECT - dw StatModifierUpEffect ; SPEED_UP1_EFFECT - dw StatModifierUpEffect ; SPECIAL_UP1_EFFECT - dw StatModifierUpEffect ; ACCURACY_UP1_EFFECT - dw StatModifierUpEffect ; EVASION_UP1_EFFECT - dw PayDayEffect ; PAY_DAY_EFFECT - dw $0000 ; SWIFT_EFFECT - dw StatModifierDownEffect ; ATTACK_DOWN1_EFFECT - dw StatModifierDownEffect ; DEFENSE_DOWN1_EFFECT - dw StatModifierDownEffect ; SPEED_DOWN1_EFFECT - dw StatModifierDownEffect ; SPECIAL_DOWN1_EFFECT - dw StatModifierDownEffect ; ACCURACY_DOWN1_EFFECT - dw StatModifierDownEffect ; EVASION_DOWN1_EFFECT - dw ConversionEffect ; CONVERSION_EFFECT - dw HazeEffect ; HAZE_EFFECT - dw BideEffect ; BIDE_EFFECT - dw ThrashPetalDanceEffect ; THRASH_PETAL_DANCE_EFFECT - dw SwitchAndTeleportEffect ; SWITCH_AND_TELEPORT_EFFECT - dw TwoToFiveAttacksEffect ; TWO_TO_FIVE_ATTACKS_EFFECT - dw TwoToFiveAttacksEffect ; unused effect - dw FlinchSideEffect ; FLINCH_SIDE_EFFECT1 - dw SleepEffect ; SLEEP_EFFECT - dw PoisonEffect ; POISON_SIDE_EFFECT2 - dw FreezeBurnParalyzeEffect ; BURN_SIDE_EFFECT2 - dw FreezeBurnParalyzeEffect ; unused effect - dw FreezeBurnParalyzeEffect ; PARALYZE_SIDE_EFFECT2 - dw FlinchSideEffect ; FLINCH_SIDE_EFFECT2 - dw OneHitKOEffect ; OHKO_EFFECT - dw ChargeEffect ; CHARGE_EFFECT - dw $0000 ; SUPER_FANG_EFFECT - dw $0000 ; SPECIAL_DAMAGE_EFFECT - dw TrappingEffect ; TRAPPING_EFFECT - dw ChargeEffect ; FLY_EFFECT - dw TwoToFiveAttacksEffect ; ATTACK_TWICE_EFFECT - dw $0000 ; JUMP_KICK_EFFECT - dw MistEffect ; MIST_EFFECT - dw FocusEnergyEffect ; FOCUS_ENERGY_EFFECT - dw RecoilEffect ; RECOIL_EFFECT - dw ConfusionEffect ; CONFUSION_EFFECT - dw StatModifierUpEffect ; ATTACK_UP2_EFFECT - dw StatModifierUpEffect ; DEFENSE_UP2_EFFECT - dw StatModifierUpEffect ; SPEED_UP2_EFFECT - dw StatModifierUpEffect ; SPECIAL_UP2_EFFECT - dw StatModifierUpEffect ; ACCURACY_UP2_EFFECT - dw StatModifierUpEffect ; EVASION_UP2_EFFECT - dw HealEffect ; HEAL_EFFECT - dw TransformEffect ; TRANSFORM_EFFECT - dw StatModifierDownEffect ; ATTACK_DOWN2_EFFECT - dw StatModifierDownEffect ; DEFENSE_DOWN2_EFFECT - dw StatModifierDownEffect ; SPEED_DOWN2_EFFECT - dw StatModifierDownEffect ; SPECIAL_DOWN2_EFFECT - dw StatModifierDownEffect ; ACCURACY_DOWN2_EFFECT - dw StatModifierDownEffect ; EVASION_DOWN2_EFFECT - dw ReflectLightScreenEffect ; LIGHT_SCREEN_EFFECT - dw ReflectLightScreenEffect ; REFLECT_EFFECT - dw PoisonEffect ; POISON_EFFECT - dw ParalyzeEffect ; PARALYZE_EFFECT - dw StatModifierDownEffect ; ATTACK_DOWN_SIDE_EFFECT - dw StatModifierDownEffect ; DEFENSE_DOWN_SIDE_EFFECT - dw StatModifierDownEffect ; SPEED_DOWN_SIDE_EFFECT - dw StatModifierDownEffect ; SPECIAL_DOWN_SIDE_EFFECT - dw StatModifierDownEffect ; unused effect - dw StatModifierDownEffect ; unused effect - dw StatModifierDownEffect ; unused effect - dw StatModifierDownEffect ; unused effect - dw ConfusionSideEffect ; CONFUSION_SIDE_EFFECT - dw TwoToFiveAttacksEffect ; TWINEEDLE_EFFECT - dw $0000 ; unused effect - dw SubstituteEffect ; SUBSTITUTE_EFFECT - dw HyperBeamEffect ; HYPER_BEAM_EFFECT - dw RageEffect ; RAGE_EFFECT - dw MimicEffect ; MIMIC_EFFECT - dw $0000 ; METRONOME_EFFECT - dw LeechSeedEffect ; LEECH_SEED_EFFECT - dw SplashEffect ; SPLASH_EFFECT - dw DisableEffect ; DISABLE_EFFECT - -SleepEffect: - ld de, wEnemyMonStatus - ld bc, wEnemyBattleStatus2 - ld a, [H_WHOSETURN] - and a - jp z, .sleepEffect - ld de, wBattleMonStatus - ld bc, wPlayerBattleStatus2 - -.sleepEffect - ld a, [bc] - bit NEEDS_TO_RECHARGE, a ; does the target need to recharge? (hyper beam) - res NEEDS_TO_RECHARGE, a ; target no longer needs to recharge - ld [bc], a - jr nz, .setSleepCounter ; if the target had to recharge, all hit tests will be skipped - ; including the event where the target already has another status - ld a, [de] - ld b, a - and $7 - jr z, .notAlreadySleeping ; can't affect a mon that is already asleep - ld hl, AlreadyAsleepText - jp PrintText -.notAlreadySleeping - ld a, b - and a - jr nz, .didntAffect ; can't affect a mon that is already statused - push de - call MoveHitTest ; apply accuracy tests - pop de - ld a, [wMoveMissed] - and a - jr nz, .didntAffect -.setSleepCounter -; set target's sleep counter to a random number between 1 and 7 - call BattleRandom - and $7 - jr z, .setSleepCounter - ld b, a - ld a, [wUnknownSerialFlag_d499] - and a - jr z, .asm_3f1ba ; XXX stadium stuff? - ld a, b - and $3 - jr z, .setSleepCounter - ld b, a -.asm_3f1ba - ld a, b - ld [de], a - call PlayCurrentMoveAnimation2 - ld hl, FellAsleepText - jp PrintText -.didntAffect - jp PrintDidntAffectText - -FellAsleepText: - TX_FAR _FellAsleepText - db "@" - -AlreadyAsleepText: - TX_FAR _AlreadyAsleepText - db "@" - -PoisonEffect: - ld hl, wEnemyMonStatus - ld de, wPlayerMoveEffect - ld a, [H_WHOSETURN] - and a - jr z, .poisonEffect - ld hl, wBattleMonStatus - ld de, wEnemyMoveEffect -.poisonEffect - call CheckTargetSubstitute - jr nz, .noEffect ; can't poison a substitute target - ld a, [hli] - ld b, a - and a - jr nz, .noEffect ; miss if target is already statused - ld a, [hli] - cp POISON ; can't poison a poison-type target - jr z, .noEffect - ld a, [hld] - cp POISON ; can't poison a poison-type target - jr z, .noEffect - ld a, [de] - cp POISON_SIDE_EFFECT1 - ld b, $34 ; ~20% chance of poisoning - jr z, .sideEffectTest - cp POISON_SIDE_EFFECT2 - ld b, $67 ; ~40% chance of poisoning - jr z, .sideEffectTest - push hl - push de - call MoveHitTest ; apply accuracy tests - pop de - pop hl - ld a, [wMoveMissed] - and a - jr nz, .didntAffect - jr .inflictPoison -.sideEffectTest - call BattleRandom - cp b ; was side effect successful? - ret nc -.inflictPoison - dec hl - set 3, [hl] ; mon is now poisoned - push de - dec de - ld a, [H_WHOSETURN] - and a - ld b, ANIM_C7 - ld hl, wPlayerBattleStatus3 - ld a, [de] - ld de, wPlayerToxicCounter - jr nz, .ok - ld b, ANIM_A9 - ld hl, wEnemyBattleStatus3 - ld de, wEnemyToxicCounter -.ok - cp TOXIC - jr nz, .normalPoison ; done if move is not Toxic - set BADLY_POISONED, [hl] ; else set Toxic battstatus - xor a - ld [de], a - ld hl, BadlyPoisonedText - jr .continue -.normalPoison - ld hl, PoisonedText -.continue - pop de - ld a, [de] - cp POISON_EFFECT - jr z, .regularPoisonEffect - ld a, b - call PlayBattleAnimation2 - jp PrintText -.regularPoisonEffect - call PlayCurrentMoveAnimation2 - jp PrintText -.noEffect - ld a, [de] - cp POISON_EFFECT - ret nz -.didntAffect - ld c, 50 - call DelayFrames - jp PrintDidntAffectText - -PoisonedText: - TX_FAR _PoisonedText - db "@" - -BadlyPoisonedText: - TX_FAR _BadlyPoisonedText - db "@" - -DrainHPEffect: - jpab DrainHPEffect_ - -ExplodeEffect: - ld hl, wBattleMonHP - ld de, wPlayerBattleStatus2 - ld a, [H_WHOSETURN] - and a - jr z, .faintUser - ld hl, wEnemyMonHP - ld de, wEnemyBattleStatus2 -.faintUser - xor a - ld [hli], a ; set the mon's HP to 0 - ld [hli], a - inc hl - ld [hl], a ; set mon's status to 0 - ld a, [de] - res SEEDED, a ; clear mon's leech seed status - ld [de], a - ret - -FreezeBurnParalyzeEffect: - xor a - ld [wAnimationType], a - call CheckTargetSubstitute ; test bit 4 of d063/d068 flags [target has substitute flag] - ret nz ; return if they have a substitute, can't effect them - ld a, [H_WHOSETURN] - and a - jp nz, .opponentAttacker - ld a, [wEnemyMonStatus] - and a - jp nz, CheckDefrost ; can't inflict status if opponent is already statused - ld a, [wPlayerMoveType] - ld b, a - ld a, [wEnemyMonType1] - cp b ; do target type 1 and move type match? - ret z ; return if they match (an ice move can't freeze an ice-type, body slam can't paralyze a normal-type, etc.) - ld a, [wEnemyMonType2] - cp b ; do target type 2 and move type match? - ret z ; return if they match - ld a, [wPlayerMoveEffect] - cp UNUSED_EFFECT_23 ; more stadium stuff - jr nz, .asm_3f2c7 - ld a, [wUnknownSerialFlag_d499] - and a - ld a, FREEZE_SIDE_EFFECT - ld b, $4d ; else use 0x4D/0x100 or 77/256 = 30.1%~ chance - jr z, .next1 - ld b, $1a ; 0x1A/0x100 or 26/256 = 10.2%~ chance - jr .next1 -.asm_3f2c7 - cp a, PARALYZE_SIDE_EFFECT1 + 1 ; 10% status effects are 04, 05, 06 so 07 will set carry for those - ld b, $1a ; 0x1A/0x100 or 26/256 = 10.2%~ chance - jr c, .next1 ; branch ahead if this is a 10% chance effect.. - ld b, $4d ; else use 0x4D/0x100 or 77/256 = 30.1%~ chance - sub $1e ; subtract $1E to map to equivalent 10% chance effects -.next1 - push af - call BattleRandom ; get random 8bit value for probability test - cp b - pop bc - ret nc ; do nothing if random value is >= 1A or 4D [no status applied] - ld a, b ; what type of effect is this? - cp BURN_SIDE_EFFECT1 - jr z, .burn1 - cp FREEZE_SIDE_EFFECT - jr z, .freeze1 -; .paralyze - ld a, 1 << PAR - ld [wEnemyMonStatus], a - call QuarterSpeedDueToParalysis ; quarter speed of affected mon - ld a, ANIM_A9 - call PlayBattleAnimation - jp PrintMayNotAttackText ; print paralysis text -.burn1 - ld a, 1 << BRN - ld [wEnemyMonStatus], a - call HalveAttackDueToBurn ; halve attack of affected mon - ld a, ANIM_A9 - call PlayBattleAnimation - ld hl, BurnedText - jp PrintText -.freeze1 - call ClearHyperBeam ; resets hyper beam (recharge) condition from target - ld a, 1 << FRZ - ld [wEnemyMonStatus], a - ld a, ANIM_A9 - call PlayBattleAnimation - ld hl, FrozenText - jp PrintText -.opponentAttacker - ld a, [wBattleMonStatus] ; mostly same as above with addresses swapped for opponent - and a - jp nz, CheckDefrost - ld a, [wEnemyMoveType] - ld b, a - ld a, [wBattleMonType1] - cp b - ret z - ld a, [wBattleMonType2] - cp b - ret z - ld a, [wEnemyMoveEffect] - cp UNUSED_EFFECT_23 ; more stadium stuff - jr nz, .asm_3f341 - ld a, [wUnknownSerialFlag_d499] - and a - ld a, FREEZE_SIDE_EFFECT - ld b, $4d ; else use 0x4D/0x100 or 77/256 = 30.1%~ chance - jr z, .next2 - ld b, $1a ; 0x1A/0x100 or 26/256 = 10.2%~ chance - jr .next2 -.asm_3f341 - cp a, PARALYZE_SIDE_EFFECT1 + 1 - ld b, $1a - jr c, .next2 - ld b, $4d - sub $1e -.next2 - push af - call BattleRandom - cp b - pop bc - ret nc - ld a, b - cp BURN_SIDE_EFFECT1 - jr z, .burn2 - cp FREEZE_SIDE_EFFECT - jr z, .freeze2 - ld a, 1 << PAR - ld [wBattleMonStatus], a - call QuarterSpeedDueToParalysis - ld a, ANIM_C7 - call PlayBattleAnimation2 - jp PrintMayNotAttackText -.burn2 - ld a, 1 << BRN - ld [wBattleMonStatus], a - call HalveAttackDueToBurn - ld a, ANIM_C7 - call PlayBattleAnimation2 - ld hl, BurnedText - jp PrintText -.freeze2 -; hyper beam bits aren't reseted for opponent's side - ld a, 1 << FRZ - ld [wBattleMonStatus], a - ld a, ANIM_C7 - call PlayBattleAnimation2 - ld hl, FrozenText - jp PrintText - -BurnedText: - TX_FAR _BurnedText - db "@" - -FrozenText: - TX_FAR _FrozenText - db "@" - -CheckDefrost: -; any fire-type move that has a chance inflict burn (all but Fire Spin) will defrost a frozen target - and 1 << FRZ ; are they frozen? - ret z ; return if so - ld a, [H_WHOSETURN] - and a - jr nz, .opponent - ;player [attacker] - ld a, [wPlayerMoveType] - sub FIRE - ret nz ; return if type of move used isn't fire - ld [wEnemyMonStatus], a ; set opponent status to 00 ["defrost" a frozen monster] - ld hl, wEnemyMon1Status - ld a, [wEnemyMonPartyPos] - ld bc, wEnemyMon2 - wEnemyMon1 - call AddNTimes - xor a - ld [hl], a ; clear status in roster - ld hl, FireDefrostedText - jr .common -.opponent - ld a, [wEnemyMoveType] ; same as above with addresses swapped - sub FIRE - ret nz - ld [wBattleMonStatus], a - ld hl, wPartyMon1Status - ld a, [wPlayerMonNumber] - ld bc, wPartyMon2 - wPartyMon1 - call AddNTimes - xor a - ld [hl], a - ld hl, FireDefrostedText -.common - jp PrintText - -FireDefrostedText: - TX_FAR _FireDefrostedText - db "@" - -StatModifierUpEffect: - ld hl, wPlayerMonStatMods - ld de, wPlayerMoveEffect - ld a, [H_WHOSETURN] - and a - jr z, .statModifierUpEffect - ld hl, wEnemyMonStatMods - ld de, wEnemyMoveEffect -.statModifierUpEffect - ld a, [de] - sub ATTACK_UP1_EFFECT - cp EVASION_UP1_EFFECT + $3 - ATTACK_UP1_EFFECT ; covers all +1 effects - jr c, .incrementStatMod - sub ATTACK_UP2_EFFECT - ATTACK_UP1_EFFECT ; map +2 effects to equivalent +1 effect -.incrementStatMod - ld c, a - ld b, $0 - add hl, bc - ld b, [hl] - inc b ; increment corresponding stat mod - ld a, $d - cp b ; can't raise stat past +6 ($d or 13) - jp c, PrintNothingHappenedText - ld a, [de] - cp ATTACK_UP1_EFFECT + $8 ; is it a +2 effect? - jr c, .ok - inc b ; if so, increment stat mod again - ld a, $d - cp b ; unless it's already +6 - jr nc, .ok - ld b, a -.ok - ld [hl], b - ld a, c - cp $4 - jr nc, UpdateStatDone ; jump if mod affected is evasion/accuracy - push hl - ld hl, wBattleMonAttack + 1 - ld de, wPlayerMonUnmodifiedAttack - ld a, [H_WHOSETURN] - and a - jr z, .pointToStats - ld hl, wEnemyMonAttack + 1 - ld de, wEnemyMonUnmodifiedAttack -.pointToStats - push bc - sla c - ld b, $0 - add hl, bc ; hl = modified stat - ld a, c - add e - ld e, a - jr nc, .checkIf999 - inc d ; de = unmodified (original) stat -.checkIf999 - pop bc - ld a, [hld] - sub 999 % $100 ; check if stat is already 999 - jr nz, .recalculateStat - ld a, [hl] - sbc 999 / $100 - jp z, RestoreOriginalStatModifier -.recalculateStat ; recalculate affected stat - ; paralysis and burn penalties, as well as badge boosts are ignored - push hl - push bc - ld hl, StatModifierRatios - dec b - sla b - ld c, b - ld b, $0 - add hl, bc - pop bc - xor a - ld [H_MULTIPLICAND], a - ld a, [de] - ld [H_MULTIPLICAND + 1], a - inc de - ld a, [de] - ld [H_MULTIPLICAND + 2], a - ld a, [hli] - ld [H_MULTIPLIER], a - call Multiply - ld a, [hl] - ld [H_DIVISOR], a - ld b, $4 - call Divide - pop hl -; cap at 999 - ld a, [H_PRODUCT + 3] - sub 999 % $100 - ld a, [H_PRODUCT + 2] - sbc 999 / $100 - jp c, UpdateStat - ld a, 999 / $100 - ld [H_MULTIPLICAND + 1], a - ld a, 999 % $100 - ld [H_MULTIPLICAND + 2], a - -UpdateStat: - ld a, [H_PRODUCT + 2] - ld [hli], a - ld a, [H_PRODUCT + 3] - ld [hl], a - pop hl -UpdateStatDone: - ld b, c - inc b - call PrintStatText - ld hl, wPlayerBattleStatus2 - ld de, wPlayerMoveNum - ld bc, wPlayerMonMinimized - ld a, [H_WHOSETURN] - and a - jr z, .playerTurn - ld hl, wEnemyBattleStatus2 - ld de, wEnemyMoveNum - ld bc, wEnemyMonMinimized -.playerTurn - ld a, [de] - cp MINIMIZE - jr nz, .notMinimize - ; if a substitute is up, slide off the substitute and show the mon pic before - ; playing the minimize animation - bit HAS_SUBSTITUTE_UP, [hl] - push af - push bc - push de - ld hl, HideSubstituteShowMonAnim - ld b, BANK(HideSubstituteShowMonAnim) - call nz, Bankswitch - pop de -.notMinimize - call PlayCurrentMoveAnimation - ld a, [de] - cp MINIMIZE - jr nz, .applyBadgeBoostsAndStatusPenalties - pop bc - ld a, $1 - ld [bc], a - ld hl, ReshowSubstituteAnim - ld b, BANK(ReshowSubstituteAnim) - pop af - call nz, Bankswitch -.applyBadgeBoostsAndStatusPenalties - ld a, [H_WHOSETURN] - and a - call z, ApplyBadgeStatBoosts ; whenever the player uses a stat-up move, badge boosts get reapplied again to every stat, - ; even to those not affected by the stat-up move (will be boosted further) - ld hl, MonsStatsRoseText - call PrintText - -; these shouldn't be here - call QuarterSpeedDueToParalysis ; apply speed penalty to the player whose turn is not, if it's paralyzed - jp HalveAttackDueToBurn ; apply attack penalty to the player whose turn is not, if it's burned - -RestoreOriginalStatModifier: - pop hl - dec [hl] - -PrintNothingHappenedText: - ld hl, NothingHappenedText - jp PrintText - -MonsStatsRoseText: - TX_FAR _MonsStatsRoseText - TX_ASM - ld hl, GreatlyRoseText - ld a, [H_WHOSETURN] - and a - ld a, [wPlayerMoveEffect] - jr z, .playerTurn - ld a, [wEnemyMoveEffect] -.playerTurn - cp ATTACK_DOWN1_EFFECT - ret nc - ld hl, RoseText - ret - -GreatlyRoseText: - TX_DELAY - TX_FAR _GreatlyRoseText -; fallthrough -RoseText: - TX_FAR _RoseText - db "@" - -StatModifierDownEffect: - ld hl, wEnemyMonStatMods - ld de, wPlayerMoveEffect - ld bc, wEnemyBattleStatus1 - ld a, [H_WHOSETURN] - and a - jr z, .statModifierDownEffect - ld hl, wPlayerMonStatMods - ld de, wEnemyMoveEffect - ld bc, wPlayerBattleStatus1 - ld a, [wLinkState] - cp LINK_STATE_BATTLING - jr z, .statModifierDownEffect - call BattleRandom - cp $40 ; 1/4 chance to miss by in regular battle - jp c, MoveMissed -.statModifierDownEffect - call CheckTargetSubstitute ; can't hit through substitute - jp nz, MoveMissed - ld a, [de] - cp ATTACK_DOWN_SIDE_EFFECT - jr c, .nonSideEffect - call BattleRandom - cp $55 ; 85/256 chance for side effects - jp nc, CantLowerAnymore - ld a, [de] - sub ATTACK_DOWN_SIDE_EFFECT ; map each stat to 0-3 - jr .decrementStatMod -.nonSideEffect ; non-side effects only - push hl - push de - push bc - call MoveHitTest ; apply accuracy tests - pop bc - pop de - pop hl - ld a, [wMoveMissed] - and a - jp nz, MoveMissed - ld a, [bc] - bit INVULNERABLE, a ; fly/dig - jp nz, MoveMissed - ld a, [de] - sub ATTACK_DOWN1_EFFECT - cp EVASION_DOWN1_EFFECT + $3 - ATTACK_DOWN1_EFFECT ; covers all -1 effects - jr c, .decrementStatMod - sub ATTACK_DOWN2_EFFECT - ATTACK_DOWN1_EFFECT ; map -2 effects to corresponding -1 effect -.decrementStatMod - ld c, a - ld b, $0 - add hl, bc - ld b, [hl] - dec b ; dec corresponding stat mod - jp z, CantLowerAnymore ; if stat mod is 1 (-6), can't lower anymore - ld a, [de] - cp ATTACK_DOWN2_EFFECT - $16 ; $24 - jr c, .ok - cp EVASION_DOWN2_EFFECT + $5 ; $44 - jr nc, .ok - dec b ; stat down 2 effects only (dec mod again) - jr nz, .ok - inc b ; increment mod to 1 (-6) if it would become 0 (-7) -.ok - ld [hl], b ; save modified mod - ld a, c - cp $4 - jr nc, UpdateLoweredStatDone ; jump for evasion/accuracy - push hl - push de - ld hl, wEnemyMonAttack + 1 - ld de, wEnemyMonUnmodifiedAttack - ld a, [H_WHOSETURN] - and a - jr z, .pointToStat - ld hl, wBattleMonAttack + 1 - ld de, wPlayerMonUnmodifiedAttack -.pointToStat - push bc - sla c - ld b, $0 - add hl, bc ; hl = modified stat - ld a, c - add e - ld e, a - jr nc, .noCarry - inc d ; de = unmodified stat -.noCarry - pop bc - ld a, [hld] - sub $1 ; can't lower stat below 1 (-6) - jr nz, .recalculateStat - ld a, [hl] - and a - jp z, CantLowerAnymore_Pop -.recalculateStat -; recalculate affected stat -; paralysis and burn penalties, as well as badge boosts are ignored - push hl - push bc - ld hl, StatModifierRatios - dec b - sla b - ld c, b - ld b, $0 - add hl, bc - pop bc - xor a - ld [H_MULTIPLICAND], a - ld a, [de] - ld [H_MULTIPLICAND + 1], a - inc de - ld a, [de] - ld [H_MULTIPLICAND + 2], a - ld a, [hli] - ld [H_MULTIPLIER], a - call Multiply - ld a, [hl] - ld [H_DIVISOR], a - ld b, $4 - call Divide - pop hl - ld a, [H_PRODUCT + 3] - ld b, a - ld a, [H_PRODUCT + 2] - or b - jp nz, UpdateLoweredStat - ld [H_MULTIPLICAND + 1], a - ld a, $1 - ld [H_MULTIPLICAND + 2], a - -UpdateLoweredStat: - ld a, [H_PRODUCT + 2] - ld [hli], a - ld a, [H_PRODUCT + 3] - ld [hl], a - pop de - pop hl -UpdateLoweredStatDone: - ld b, c - inc b - push de - call PrintStatText - pop de - ld a, [de] - cp $44 - jr nc, .ApplyBadgeBoostsAndStatusPenalties - call PlayCurrentMoveAnimation2 -.ApplyBadgeBoostsAndStatusPenalties - ld a, [H_WHOSETURN] - and a - call nz, ApplyBadgeStatBoosts ; whenever the player uses a stat-down move, badge boosts get reapplied again to every stat, - ; even to those not affected by the stat-up move (will be boosted further) - ld hl, MonsStatsFellText - call PrintText - -; These where probably added given that a stat-down move affecting speed or attack will override -; the stat penalties from paralysis and burn respectively. -; But they are always called regardless of the stat affected by the stat-down move. - call QuarterSpeedDueToParalysis - jp HalveAttackDueToBurn - -CantLowerAnymore_Pop: - pop de - pop hl - inc [hl] - -CantLowerAnymore: - ld a, [de] - cp ATTACK_DOWN_SIDE_EFFECT - ret nc - ld hl, NothingHappenedText - jp PrintText - -MoveMissed: - ld a, [de] - cp $44 - ret nc - jp ConditionalPrintButItFailed - -MonsStatsFellText: - TX_FAR _MonsStatsFellText - TX_ASM - ld hl, FellText - ld a, [H_WHOSETURN] - and a - ld a, [wPlayerMoveEffect] - jr z, .playerTurn - ld a, [wEnemyMoveEffect] -.playerTurn -; check if the move's effect decreases a stat by 2 - cp BIDE_EFFECT - ret c - cp ATTACK_DOWN_SIDE_EFFECT - ret nc - ld hl, GreatlyFellText - ret - -GreatlyFellText: - TX_DELAY - TX_FAR _GreatlyFellText -; fallthrough -FellText: - TX_FAR _FellText - db "@" - -PrintStatText: - ld hl, StatsTextStrings - ld c, "@" -.findStatName_outer - dec b - jr z, .foundStatName -.findStatName_inner - ld a, [hli] - cp c - jr z, .findStatName_outer - jr .findStatName_inner -.foundStatName - ld de, wcf4b - ld bc, $a - jp CopyData - -StatsTextStrings: - db "ATTACK@" - db "DEFENSE@" - db "SPEED@" - db "SPECIAL@" - db "ACCURACY@" - db "EVADE@" - -StatModifierRatios: -; first byte is numerator, second byte is denominator - db 25, 100 ; 0.25 - db 28, 100 ; 0.28 - db 33, 100 ; 0.33 - db 40, 100 ; 0.40 - db 50, 100 ; 0.50 - db 66, 100 ; 0.66 - db 1, 1 ; 1.00 - db 15, 10 ; 1.50 - db 2, 1 ; 2.00 - db 25, 10 ; 2.50 - db 3, 1 ; 3.00 - db 35, 10 ; 3.50 - db 4, 1 ; 4.00 - -BideEffect: - ld hl, wPlayerBattleStatus1 - ld de, wPlayerBideAccumulatedDamage - ld bc, wPlayerNumAttacksLeft - ld a, [H_WHOSETURN] - and a - jr z, .bideEffect - ld hl, wEnemyBattleStatus1 - ld de, wEnemyBideAccumulatedDamage - ld bc, wEnemyNumAttacksLeft -.bideEffect - set STORING_ENERGY, [hl] ; mon is now using bide - xor a - ld [de], a - inc de - ld [de], a - ld [wPlayerMoveEffect], a - ld [wEnemyMoveEffect], a - call BattleRandom - and $1 - inc a - inc a - ld [bc], a ; set Bide counter to 2 or 3 at random - ld a, [H_WHOSETURN] - add XSTATITEM_ANIM - jp PlayBattleAnimation2 - -ThrashPetalDanceEffect: - ld hl, wPlayerBattleStatus1 - ld de, wPlayerNumAttacksLeft - ld a, [H_WHOSETURN] - and a - jr z, .thrashPetalDanceEffect - ld hl, wEnemyBattleStatus1 - ld de, wEnemyNumAttacksLeft -.thrashPetalDanceEffect - set THRASHING_ABOUT, [hl] ; mon is now using thrash/petal dance - call BattleRandom - and $1 - inc a - inc a - ld [de], a ; set thrash/petal dance counter to 2 or 3 at random - ld a, [H_WHOSETURN] - add ANIM_B0 - jp PlayBattleAnimation2 - -SwitchAndTeleportEffect: - ld a, [H_WHOSETURN] - and a - jr nz, .handleEnemy - ld a, [wIsInBattle] - dec a - jr nz, .notWildBattle1 - ld a, [wCurEnemyLVL] - ld b, a - ld a, [wBattleMonLevel] - cp b ; is the player's level greater than the enemy's level? - jr nc, .playerMoveWasSuccessful ; if so, teleport will always succeed - add b - ld c, a - inc c ; c = sum of player level and enemy level -.rejectionSampleLoop1 - call BattleRandom - cp c ; get a random number between 0 and c - jr nc, .rejectionSampleLoop1 - srl b - srl b ; b = enemyLevel / 4 - cp b ; is rand[0, playerLevel + enemyLevel) >= (enemyLevel / 4)? - jr nc, .playerMoveWasSuccessful ; if so, allow teleporting - ld c, 50 - call DelayFrames - ld a, [wPlayerMoveNum] - cp TELEPORT - jp nz, PrintDidntAffectText - jp PrintButItFailedText_ -.playerMoveWasSuccessful - call ReadPlayerMonCurHPAndStatus - xor a - ld [wAnimationType], a - inc a - ld [wEscapedFromBattle], a - ld a, [wPlayerMoveNum] - jr .playAnimAndPrintText -.notWildBattle1 - ld c, 50 - call DelayFrames - ld hl, IsUnaffectedText - ld a, [wPlayerMoveNum] - cp TELEPORT - jp nz, PrintText - jp PrintButItFailedText_ -.handleEnemy - ld a, [wIsInBattle] - dec a - jr nz, .notWildBattle2 - ld a, [wBattleMonLevel] - ld b, a - ld a, [wCurEnemyLVL] - cp b - jr nc, .enemyMoveWasSuccessful - add b - ld c, a - inc c -.rejectionSampleLoop2 - call BattleRandom - cp c - jr nc, .rejectionSampleLoop2 - srl b - srl b - cp b - jr nc, .enemyMoveWasSuccessful - ld c, 50 - call DelayFrames - ld a, [wEnemyMoveNum] - cp TELEPORT - jp nz, PrintDidntAffectText - jp PrintButItFailedText_ -.enemyMoveWasSuccessful - call ReadPlayerMonCurHPAndStatus - xor a - ld [wAnimationType], a - inc a - ld [wEscapedFromBattle], a - ld a, [wEnemyMoveNum] - jr .playAnimAndPrintText -.notWildBattle2 - ld c, 50 - call DelayFrames - ld hl, IsUnaffectedText - ld a, [wEnemyMoveNum] - cp TELEPORT - jp nz, PrintText - jp ConditionalPrintButItFailed -.playAnimAndPrintText - push af - call PlayBattleAnimation - ld c, 20 - call DelayFrames - pop af - ld hl, RanFromBattleText - cp TELEPORT - jr z, .printText - ld hl, RanAwayScaredText - cp ROAR - jr z, .printText - ld hl, WasBlownAwayText -.printText - jp PrintText - -RanFromBattleText: - TX_FAR _RanFromBattleText - db "@" - -RanAwayScaredText: - TX_FAR _RanAwayScaredText - db "@" - -WasBlownAwayText: - TX_FAR _WasBlownAwayText - db "@" - -TwoToFiveAttacksEffect: - ld hl, wPlayerBattleStatus1 - ld de, wPlayerNumAttacksLeft - ld bc, wPlayerNumHits - ld a, [H_WHOSETURN] - and a - jr z, .twoToFiveAttacksEffect - ld hl, wEnemyBattleStatus1 - ld de, wEnemyNumAttacksLeft - ld bc, wEnemyNumHits -.twoToFiveAttacksEffect - bit ATTACKING_MULTIPLE_TIMES, [hl] ; is mon attacking multiple times? - ret nz - set ATTACKING_MULTIPLE_TIMES, [hl] ; mon is now attacking multiple times - ld hl, wPlayerMoveEffect - ld a, [H_WHOSETURN] - and a - jr z, .setNumberOfHits - ld hl, wEnemyMoveEffect -.setNumberOfHits - ld a, [hl] - cp TWINEEDLE_EFFECT - jr z, .twineedle - cp ATTACK_TWICE_EFFECT - ld a, $2 ; number of hits it's always 2 for ATTACK_TWICE_EFFECT - jr z, .saveNumberOfHits -; for TWO_TO_FIVE_ATTACKS_EFFECT 3/8 chance for 2 and 3 hits, and 1/8 chance for 4 and 5 hits - call BattleRandom - and $3 - cp $2 - jr c, .gotNumHits -; if the number of hits was greater than 2, re-roll again for a lower chance - call BattleRandom - and $3 -.gotNumHits - inc a - inc a -.saveNumberOfHits - ld [de], a - ld [bc], a - ret -.twineedle - ld a, POISON_SIDE_EFFECT1 - ld [hl], a ; set Twineedle's effect to poison effect - jr .saveNumberOfHits - -FlinchSideEffect: - call CheckTargetSubstitute - ret nz - ld hl, wEnemyBattleStatus1 - ld de, wPlayerMoveEffect - ld a, [H_WHOSETURN] - and a - jr z, .flinchSideEffect - ld hl, wPlayerBattleStatus1 - ld de, wEnemyMoveEffect -.flinchSideEffect - ld a, [wLinkState] - cp LINK_STATE_BATTLING - call z, ClearHyperBeam - ld a, [de] - cp FLINCH_SIDE_EFFECT1 - ld b, $1a ; ~10% chance of flinch - jr z, .gotEffectChance - ld b, $4d ; ~30% chance of flinch -.gotEffectChance - call BattleRandom - cp b - ret nc - set FLINCHED, [hl] ; set mon's status to flinching - call ClearHyperBeam - ret - -OneHitKOEffect: - jpab OneHitKOEffect_ - -ChargeEffect: - ld hl, wPlayerBattleStatus1 - ld de, wPlayerMoveEffect - ld a, [H_WHOSETURN] - and a - ld b, XSTATITEM_ANIM - jr z, .chargeEffect - ld hl, wEnemyBattleStatus1 - ld de, wEnemyMoveEffect - ld b, ANIM_AF -.chargeEffect - set CHARGING_UP, [hl] - ld a, [de] - dec de ; de contains enemy or player MOVENUM - cp FLY_EFFECT - jr nz, .notFly - set INVULNERABLE, [hl] ; mon is now invulnerable to typical attacks (fly/dig) - ld b, TELEPORT ; load Teleport's animation -.notFly - ld a, [de] - cp DIG - jr nz, .notDigOrFly - set INVULNERABLE, [hl] ; mon is now invulnerable to typical attacks (fly/dig) - ld b, ANIM_C0 -.notDigOrFly - push de - push bc - inc hl ; battle status 2 - push hl - ld a, [hl] - bit HAS_SUBSTITUTE_UP, a - ld hl, HideSubstituteShowMonAnim - ld b, BANK(HideSubstituteShowMonAnim) - call nz, Bankswitch - pop hl - pop bc - xor a - ld [wAnimationType], a - ld a, b - call PlayBattleAnimation - ld a, [hl] - bit HAS_SUBSTITUTE_UP, a - ld hl, ReshowSubstituteAnim - ld b, BANK(ReshowSubstituteAnim) - call nz, Bankswitch - pop de - ld a, [de] - ld [wChargeMoveNum], a - ld hl, ChargeMoveEffectText - jp PrintText - -ChargeMoveEffectText: - TX_FAR _ChargeMoveEffectText - TX_ASM - ld a, [wChargeMoveNum] - cp RAZOR_WIND - ld hl, MadeWhirlwindText - jr z, .gotText - cp SOLARBEAM - ld hl, TookInSunlightText - jr z, .gotText - cp SKULL_BASH - ld hl, LoweredItsHeadText - jr z, .gotText - cp SKY_ATTACK - ld hl, SkyAttackGlowingText - jr z, .gotText - cp FLY - ld hl, FlewUpHighText - jr z, .gotText - cp DIG - ld hl, DugAHoleText -.gotText - ret - -MadeWhirlwindText: - TX_FAR _MadeWhirlwindText - db "@" - -TookInSunlightText: - TX_FAR _TookInSunlightText - db "@" - -LoweredItsHeadText: - TX_FAR _LoweredItsHeadText - db "@" - -SkyAttackGlowingText: - TX_FAR _SkyAttackGlowingText - db "@" - -FlewUpHighText: - TX_FAR _FlewUpHighText - db "@" - -DugAHoleText: - TX_FAR _DugAHoleText - db "@" - -TrappingEffect: - ld hl, wPlayerBattleStatus1 - ld de, wPlayerNumAttacksLeft - ld a, [H_WHOSETURN] - and a - jr z, .trappingEffect - ld hl, wEnemyBattleStatus1 - ld de, wEnemyNumAttacksLeft -.trappingEffect - bit USING_TRAPPING_MOVE, [hl] - ret nz - call ClearHyperBeam ; since this effect is called before testing whether the move will hit, - ; the target won't need to recharge even if the trapping move missed - set USING_TRAPPING_MOVE, [hl] ; mon is now using a trapping move - call BattleRandom ; 3/8 chance for 2 and 3 attacks, and 1/8 chance for 4 and 5 attacks - and $3 - cp $2 - jr c, .setTrappingCounter - call BattleRandom - and $3 -.setTrappingCounter - inc a - ld [de], a - ret - -MistEffect: - jpab MistEffect_ - -FocusEnergyEffect: - jpab FocusEnergyEffect_ - -RecoilEffect: - jpab RecoilEffect_ - -ConfusionSideEffect: - call BattleRandom - cp $19 ; ~10% chance - ret nc - jr ConfusionSideEffectSuccess - -ConfusionEffect: - call CheckTargetSubstitute - jr nz, ConfusionEffectFailed - call MoveHitTest - ld a, [wMoveMissed] - and a - jr nz, ConfusionEffectFailed - -ConfusionSideEffectSuccess: - ld a, [H_WHOSETURN] - and a - ld hl, wEnemyBattleStatus1 - ld bc, wEnemyConfusedCounter - ld a, [wPlayerMoveEffect] - jr z, .confuseTarget - ld hl, wPlayerBattleStatus1 - ld bc, wPlayerConfusedCounter - ld a, [wEnemyMoveEffect] -.confuseTarget - bit CONFUSED, [hl] ; is mon confused? - jr nz, ConfusionEffectFailed - set CONFUSED, [hl] ; mon is now confused - push af - call BattleRandom - and $3 - inc a - inc a - ld [bc], a ; confusion status will last 2-5 turns - pop af - cp CONFUSION_SIDE_EFFECT - call nz, PlayCurrentMoveAnimation2 - ld hl, BecameConfusedText - jp PrintText - -BecameConfusedText: - TX_FAR _BecameConfusedText - db "@" - -ConfusionEffectFailed: - cp CONFUSION_SIDE_EFFECT - ret z - ld c, 50 - call DelayFrames - jp ConditionalPrintButItFailed - -ParalyzeEffect: - jpab ParalyzeEffect_ - -SubstituteEffect: - jpab SubstituteEffect_ - -HyperBeamEffect: - ld hl, wPlayerBattleStatus2 - ld a, [H_WHOSETURN] - and a - jr z, .hyperBeamEffect - ld hl, wEnemyBattleStatus2 -.hyperBeamEffect - set NEEDS_TO_RECHARGE, [hl] ; mon now needs to recharge - ret - -ClearHyperBeam: - push hl - ld hl, wEnemyBattleStatus2 - ld a, [H_WHOSETURN] - and a - jr z, .playerTurn - ld hl, wPlayerBattleStatus2 -.playerTurn - res NEEDS_TO_RECHARGE, [hl] ; mon no longer needs to recharge - pop hl - ret - -RageEffect: - ld hl, wPlayerBattleStatus2 - ld a, [H_WHOSETURN] - and a - jr z, .player - ld hl, wEnemyBattleStatus2 -.player - set USING_RAGE, [hl] ; mon is now in "rage" mode - ret - -MimicEffect: - ld c, 50 - call DelayFrames - call MoveHitTest - ld a, [wMoveMissed] - and a - jr nz, .mimicMissed - ld a, [H_WHOSETURN] - and a - ld hl, wBattleMonMoves - ld a, [wPlayerBattleStatus1] - jr nz, .enemyTurn - ld a, [wLinkState] - cp LINK_STATE_BATTLING - jr nz, .letPlayerChooseMove - ld hl, wEnemyMonMoves - ld a, [wEnemyBattleStatus1] -.enemyTurn - bit INVULNERABLE, a - jr nz, .mimicMissed -.getRandomMove - push hl - call BattleRandom - and $3 - ld c, a - ld b, $0 - add hl, bc - ld a, [hl] - pop hl - and a - jr z, .getRandomMove - ld d, a - ld a, [H_WHOSETURN] - and a - ld hl, wBattleMonMoves - ld a, [wPlayerMoveListIndex] - jr z, .playerTurn - ld hl, wEnemyMonMoves - ld a, [wEnemyMoveListIndex] - jr .playerTurn -.letPlayerChooseMove - ld a, [wEnemyBattleStatus1] - bit INVULNERABLE, a - jr nz, .mimicMissed - ld a, [wCurrentMenuItem] - push af - ld a, $1 - ld [wMoveMenuType], a - call MoveSelectionMenu - call LoadScreenTilesFromBuffer1 - ld hl, wEnemyMonMoves - ld a, [wCurrentMenuItem] - ld c, a - ld b, $0 - add hl, bc - ld d, [hl] - pop af - ld hl, wBattleMonMoves -.playerTurn - ld c, a - ld b, $0 - add hl, bc - ld a, d - ld [hl], a - ld [wd11e], a - call GetMoveName - call PlayCurrentMoveAnimation - ld hl, MimicLearnedMoveText - jp PrintText -.mimicMissed - jp PrintButItFailedText_ - -MimicLearnedMoveText: - TX_FAR _MimicLearnedMoveText - db "@" - -LeechSeedEffect: - jpab LeechSeedEffect_ - -SplashEffect: - call PlayCurrentMoveAnimation - jp PrintNoEffectText - -DisableEffect: - call MoveHitTest - ld a, [wMoveMissed] - and a - jr nz, .moveMissed - ld de, wEnemyDisabledMove - ld hl, wEnemyMonMoves - ld a, [H_WHOSETURN] - and a - jr z, .disableEffect - ld de, wPlayerDisabledMove - ld hl, wBattleMonMoves -.disableEffect -; no effect if target already has a move disabled - ld a, [de] - and a - jr nz, .moveMissed -.pickMoveToDisable - push hl - call BattleRandom - and $3 - ld c, a - ld b, $0 - add hl, bc - ld a, [hl] - pop hl - and a - jr z, .pickMoveToDisable ; loop until a non-00 move slot is found - ld [wd11e], a ; store move number - push hl - ld a, [H_WHOSETURN] - and a - ld hl, wBattleMonPP - jr nz, .enemyTurn - ld a, [wLinkState] - cp LINK_STATE_BATTLING - pop hl ; wEnemyMonMoves - jr nz, .playerTurnNotLinkBattle -; .playerTurnLinkBattle - push hl - ld hl, wEnemyMonPP -.enemyTurn - push hl - ld a, [hli] - or [hl] - inc hl - or [hl] - inc hl - or [hl] - and $3f - pop hl ; wBattleMonPP or wEnemyMonPP - jr z, .moveMissedPopHL ; nothing to do if all moves have no PP left - add hl, bc - ld a, [hl] - pop hl - and a - jr z, .pickMoveToDisable ; pick another move if this one had 0 PP -.playerTurnNotLinkBattle -; non-link battle enemies have unlimited PP so the previous checks aren't needed - call BattleRandom - and $7 - inc a ; 1-8 turns disabled - inc c ; move 1-4 will be disabled - swap c - add c ; map disabled move to high nibble of wEnemyDisabledMove / wPlayerDisabledMove - ld [de], a - call PlayCurrentMoveAnimation2 - ld hl, wPlayerDisabledMoveNumber - ld a, [H_WHOSETURN] - and a - jr nz, .printDisableText - inc hl ; wEnemyDisabledMoveNumber -.printDisableText - ld a, [wd11e] ; move number - ld [hl], a - call GetMoveName - ld hl, MoveWasDisabledText - jp PrintText -.moveMissedPopHL - pop hl -.moveMissed - jp PrintButItFailedText_ - -MoveWasDisabledText: - TX_FAR _MoveWasDisabledText - db "@" - -PayDayEffect: - jpab PayDayEffect_ - -ConversionEffect: - jpab ConversionEffect_ - -HazeEffect: - jpab HazeEffect_ - -HealEffect: - jpab HealEffect_ - -TransformEffect: - jpab TransformEffect_ - -ReflectLightScreenEffect: - jpab ReflectLightScreenEffect_ - -NothingHappenedText: - TX_FAR _NothingHappenedText - db "@" - -PrintNoEffectText: - ld hl, NoEffectText - jp PrintText - -NoEffectText: - TX_FAR _NoEffectText - db "@" - -ConditionalPrintButItFailed: - ld a, [wMoveDidntMiss] - and a - ret nz ; return if the side effect failed, yet the attack was successful - -PrintButItFailedText_: - ld hl, ButItFailedText - jp PrintText - -ButItFailedText: - TX_FAR _ButItFailedText - db "@" - -PrintDidntAffectText: - ld hl, DidntAffectText - jp PrintText - -DidntAffectText: - TX_FAR _DidntAffectText - db "@" - -IsUnaffectedText: - TX_FAR _IsUnaffectedText - db "@" - -PrintMayNotAttackText: - ld hl, ParalyzedMayNotAttackText - jp PrintText - -ParalyzedMayNotAttackText: - TX_FAR _ParalyzedMayNotAttackText - db "@" - -CheckTargetSubstitute: - push hl - ld hl, wEnemyBattleStatus2 - ld a, [H_WHOSETURN] - and a - jr z, .next1 - ld hl, wPlayerBattleStatus2 -.next1 - bit HAS_SUBSTITUTE_UP, [hl] - pop hl - ret - -PlayCurrentMoveAnimation2: -; animation at MOVENUM will be played unless MOVENUM is 0 -; plays wAnimationType 3 or 6 - ld a, [H_WHOSETURN] - and a - ld a, [wPlayerMoveNum] - jr z, .notEnemyTurn - ld a, [wEnemyMoveNum] -.notEnemyTurn - and a - ret z - -PlayBattleAnimation2: -; play animation ID at a and animation type 6 or 3 - ld [wAnimationID], a - ld a, [H_WHOSETURN] - and a - ld a, $6 - jr z, .storeAnimationType - ld a, $3 -.storeAnimationType - ld [wAnimationType], a - jp PlayBattleAnimationGotID - -PlayCurrentMoveAnimation: -; animation at MOVENUM will be played unless MOVENUM is 0 -; resets wAnimationType - xor a - ld [wAnimationType], a - ld a, [H_WHOSETURN] - and a - ld a, [wPlayerMoveNum] - jr z, .notEnemyTurn - ld a, [wEnemyMoveNum] -.notEnemyTurn - and a - ret z - -PlayBattleAnimation: -; play animation ID at a and predefined animation type - ld [wAnimationID], a - -PlayBattleAnimationGotID: -; play animation at wAnimationID - push hl - push de - push bc - predef MoveAnimation - callab Func_78e98 - pop bc - pop de - pop hl + callfar Func_78e98 ret diff --git a/engine/battle/decrement_pp.asm b/engine/battle/decrement_pp.asm index b7c428f7..441bbb81 100644 --- a/engine/battle/decrement_pp.asm +++ b/engine/battle/decrement_pp.asm @@ -37,7 +37,7 @@ DecrementPP: ld a, [wPlayerMoveListIndex] ; which move (0, 1, 2, 3) did we use? ld c, a ld b, 0 - add hl ,bc ; calculate the address in memory of the PP we need to decrement + add hl, bc ; calculate the address in memory of the PP we need to decrement ; based on the move chosen. dec [hl] ; Decrement PP ret diff --git a/engine/battle/display_effectiveness.asm b/engine/battle/display_effectiveness.asm index 1bf14460..b23695cf 100644 --- a/engine/battle/display_effectiveness.asm +++ b/engine/battle/display_effectiveness.asm @@ -10,9 +10,9 @@ DisplayEffectiveness: jp PrintText SuperEffectiveText: - TX_FAR _SuperEffectiveText - db "@" + text_far _SuperEffectiveText + text_end NotVeryEffectiveText: - TX_FAR _NotVeryEffectiveText - db "@" + text_far _NotVeryEffectiveText + text_end diff --git a/engine/battle/draw_hud_pokeball_gfx.asm b/engine/battle/draw_hud_pokeball_gfx.asm index 96294774..6aed1d0a 100644 --- a/engine/battle/draw_hud_pokeball_gfx.asm +++ b/engine/battle/draw_hud_pokeball_gfx.asm @@ -12,7 +12,7 @@ DrawEnemyPokeballs: LoadPartyPokeballGfx: ld de, PokeballTileGraphics - ld hl, vSprites + $310 + ld hl, vSprites tile $31 lb bc, BANK(PokeballTileGraphics), (PokeballTileGraphicsEnd - PokeballTileGraphics) / $10 jp CopyVideoData @@ -125,7 +125,7 @@ PlacePlayerHUDTiles: ld de, wHUDGraphicsTiles ld bc, $3 call CopyData - coord hl, 18, 10 + hlcoord 18, 10 ld de, -1 jr PlaceHUDTiles @@ -140,7 +140,7 @@ PlaceEnemyHUDTiles: ld de, wHUDGraphicsTiles ld bc, $3 call CopyData - coord hl, 1, 2 + hlcoord 1, 2 ld de, $1 jr PlaceHUDTiles @@ -196,5 +196,5 @@ SetupPlayerAndEnemyPokeballs: ; four tiles: pokeball, black pokeball (status ailment), crossed out pokeball (fainted) and pokeball slot (no mon) PokeballTileGraphics:: - INCBIN "gfx/pokeball.2bpp" + INCBIN "gfx/battle/balls.2bpp" PokeballTileGraphicsEnd: diff --git a/engine/battle/effects.asm b/engine/battle/effects.asm new file mode 100644 index 00000000..c4e81816 --- /dev/null +++ b/engine/battle/effects.asm @@ -0,0 +1,1551 @@ +JumpMoveEffect: + call _JumpMoveEffect + ld b, $1 + ret + +_JumpMoveEffect: + ldh a, [hWhoseTurn] + and a + ld a, [wPlayerMoveEffect] + jr z, .next1 + ld a, [wEnemyMoveEffect] +.next1 + dec a ; subtract 1, there is no special effect for 00 + add a ; x2, 16bit pointers + ld hl, MoveEffectPointerTable + ld b, 0 + ld c, a + add hl, bc + ld a, [hli] + ld h, [hl] + ld l, a + jp hl ; jump to special effect handler + +INCLUDE "data/moves/effects_pointers.asm" + +SleepEffect: + ld de, wEnemyMonStatus + ld bc, wEnemyBattleStatus2 + ldh a, [hWhoseTurn] + and a + jp z, .sleepEffect + ld de, wBattleMonStatus + ld bc, wPlayerBattleStatus2 + +.sleepEffect + ld a, [bc] + bit NEEDS_TO_RECHARGE, a ; does the target need to recharge? (hyper beam) + res NEEDS_TO_RECHARGE, a ; target no longer needs to recharge + ld [bc], a + jr nz, .setSleepCounter ; if the target had to recharge, all hit tests will be skipped + ; including the event where the target already has another status + ld a, [de] + ld b, a + and $7 + jr z, .notAlreadySleeping ; can't affect a mon that is already asleep + ld hl, AlreadyAsleepText + jp PrintText +.notAlreadySleeping + ld a, b + and a + jr nz, .didntAffect ; can't affect a mon that is already statused + push de + call MoveHitTest ; apply accuracy tests + pop de + ld a, [wMoveMissed] + and a + jr nz, .didntAffect +.setSleepCounter +; set target's sleep counter to a random number between 1 and 7 + call BattleRandom + and $7 + jr z, .setSleepCounter + ld b, a + ld a, [wUnknownSerialFlag_d499] + and a + jr z, .asm_3f1ba ; XXX stadium stuff? + ld a, b + and $3 + jr z, .setSleepCounter + ld b, a +.asm_3f1ba + ld a, b + ld [de], a + call PlayCurrentMoveAnimation2 + ld hl, FellAsleepText + jp PrintText +.didntAffect + jp PrintDidntAffectText + +FellAsleepText: + text_far _FellAsleepText + text_end + +AlreadyAsleepText: + text_far _AlreadyAsleepText + text_end + +PoisonEffect: + ld hl, wEnemyMonStatus + ld de, wPlayerMoveEffect + ldh a, [hWhoseTurn] + and a + jr z, .poisonEffect + ld hl, wBattleMonStatus + ld de, wEnemyMoveEffect +.poisonEffect + call CheckTargetSubstitute + jr nz, .noEffect ; can't poison a substitute target + ld a, [hli] + ld b, a + and a + jr nz, .noEffect ; miss if target is already statused + ld a, [hli] + cp POISON ; can't poison a poison-type target + jr z, .noEffect + ld a, [hld] + cp POISON ; can't poison a poison-type target + jr z, .noEffect + ld a, [de] + cp POISON_SIDE_EFFECT1 + ld b, $34 ; ~20% chance of poisoning + jr z, .sideEffectTest + cp POISON_SIDE_EFFECT2 + ld b, $67 ; ~40% chance of poisoning + jr z, .sideEffectTest + push hl + push de + call MoveHitTest ; apply accuracy tests + pop de + pop hl + ld a, [wMoveMissed] + and a + jr nz, .didntAffect + jr .inflictPoison +.sideEffectTest + call BattleRandom + cp b ; was side effect successful? + ret nc +.inflictPoison + dec hl + set 3, [hl] ; mon is now poisoned + push de + dec de + ldh a, [hWhoseTurn] + and a + ld b, ANIM_C7 + ld hl, wPlayerBattleStatus3 + ld a, [de] + ld de, wPlayerToxicCounter + jr nz, .ok + ld b, ANIM_A9 + ld hl, wEnemyBattleStatus3 + ld de, wEnemyToxicCounter +.ok + cp TOXIC + jr nz, .normalPoison ; done if move is not Toxic + set BADLY_POISONED, [hl] ; else set Toxic battstatus + xor a + ld [de], a + ld hl, BadlyPoisonedText + jr .continue +.normalPoison + ld hl, PoisonedText +.continue + pop de + ld a, [de] + cp POISON_EFFECT + jr z, .regularPoisonEffect + ld a, b + call PlayBattleAnimation2 + jp PrintText +.regularPoisonEffect + call PlayCurrentMoveAnimation2 + jp PrintText +.noEffect + ld a, [de] + cp POISON_EFFECT + ret nz +.didntAffect + ld c, 50 + call DelayFrames + jp PrintDidntAffectText + +PoisonedText: + text_far _PoisonedText + text_end + +BadlyPoisonedText: + text_far _BadlyPoisonedText + text_end + +DrainHPEffect: + jpfar DrainHPEffect_ + +ExplodeEffect: + ld hl, wBattleMonHP + ld de, wPlayerBattleStatus2 + ldh a, [hWhoseTurn] + and a + jr z, .faintUser + ld hl, wEnemyMonHP + ld de, wEnemyBattleStatus2 +.faintUser + xor a + ld [hli], a ; set the mon's HP to 0 + ld [hli], a + inc hl + ld [hl], a ; set mon's status to 0 + ld a, [de] + res SEEDED, a ; clear mon's leech seed status + ld [de], a + ret + +FreezeBurnParalyzeEffect: + xor a + ld [wAnimationType], a + call CheckTargetSubstitute ; test bit 4 of d063/d068 flags [target has substitute flag] + ret nz ; return if they have a substitute, can't effect them + ldh a, [hWhoseTurn] + and a + jp nz, .opponentAttacker + ld a, [wEnemyMonStatus] + and a + jp nz, CheckDefrost ; can't inflict status if opponent is already statused + ld a, [wPlayerMoveType] + ld b, a + ld a, [wEnemyMonType1] + cp b ; do target type 1 and move type match? + ret z ; return if they match (an ice move can't freeze an ice-type, body slam can't paralyze a normal-type, etc.) + ld a, [wEnemyMonType2] + cp b ; do target type 2 and move type match? + ret z ; return if they match + ld a, [wPlayerMoveEffect] + cp UNUSED_EFFECT_23 ; more stadium stuff + jr nz, .asm_3f2c7 + ld a, [wUnknownSerialFlag_d499] + and a + ld a, FREEZE_SIDE_EFFECT + ld b, $4d ; else use 0x4D/0x100 or 77/256 = 30.1%~ chance + jr z, .next1 + ld b, $1a ; 0x1A/0x100 or 26/256 = 10.2%~ chance + jr .next1 +.asm_3f2c7 + cp a, PARALYZE_SIDE_EFFECT1 + 1 ; 10% status effects are 04, 05, 06 so 07 will set carry for those + ld b, $1a ; 0x1A/0x100 or 26/256 = 10.2%~ chance + jr c, .next1 ; branch ahead if this is a 10% chance effect.. + ld b, $4d ; else use 0x4D/0x100 or 77/256 = 30.1%~ chance + sub $1e ; subtract $1E to map to equivalent 10% chance effects +.next1 + push af + call BattleRandom ; get random 8bit value for probability test + cp b + pop bc + ret nc ; do nothing if random value is >= 1A or 4D [no status applied] + ld a, b ; what type of effect is this? + cp BURN_SIDE_EFFECT1 + jr z, .burn1 + cp FREEZE_SIDE_EFFECT + jr z, .freeze1 +; .paralyze + ld a, 1 << PAR + ld [wEnemyMonStatus], a + call QuarterSpeedDueToParalysis ; quarter speed of affected mon + ld a, ANIM_A9 + call PlayBattleAnimation + jp PrintMayNotAttackText ; print paralysis text +.burn1 + ld a, 1 << BRN + ld [wEnemyMonStatus], a + call HalveAttackDueToBurn ; halve attack of affected mon + ld a, ANIM_A9 + call PlayBattleAnimation + ld hl, BurnedText + jp PrintText +.freeze1 + call ClearHyperBeam ; resets hyper beam (recharge) condition from target + ld a, 1 << FRZ + ld [wEnemyMonStatus], a + ld a, ANIM_A9 + call PlayBattleAnimation + ld hl, FrozenText + jp PrintText +.opponentAttacker + ld a, [wBattleMonStatus] ; mostly same as above with addresses swapped for opponent + and a + jp nz, CheckDefrost + ld a, [wEnemyMoveType] + ld b, a + ld a, [wBattleMonType1] + cp b + ret z + ld a, [wBattleMonType2] + cp b + ret z + ld a, [wEnemyMoveEffect] + cp UNUSED_EFFECT_23 ; more stadium stuff + jr nz, .asm_3f341 + ld a, [wUnknownSerialFlag_d499] + and a + ld a, FREEZE_SIDE_EFFECT + ld b, $4d ; else use 0x4D/0x100 or 77/256 = 30.1%~ chance + jr z, .next2 + ld b, $1a ; 0x1A/0x100 or 26/256 = 10.2%~ chance + jr .next2 +.asm_3f341 + cp a, PARALYZE_SIDE_EFFECT1 + 1 + ld b, $1a + jr c, .next2 + ld b, $4d + sub $1e +.next2 + push af + call BattleRandom + cp b + pop bc + ret nc + ld a, b + cp BURN_SIDE_EFFECT1 + jr z, .burn2 + cp FREEZE_SIDE_EFFECT + jr z, .freeze2 + ld a, 1 << PAR + ld [wBattleMonStatus], a + call QuarterSpeedDueToParalysis + ld a, ANIM_C7 + call PlayBattleAnimation2 + jp PrintMayNotAttackText +.burn2 + ld a, 1 << BRN + ld [wBattleMonStatus], a + call HalveAttackDueToBurn + ld a, ANIM_C7 + call PlayBattleAnimation2 + ld hl, BurnedText + jp PrintText +.freeze2 +; hyper beam bits aren't reseted for opponent's side + ld a, 1 << FRZ + ld [wBattleMonStatus], a + ld a, ANIM_C7 + call PlayBattleAnimation2 + ld hl, FrozenText + jp PrintText + +BurnedText: + text_far _BurnedText + text_end + +FrozenText: + text_far _FrozenText + text_end + +CheckDefrost: +; any fire-type move that has a chance inflict burn (all but Fire Spin) will defrost a frozen target + and 1 << FRZ ; are they frozen? + ret z ; return if so + ldh a, [hWhoseTurn] + and a + jr nz, .opponent + ;player [attacker] + ld a, [wPlayerMoveType] + sub FIRE + ret nz ; return if type of move used isn't fire + ld [wEnemyMonStatus], a ; set opponent status to 00 ["defrost" a frozen monster] + ld hl, wEnemyMon1Status + ld a, [wEnemyMonPartyPos] + ld bc, wEnemyMon2 - wEnemyMon1 + call AddNTimes + xor a + ld [hl], a ; clear status in roster + ld hl, FireDefrostedText + jr .common +.opponent + ld a, [wEnemyMoveType] ; same as above with addresses swapped + sub FIRE + ret nz + ld [wBattleMonStatus], a + ld hl, wPartyMon1Status + ld a, [wPlayerMonNumber] + ld bc, wPartyMon2 - wPartyMon1 + call AddNTimes + xor a + ld [hl], a + ld hl, FireDefrostedText +.common + jp PrintText + +FireDefrostedText: + text_far _FireDefrostedText + text_end + +StatModifierUpEffect: + ld hl, wPlayerMonStatMods + ld de, wPlayerMoveEffect + ldh a, [hWhoseTurn] + and a + jr z, .statModifierUpEffect + ld hl, wEnemyMonStatMods + ld de, wEnemyMoveEffect +.statModifierUpEffect + ld a, [de] + sub ATTACK_UP1_EFFECT + cp EVASION_UP1_EFFECT + $3 - ATTACK_UP1_EFFECT ; covers all +1 effects + jr c, .incrementStatMod + sub ATTACK_UP2_EFFECT - ATTACK_UP1_EFFECT ; map +2 effects to equivalent +1 effect +.incrementStatMod + ld c, a + ld b, $0 + add hl, bc + ld b, [hl] + inc b ; increment corresponding stat mod + ld a, $d + cp b ; can't raise stat past +6 ($d or 13) + jp c, PrintNothingHappenedText + ld a, [de] + cp ATTACK_UP1_EFFECT + $8 ; is it a +2 effect? + jr c, .ok + inc b ; if so, increment stat mod again + ld a, $d + cp b ; unless it's already +6 + jr nc, .ok + ld b, a +.ok + ld [hl], b + ld a, c + cp $4 + jr nc, UpdateStatDone ; jump if mod affected is evasion/accuracy + push hl + ld hl, wBattleMonAttack + 1 + ld de, wPlayerMonUnmodifiedAttack + ldh a, [hWhoseTurn] + and a + jr z, .pointToStats + ld hl, wEnemyMonAttack + 1 + ld de, wEnemyMonUnmodifiedAttack +.pointToStats + push bc + sla c + ld b, $0 + add hl, bc ; hl = modified stat + ld a, c + add e + ld e, a + jr nc, .checkIf999 + inc d ; de = unmodified (original) stat +.checkIf999 + pop bc + ; check if stat is already 999 + ld a, [hld] + sub LOW(MAX_STAT_VALUE) + jr nz, .recalculateStat + ld a, [hl] + sbc HIGH(MAX_STAT_VALUE) + jp z, RestoreOriginalStatModifier +.recalculateStat ; recalculate affected stat + ; paralysis and burn penalties, as well as badge boosts are ignored + push hl + push bc + ld hl, StatModifierRatios + dec b + sla b + ld c, b + ld b, $0 + add hl, bc + pop bc + xor a + ldh [hMultiplicand], a + ld a, [de] + ldh [hMultiplicand + 1], a + inc de + ld a, [de] + ldh [hMultiplicand + 2], a + ld a, [hli] + ldh [hMultiplier], a + call Multiply + ld a, [hl] + ldh [hDivisor], a + ld b, $4 + call Divide + pop hl +; cap at MAX_STAT_VALUE (999) + ldh a, [hProduct + 3] + sub LOW(MAX_STAT_VALUE) + ldh a, [hProduct + 2] + sbc HIGH(MAX_STAT_VALUE) + jp c, UpdateStat + ld a, HIGH(MAX_STAT_VALUE) + ldh [hMultiplicand + 1], a + ld a, LOW(MAX_STAT_VALUE) + ldh [hMultiplicand + 2], a + +UpdateStat: + ldh a, [hProduct + 2] + ld [hli], a + ldh a, [hProduct + 3] + ld [hl], a + pop hl +UpdateStatDone: + ld b, c + inc b + call PrintStatText + ld hl, wPlayerBattleStatus2 + ld de, wPlayerMoveNum + ld bc, wPlayerMonMinimized + ldh a, [hWhoseTurn] + and a + jr z, .playerTurn + ld hl, wEnemyBattleStatus2 + ld de, wEnemyMoveNum + ld bc, wEnemyMonMinimized +.playerTurn + ld a, [de] + cp MINIMIZE + jr nz, .notMinimize + ; if a substitute is up, slide off the substitute and show the mon pic before + ; playing the minimize animation + bit HAS_SUBSTITUTE_UP, [hl] + push af + push bc + push de + ld hl, HideSubstituteShowMonAnim + ld b, BANK(HideSubstituteShowMonAnim) + call nz, Bankswitch + pop de +.notMinimize + call PlayCurrentMoveAnimation + ld a, [de] + cp MINIMIZE + jr nz, .applyBadgeBoostsAndStatusPenalties + pop bc + ld a, $1 + ld [bc], a + ld hl, ReshowSubstituteAnim + ld b, BANK(ReshowSubstituteAnim) + pop af + call nz, Bankswitch +.applyBadgeBoostsAndStatusPenalties + ldh a, [hWhoseTurn] + and a + call z, ApplyBadgeStatBoosts ; whenever the player uses a stat-up move, badge boosts get reapplied again to every stat, + ; even to those not affected by the stat-up move (will be boosted further) + ld hl, MonsStatsRoseText + call PrintText + +; these shouldn't be here + call QuarterSpeedDueToParalysis ; apply speed penalty to the player whose turn is not, if it's paralyzed + jp HalveAttackDueToBurn ; apply attack penalty to the player whose turn is not, if it's burned + +RestoreOriginalStatModifier: + pop hl + dec [hl] + +PrintNothingHappenedText: + ld hl, NothingHappenedText + jp PrintText + +MonsStatsRoseText: + text_far _MonsStatsRoseText + text_asm + ld hl, GreatlyRoseText + ldh a, [hWhoseTurn] + and a + ld a, [wPlayerMoveEffect] + jr z, .playerTurn + ld a, [wEnemyMoveEffect] +.playerTurn + cp ATTACK_DOWN1_EFFECT + ret nc + ld hl, RoseText + ret + +GreatlyRoseText: + text_pause + text_far _GreatlyRoseText +; fallthrough +RoseText: + text_far _RoseText + text_end + +StatModifierDownEffect: + ld hl, wEnemyMonStatMods + ld de, wPlayerMoveEffect + ld bc, wEnemyBattleStatus1 + ldh a, [hWhoseTurn] + and a + jr z, .statModifierDownEffect + ld hl, wPlayerMonStatMods + ld de, wEnemyMoveEffect + ld bc, wPlayerBattleStatus1 + ld a, [wLinkState] + cp LINK_STATE_BATTLING + jr z, .statModifierDownEffect + call BattleRandom + cp $40 ; 1/4 chance to miss by in regular battle + jp c, MoveMissed +.statModifierDownEffect + call CheckTargetSubstitute ; can't hit through substitute + jp nz, MoveMissed + ld a, [de] + cp ATTACK_DOWN_SIDE_EFFECT + jr c, .nonSideEffect + call BattleRandom + cp $55 ; 85/256 chance for side effects + jp nc, CantLowerAnymore + ld a, [de] + sub ATTACK_DOWN_SIDE_EFFECT ; map each stat to 0-3 + jr .decrementStatMod +.nonSideEffect ; non-side effects only + push hl + push de + push bc + call MoveHitTest ; apply accuracy tests + pop bc + pop de + pop hl + ld a, [wMoveMissed] + and a + jp nz, MoveMissed + ld a, [bc] + bit INVULNERABLE, a ; fly/dig + jp nz, MoveMissed + ld a, [de] + sub ATTACK_DOWN1_EFFECT + cp EVASION_DOWN1_EFFECT + $3 - ATTACK_DOWN1_EFFECT ; covers all -1 effects + jr c, .decrementStatMod + sub ATTACK_DOWN2_EFFECT - ATTACK_DOWN1_EFFECT ; map -2 effects to corresponding -1 effect +.decrementStatMod + ld c, a + ld b, $0 + add hl, bc + ld b, [hl] + dec b ; dec corresponding stat mod + jp z, CantLowerAnymore ; if stat mod is 1 (-6), can't lower anymore + ld a, [de] + cp ATTACK_DOWN2_EFFECT - $16 ; $24 + jr c, .ok + cp EVASION_DOWN2_EFFECT + $5 ; $44 + jr nc, .ok + dec b ; stat down 2 effects only (dec mod again) + jr nz, .ok + inc b ; increment mod to 1 (-6) if it would become 0 (-7) +.ok + ld [hl], b ; save modified mod + ld a, c + cp $4 + jr nc, UpdateLoweredStatDone ; jump for evasion/accuracy + push hl + push de + ld hl, wEnemyMonAttack + 1 + ld de, wEnemyMonUnmodifiedAttack + ldh a, [hWhoseTurn] + and a + jr z, .pointToStat + ld hl, wBattleMonAttack + 1 + ld de, wPlayerMonUnmodifiedAttack +.pointToStat + push bc + sla c + ld b, $0 + add hl, bc ; hl = modified stat + ld a, c + add e + ld e, a + jr nc, .noCarry + inc d ; de = unmodified stat +.noCarry + pop bc + ld a, [hld] + sub $1 ; can't lower stat below 1 (-6) + jr nz, .recalculateStat + ld a, [hl] + and a + jp z, CantLowerAnymore_Pop +.recalculateStat +; recalculate affected stat +; paralysis and burn penalties, as well as badge boosts are ignored + push hl + push bc + ld hl, StatModifierRatios + dec b + sla b + ld c, b + ld b, $0 + add hl, bc + pop bc + xor a + ldh [hMultiplicand], a + ld a, [de] + ldh [hMultiplicand + 1], a + inc de + ld a, [de] + ldh [hMultiplicand + 2], a + ld a, [hli] + ldh [hMultiplier], a + call Multiply + ld a, [hl] + ldh [hDivisor], a + ld b, $4 + call Divide + pop hl + ldh a, [hProduct + 3] + ld b, a + ldh a, [hProduct + 2] + or b + jp nz, UpdateLoweredStat + ldh [hMultiplicand + 1], a + ld a, $1 + ldh [hMultiplicand + 2], a + +UpdateLoweredStat: + ldh a, [hProduct + 2] + ld [hli], a + ldh a, [hProduct + 3] + ld [hl], a + pop de + pop hl +UpdateLoweredStatDone: + ld b, c + inc b + push de + call PrintStatText + pop de + ld a, [de] + cp $44 + jr nc, .ApplyBadgeBoostsAndStatusPenalties + call PlayCurrentMoveAnimation2 +.ApplyBadgeBoostsAndStatusPenalties + ldh a, [hWhoseTurn] + and a + call nz, ApplyBadgeStatBoosts ; whenever the player uses a stat-down move, badge boosts get reapplied again to every stat, + ; even to those not affected by the stat-up move (will be boosted further) + ld hl, MonsStatsFellText + call PrintText + +; These where probably added given that a stat-down move affecting speed or attack will override +; the stat penalties from paralysis and burn respectively. +; But they are always called regardless of the stat affected by the stat-down move. + call QuarterSpeedDueToParalysis + jp HalveAttackDueToBurn + +CantLowerAnymore_Pop: + pop de + pop hl + inc [hl] + +CantLowerAnymore: + ld a, [de] + cp ATTACK_DOWN_SIDE_EFFECT + ret nc + ld hl, NothingHappenedText + jp PrintText + +MoveMissed: + ld a, [de] + cp $44 + ret nc + jp ConditionalPrintButItFailed + +MonsStatsFellText: + text_far _MonsStatsFellText + text_asm + ld hl, FellText + ldh a, [hWhoseTurn] + and a + ld a, [wPlayerMoveEffect] + jr z, .playerTurn + ld a, [wEnemyMoveEffect] +.playerTurn +; check if the move's effect decreases a stat by 2 + cp BIDE_EFFECT + ret c + cp ATTACK_DOWN_SIDE_EFFECT + ret nc + ld hl, GreatlyFellText + ret + +GreatlyFellText: + text_pause + text_far _GreatlyFellText +; fallthrough +FellText: + text_far _FellText + text_end + +PrintStatText: + ld hl, StatsTextStrings + ld c, "@" +.findStatName_outer + dec b + jr z, .foundStatName +.findStatName_inner + ld a, [hli] + cp c + jr z, .findStatName_outer + jr .findStatName_inner +.foundStatName + ld de, wcf4b + ld bc, $a + jp CopyData + +INCLUDE "data/battle/stat_names.asm" + +INCLUDE "data/battle/stat_modifiers.asm" + +BideEffect: + ld hl, wPlayerBattleStatus1 + ld de, wPlayerBideAccumulatedDamage + ld bc, wPlayerNumAttacksLeft + ldh a, [hWhoseTurn] + and a + jr z, .bideEffect + ld hl, wEnemyBattleStatus1 + ld de, wEnemyBideAccumulatedDamage + ld bc, wEnemyNumAttacksLeft +.bideEffect + set STORING_ENERGY, [hl] ; mon is now using bide + xor a + ld [de], a + inc de + ld [de], a + ld [wPlayerMoveEffect], a + ld [wEnemyMoveEffect], a + call BattleRandom + and $1 + inc a + inc a + ld [bc], a ; set Bide counter to 2 or 3 at random + ldh a, [hWhoseTurn] + add XSTATITEM_ANIM + jp PlayBattleAnimation2 + +ThrashPetalDanceEffect: + ld hl, wPlayerBattleStatus1 + ld de, wPlayerNumAttacksLeft + ldh a, [hWhoseTurn] + and a + jr z, .thrashPetalDanceEffect + ld hl, wEnemyBattleStatus1 + ld de, wEnemyNumAttacksLeft +.thrashPetalDanceEffect + set THRASHING_ABOUT, [hl] ; mon is now using thrash/petal dance + call BattleRandom + and $1 + inc a + inc a + ld [de], a ; set thrash/petal dance counter to 2 or 3 at random + ldh a, [hWhoseTurn] + add ANIM_B0 + jp PlayBattleAnimation2 + +SwitchAndTeleportEffect: + ldh a, [hWhoseTurn] + and a + jr nz, .handleEnemy + ld a, [wIsInBattle] + dec a + jr nz, .notWildBattle1 + ld a, [wCurEnemyLVL] + ld b, a + ld a, [wBattleMonLevel] + cp b ; is the player's level greater than the enemy's level? + jr nc, .playerMoveWasSuccessful ; if so, teleport will always succeed + add b + ld c, a + inc c ; c = sum of player level and enemy level +.rejectionSampleLoop1 + call BattleRandom + cp c ; get a random number between 0 and c + jr nc, .rejectionSampleLoop1 + srl b + srl b ; b = enemyLevel / 4 + cp b ; is rand[0, playerLevel + enemyLevel) >= (enemyLevel / 4)? + jr nc, .playerMoveWasSuccessful ; if so, allow teleporting + ld c, 50 + call DelayFrames + ld a, [wPlayerMoveNum] + cp TELEPORT + jp nz, PrintDidntAffectText + jp PrintButItFailedText_ +.playerMoveWasSuccessful + call ReadPlayerMonCurHPAndStatus + xor a + ld [wAnimationType], a + inc a + ld [wEscapedFromBattle], a + ld a, [wPlayerMoveNum] + jr .playAnimAndPrintText +.notWildBattle1 + ld c, 50 + call DelayFrames + ld hl, IsUnaffectedText + ld a, [wPlayerMoveNum] + cp TELEPORT + jp nz, PrintText + jp PrintButItFailedText_ +.handleEnemy + ld a, [wIsInBattle] + dec a + jr nz, .notWildBattle2 + ld a, [wBattleMonLevel] + ld b, a + ld a, [wCurEnemyLVL] + cp b + jr nc, .enemyMoveWasSuccessful + add b + ld c, a + inc c +.rejectionSampleLoop2 + call BattleRandom + cp c + jr nc, .rejectionSampleLoop2 + srl b + srl b + cp b + jr nc, .enemyMoveWasSuccessful + ld c, 50 + call DelayFrames + ld a, [wEnemyMoveNum] + cp TELEPORT + jp nz, PrintDidntAffectText + jp PrintButItFailedText_ +.enemyMoveWasSuccessful + call ReadPlayerMonCurHPAndStatus + xor a + ld [wAnimationType], a + inc a + ld [wEscapedFromBattle], a + ld a, [wEnemyMoveNum] + jr .playAnimAndPrintText +.notWildBattle2 + ld c, 50 + call DelayFrames + ld hl, IsUnaffectedText + ld a, [wEnemyMoveNum] + cp TELEPORT + jp nz, PrintText + jp ConditionalPrintButItFailed +.playAnimAndPrintText + push af + call PlayBattleAnimation + ld c, 20 + call DelayFrames + pop af + ld hl, RanFromBattleText + cp TELEPORT + jr z, .printText + ld hl, RanAwayScaredText + cp ROAR + jr z, .printText + ld hl, WasBlownAwayText +.printText + jp PrintText + +RanFromBattleText: + text_far _RanFromBattleText + text_end + +RanAwayScaredText: + text_far _RanAwayScaredText + text_end + +WasBlownAwayText: + text_far _WasBlownAwayText + text_end + +TwoToFiveAttacksEffect: + ld hl, wPlayerBattleStatus1 + ld de, wPlayerNumAttacksLeft + ld bc, wPlayerNumHits + ldh a, [hWhoseTurn] + and a + jr z, .twoToFiveAttacksEffect + ld hl, wEnemyBattleStatus1 + ld de, wEnemyNumAttacksLeft + ld bc, wEnemyNumHits +.twoToFiveAttacksEffect + bit ATTACKING_MULTIPLE_TIMES, [hl] ; is mon attacking multiple times? + ret nz + set ATTACKING_MULTIPLE_TIMES, [hl] ; mon is now attacking multiple times + ld hl, wPlayerMoveEffect + ldh a, [hWhoseTurn] + and a + jr z, .setNumberOfHits + ld hl, wEnemyMoveEffect +.setNumberOfHits + ld a, [hl] + cp TWINEEDLE_EFFECT + jr z, .twineedle + cp ATTACK_TWICE_EFFECT + ld a, $2 ; number of hits it's always 2 for ATTACK_TWICE_EFFECT + jr z, .saveNumberOfHits +; for TWO_TO_FIVE_ATTACKS_EFFECT 3/8 chance for 2 and 3 hits, and 1/8 chance for 4 and 5 hits + call BattleRandom + and $3 + cp $2 + jr c, .gotNumHits +; if the number of hits was greater than 2, re-roll again for a lower chance + call BattleRandom + and $3 +.gotNumHits + inc a + inc a +.saveNumberOfHits + ld [de], a + ld [bc], a + ret +.twineedle + ld a, POISON_SIDE_EFFECT1 + ld [hl], a ; set Twineedle's effect to poison effect + jr .saveNumberOfHits + +FlinchSideEffect: + call CheckTargetSubstitute + ret nz + ld hl, wEnemyBattleStatus1 + ld de, wPlayerMoveEffect + ldh a, [hWhoseTurn] + and a + jr z, .flinchSideEffect + ld hl, wPlayerBattleStatus1 + ld de, wEnemyMoveEffect +.flinchSideEffect + ld a, [wLinkState] + cp LINK_STATE_BATTLING + call z, ClearHyperBeam + ld a, [de] + cp FLINCH_SIDE_EFFECT1 + ld b, $1a ; ~10% chance of flinch + jr z, .gotEffectChance + ld b, $4d ; ~30% chance of flinch +.gotEffectChance + call BattleRandom + cp b + ret nc + set FLINCHED, [hl] ; set mon's status to flinching + call ClearHyperBeam + ret + +OneHitKOEffect: + jpfar OneHitKOEffect_ + +ChargeEffect: + ld hl, wPlayerBattleStatus1 + ld de, wPlayerMoveEffect + ldh a, [hWhoseTurn] + and a + ld b, XSTATITEM_ANIM + jr z, .chargeEffect + ld hl, wEnemyBattleStatus1 + ld de, wEnemyMoveEffect + ld b, ANIM_AF +.chargeEffect + set CHARGING_UP, [hl] + ld a, [de] + dec de ; de contains enemy or player MOVENUM + cp FLY_EFFECT + jr nz, .notFly + set INVULNERABLE, [hl] ; mon is now invulnerable to typical attacks (fly/dig) + ld b, TELEPORT ; load Teleport's animation +.notFly + ld a, [de] + cp DIG + jr nz, .notDigOrFly + set INVULNERABLE, [hl] ; mon is now invulnerable to typical attacks (fly/dig) + ld b, ANIM_C0 +.notDigOrFly + push de + push bc + inc hl ; battle status 2 + push hl + ld a, [hl] + bit HAS_SUBSTITUTE_UP, a + ld hl, HideSubstituteShowMonAnim + ld b, BANK(HideSubstituteShowMonAnim) + call nz, Bankswitch + pop hl + pop bc + xor a + ld [wAnimationType], a + ld a, b + call PlayBattleAnimation + ld a, [hl] + bit HAS_SUBSTITUTE_UP, a + ld hl, ReshowSubstituteAnim + ld b, BANK(ReshowSubstituteAnim) + call nz, Bankswitch + pop de + ld a, [de] + ld [wChargeMoveNum], a + ld hl, ChargeMoveEffectText + jp PrintText + +ChargeMoveEffectText: + text_far _ChargeMoveEffectText + text_asm + ld a, [wChargeMoveNum] + cp RAZOR_WIND + ld hl, MadeWhirlwindText + jr z, .gotText + cp SOLARBEAM + ld hl, TookInSunlightText + jr z, .gotText + cp SKULL_BASH + ld hl, LoweredItsHeadText + jr z, .gotText + cp SKY_ATTACK + ld hl, SkyAttackGlowingText + jr z, .gotText + cp FLY + ld hl, FlewUpHighText + jr z, .gotText + cp DIG + ld hl, DugAHoleText +.gotText + ret + +MadeWhirlwindText: + text_far _MadeWhirlwindText + text_end + +TookInSunlightText: + text_far _TookInSunlightText + text_end + +LoweredItsHeadText: + text_far _LoweredItsHeadText + text_end + +SkyAttackGlowingText: + text_far _SkyAttackGlowingText + text_end + +FlewUpHighText: + text_far _FlewUpHighText + text_end + +DugAHoleText: + text_far _DugAHoleText + text_end + +TrappingEffect: + ld hl, wPlayerBattleStatus1 + ld de, wPlayerNumAttacksLeft + ldh a, [hWhoseTurn] + and a + jr z, .trappingEffect + ld hl, wEnemyBattleStatus1 + ld de, wEnemyNumAttacksLeft +.trappingEffect + bit USING_TRAPPING_MOVE, [hl] + ret nz + call ClearHyperBeam ; since this effect is called before testing whether the move will hit, + ; the target won't need to recharge even if the trapping move missed + set USING_TRAPPING_MOVE, [hl] ; mon is now using a trapping move + call BattleRandom ; 3/8 chance for 2 and 3 attacks, and 1/8 chance for 4 and 5 attacks + and $3 + cp $2 + jr c, .setTrappingCounter + call BattleRandom + and $3 +.setTrappingCounter + inc a + ld [de], a + ret + +MistEffect: + jpfar MistEffect_ + +FocusEnergyEffect: + jpfar FocusEnergyEffect_ + +RecoilEffect: + jpfar RecoilEffect_ + +ConfusionSideEffect: + call BattleRandom + cp $19 ; ~10% chance + ret nc + jr ConfusionSideEffectSuccess + +ConfusionEffect: + call CheckTargetSubstitute + jr nz, ConfusionEffectFailed + call MoveHitTest + ld a, [wMoveMissed] + and a + jr nz, ConfusionEffectFailed + +ConfusionSideEffectSuccess: + ldh a, [hWhoseTurn] + and a + ld hl, wEnemyBattleStatus1 + ld bc, wEnemyConfusedCounter + ld a, [wPlayerMoveEffect] + jr z, .confuseTarget + ld hl, wPlayerBattleStatus1 + ld bc, wPlayerConfusedCounter + ld a, [wEnemyMoveEffect] +.confuseTarget + bit CONFUSED, [hl] ; is mon confused? + jr nz, ConfusionEffectFailed + set CONFUSED, [hl] ; mon is now confused + push af + call BattleRandom + and $3 + inc a + inc a + ld [bc], a ; confusion status will last 2-5 turns + pop af + cp CONFUSION_SIDE_EFFECT + call nz, PlayCurrentMoveAnimation2 + ld hl, BecameConfusedText + jp PrintText + +BecameConfusedText: + text_far _BecameConfusedText + text_end + +ConfusionEffectFailed: + cp CONFUSION_SIDE_EFFECT + ret z + ld c, 50 + call DelayFrames + jp ConditionalPrintButItFailed + +ParalyzeEffect: + jpfar ParalyzeEffect_ + +SubstituteEffect: + jpfar SubstituteEffect_ + +HyperBeamEffect: + ld hl, wPlayerBattleStatus2 + ldh a, [hWhoseTurn] + and a + jr z, .hyperBeamEffect + ld hl, wEnemyBattleStatus2 +.hyperBeamEffect + set NEEDS_TO_RECHARGE, [hl] ; mon now needs to recharge + ret + +ClearHyperBeam: + push hl + ld hl, wEnemyBattleStatus2 + ldh a, [hWhoseTurn] + and a + jr z, .playerTurn + ld hl, wPlayerBattleStatus2 +.playerTurn + res NEEDS_TO_RECHARGE, [hl] ; mon no longer needs to recharge + pop hl + ret + +RageEffect: + ld hl, wPlayerBattleStatus2 + ldh a, [hWhoseTurn] + and a + jr z, .player + ld hl, wEnemyBattleStatus2 +.player + set USING_RAGE, [hl] ; mon is now in "rage" mode + ret + +MimicEffect: + ld c, 50 + call DelayFrames + call MoveHitTest + ld a, [wMoveMissed] + and a + jr nz, .mimicMissed + ldh a, [hWhoseTurn] + and a + ld hl, wBattleMonMoves + ld a, [wPlayerBattleStatus1] + jr nz, .enemyTurn + ld a, [wLinkState] + cp LINK_STATE_BATTLING + jr nz, .letPlayerChooseMove + ld hl, wEnemyMonMoves + ld a, [wEnemyBattleStatus1] +.enemyTurn + bit INVULNERABLE, a + jr nz, .mimicMissed +.getRandomMove + push hl + call BattleRandom + and $3 + ld c, a + ld b, $0 + add hl, bc + ld a, [hl] + pop hl + and a + jr z, .getRandomMove + ld d, a + ldh a, [hWhoseTurn] + and a + ld hl, wBattleMonMoves + ld a, [wPlayerMoveListIndex] + jr z, .playerTurn + ld hl, wEnemyMonMoves + ld a, [wEnemyMoveListIndex] + jr .playerTurn +.letPlayerChooseMove + ld a, [wEnemyBattleStatus1] + bit INVULNERABLE, a + jr nz, .mimicMissed + ld a, [wCurrentMenuItem] + push af + ld a, $1 + ld [wMoveMenuType], a + call MoveSelectionMenu + call LoadScreenTilesFromBuffer1 + ld hl, wEnemyMonMoves + ld a, [wCurrentMenuItem] + ld c, a + ld b, $0 + add hl, bc + ld d, [hl] + pop af + ld hl, wBattleMonMoves +.playerTurn + ld c, a + ld b, $0 + add hl, bc + ld a, d + ld [hl], a + ld [wd11e], a + call GetMoveName + call PlayCurrentMoveAnimation + ld hl, MimicLearnedMoveText + jp PrintText +.mimicMissed + jp PrintButItFailedText_ + +MimicLearnedMoveText: + text_far _MimicLearnedMoveText + text_end + +LeechSeedEffect: + jpfar LeechSeedEffect_ + +SplashEffect: + call PlayCurrentMoveAnimation + jp PrintNoEffectText + +DisableEffect: + call MoveHitTest + ld a, [wMoveMissed] + and a + jr nz, .moveMissed + ld de, wEnemyDisabledMove + ld hl, wEnemyMonMoves + ldh a, [hWhoseTurn] + and a + jr z, .disableEffect + ld de, wPlayerDisabledMove + ld hl, wBattleMonMoves +.disableEffect +; no effect if target already has a move disabled + ld a, [de] + and a + jr nz, .moveMissed +.pickMoveToDisable + push hl + call BattleRandom + and $3 + ld c, a + ld b, $0 + add hl, bc + ld a, [hl] + pop hl + and a + jr z, .pickMoveToDisable ; loop until a non-00 move slot is found + ld [wd11e], a ; store move number + push hl + ldh a, [hWhoseTurn] + and a + ld hl, wBattleMonPP + jr nz, .enemyTurn + ld a, [wLinkState] + cp LINK_STATE_BATTLING + pop hl ; wEnemyMonMoves + jr nz, .playerTurnNotLinkBattle +; .playerTurnLinkBattle + push hl + ld hl, wEnemyMonPP +.enemyTurn + push hl + ld a, [hli] + or [hl] + inc hl + or [hl] + inc hl + or [hl] + and $3f + pop hl ; wBattleMonPP or wEnemyMonPP + jr z, .moveMissedPopHL ; nothing to do if all moves have no PP left + add hl, bc + ld a, [hl] + pop hl + and a + jr z, .pickMoveToDisable ; pick another move if this one had 0 PP +.playerTurnNotLinkBattle +; non-link battle enemies have unlimited PP so the previous checks aren't needed + call BattleRandom + and $7 + inc a ; 1-8 turns disabled + inc c ; move 1-4 will be disabled + swap c + add c ; map disabled move to high nibble of wEnemyDisabledMove / wPlayerDisabledMove + ld [de], a + call PlayCurrentMoveAnimation2 + ld hl, wPlayerDisabledMoveNumber + ldh a, [hWhoseTurn] + and a + jr nz, .printDisableText + inc hl ; wEnemyDisabledMoveNumber +.printDisableText + ld a, [wd11e] ; move number + ld [hl], a + call GetMoveName + ld hl, MoveWasDisabledText + jp PrintText +.moveMissedPopHL + pop hl +.moveMissed + jp PrintButItFailedText_ + +MoveWasDisabledText: + text_far _MoveWasDisabledText + text_end + +PayDayEffect: + jpfar PayDayEffect_ + +ConversionEffect: + jpfar ConversionEffect_ + +HazeEffect: + jpfar HazeEffect_ + +HealEffect: + jpfar HealEffect_ + +TransformEffect: + jpfar TransformEffect_ + +ReflectLightScreenEffect: + jpfar ReflectLightScreenEffect_ + +NothingHappenedText: + text_far _NothingHappenedText + text_end + +PrintNoEffectText: + ld hl, NoEffectText + jp PrintText + +NoEffectText: + text_far _NoEffectText + text_end + +ConditionalPrintButItFailed: + ld a, [wMoveDidntMiss] + and a + ret nz ; return if the side effect failed, yet the attack was successful + +PrintButItFailedText_: + ld hl, ButItFailedText + jp PrintText + +ButItFailedText: + text_far _ButItFailedText + text_end + +PrintDidntAffectText: + ld hl, DidntAffectText + jp PrintText + +DidntAffectText: + text_far _DidntAffectText + text_end + +IsUnaffectedText: + text_far _IsUnaffectedText + text_end + +PrintMayNotAttackText: + ld hl, ParalyzedMayNotAttackText + jp PrintText + +ParalyzedMayNotAttackText: + text_far _ParalyzedMayNotAttackText + text_end + +CheckTargetSubstitute: + push hl + ld hl, wEnemyBattleStatus2 + ldh a, [hWhoseTurn] + and a + jr z, .next1 + ld hl, wPlayerBattleStatus2 +.next1 + bit HAS_SUBSTITUTE_UP, [hl] + pop hl + ret + +PlayCurrentMoveAnimation2: +; animation at MOVENUM will be played unless MOVENUM is 0 +; plays wAnimationType 3 or 6 + ldh a, [hWhoseTurn] + and a + ld a, [wPlayerMoveNum] + jr z, .notEnemyTurn + ld a, [wEnemyMoveNum] +.notEnemyTurn + and a + ret z + +PlayBattleAnimation2: +; play animation ID at a and animation type 6 or 3 + ld [wAnimationID], a + ldh a, [hWhoseTurn] + and a + ld a, $6 + jr z, .storeAnimationType + ld a, $3 +.storeAnimationType + ld [wAnimationType], a + jp PlayBattleAnimationGotID + +PlayCurrentMoveAnimation: +; animation at MOVENUM will be played unless MOVENUM is 0 +; resets wAnimationType + xor a + ld [wAnimationType], a + ldh a, [hWhoseTurn] + and a + ld a, [wPlayerMoveNum] + jr z, .notEnemyTurn + ld a, [wEnemyMoveNum] +.notEnemyTurn + and a + ret z + +PlayBattleAnimation: +; play animation ID at a and predefined animation type + ld [wAnimationID], a + +PlayBattleAnimationGotID: +; play animation at wAnimationID + push hl + push de + push bc + predef MoveAnimation + callfar Func_78e98 + pop bc + pop de + pop hl + ret diff --git a/engine/battle/end_of_battle.asm b/engine/battle/end_of_battle.asm index 5c0c3991..e64f54e7 100755 --- a/engine/battle/end_of_battle.asm +++ b/engine/battle/end_of_battle.asm @@ -12,7 +12,7 @@ EndOfBattle: call ClearScreen ld b, SET_PAL_OVERWORLD call RunPaletteCommand - callab DisplayLinkBattleVersusTextBox + callfar DisplayLinkBattleVersusTextBox ld a, [wBattleResult] cp $1 ld de, YouWinText @@ -21,7 +21,7 @@ EndOfBattle: jr z, .placeWinOrLoseString ld de, DrawText .placeWinOrLoseString - coord hl, 6, 8 + hlcoord 6, 8 call PlaceString ld c, 200 call DelayFrames @@ -46,7 +46,7 @@ EndOfBattle: ld [wForceEvolution], a predef EvolutionAfterBattle ld d, $82 - callab UpdatePikachuMoodAfterBattle + callfar UpdatePikachuMoodAfterBattle .resetVariables xor a ld [wLowHealthAlarm], a ;disable low health alarm @@ -88,5 +88,5 @@ DrawText: db " DRAW@" PickUpPayDayMoneyText: - TX_FAR _PickUpPayDayMoneyText - db "@" + text_far _PickUpPayDayMoneyText + text_end diff --git a/engine/battle/experience.asm b/engine/battle/experience.asm index 722685c2..bab804bb 100644 --- a/engine/battle/experience.asm +++ b/engine/battle/experience.asm @@ -55,15 +55,15 @@ GainExperience: jr .gainStatExpLoop .statExpDone xor a - ld [H_MULTIPLICAND], a - ld [H_MULTIPLICAND + 1], a + ldh [hMultiplicand], a + ldh [hMultiplicand + 1], a ld a, [wEnemyMonBaseExp] - ld [H_MULTIPLICAND + 2], a + ldh [hMultiplicand + 2], a ld a, [wEnemyMonLevel] - ld [H_MULTIPLIER], a + ldh [hMultiplier], a call Multiply ld a, 7 - ld [H_DIVISOR], a + ldh [hDivisor], a ld b, 4 call Divide ld hl, wPartyMon1OTID - (wPartyMon1DVs - 1) @@ -91,12 +91,12 @@ GainExperience: inc hl ; add the gained exp to the party mon's exp ld b, [hl] - ld a, [H_QUOTIENT + 3] + ldh a, [hQuotient + 3] ld [wExpAmountGained + 1], a add b ld [hld], a ld b, [hl] - ld a, [H_QUOTIENT + 2] + ldh a, [hQuotient + 2] ld [wExpAmountGained], a adc b ld [hl], a @@ -117,13 +117,13 @@ GainExperience: ld [wd0b5], a call GetMonHeader ld d, MAX_LEVEL - callab CalcExperience ; get max exp + callfar CalcExperience ; get max exp ; compare max exp with current exp - ld a, [hExperience] + ldh a, [hExperience] ld b, a - ld a, [hExperience + 1] + ldh a, [hExperience + 1] ld c, a - ld a, [hExperience + 2] + ldh a, [hExperience + 2] ld d, a pop hl ld a, [hld] @@ -155,7 +155,7 @@ GainExperience: ld bc, wPartyMon1Level - wPartyMon1Exp add hl, bc push hl - callba CalcLevelFromExperience + farcall CalcLevelFromExperience pop hl ld a, [hl] ; current level cp d @@ -252,7 +252,7 @@ GainExperience: ld [wMonDataLocation], a call LoadMonData ld d, $1 - callab PrintStatsBox + callfar PrintStatsBox call WaitForTextScrollButtonPress call LoadScreenTilesFromBuffer1 xor a ; PLAYER_PARTY_DATA @@ -317,14 +317,14 @@ DivideExpDataByNumMonsGainingExp: ld c, wEnemyMonBaseExp + 1 - wEnemyMonBaseStats .divideLoop xor a - ld [H_DIVIDEND], a + ldh [hDividend], a ld a, [hl] - ld [H_DIVIDEND + 1], a + ldh [hDividend + 1], a ld a, [wd11e] - ld [H_DIVISOR], a + ldh [hDivisor], a ld b, $2 call Divide ; divide value by number of mons gaining exp - ld a, [H_QUOTIENT + 3] + ldh a, [hQuotient + 3] ld [hli], a dec c jr nz, .divideLoop @@ -332,17 +332,17 @@ DivideExpDataByNumMonsGainingExp: ; multiplies exp by 1.5 BoostExp: - ld a, [H_QUOTIENT + 2] + ldh a, [hQuotient + 2] ld b, a - ld a, [H_QUOTIENT + 3] + ldh a, [hQuotient + 3] ld c, a srl b rr c add c - ld [H_QUOTIENT + 3], a - ld a, [H_QUOTIENT + 2] + ldh [hQuotient + 3], a + ldh a, [hQuotient + 2] adc b - ld [H_QUOTIENT + 2], a + ldh [hQuotient + 2], a ret Bankswitch15ToF: @@ -350,8 +350,8 @@ Bankswitch15ToF: jp Bankswitch GainedText: - TX_FAR _GainedText - TX_ASM + text_far _GainedText + text_asm ld a, [wBoostExpByExpAll] ld hl, WithExpAllText and a @@ -364,19 +364,19 @@ GainedText: ret WithExpAllText: - TX_FAR _WithExpAllText - TX_ASM + text_far _WithExpAllText + text_asm ld hl, ExpPointsText ret BoostedText: - TX_FAR _BoostedText + text_far _BoostedText ExpPointsText: - TX_FAR _ExpPointsText - db "@" + text_far _ExpPointsText + text_end GrewLevelText: - TX_FAR _GrewLevelText - TX_SFX_LEVEL_UP - db "@" + text_far _GrewLevelText + sound_level_up + text_end diff --git a/engine/battle/get_trainer_name.asm b/engine/battle/get_trainer_name.asm index 36ca019e..b2daebfe 100644 --- a/engine/battle/get_trainer_name.asm +++ b/engine/battle/get_trainer_name.asm @@ -1,15 +1,15 @@ -GetTrainerName_: +GetTrainerName_:: ld hl, wGrassRate ld a, [wLinkState] and a jr nz, .foundName ld hl, wRivalName ld a, [wTrainerClass] - cp SONY1 + cp RIVAL1 jr z, .foundName - cp SONY2 + cp RIVAL2 jr z, .foundName - cp SONY3 + cp RIVAL3 jr z, .foundName ld [wd0b5], a ld a, TRAINER_NAME diff --git a/engine/battle/ghost_marowak_anim.asm b/engine/battle/ghost_marowak_anim.asm index 972d5bf5..03059022 100644 --- a/engine/battle/ghost_marowak_anim.asm +++ b/engine/battle/ghost_marowak_anim.asm @@ -1,22 +1,22 @@ MarowakAnim: ; animate the ghost being unveiled as a Marowak ld a, $e4 - ld [rOBP1], a + ldh [rOBP1], a call UpdateGBCPal_OBP1 call CopyMonPicFromBGToSpriteVRAM ; cover the BG ghost pic with a sprite ghost pic that looks the same ; now that the ghost pic is being displayed using sprites, clear the ghost pic from the BG tilemap - coord hl, 12, 0 + hlcoord 12, 0 lb bc, 7, 7 call ClearScreenArea call Delay3 xor a - ld [H_AUTOBGTRANSFERENABLED], a ; disable BG transfer so we don't see the Marowak too soon + ldh [hAutoBGTransferEnabled], a ; disable BG transfer so we don't see the Marowak too soon ; replace ghost pic with Marowak in BG ld a, RESTLESS_SOUL ld [wChangeMonPicEnemyTurnSpecies], a ld a, $1 - ld [H_WHOSETURN], a - callab ChangeMonPic + ldh [hWhoseTurn], a + callfar ChangeMonPic ; alternate between black and light grey 8 times. ; this makes the ghost's body appear to flash ld d, $80 @@ -24,10 +24,10 @@ MarowakAnim: .fadeOutGhostLoop ld c, 10 call DelayFrames - ld a, [rOBP1] + ldh a, [rOBP1] sla a sla a - ld [rOBP1], a + ldh [rOBP1], a call UpdateGBCPal_OBP1 jr nz, .fadeOutGhostLoop call ClearSprites @@ -36,18 +36,18 @@ MarowakAnim: .fadeInMarowakLoop ld c, 10 call DelayFrames - ld a, [rOBP1] + ldh a, [rOBP1] srl b rra srl b rra - ld [rOBP1], a + ldh [rOBP1], a call UpdateGBCPal_OBP1 ld a, b and a jr nz, .fadeInMarowakLoop ld a, $1 - ld [H_AUTOBGTRANSFERENABLED], a ; enable BG transfer so the BG Marowak pic will be visible after the sprite one is cleared + ldh [hAutoBGTransferEnabled], a ; enable BG transfer so the BG Marowak pic will be visible after the sprite one is cleared call Delay3 jp ClearSprites diff --git a/engine/battle/init_battle_variables.asm b/engine/battle/init_battle_variables.asm index 7bc912d2..0d403b55 100644 --- a/engine/battle/init_battle_variables.asm +++ b/engine/battle/init_battle_variables.asm @@ -1,5 +1,5 @@ InitBattleVariables: - ld a, [hTilesetType] + ldh a, [hTilesetType] ld [wSavedTilesetType], a xor a ld [wActionResultOrTookBattleTurn], a @@ -35,4 +35,4 @@ InitBattleVariables: ld a, BATTLE_TYPE_SAFARI ld [wBattleType], a .notSafariBattle - jpab PlayBattleMusic + jpfar PlayBattleMusic diff --git a/engine/battle/link_battle_versus_text.asm b/engine/battle/link_battle_versus_text.asm index 63142ba6..e55a0672 100644 --- a/engine/battle/link_battle_versus_text.asm +++ b/engine/battle/link_battle_versus_text.asm @@ -1,22 +1,22 @@ ; display "[player] VS [enemy]" text box with pokeballs representing their parties next to the names DisplayLinkBattleVersusTextBox: call LoadTextBoxTilePatterns - coord hl, 3, 4 + hlcoord 3, 4 lb bc, 7, 12 call TextBoxBorder - coord hl, 4, 5 + hlcoord 4, 5 ld de, wPlayerName call PlaceString - coord hl, 4, 10 + hlcoord 4, 10 ld de, wLinkEnemyTrainerName call PlaceString ; place bold "VS" tiles between the names - coord hl, 9, 8 + hlcoord 9, 8 ld a, $69 ld [hli], a ld [hl], $6a xor a ld [wUpdateSpritesEnabled], a - callab SetupPlayerAndEnemyPokeballs + callfar SetupPlayerAndEnemyPokeballs ld c, 150 jp DelayFrames diff --git a/engine/battle/misc.asm b/engine/battle/misc.asm new file mode 100755 index 00000000..df9145f2 --- /dev/null +++ b/engine/battle/misc.asm @@ -0,0 +1,103 @@ +; formats a string at wMovesString that lists the moves at wMoves +FormatMovesString: + ld hl, wMoves + ld de, wMovesString + ld b, $0 +.printMoveNameLoop + ld a, [hli] + and a ; end of move list? + jr z, .printDashLoop ; print dashes when no moves are left + push hl + ld [wd0b5], a + ld a, BANK(MoveNames) + ld [wPredefBank], a + ld a, MOVE_NAME + ld [wNameListType], a + call GetName + ld hl, wcd6d +.copyNameLoop + ld a, [hli] + cp $50 + jr z, .doneCopyingName + ld [de], a + inc de + jr .copyNameLoop +.doneCopyingName + ld a, b + ld [wNumMovesMinusOne], a + inc b + ld a, $4e ; line break + ld [de], a + inc de + pop hl + ld a, b + cp NUM_MOVES + jr z, .done + jr .printMoveNameLoop +.printDashLoop + ld a, "-" + ld [de], a + inc de + inc b + ld a, b + cp NUM_MOVES + jr z, .done + ld a, $4e ; line break + ld [de], a + inc de + jr .printDashLoop +.done + ld a, "@" + ld [de], a + ret + +; XXX this is called in a few places, but it doesn't appear to do anything useful +InitList: + ld a, [wInitListType] + cp INIT_ENEMYOT_LIST + jr nz, .notEnemy + ld hl, wEnemyPartyCount + ld de, wEnemyMonOT + ld a, ENEMYOT_NAME + jr .done +.notEnemy + cp INIT_PLAYEROT_LIST + jr nz, .notPlayer + ld hl, wPartyCount + ld de, wPartyMonOT + ld a, PLAYEROT_NAME + jr .done +.notPlayer + cp INIT_MON_LIST + jr nz, .notMonster + ld hl, wItemList + ld de, MonsterNames + ld a, MONSTER_NAME + jr .done +.notMonster + cp INIT_BAG_ITEM_LIST + jr nz, .notBag + ld hl, wNumBagItems + ld de, ItemNames + ld a, ITEM_NAME + jr .done +.notBag + ld hl, wItemList + ld de, ItemNames + ld a, ITEM_NAME +.done + ld [wNameListType], a + ld a, l + ld [wListPointer], a + ld a, h + ld [wListPointer + 1], a + ld a, e + ld [wUnusedCF8D], a + ld a, d + ld [wUnusedCF8D + 1], a + ld bc, ItemPrices + ld a, c + ld [wItemPrices], a + ld a, b + ld [wItemPrices + 1], a + ret diff --git a/engine/battle/moveEffects/conversion_effect.asm b/engine/battle/moveEffects/conversion_effect.asm deleted file mode 100644 index f23c3d70..00000000 --- a/engine/battle/moveEffects/conversion_effect.asm +++ /dev/null @@ -1,35 +0,0 @@ -ConversionEffect_: - ld hl, wEnemyMonType1 - ld de, wBattleMonType1 - ld a, [H_WHOSETURN] - and a - ld a, [wEnemyBattleStatus1] - jr z, .conversionEffect - push hl - ld h, d - ld l, e - pop de - ld a, [wPlayerBattleStatus1] -.conversionEffect - bit INVULNERABLE, a ; is mon immune to typical attacks (dig/fly) - jr nz, PrintButItFailedText -; copy target's types to user - ld a, [hli] - ld [de], a - inc de - ld a, [hl] - ld [de], a - ld hl, PlayCurrentMoveAnimation - call CallBankF - ld hl, ConvertedTypeText - jp PrintText - -ConvertedTypeText: - TX_FAR _ConvertedTypeText - db "@" - -PrintButItFailedText: - ld hl, PrintButItFailedText_ -CallBankF: - ld b, BANK(PrintButItFailedText_) - jp Bankswitch diff --git a/engine/battle/moveEffects/drain_hp_effect.asm b/engine/battle/moveEffects/drain_hp_effect.asm deleted file mode 100644 index e5f4681a..00000000 --- a/engine/battle/moveEffects/drain_hp_effect.asm +++ /dev/null @@ -1,104 +0,0 @@ -DrainHPEffect_: - ld hl, wDamage - ld a, [hl] - srl a ; divide damage by 2 - ld [hli], a - ld a, [hl] - rr a - ld [hld], a - or [hl] ; is damage 0? - jr nz, .getAttackerHP -; if damage is 0, increase to 1 so that the attacker gains at least 1 HP - inc hl - inc [hl] -.getAttackerHP - ld hl, wBattleMonHP - ld de, wBattleMonMaxHP - ld a, [H_WHOSETURN] - and a - jp z, .addDamageToAttackerHP - ld hl, wEnemyMonHP - ld de, wEnemyMonMaxHP -.addDamageToAttackerHP - ld bc, wHPBarOldHP+1 -; copy current HP to wHPBarOldHP - ld a, [hli] - ld [bc], a - ld a, [hl] - dec bc - ld [bc], a -; copy max HP to wHPBarMaxHP - ld a, [de] - dec bc - ld [bc], a - inc de - ld a, [de] - dec bc - ld [bc], a -; add damage to attacker's HP and copy new HP to wHPBarNewHP - ld a, [wDamage + 1] - ld b, [hl] - add b - ld [hld], a - ld [wHPBarNewHP], a - ld a, [wDamage] - ld b, [hl] - adc b - ld [hli], a - ld [wHPBarNewHP+1], a - jr c, .capToMaxHP ; if HP > 65,535, cap to max HP -; compare HP with max HP - ld a, [hld] - ld b, a - ld a, [de] - dec de - sub b - ld a, [hli] - ld b, a - ld a, [de] - inc de - sbc b - jr nc, .next -.capToMaxHP - ld a, [de] - ld [hld], a - ld [wHPBarNewHP], a - dec de - ld a, [de] - ld [hli], a - ld [wHPBarNewHP+1], a - inc de -.next - ld a, [H_WHOSETURN] - and a - coord hl, 10, 9 - ld a, $1 - jr z, .next2 - coord hl, 2, 2 - xor a -.next2 - ld [wHPBarType], a - predef UpdateHPBar2 - predef DrawPlayerHUDAndHPBar - predef DrawEnemyHUDAndHPBar - callab ReadPlayerMonCurHPAndStatus - ld hl, SuckedHealthText - ld a, [H_WHOSETURN] - and a - ld a, [wPlayerMoveEffect] - jr z, .next3 - ld a, [wEnemyMoveEffect] -.next3 - cp DREAM_EATER_EFFECT - jr nz, .printText - ld hl, DreamWasEatenText -.printText - jp PrintText - -SuckedHealthText: - TX_FAR _SuckedHealthText - db "@" - -DreamWasEatenText: - TX_FAR _DreamWasEatenText - db "@" diff --git a/engine/battle/moveEffects/focus_energy_effect.asm b/engine/battle/moveEffects/focus_energy_effect.asm deleted file mode 100644 index 16dad7bb..00000000 --- a/engine/battle/moveEffects/focus_energy_effect.asm +++ /dev/null @@ -1,22 +0,0 @@ -FocusEnergyEffect_: - ld hl, wPlayerBattleStatus2 - ld a, [H_WHOSETURN] - and a - jr z, .notEnemy - ld hl, wEnemyBattleStatus2 -.notEnemy - bit GETTING_PUMPED, [hl] ; is mon already using focus energy? - jr nz, .alreadyUsing - set GETTING_PUMPED, [hl] ; mon is now using focus energy - callab PlayCurrentMoveAnimation - ld hl, GettingPumpedText - jp PrintText -.alreadyUsing - ld c, 50 - call DelayFrames - jpab PrintButItFailedText_ - -GettingPumpedText: - TX_DELAY - TX_FAR _GettingPumpedText - db "@" diff --git a/engine/battle/moveEffects/haze_effect.asm b/engine/battle/moveEffects/haze_effect.asm deleted file mode 100644 index 47723ba2..00000000 --- a/engine/battle/moveEffects/haze_effect.asm +++ /dev/null @@ -1,81 +0,0 @@ -HazeEffect_: - ld a, $7 -; store 7 on every stat mod - ld hl, wPlayerMonAttackMod - call ResetStatMods - ld hl, wEnemyMonAttackMod - call ResetStatMods -; copy unmodified stats to battle stats - ld hl, wPlayerMonUnmodifiedAttack - ld de, wBattleMonAttack - call ResetStats - ld hl, wEnemyMonUnmodifiedAttack - ld de, wEnemyMonAttack - call ResetStats -; cure non-volatile status, but only for the target - ld hl, wEnemyMonStatus - ld de, wEnemySelectedMove - ld a, [H_WHOSETURN] - and a - jr z, .cureStatuses - ld hl, wBattleMonStatus - dec de ; wPlayerSelectedMove - -.cureStatuses - ld a, [hl] - ld [hl], $0 - and SLP | (1 << FRZ) - jr z, .cureVolatileStatuses -; prevent the Pokemon from executing a move if it was asleep or frozen - ld a, $ff - ld [de], a - -.cureVolatileStatuses - xor a - ld [wPlayerDisabledMove], a - ld [wEnemyDisabledMove], a - ld hl, wPlayerDisabledMoveNumber - ld [hli], a - ld [hl], a - ld hl, wPlayerBattleStatus1 - call CureVolatileStatuses - ld hl, wEnemyBattleStatus1 - call CureVolatileStatuses - ld hl, PlayCurrentMoveAnimation - call CallBankF - ld hl, StatusChangesEliminatedText - jp PrintText - -CureVolatileStatuses: - res CONFUSED, [hl] - inc hl ; BATTSTATUS2 - ld a, [hl] - ; clear USING_X_ACCURACY, PROTECTED_BY_MIST, GETTING_PUMPED, and SEEDED statuses - and $ff ^((1 << USING_X_ACCURACY) | (1 << PROTECTED_BY_MIST) | (1 << GETTING_PUMPED) | (1 << SEEDED)) - ld [hli], a ; BATTSTATUS3 - ld a, [hl] - and %11110000 | (1 << TRANSFORMED) ; clear Bad Poison, Reflect and Light Screen statuses - ld [hl], a - ret - -ResetStatMods: - ld b, $8 -.loop - ld [hli], a - dec b - jr nz, .loop - ret - -ResetStats: - ld b, $8 -.loop - ld a, [hli] - ld [de], a - inc de - dec b - jr nz, .loop - ret - -StatusChangesEliminatedText: - TX_FAR _StatusChangesEliminatedText - db "@" diff --git a/engine/battle/moveEffects/heal_effect.asm b/engine/battle/moveEffects/heal_effect.asm deleted file mode 100644 index 97afa394..00000000 --- a/engine/battle/moveEffects/heal_effect.asm +++ /dev/null @@ -1,120 +0,0 @@ -HealEffect_: - ld a, [H_WHOSETURN] - and a - ld de, wBattleMonHP - ld hl, wBattleMonMaxHP - ld a, [wPlayerMoveNum] - jr z, .healEffect - ld de, wEnemyMonHP - ld hl, wEnemyMonMaxHP - ld a, [wEnemyMoveNum] -.healEffect - ld b, a - ld a, [de] - cp [hl] ; most significant bytes comparison is ignored - ; causes the move to miss if max HP is 255 or 511 points higher than the current HP - inc de - inc hl - ld a, [de] - sbc [hl] - jp z, .failed ; no effect if user's HP is already at its maximum - ld a, b - cp REST - jr nz, .healHP - push hl - push de - push af - ld c, 50 - call DelayFrames - ld hl, wBattleMonStatus - ld a, [H_WHOSETURN] - and a - jr z, .restEffect - ld hl, wEnemyMonStatus -.restEffect - ld a, [hl] - and a - ld [hl], 2 ; clear status and set number of turns asleep to 2 - ld hl, StartedSleepingEffect ; if mon didn't have an status - jr z, .printRestText - ld hl, FellAsleepBecameHealthyText ; if mon had an status -.printRestText - call PrintText - pop af - pop de - pop hl -.healHP - ld a, [hld] - ld [wHPBarMaxHP], a - ld c, a - ld a, [hl] - ld [wHPBarMaxHP+1], a - ld b, a - jr z, .gotHPAmountToHeal -; Recover and Softboiled only heal for half the mon's max HP - srl b - rr c -.gotHPAmountToHeal -; update HP - ld a, [de] - ld [wHPBarOldHP], a - add c - ld [de], a - ld [wHPBarNewHP], a - dec de - ld a, [de] - ld [wHPBarOldHP+1], a - adc b - ld [de], a - ld [wHPBarNewHP+1], a - inc hl - inc de - ld a, [de] - dec de - sub [hl] - dec hl - ld a, [de] - sbc [hl] - jr c, .playAnim -; copy max HP to current HP if an overflow occurred - ld a, [hli] - ld [de], a - ld [wHPBarNewHP+1], a - inc de - ld a, [hl] - ld [de], a - ld [wHPBarNewHP], a -.playAnim - ld hl, PlayCurrentMoveAnimation - call Bankswitch3DtoF - ld a, [H_WHOSETURN] - and a - coord hl, 10, 9 - ld a, $1 - jr z, .updateHPBar - coord hl, 2, 2 - xor a -.updateHPBar - ld [wHPBarType], a - predef UpdateHPBar2 - ld hl, DrawHUDsAndHPBars - call Bankswitch3DtoF - ld hl, RegainedHealthText - jp PrintText -.failed - ld c, 50 - call DelayFrames - ld hl, PrintButItFailedText_ - jp Bankswitch3DtoF - -StartedSleepingEffect: - TX_FAR _StartedSleepingEffect - db "@" - -FellAsleepBecameHealthyText: - TX_FAR _FellAsleepBecameHealthyText - db "@" - -RegainedHealthText: - TX_FAR _RegainedHealthText - db "@" diff --git a/engine/battle/moveEffects/leech_seed_effect.asm b/engine/battle/moveEffects/leech_seed_effect.asm deleted file mode 100644 index f4d3ee9c..00000000 --- a/engine/battle/moveEffects/leech_seed_effect.asm +++ /dev/null @@ -1,40 +0,0 @@ -LeechSeedEffect_: - callab MoveHitTest - ld a, [wMoveMissed] - and a - jr nz, .moveMissed - ld hl, wEnemyBattleStatus2 - ld de, wEnemyMonType1 - ld a, [H_WHOSETURN] - and a - jr z, .leechSeedEffect - ld hl, wPlayerBattleStatus2 - ld de, wBattleMonType1 -.leechSeedEffect -; miss if the target is grass-type or already seeded - ld a, [de] - cp GRASS - jr z, .moveMissed - inc de - ld a, [de] - cp GRASS - jr z, .moveMissed - bit SEEDED, [hl] - jr nz, .moveMissed - set SEEDED, [hl] - callab PlayCurrentMoveAnimation - ld hl, WasSeededText - jp PrintText -.moveMissed - ld c, 50 - call DelayFrames - ld hl, EvadedAttackText - jp PrintText - -WasSeededText: - TX_FAR _WasSeededText - db "@" - -EvadedAttackText: - TX_FAR _EvadedAttackText - db "@" diff --git a/engine/battle/moveEffects/mist_effect.asm b/engine/battle/moveEffects/mist_effect.asm deleted file mode 100644 index 65070a3e..00000000 --- a/engine/battle/moveEffects/mist_effect.asm +++ /dev/null @@ -1,19 +0,0 @@ -MistEffect_: - ld hl, wPlayerBattleStatus2 - ld a, [H_WHOSETURN] - and a - jr z, .mistEffect - ld hl, wEnemyBattleStatus2 -.mistEffect - bit PROTECTED_BY_MIST, [hl] ; is mon protected by mist? - jr nz, .mistAlreadyInUse - set PROTECTED_BY_MIST, [hl] ; mon is now protected by mist - callab PlayCurrentMoveAnimation - ld hl, ShroudedInMistText - jp PrintText -.mistAlreadyInUse - jpab PrintButItFailedText_ - -ShroudedInMistText: - TX_FAR _ShroudedInMistText - db "@" diff --git a/engine/battle/moveEffects/one_hit_ko_effect.asm b/engine/battle/moveEffects/one_hit_ko_effect.asm deleted file mode 100644 index 827e2197..00000000 --- a/engine/battle/moveEffects/one_hit_ko_effect.asm +++ /dev/null @@ -1,38 +0,0 @@ -OneHitKOEffect_: - ld hl, wDamage - xor a - ld [hli], a - ld [hl], a ; set the damage output to zero - dec a - ld [wCriticalHitOrOHKO], a - ld hl, wBattleMonSpeed + 1 - ld de, wEnemyMonSpeed + 1 - ld a, [H_WHOSETURN] - and a - jr z, .compareSpeed - ld hl, wEnemyMonSpeed + 1 - ld de, wBattleMonSpeed + 1 -.compareSpeed -; set damage to 65535 and OHKO flag is the user's current speed is higher than the target's - ld a, [de] - dec de - ld b, a - ld a, [hld] - sub b - ld a, [de] - ld b, a - ld a, [hl] - sbc b - jr c, .userIsSlower - ld hl, wDamage - ld a, $ff - ld [hli], a - ld [hl], a - ld a, $2 - ld [wCriticalHitOrOHKO], a - ret -.userIsSlower -; keep damage at 0 and set move missed flag if target's current speed is higher instead - ld a, $1 - ld [wMoveMissed], a - ret diff --git a/engine/battle/moveEffects/paralyze_effect.asm b/engine/battle/moveEffects/paralyze_effect.asm deleted file mode 100644 index 95979ae6..00000000 --- a/engine/battle/moveEffects/paralyze_effect.asm +++ /dev/null @@ -1,47 +0,0 @@ -ParalyzeEffect_: - ld hl, wEnemyMonStatus - ld de, wPlayerMoveType - ld a, [H_WHOSETURN] - and a - jp z, .next - ld hl, wBattleMonStatus - ld de, wEnemyMoveType -.next - ld a, [hl] - and a ; does the target already have a status ailment? - jr nz, .didntAffect -; check if the target is immune due to types - ld a, [de] - cp ELECTRIC - jr nz, .hitTest - ld b, h - ld c, l - inc bc - ld a, [bc] - cp GROUND - jr z, .doesntAffect - inc bc - ld a, [bc] - cp GROUND - jr z, .doesntAffect -.hitTest - push hl - callab MoveHitTest - pop hl - ld a, [wMoveMissed] - and a - jr nz, .didntAffect - set PAR, [hl] - callab QuarterSpeedDueToParalysis - ld c, 30 - call DelayFrames - callab PlayCurrentMoveAnimation - jpab PrintMayNotAttackText -.didntAffect - ld c, 50 - call DelayFrames - jpab PrintDidntAffectText -.doesntAffect - ld c, 50 - call DelayFrames - jpab PrintDoesntAffectText diff --git a/engine/battle/moveEffects/pay_day_effect.asm b/engine/battle/moveEffects/pay_day_effect.asm deleted file mode 100644 index e5daf014..00000000 --- a/engine/battle/moveEffects/pay_day_effect.asm +++ /dev/null @@ -1,45 +0,0 @@ -PayDayEffect_: - xor a - ld hl, wcd6d - ld [hli], a - ld a, [H_WHOSETURN] - and a - ld a, [wBattleMonLevel] - jr z, .payDayEffect - ld a, [wEnemyMonLevel] -.payDayEffect -; level * 2 - add a - ld [H_DIVIDEND + 3], a - xor a - ld [H_DIVIDEND], a - ld [H_DIVIDEND + 1], a - ld [H_DIVIDEND + 2], a -; convert to BCD - ld a, 100 - ld [H_DIVISOR], a - ld b, $4 - call Divide - ld a, [H_QUOTIENT + 3] - ld [hli], a - ld a, [H_REMAINDER] - ld [H_DIVIDEND + 3], a - ld a, 10 - ld [H_DIVISOR], a - ld b, $4 - call Divide - ld a, [H_QUOTIENT + 3] - swap a - ld b, a - ld a, [H_REMAINDER] - add b - ld [hl], a - ld de, wTotalPayDayMoney + 2 - ld c, $3 - predef AddBCDPredef - ld hl, CoinsScatteredText - jp PrintText - -CoinsScatteredText: - TX_FAR _CoinsScatteredText - db "@" diff --git a/engine/battle/moveEffects/recoil_effect.asm b/engine/battle/moveEffects/recoil_effect.asm deleted file mode 100644 index 0f2f087b..00000000 --- a/engine/battle/moveEffects/recoil_effect.asm +++ /dev/null @@ -1,70 +0,0 @@ -RecoilEffect_: - ld a, [H_WHOSETURN] - and a - ld a, [wPlayerMoveNum] - ld hl, wBattleMonMaxHP - jr z, .recoilEffect - ld a, [wEnemyMoveNum] - ld hl, wEnemyMonMaxHP -.recoilEffect - ld d, a - ld a, [wDamage] - ld b, a - ld a, [wDamage + 1] - ld c, a - srl b - rr c - ld a, d - cp STRUGGLE ; struggle deals 50% recoil damage - jr z, .gotRecoilDamage - srl b - rr c -.gotRecoilDamage - ld a, b - or c - jr nz, .updateHP - inc c ; minimum recoil damage is 1 -.updateHP -; subtract HP from user due to the recoil damage - ld a, [hli] - ld [wHPBarMaxHP+1], a - ld a, [hl] - ld [wHPBarMaxHP], a - push bc - ld bc, wBattleMonHP - wBattleMonMaxHP - add hl, bc - pop bc - ld a, [hl] - ld [wHPBarOldHP], a - sub c - ld [hld], a - ld [wHPBarNewHP], a - ld a, [hl] - ld [wHPBarOldHP+1], a - sbc b - ld [hl], a - ld [wHPBarNewHP+1], a - jr nc, .getHPBarCoords -; if recoil damage is higher than the Pokemon's HP, set its HP to 0 - xor a - ld [hli], a - ld [hl], a - ld hl, wHPBarNewHP - ld [hli], a - ld [hl], a -.getHPBarCoords - coord hl, 10, 9 - ld a, [H_WHOSETURN] - and a - ld a, $1 - jr z, .updateHPBar - coord hl, 2, 2 - xor a -.updateHPBar - ld [wHPBarType], a - predef UpdateHPBar2 - ld hl, HitWithRecoilText - jp PrintText -HitWithRecoilText: - TX_FAR _HitWithRecoilText - db "@" diff --git a/engine/battle/moveEffects/reflect_light_screen_effect.asm b/engine/battle/moveEffects/reflect_light_screen_effect.asm deleted file mode 100644 index e5748b19..00000000 --- a/engine/battle/moveEffects/reflect_light_screen_effect.asm +++ /dev/null @@ -1,45 +0,0 @@ -ReflectLightScreenEffect_: - ld hl, wPlayerBattleStatus3 - ld de, wPlayerMoveEffect - ld a, [H_WHOSETURN] - and a - jr z, .reflectLightScreenEffect - ld hl, wEnemyBattleStatus3 - ld de, wEnemyMoveEffect -.reflectLightScreenEffect - ld a, [de] - cp LIGHT_SCREEN_EFFECT - jr nz, .reflect - bit HAS_LIGHT_SCREEN_UP, [hl] ; is mon already protected by light screen? - jr nz, .moveFailed - set HAS_LIGHT_SCREEN_UP, [hl] ; mon is now protected by light screen - ld hl, LightScreenProtectedText - jr .playAnim -.reflect - bit HAS_REFLECT_UP, [hl] ; is mon already protected by reflect? - jr nz, .moveFailed - set HAS_REFLECT_UP, [hl] ; mon is now protected by reflect - ld hl, ReflectGainedArmorText -.playAnim - push hl - ld hl, PlayCurrentMoveAnimation - call Bankswitch3DtoF - pop hl - jp PrintText -.moveFailed - ld c, 50 - call DelayFrames - ld hl, PrintButItFailedText_ - jp Bankswitch3DtoF - -LightScreenProtectedText: - TX_FAR _LightScreenProtectedText - db "@" - -ReflectGainedArmorText: - TX_FAR _ReflectGainedArmorText - db "@" - -Bankswitch3DtoF: - ld b, BANK(BattleCore) - jp Bankswitch diff --git a/engine/battle/moveEffects/substitute_effect.asm b/engine/battle/moveEffects/substitute_effect.asm deleted file mode 100644 index b5d006fc..00000000 --- a/engine/battle/moveEffects/substitute_effect.asm +++ /dev/null @@ -1,77 +0,0 @@ -SubstituteEffect_: - ld c, 50 - call DelayFrames - ld hl, wBattleMonMaxHP - ld de, wPlayerSubstituteHP - ld bc, wPlayerBattleStatus2 - ld a, [H_WHOSETURN] - and a - jr z, .notEnemy - ld hl, wEnemyMonMaxHP - ld de, wEnemySubstituteHP - ld bc, wEnemyBattleStatus2 -.notEnemy - ld a, [bc] - bit HAS_SUBSTITUTE_UP, a ; user already has substitute? - jr nz, .alreadyHasSubstitute -; quarter health to remove from user -; assumes max HP is 1023 or lower - push bc - ld a, [hli] - ld b, [hl] - srl a - rr b - srl a - rr b ; max hp / 4 - push de - ld de, wBattleMonHP - wBattleMonMaxHP - add hl, de ; point hl to current HP low byte - pop de - ld a, b - ld [de], a ; save copy of HP to subtract in ccd7/ccd8 [how much HP substitute has] - ld a, [hld] -; subtract [max hp / 4] to current HP - sub b - ld d, a - ld a, [hl] - sbc 0 - pop bc - jr c, .notEnoughHP ; underflow means user would be left with negative health - ; bug: since it only branches on carry, it will possibly leave user with 0 HP -.userHasZeroOrMoreHP - ldi [hl], a ; save resulting HP after subtraction into current HP - ld [hl], d - ld h, b - ld l, c - set HAS_SUBSTITUTE_UP, [hl] - ld a, [wOptions] - bit 7, a ; battle animation is enabled? - ld hl, PlayCurrentMoveAnimation - ld b, BANK(PlayCurrentMoveAnimation) - jr z, .animationEnabled - ld hl, AnimationSubstitute - ld b, BANK(AnimationSubstitute) -.animationEnabled - call Bankswitch ; jump to routine depending on animation setting - ld hl, SubstituteText - call PrintText - jpab DrawHUDsAndHPBars -.alreadyHasSubstitute - ld hl, HasSubstituteText - jr .printText -.notEnoughHP - ld hl, TooWeakSubstituteText -.printText - jp PrintText - -SubstituteText: - TX_FAR _SubstituteText - db "@" - -HasSubstituteText: - TX_FAR _HasSubstituteText - db "@" - -TooWeakSubstituteText: - TX_FAR _TooWeakSubstituteText - db "@" diff --git a/engine/battle/moveEffects/transform_effect.asm b/engine/battle/moveEffects/transform_effect.asm deleted file mode 100644 index ec07b303..00000000 --- a/engine/battle/moveEffects/transform_effect.asm +++ /dev/null @@ -1,141 +0,0 @@ -TransformEffect_: - ld hl, wBattleMonSpecies - ld de, wEnemyMonSpecies - ld bc, wEnemyBattleStatus3 - ld a, [wEnemyBattleStatus1] - ld a, [H_WHOSETURN] - and a - jr nz, .hitTest - ld hl, wEnemyMonSpecies - ld de, wBattleMonSpecies - ld bc, wPlayerBattleStatus3 - ld [wPlayerMoveListIndex], a - ld a, [wPlayerBattleStatus1] -.hitTest - bit INVULNERABLE, a ; is mon invulnerable to typical attacks? (fly/dig) - jp nz, .failed - push hl - push de - push bc - ld hl, wPlayerBattleStatus2 - ld a, [H_WHOSETURN] - and a - jr z, .transformEffect - ld hl, wEnemyBattleStatus2 -.transformEffect -; animation(s) played are different if target has Substitute up - bit HAS_SUBSTITUTE_UP, [hl] - push af - ld hl, HideSubstituteShowMonAnim - ld b, BANK(HideSubstituteShowMonAnim) - call nz, Bankswitch - ld a, [wOptions] - add a - ld hl, PlayCurrentMoveAnimation - ld b, BANK(PlayCurrentMoveAnimation) - jr nc, .gotAnimToPlay - ld hl, AnimationTransformMon - ld b, BANK(AnimationTransformMon) -.gotAnimToPlay - call Bankswitch - ld hl, ReshowSubstituteAnim - ld b, BANK(ReshowSubstituteAnim) - pop af - call nz, Bankswitch - pop bc - ld a, [bc] - set TRANSFORMED, a ; mon is now transformed - ld [bc], a - pop de - pop hl - push hl -; transform user into opposing Pokemon -; species - ld a, [hl] - ld [de], a -; type 1, type 2, catch rate, and moves - ld bc, $5 - add hl, bc - inc de - inc de - inc de - inc de - inc de - inc bc - inc bc - call CopyData - ld a, [H_WHOSETURN] - and a - jr z, .next -; save enemy mon DVs at wTransformedEnemyMonOriginalDVs - ld a, [de] - ld [wTransformedEnemyMonOriginalDVs], a - inc de - ld a, [de] - ld [wTransformedEnemyMonOriginalDVs + 1], a - dec de -.next -; DVs - ld a, [hli] - ld [de], a - inc de - ld a, [hli] - ld [de], a - inc de -; Attack, Defense, Speed, and Special stats - inc hl - inc hl - inc hl - inc de - inc de - inc de - ld bc, $8 - call CopyData - ld bc, wBattleMonMoves - wBattleMonPP - add hl, bc ; ld hl, wBattleMonMoves - ld b, NUM_MOVES -.copyPPLoop -; 5 PP for all moves - ld a, [hli] - and a - jr z, .lessThanFourMoves - ld a, $5 -.lessThanFourMoves - ld [de], a - inc de - dec b - jr nz, .copyPPLoop -.copyStats -; original (unmodified) stats and stat mods - pop hl - ld a, [hl] - ld [wd11e], a - call GetMonName - ld hl, wEnemyMonUnmodifiedAttack - ld de, wPlayerMonUnmodifiedAttack - call .copyBasedOnTurn ; original (unmodified) stats - ld hl, wEnemyMonStatMods - ld de, wPlayerMonStatMods - call .copyBasedOnTurn ; stat mods - ld hl, TransformedText - jp PrintText - -.copyBasedOnTurn - ld a, [H_WHOSETURN] - and a - jr z, .gotStatsOrModsToCopy - push hl - ld h, d - ld l, e - pop de -.gotStatsOrModsToCopy - ld bc, $8 - jp CopyData - -.failed - ld hl, PrintButItFailedText_ - jp Bankswitch3DtoF - -TransformedText: - TX_FAR _TransformedText - db "@" diff --git a/engine/battle/move_effects/conversion.asm b/engine/battle/move_effects/conversion.asm new file mode 100644 index 00000000..1f64ec5b --- /dev/null +++ b/engine/battle/move_effects/conversion.asm @@ -0,0 +1,35 @@ +ConversionEffect_: + ld hl, wEnemyMonType1 + ld de, wBattleMonType1 + ldh a, [hWhoseTurn] + and a + ld a, [wEnemyBattleStatus1] + jr z, .conversionEffect + push hl + ld h, d + ld l, e + pop de + ld a, [wPlayerBattleStatus1] +.conversionEffect + bit INVULNERABLE, a ; is mon immune to typical attacks (dig/fly) + jr nz, PrintButItFailedText +; copy target's types to user + ld a, [hli] + ld [de], a + inc de + ld a, [hl] + ld [de], a + ld hl, PlayCurrentMoveAnimation + call CallBankF + ld hl, ConvertedTypeText + jp PrintText + +ConvertedTypeText: + text_far _ConvertedTypeText + text_end + +PrintButItFailedText: + ld hl, PrintButItFailedText_ +CallBankF: + ld b, BANK(PrintButItFailedText_) + jp Bankswitch diff --git a/engine/battle/move_effects/drain_hp.asm b/engine/battle/move_effects/drain_hp.asm new file mode 100644 index 00000000..04a585cc --- /dev/null +++ b/engine/battle/move_effects/drain_hp.asm @@ -0,0 +1,104 @@ +DrainHPEffect_: + ld hl, wDamage + ld a, [hl] + srl a ; divide damage by 2 + ld [hli], a + ld a, [hl] + rr a + ld [hld], a + or [hl] ; is damage 0? + jr nz, .getAttackerHP +; if damage is 0, increase to 1 so that the attacker gains at least 1 HP + inc hl + inc [hl] +.getAttackerHP + ld hl, wBattleMonHP + ld de, wBattleMonMaxHP + ldh a, [hWhoseTurn] + and a + jp z, .addDamageToAttackerHP + ld hl, wEnemyMonHP + ld de, wEnemyMonMaxHP +.addDamageToAttackerHP + ld bc, wHPBarOldHP+1 +; copy current HP to wHPBarOldHP + ld a, [hli] + ld [bc], a + ld a, [hl] + dec bc + ld [bc], a +; copy max HP to wHPBarMaxHP + ld a, [de] + dec bc + ld [bc], a + inc de + ld a, [de] + dec bc + ld [bc], a +; add damage to attacker's HP and copy new HP to wHPBarNewHP + ld a, [wDamage + 1] + ld b, [hl] + add b + ld [hld], a + ld [wHPBarNewHP], a + ld a, [wDamage] + ld b, [hl] + adc b + ld [hli], a + ld [wHPBarNewHP+1], a + jr c, .capToMaxHP ; if HP > 65,535, cap to max HP +; compare HP with max HP + ld a, [hld] + ld b, a + ld a, [de] + dec de + sub b + ld a, [hli] + ld b, a + ld a, [de] + inc de + sbc b + jr nc, .next +.capToMaxHP + ld a, [de] + ld [hld], a + ld [wHPBarNewHP], a + dec de + ld a, [de] + ld [hli], a + ld [wHPBarNewHP+1], a + inc de +.next + ldh a, [hWhoseTurn] + and a + hlcoord 10, 9 + ld a, $1 + jr z, .next2 + hlcoord 2, 2 + xor a +.next2 + ld [wHPBarType], a + predef UpdateHPBar2 + predef DrawPlayerHUDAndHPBar + predef DrawEnemyHUDAndHPBar + callfar ReadPlayerMonCurHPAndStatus + ld hl, SuckedHealthText + ldh a, [hWhoseTurn] + and a + ld a, [wPlayerMoveEffect] + jr z, .next3 + ld a, [wEnemyMoveEffect] +.next3 + cp DREAM_EATER_EFFECT + jr nz, .printText + ld hl, DreamWasEatenText +.printText + jp PrintText + +SuckedHealthText: + text_far _SuckedHealthText + text_end + +DreamWasEatenText: + text_far _DreamWasEatenText + text_end diff --git a/engine/battle/move_effects/focus_energy.asm b/engine/battle/move_effects/focus_energy.asm new file mode 100644 index 00000000..1fafe920 --- /dev/null +++ b/engine/battle/move_effects/focus_energy.asm @@ -0,0 +1,22 @@ +FocusEnergyEffect_: + ld hl, wPlayerBattleStatus2 + ldh a, [hWhoseTurn] + and a + jr z, .notEnemy + ld hl, wEnemyBattleStatus2 +.notEnemy + bit GETTING_PUMPED, [hl] ; is mon already using focus energy? + jr nz, .alreadyUsing + set GETTING_PUMPED, [hl] ; mon is now using focus energy + callfar PlayCurrentMoveAnimation + ld hl, GettingPumpedText + jp PrintText +.alreadyUsing + ld c, 50 + call DelayFrames + jpfar PrintButItFailedText_ + +GettingPumpedText: + text_pause + text_far _GettingPumpedText + text_end diff --git a/engine/battle/move_effects/haze.asm b/engine/battle/move_effects/haze.asm new file mode 100644 index 00000000..915eeed8 --- /dev/null +++ b/engine/battle/move_effects/haze.asm @@ -0,0 +1,81 @@ +HazeEffect_: + ld a, $7 +; store 7 on every stat mod + ld hl, wPlayerMonAttackMod + call ResetStatMods + ld hl, wEnemyMonAttackMod + call ResetStatMods +; copy unmodified stats to battle stats + ld hl, wPlayerMonUnmodifiedAttack + ld de, wBattleMonAttack + call ResetStats + ld hl, wEnemyMonUnmodifiedAttack + ld de, wEnemyMonAttack + call ResetStats +; cure non-volatile status, but only for the target + ld hl, wEnemyMonStatus + ld de, wEnemySelectedMove + ldh a, [hWhoseTurn] + and a + jr z, .cureStatuses + ld hl, wBattleMonStatus + dec de ; wPlayerSelectedMove + +.cureStatuses + ld a, [hl] + ld [hl], $0 + and SLP | (1 << FRZ) + jr z, .cureVolatileStatuses +; prevent the Pokemon from executing a move if it was asleep or frozen + ld a, $ff + ld [de], a + +.cureVolatileStatuses + xor a + ld [wPlayerDisabledMove], a + ld [wEnemyDisabledMove], a + ld hl, wPlayerDisabledMoveNumber + ld [hli], a + ld [hl], a + ld hl, wPlayerBattleStatus1 + call CureVolatileStatuses + ld hl, wEnemyBattleStatus1 + call CureVolatileStatuses + ld hl, PlayCurrentMoveAnimation + call CallBankF + ld hl, StatusChangesEliminatedText + jp PrintText + +CureVolatileStatuses: + res CONFUSED, [hl] + inc hl ; BATTSTATUS2 + ld a, [hl] + ; clear USING_X_ACCURACY, PROTECTED_BY_MIST, GETTING_PUMPED, and SEEDED statuses + and $ff ^((1 << USING_X_ACCURACY) | (1 << PROTECTED_BY_MIST) | (1 << GETTING_PUMPED) | (1 << SEEDED)) + ld [hli], a ; BATTSTATUS3 + ld a, [hl] + and %11110000 | (1 << TRANSFORMED) ; clear Bad Poison, Reflect and Light Screen statuses + ld [hl], a + ret + +ResetStatMods: + ld b, $8 +.loop + ld [hli], a + dec b + jr nz, .loop + ret + +ResetStats: + ld b, $8 +.loop + ld a, [hli] + ld [de], a + inc de + dec b + jr nz, .loop + ret + +StatusChangesEliminatedText: + text_far _StatusChangesEliminatedText + text_end diff --git a/engine/battle/move_effects/heal.asm b/engine/battle/move_effects/heal.asm new file mode 100644 index 00000000..80923a29 --- /dev/null +++ b/engine/battle/move_effects/heal.asm @@ -0,0 +1,120 @@ +HealEffect_: + ldh a, [hWhoseTurn] + and a + ld de, wBattleMonHP + ld hl, wBattleMonMaxHP + ld a, [wPlayerMoveNum] + jr z, .healEffect + ld de, wEnemyMonHP + ld hl, wEnemyMonMaxHP + ld a, [wEnemyMoveNum] +.healEffect + ld b, a + ld a, [de] + cp [hl] ; most significant bytes comparison is ignored + ; causes the move to miss if max HP is 255 or 511 points higher than the current HP + inc de + inc hl + ld a, [de] + sbc [hl] + jp z, .failed ; no effect if user's HP is already at its maximum + ld a, b + cp REST + jr nz, .healHP + push hl + push de + push af + ld c, 50 + call DelayFrames + ld hl, wBattleMonStatus + ldh a, [hWhoseTurn] + and a + jr z, .restEffect + ld hl, wEnemyMonStatus +.restEffect + ld a, [hl] + and a + ld [hl], 2 ; clear status and set number of turns asleep to 2 + ld hl, StartedSleepingEffect ; if mon didn't have an status + jr z, .printRestText + ld hl, FellAsleepBecameHealthyText ; if mon had an status +.printRestText + call PrintText + pop af + pop de + pop hl +.healHP + ld a, [hld] + ld [wHPBarMaxHP], a + ld c, a + ld a, [hl] + ld [wHPBarMaxHP+1], a + ld b, a + jr z, .gotHPAmountToHeal +; Recover and Softboiled only heal for half the mon's max HP + srl b + rr c +.gotHPAmountToHeal +; update HP + ld a, [de] + ld [wHPBarOldHP], a + add c + ld [de], a + ld [wHPBarNewHP], a + dec de + ld a, [de] + ld [wHPBarOldHP+1], a + adc b + ld [de], a + ld [wHPBarNewHP+1], a + inc hl + inc de + ld a, [de] + dec de + sub [hl] + dec hl + ld a, [de] + sbc [hl] + jr c, .playAnim +; copy max HP to current HP if an overflow occurred + ld a, [hli] + ld [de], a + ld [wHPBarNewHP+1], a + inc de + ld a, [hl] + ld [de], a + ld [wHPBarNewHP], a +.playAnim + ld hl, PlayCurrentMoveAnimation + call Bankswitch3DtoF + ldh a, [hWhoseTurn] + and a + hlcoord 10, 9 + ld a, $1 + jr z, .updateHPBar + hlcoord 2, 2 + xor a +.updateHPBar + ld [wHPBarType], a + predef UpdateHPBar2 + ld hl, DrawHUDsAndHPBars + call Bankswitch3DtoF + ld hl, RegainedHealthText + jp PrintText +.failed + ld c, 50 + call DelayFrames + ld hl, PrintButItFailedText_ + jp Bankswitch3DtoF + +StartedSleepingEffect: + text_far _StartedSleepingEffect + text_end + +FellAsleepBecameHealthyText: + text_far _FellAsleepBecameHealthyText + text_end + +RegainedHealthText: + text_far _RegainedHealthText + text_end diff --git a/engine/battle/move_effects/leech_seed.asm b/engine/battle/move_effects/leech_seed.asm new file mode 100644 index 00000000..61bd982a --- /dev/null +++ b/engine/battle/move_effects/leech_seed.asm @@ -0,0 +1,40 @@ +LeechSeedEffect_: + callfar MoveHitTest + ld a, [wMoveMissed] + and a + jr nz, .moveMissed + ld hl, wEnemyBattleStatus2 + ld de, wEnemyMonType1 + ldh a, [hWhoseTurn] + and a + jr z, .leechSeedEffect + ld hl, wPlayerBattleStatus2 + ld de, wBattleMonType1 +.leechSeedEffect +; miss if the target is grass-type or already seeded + ld a, [de] + cp GRASS + jr z, .moveMissed + inc de + ld a, [de] + cp GRASS + jr z, .moveMissed + bit SEEDED, [hl] + jr nz, .moveMissed + set SEEDED, [hl] + callfar PlayCurrentMoveAnimation + ld hl, WasSeededText + jp PrintText +.moveMissed + ld c, 50 + call DelayFrames + ld hl, EvadedAttackText + jp PrintText + +WasSeededText: + text_far _WasSeededText + text_end + +EvadedAttackText: + text_far _EvadedAttackText + text_end diff --git a/engine/battle/move_effects/mist.asm b/engine/battle/move_effects/mist.asm new file mode 100644 index 00000000..163d386f --- /dev/null +++ b/engine/battle/move_effects/mist.asm @@ -0,0 +1,19 @@ +MistEffect_: + ld hl, wPlayerBattleStatus2 + ldh a, [hWhoseTurn] + and a + jr z, .mistEffect + ld hl, wEnemyBattleStatus2 +.mistEffect + bit PROTECTED_BY_MIST, [hl] ; is mon protected by mist? + jr nz, .mistAlreadyInUse + set PROTECTED_BY_MIST, [hl] ; mon is now protected by mist + callfar PlayCurrentMoveAnimation + ld hl, ShroudedInMistText + jp PrintText +.mistAlreadyInUse + jpfar PrintButItFailedText_ + +ShroudedInMistText: + text_far _ShroudedInMistText + text_end diff --git a/engine/battle/move_effects/one_hit_ko.asm b/engine/battle/move_effects/one_hit_ko.asm new file mode 100644 index 00000000..7e5db0f7 --- /dev/null +++ b/engine/battle/move_effects/one_hit_ko.asm @@ -0,0 +1,38 @@ +OneHitKOEffect_: + ld hl, wDamage + xor a + ld [hli], a + ld [hl], a ; set the damage output to zero + dec a + ld [wCriticalHitOrOHKO], a + ld hl, wBattleMonSpeed + 1 + ld de, wEnemyMonSpeed + 1 + ldh a, [hWhoseTurn] + and a + jr z, .compareSpeed + ld hl, wEnemyMonSpeed + 1 + ld de, wBattleMonSpeed + 1 +.compareSpeed +; set damage to 65535 and OHKO flag is the user's current speed is higher than the target's + ld a, [de] + dec de + ld b, a + ld a, [hld] + sub b + ld a, [de] + ld b, a + ld a, [hl] + sbc b + jr c, .userIsSlower + ld hl, wDamage + ld a, $ff + ld [hli], a + ld [hl], a + ld a, $2 + ld [wCriticalHitOrOHKO], a + ret +.userIsSlower +; keep damage at 0 and set move missed flag if target's current speed is higher instead + ld a, $1 + ld [wMoveMissed], a + ret diff --git a/engine/battle/move_effects/paralyze.asm b/engine/battle/move_effects/paralyze.asm new file mode 100644 index 00000000..dbaa0fb8 --- /dev/null +++ b/engine/battle/move_effects/paralyze.asm @@ -0,0 +1,47 @@ +ParalyzeEffect_: + ld hl, wEnemyMonStatus + ld de, wPlayerMoveType + ldh a, [hWhoseTurn] + and a + jp z, .next + ld hl, wBattleMonStatus + ld de, wEnemyMoveType +.next + ld a, [hl] + and a ; does the target already have a status ailment? + jr nz, .didntAffect +; check if the target is immune due to types + ld a, [de] + cp ELECTRIC + jr nz, .hitTest + ld b, h + ld c, l + inc bc + ld a, [bc] + cp GROUND + jr z, .doesntAffect + inc bc + ld a, [bc] + cp GROUND + jr z, .doesntAffect +.hitTest + push hl + callfar MoveHitTest + pop hl + ld a, [wMoveMissed] + and a + jr nz, .didntAffect + set PAR, [hl] + callfar QuarterSpeedDueToParalysis + ld c, 30 + call DelayFrames + callfar PlayCurrentMoveAnimation + jpfar PrintMayNotAttackText +.didntAffect + ld c, 50 + call DelayFrames + jpfar PrintDidntAffectText +.doesntAffect + ld c, 50 + call DelayFrames + jpfar PrintDoesntAffectText diff --git a/engine/battle/move_effects/pay_day.asm b/engine/battle/move_effects/pay_day.asm new file mode 100644 index 00000000..fa373038 --- /dev/null +++ b/engine/battle/move_effects/pay_day.asm @@ -0,0 +1,45 @@ +PayDayEffect_: + xor a + ld hl, wcd6d + ld [hli], a + ldh a, [hWhoseTurn] + and a + ld a, [wBattleMonLevel] + jr z, .payDayEffect + ld a, [wEnemyMonLevel] +.payDayEffect +; level * 2 + add a + ldh [hDividend + 3], a + xor a + ldh [hDividend], a + ldh [hDividend + 1], a + ldh [hDividend + 2], a +; convert to BCD + ld a, 100 + ldh [hDivisor], a + ld b, $4 + call Divide + ldh a, [hQuotient + 3] + ld [hli], a + ldh a, [hRemainder] + ldh [hDividend + 3], a + ld a, 10 + ldh [hDivisor], a + ld b, $4 + call Divide + ldh a, [hQuotient + 3] + swap a + ld b, a + ldh a, [hRemainder] + add b + ld [hl], a + ld de, wTotalPayDayMoney + 2 + ld c, $3 + predef AddBCDPredef + ld hl, CoinsScatteredText + jp PrintText + +CoinsScatteredText: + text_far _CoinsScatteredText + text_end diff --git a/engine/battle/move_effects/recoil.asm b/engine/battle/move_effects/recoil.asm new file mode 100644 index 00000000..85110d50 --- /dev/null +++ b/engine/battle/move_effects/recoil.asm @@ -0,0 +1,70 @@ +RecoilEffect_: + ldh a, [hWhoseTurn] + and a + ld a, [wPlayerMoveNum] + ld hl, wBattleMonMaxHP + jr z, .recoilEffect + ld a, [wEnemyMoveNum] + ld hl, wEnemyMonMaxHP +.recoilEffect + ld d, a + ld a, [wDamage] + ld b, a + ld a, [wDamage + 1] + ld c, a + srl b + rr c + ld a, d + cp STRUGGLE ; struggle deals 50% recoil damage + jr z, .gotRecoilDamage + srl b + rr c +.gotRecoilDamage + ld a, b + or c + jr nz, .updateHP + inc c ; minimum recoil damage is 1 +.updateHP +; subtract HP from user due to the recoil damage + ld a, [hli] + ld [wHPBarMaxHP+1], a + ld a, [hl] + ld [wHPBarMaxHP], a + push bc + ld bc, wBattleMonHP - wBattleMonMaxHP + add hl, bc + pop bc + ld a, [hl] + ld [wHPBarOldHP], a + sub c + ld [hld], a + ld [wHPBarNewHP], a + ld a, [hl] + ld [wHPBarOldHP+1], a + sbc b + ld [hl], a + ld [wHPBarNewHP+1], a + jr nc, .getHPBarCoords +; if recoil damage is higher than the Pokemon's HP, set its HP to 0 + xor a + ld [hli], a + ld [hl], a + ld hl, wHPBarNewHP + ld [hli], a + ld [hl], a +.getHPBarCoords + hlcoord 10, 9 + ldh a, [hWhoseTurn] + and a + ld a, $1 + jr z, .updateHPBar + hlcoord 2, 2 + xor a +.updateHPBar + ld [wHPBarType], a + predef UpdateHPBar2 + ld hl, HitWithRecoilText + jp PrintText +HitWithRecoilText: + text_far _HitWithRecoilText + text_end diff --git a/engine/battle/move_effects/reflect_light_screen.asm b/engine/battle/move_effects/reflect_light_screen.asm new file mode 100644 index 00000000..c05055fa --- /dev/null +++ b/engine/battle/move_effects/reflect_light_screen.asm @@ -0,0 +1,45 @@ +ReflectLightScreenEffect_: + ld hl, wPlayerBattleStatus3 + ld de, wPlayerMoveEffect + ldh a, [hWhoseTurn] + and a + jr z, .reflectLightScreenEffect + ld hl, wEnemyBattleStatus3 + ld de, wEnemyMoveEffect +.reflectLightScreenEffect + ld a, [de] + cp LIGHT_SCREEN_EFFECT + jr nz, .reflect + bit HAS_LIGHT_SCREEN_UP, [hl] ; is mon already protected by light screen? + jr nz, .moveFailed + set HAS_LIGHT_SCREEN_UP, [hl] ; mon is now protected by light screen + ld hl, LightScreenProtectedText + jr .playAnim +.reflect + bit HAS_REFLECT_UP, [hl] ; is mon already protected by reflect? + jr nz, .moveFailed + set HAS_REFLECT_UP, [hl] ; mon is now protected by reflect + ld hl, ReflectGainedArmorText +.playAnim + push hl + ld hl, PlayCurrentMoveAnimation + call Bankswitch3DtoF + pop hl + jp PrintText +.moveFailed + ld c, 50 + call DelayFrames + ld hl, PrintButItFailedText_ + jp Bankswitch3DtoF + +LightScreenProtectedText: + text_far _LightScreenProtectedText + text_end + +ReflectGainedArmorText: + text_far _ReflectGainedArmorText + text_end + +Bankswitch3DtoF: + ld b, BANK(BattleCore) + jp Bankswitch diff --git a/engine/battle/move_effects/substitute.asm b/engine/battle/move_effects/substitute.asm new file mode 100644 index 00000000..860b76b6 --- /dev/null +++ b/engine/battle/move_effects/substitute.asm @@ -0,0 +1,77 @@ +SubstituteEffect_: + ld c, 50 + call DelayFrames + ld hl, wBattleMonMaxHP + ld de, wPlayerSubstituteHP + ld bc, wPlayerBattleStatus2 + ldh a, [hWhoseTurn] + and a + jr z, .notEnemy + ld hl, wEnemyMonMaxHP + ld de, wEnemySubstituteHP + ld bc, wEnemyBattleStatus2 +.notEnemy + ld a, [bc] + bit HAS_SUBSTITUTE_UP, a ; user already has substitute? + jr nz, .alreadyHasSubstitute +; quarter health to remove from user +; assumes max HP is 1023 or lower + push bc + ld a, [hli] + ld b, [hl] + srl a + rr b + srl a + rr b ; max hp / 4 + push de + ld de, wBattleMonHP - wBattleMonMaxHP + add hl, de ; point hl to current HP low byte + pop de + ld a, b + ld [de], a ; save copy of HP to subtract in wPlayerSubstituteHP/wEnemySubstituteHP + ld a, [hld] +; subtract [max hp / 4] to current HP + sub b + ld d, a + ld a, [hl] + sbc 0 + pop bc + jr c, .notEnoughHP ; underflow means user would be left with negative health + ; bug: since it only branches on carry, it will possibly leave user with 0 HP +.userHasZeroOrMoreHP + ldi [hl], a ; save resulting HP after subtraction into current HP + ld [hl], d + ld h, b + ld l, c + set HAS_SUBSTITUTE_UP, [hl] + ld a, [wOptions] + bit 7, a ; battle animation is enabled? + ld hl, PlayCurrentMoveAnimation + ld b, BANK(PlayCurrentMoveAnimation) + jr z, .animationEnabled + ld hl, AnimationSubstitute + ld b, BANK(AnimationSubstitute) +.animationEnabled + call Bankswitch ; jump to routine depending on animation setting + ld hl, SubstituteText + call PrintText + jpfar DrawHUDsAndHPBars +.alreadyHasSubstitute + ld hl, HasSubstituteText + jr .printText +.notEnoughHP + ld hl, TooWeakSubstituteText +.printText + jp PrintText + +SubstituteText: + text_far _SubstituteText + text_end + +HasSubstituteText: + text_far _HasSubstituteText + text_end + +TooWeakSubstituteText: + text_far _TooWeakSubstituteText + text_end diff --git a/engine/battle/move_effects/transform.asm b/engine/battle/move_effects/transform.asm new file mode 100644 index 00000000..d37bd94d --- /dev/null +++ b/engine/battle/move_effects/transform.asm @@ -0,0 +1,141 @@ +TransformEffect_: + ld hl, wBattleMonSpecies + ld de, wEnemyMonSpecies + ld bc, wEnemyBattleStatus3 + ld a, [wEnemyBattleStatus1] + ldh a, [hWhoseTurn] + and a + jr nz, .hitTest + ld hl, wEnemyMonSpecies + ld de, wBattleMonSpecies + ld bc, wPlayerBattleStatus3 + ld [wPlayerMoveListIndex], a + ld a, [wPlayerBattleStatus1] +.hitTest + bit INVULNERABLE, a ; is mon invulnerable to typical attacks? (fly/dig) + jp nz, .failed + push hl + push de + push bc + ld hl, wPlayerBattleStatus2 + ldh a, [hWhoseTurn] + and a + jr z, .transformEffect + ld hl, wEnemyBattleStatus2 +.transformEffect +; animation(s) played are different if target has Substitute up + bit HAS_SUBSTITUTE_UP, [hl] + push af + ld hl, HideSubstituteShowMonAnim + ld b, BANK(HideSubstituteShowMonAnim) + call nz, Bankswitch + ld a, [wOptions] + add a + ld hl, PlayCurrentMoveAnimation + ld b, BANK(PlayCurrentMoveAnimation) + jr nc, .gotAnimToPlay + ld hl, AnimationTransformMon + ld b, BANK(AnimationTransformMon) +.gotAnimToPlay + call Bankswitch + ld hl, ReshowSubstituteAnim + ld b, BANK(ReshowSubstituteAnim) + pop af + call nz, Bankswitch + pop bc + ld a, [bc] + set TRANSFORMED, a ; mon is now transformed + ld [bc], a + pop de + pop hl + push hl +; transform user into opposing Pokemon +; species + ld a, [hl] + ld [de], a +; type 1, type 2, catch rate, and moves + ld bc, $5 + add hl, bc + inc de + inc de + inc de + inc de + inc de + inc bc + inc bc + call CopyData + ldh a, [hWhoseTurn] + and a + jr z, .next +; save enemy mon DVs at wTransformedEnemyMonOriginalDVs + ld a, [de] + ld [wTransformedEnemyMonOriginalDVs], a + inc de + ld a, [de] + ld [wTransformedEnemyMonOriginalDVs + 1], a + dec de +.next +; DVs + ld a, [hli] + ld [de], a + inc de + ld a, [hli] + ld [de], a + inc de +; Attack, Defense, Speed, and Special stats + inc hl + inc hl + inc hl + inc de + inc de + inc de + ld bc, $8 + call CopyData + ld bc, wBattleMonMoves - wBattleMonPP + add hl, bc ; ld hl, wBattleMonMoves + ld b, NUM_MOVES +.copyPPLoop +; 5 PP for all moves + ld a, [hli] + and a + jr z, .lessThanFourMoves + ld a, $5 +.lessThanFourMoves + ld [de], a + inc de + dec b + jr nz, .copyPPLoop +.copyStats +; original (unmodified) stats and stat mods + pop hl + ld a, [hl] + ld [wd11e], a + call GetMonName + ld hl, wEnemyMonUnmodifiedAttack + ld de, wPlayerMonUnmodifiedAttack + call .copyBasedOnTurn ; original (unmodified) stats + ld hl, wEnemyMonStatMods + ld de, wPlayerMonStatMods + call .copyBasedOnTurn ; stat mods + ld hl, TransformedText + jp PrintText + +.copyBasedOnTurn + ldh a, [hWhoseTurn] + and a + jr z, .gotStatsOrModsToCopy + push hl + ld h, d + ld l, e + pop de +.gotStatsOrModsToCopy + ld bc, $8 + jp CopyData + +.failed + ld hl, PrintButItFailedText_ + jp Bankswitch3DtoF + +TransformedText: + text_far _TransformedText + text_end diff --git a/engine/battle/print_type.asm b/engine/battle/print_type.asm index f717f871..7da0dc8c 100644 --- a/engine/battle/print_type.asm +++ b/engine/battle/print_type.asm @@ -49,4 +49,4 @@ PrintType_: pop hl jp PlaceString -INCLUDE "text/type_names.asm" +INCLUDE "data/types/names.asm" diff --git a/engine/battle/read_trainer_party.asm b/engine/battle/read_trainer_party.asm index b4ee46a0..02fbfeda 100755 --- a/engine/battle/read_trainer_party.asm +++ b/engine/battle/read_trainer_party.asm @@ -110,7 +110,7 @@ ReadTrainer: dec a ld c, a ld b, 0 - add hl,bc + add hl, bc ld a, [de] inc de ld [hl], a diff --git a/engine/battle/safari_zone.asm b/engine/battle/safari_zone.asm index 88064f9a..9362cc3a 100755 --- a/engine/battle/safari_zone.asm +++ b/engine/battle/safari_zone.asm @@ -28,9 +28,9 @@ PrintSafariZoneBattleText: jp PrintText SafariZoneEatingText: - TX_FAR _SafariZoneEatingText - db "@" + text_far _SafariZoneEatingText + text_end SafariZoneAngryText: - TX_FAR _SafariZoneAngryText - db "@" + text_far _SafariZoneAngryText + text_end diff --git a/engine/battle/save_trainer_name.asm b/engine/battle/save_trainer_name.asm index 49d0429f..4d40fd82 100644 --- a/engine/battle/save_trainer_name.asm +++ b/engine/battle/save_trainer_name.asm @@ -1,4 +1,4 @@ -SaveTrainerName: +SaveTrainerName:: ld hl, TrainerNamePointers ld a, [wTrainerClass] dec a @@ -18,95 +18,4 @@ SaveTrainerName: jr nz, .CopyCharacter ret -TrainerNamePointers: -; what is the point of these? - dw YoungsterName - dw BugCatcherName - dw LassName - dw wTrainerName - dw JrTrainerMName - dw JrTrainerFName - dw PokemaniacName - dw SuperNerdName - dw wTrainerName - dw wTrainerName - dw BurglarName - dw EngineerName - dw JugglerXName - dw wTrainerName - dw SwimmerName - dw wTrainerName - dw wTrainerName - dw BeautyName - dw wTrainerName - dw RockerName - dw JugglerName - dw wTrainerName - dw wTrainerName - dw BlackbeltName - dw wTrainerName - dw ProfOakName - dw ChiefName - dw ScientistName - dw wTrainerName - dw RocketName - dw CooltrainerMName - dw CooltrainerFName - dw wTrainerName - dw wTrainerName - dw wTrainerName - dw wTrainerName - dw wTrainerName - dw wTrainerName - dw wTrainerName - dw wTrainerName - dw wTrainerName - dw wTrainerName - dw wTrainerName - dw wTrainerName - dw wTrainerName - dw wTrainerName - dw wTrainerName - -YoungsterName: - db "YOUNGSTER@" -BugCatcherName: - db "BUG CATCHER@" -LassName: - db "LASS@" -JrTrainerMName: - db "JR.TRAINER♂@" -JrTrainerFName: - db "JR.TRAINER♀@" -PokemaniacName: - db "POKéMANIAC@" -SuperNerdName: - db "SUPER NERD@" -BurglarName: - db "BURGLAR@" -EngineerName: - db "ENGINEER@" -JugglerXName: - db "JUGGLER@" -SwimmerName: - db "SWIMMER@" -BeautyName: - db "BEAUTY@" -RockerName: - db "ROCKER@" -JugglerName: - db "JUGGLER@" -BlackbeltName: - db "BLACKBELT@" -ProfOakName: - db "PROF.OAK@" -ChiefName: - db "CHIEF@" -ScientistName: - db "SCIENTIST@" -RocketName: - db "ROCKET@" -CooltrainerMName: - db "COOLTRAINER♂@" -CooltrainerFName: - db "COOLTRAINER♀@" +INCLUDE "data/trainers/name_pointers.asm" diff --git a/engine/battle/scale_sprites.asm b/engine/battle/scale_sprites.asm index c614d638..794a65ab 100644 --- a/engine/battle/scale_sprites.asm +++ b/engine/battle/scale_sprites.asm @@ -24,7 +24,7 @@ ScaleFirstThreeSpriteColumnsByTwo: .columnInnerLoop push bc ld a, [de] - ld bc, -(7*8)+1 ; $ffc9, scale lower nybble and seek to previous output column + ld bc, -(7*8)+1 ; -$37, scale lower nybble and seek to previous output column call ScalePixelsByTwo ld a, [de] dec de @@ -39,7 +39,7 @@ ScaleFirstThreeSpriteColumnsByTwo: dec de dec de ld a, b - ld bc, -7*8 ; $ffc8, skip one output column (which has already been written along with the current one) + ld bc, -7*8 ; -$38, skip one output column (which has already been written along with the current one) add hl, bc ld b, a dec b @@ -48,16 +48,16 @@ ScaleFirstThreeSpriteColumnsByTwo: ScaleLastSpriteColumnByTwo: ld a, 4*8 - 4 ; $1c, 4 tiles minus 4 unused rows - ld [H_SPRITEINTERLACECOUNTER], a + ldh [hSpriteInterlaceCounter], a ld bc, -1 .columnInnerLoop ld a, [de] dec de swap a ; only high nybble contains information call ScalePixelsByTwo - ld a, [H_SPRITEINTERLACECOUNTER] + ldh a, [hSpriteInterlaceCounter] dec a - ld [H_SPRITEINTERLACECOUNTER], a + ldh [hSpriteInterlaceCounter], a jr nz, .columnInnerLoop dec de ; skip last 4 rows of new column dec de @@ -86,7 +86,19 @@ ScalePixelsByTwo: ; repeats each input bit twice DuplicateBitsTable: - db $00, $03, $0c, $0f - db $30, $33, $3c, $3f - db $c0, $c3, $cc, $cf - db $f0, $f3, $fc, $ff + db %00000000 + db %00000011 + db %00001100 + db %00001111 + db %00110000 + db %00110011 + db %00111100 + db %00111111 + db %11000000 + db %11000011 + db %11001100 + db %11001111 + db %11110000 + db %11110011 + db %11111100 + db %11111111 diff --git a/engine/battle/scroll_draw_trainer_pic.asm b/engine/battle/scroll_draw_trainer_pic.asm index 98893dcf..e19d681a 100644 --- a/engine/battle/scroll_draw_trainer_pic.asm +++ b/engine/battle/scroll_draw_trainer_pic.asm @@ -5,8 +5,8 @@ _ScrollTrainerPicAfterBattle: ld [wEnemyMonSpecies2], a ld b, SET_PAL_BATTLE call RunPaletteCommand - callab _LoadTrainerPic - coord hl, 19, 0 + callfar _LoadTrainerPic + hlcoord 19, 0 ld c, $0 .scrollLoop inc c diff --git a/engine/battle/trainer_ai.asm b/engine/battle/trainer_ai.asm index c8fdfb29..17e68e75 100644 --- a/engine/battle/trainer_ai.asm +++ b/engine/battle/trainer_ai.asm @@ -134,7 +134,7 @@ AIMoveChoiceModification1: push de push bc ld hl, StatusAilmentMoveEffects - ld de, $0001 + ld de, 1 call IsInArray pop bc pop de @@ -146,11 +146,11 @@ AIMoveChoiceModification1: jr .nextMove StatusAilmentMoveEffects: - db $01 ; unused sleep effect + db EFFECT_01 ; unused sleep effect db SLEEP_EFFECT db POISON_EFFECT db PARALYZE_EFFECT - db $FF + db -1 ; end ; slightly encourage moves with specific effects. ; in particular, stat-modifying moves and other move effects @@ -204,7 +204,7 @@ AIMoveChoiceModification3: push hl push bc push de - callab AIGetTypeEffectiveness + callfar AIGetTypeEffectiveness pop de pop bc pop hl @@ -273,68 +273,19 @@ ReadMove: pop hl ret -; move choice modification methods that are applied for each trainer class -; 0 is sentinel value -TrainerClassMoveChoiceModifications: - db 0 ; YOUNGSTER - db 1,0 ; BUG CATCHER - db 1,0 ; LASS - db 1,3,0 ; SAILOR - db 1,0 ; JR_TRAINER_M - db 1,0 ; JR_TRAINER_F - db 1,2,3,0; POKEMANIAC - db 1,2,0 ; SUPER_NERD - db 1,0 ; HIKER - db 1,0 ; BIKER - db 1,3,0 ; BURGLAR - db 1,0 ; ENGINEER - db 1,2,0 ; JUGGLER_X - db 1,3,0 ; FISHER - db 1,3,0 ; SWIMMER - db 0 ; CUE_BALL - db 1,0 ; GAMBLER - db 1,3,0 ; BEAUTY - db 1,2,0 ; PSYCHIC_TR - db 1,0 ; ROCKER - db 1,0 ; JUGGLER - db 1,0 ; TAMER - db 1,0 ; BIRD_KEEPER - db 1,0 ; BLACKBELT - db 1,0 ; SONY1 - db 1,3,0 ; PROF_OAK - db 1,2,0 ; CHIEF - db 1,2,0 ; SCIENTIST - db 1,3,0 ; GIOVANNI - db 1,0 ; ROCKET - db 1,3,0 ; COOLTRAINER_M - db 1,3,0 ; COOLTRAINER_F - db 1,0 ; BRUNO - db 1,0 ; BROCK - db 1,3,0 ; MISTY - db 1,0 ; LT_SURGE - db 1,3,0 ; ERIKA - db 1,3,0 ; KOGA - db 1,0 ; BLAINE - db 1,0 ; SABRINA - db 1,2,0 ; GENTLEMAN - db 1,3,0 ; SONY2 - db 1,3,0 ; SONY3 - db 1,2,3,0; LORELEI - db 1,0 ; CHANNELER - db 1,0 ; AGATHA - db 1,3,0 ; LANCE - -INCLUDE "engine/battle/trainer_pic_money_pointers.asm" - -INCLUDE "text/trainer_names.asm" - -INCLUDE "engine/battle/bank_e_misc.asm" +INCLUDE "data/trainers/move_choices.asm" + +INCLUDE "data/trainers/pic_pointers_money.asm" + +INCLUDE "data/trainers/names.asm" + +INCLUDE "engine/battle/misc.asm" INCLUDE "engine/battle/read_trainer_party.asm" -INCLUDE "data/trainer_moves.asm" +INCLUDE "data/trainers/special_moves.asm" -INCLUDE "data/trainer_parties.asm" +INCLUDE "data/trainers/parties.asm" TrainerAI: ld a, [wIsInBattle] @@ -350,7 +301,7 @@ TrainerAI: and 1 << USING_RAGE ; %1000000 jr nz, .done ; don't follow trainer ai if opponent is locked in rage ; note that this doesn't check for hyper beam recharge which can cause problems - ld a,[wTrainerClass] ; what trainer class is this? + ld a, [wTrainerClass] ; what trainer class is this? dec a ld c, a ld b, 0 @@ -377,57 +328,7 @@ TrainerAI: and a ret -TrainerAIPointers: -; one entry per trainer class -; first byte, number of times (per Pokémon) it can occur -; next two bytes, pointer to AI subroutine for trainer class - dbw 3,GenericAI - dbw 3,GenericAI - dbw 3,GenericAI - dbw 3,GenericAI - dbw 3,GenericAI - dbw 3,GenericAI - dbw 3,GenericAI - dbw 3,GenericAI - dbw 3,GenericAI - dbw 3,GenericAI - dbw 3,GenericAI - dbw 3,GenericAI - dbw 3,JugglerAI ; juggler_x - dbw 3,GenericAI - dbw 3,GenericAI - dbw 3,GenericAI - dbw 3,GenericAI - dbw 3,GenericAI - dbw 3,GenericAI - dbw 3,GenericAI - dbw 3,JugglerAI ; juggler - dbw 3,GenericAI - dbw 3,GenericAI - dbw 2,BlackbeltAI ; blackbelt - dbw 3,GenericAI - dbw 3,GenericAI - dbw 1,GenericAI ; chief - dbw 3,GenericAI - dbw 1,GiovanniAI ; giovanni - dbw 3,GenericAI - dbw 2,CooltrainerMAI ; cooltrainerm - dbw 1,CooltrainerFAI ; cooltrainerf - dbw 2,BrunoAI ; bruno - dbw 5,BrockAI ; brock - dbw 1,MistyAI ; misty - dbw 1,LtSurgeAI ; surge - dbw 1,ErikaAI ; erika - dbw 2,KogaAI ; koga - dbw 2,BlaineAI ; blaine - dbw 1,SabrinaAI ; sabrina - dbw 3,GenericAI - dbw 1,Sony2AI ; sony2 - dbw 1,Sony3AI ; sony3 - dbw 2,LoreleiAI ; lorelei - dbw 3,GenericAI - dbw 2,AgathaAI ; agatha - dbw 1,LanceAI ; lance +INCLUDE "data/trainers/ai_pointers.asm" JugglerAI: cp 25 percent + 1 @@ -650,14 +551,14 @@ AIRecoverHP: AIPrintItemUseAndUpdateHPBar: call AIPrintItemUse_ - coord hl, 2, 2 + hlcoord 2, 2 xor a ld [wHPBarType], a predef UpdateHPBar2 jp DecrementAICount AISwitchIfEnoughMons: -; enemy trainer switches if there are 3 or more unfainted mons in party +; enemy trainer switches if there are 2 or more unfainted mons in party ld a, [wEnemyPartyCount] ld c, a ld hl, wEnemyMon1HP @@ -681,7 +582,7 @@ AISwitchIfEnoughMons: jr nz, .loop ld a, d ; how many available monsters are there? - cp 2 ; don't bother if only 1 or 2 + cp 2 ; don't bother if only 1 jp nc, SwitchEnemyMon and a ret @@ -707,7 +608,7 @@ SwitchEnemyMon: ; switching in a new mon in response to this switch. ld a, 1 ld [wFirstMonsNotOutYet], a - callab EnemySendOut + callfar EnemySendOut xor a ld [wFirstMonsNotOutYet], a @@ -718,8 +619,8 @@ SwitchEnemyMon: ret AIBattleWithdrawText: - TX_FAR _AIBattleWithdrawText - db "@" + text_far _AIBattleWithdrawText + text_end AIUseFullHeal: call AIPlayRestoringSFX @@ -763,17 +664,17 @@ AIUseDireHit: ; unused AICheckIfHPBelowFraction: ; return carry if enemy trainer's current HP is below 1 / a of the maximum - ld [H_DIVISOR], a + ldh [hDivisor], a ld hl, wEnemyMonMaxHP ld a, [hli] - ld [H_DIVIDEND], a + ldh [hDividend], a ld a, [hl] - ld [H_DIVIDEND + 1], a + ldh [hDividend + 1], a ld b, 2 call Divide - ld a, [H_QUOTIENT + 3] + ldh a, [hQuotient + 3] ld c, a - ld a, [H_QUOTIENT + 2] + ldh a, [hQuotient + 2] ld b, a ld hl, wEnemyMonHP + 1 ld a, [hld] @@ -821,7 +722,7 @@ AIIncreaseStat: ld a, ANIM_AF ld [hli], a ld [hl], b - callab StatModifierUpEffect + callfar StatModifierUpEffect pop hl pop af ld [hli], a @@ -843,5 +744,5 @@ AIPrintItemUse_: jp PrintText AIBattleUseItemText: - TX_FAR _AIBattleUseItemText - db "@" + text_far _AIBattleUseItemText + text_end diff --git a/engine/battle/trainer_pic_money_pointers.asm b/engine/battle/trainer_pic_money_pointers.asm deleted file mode 100755 index 37678e74..00000000 --- a/engine/battle/trainer_pic_money_pointers.asm +++ /dev/null @@ -1,143 +0,0 @@ -TrainerPicAndMoneyPointers: -; trainer pic pointers and base money. -; money received after battle = base money × level of highest-level enemy mon - dw YoungsterPic - money 1500 - - dw BugCatcherPic - money 1000 - - dw LassPic - money 1500 - - dw SailorPic - money 3000 - - dw JrTrainerMPic - money 2000 - - dw JrTrainerFPic - money 2000 - - dw PokemaniacPic - money 5000 - - dw SuperNerdPic - money 2500 - - dw HikerPic - money 3500 - - dw BikerPic - money 2000 - - dw BurglarPic - money 9000 - - dw EngineerPic - money 5000 - - dw JugglerPic - money 3500 - - dw FisherPic - money 3500 - - dw SwimmerPic - money 500 - - dw CueBallPic - money 2500 - - dw GamblerPic - money 7000 - - dw BeautyPic - money 7000 - - dw PsychicPic - money 1000 - - dw RockerPic - money 2500 - - dw JugglerPic - money 3500 - - dw TamerPic - money 4000 - - dw BirdKeeperPic - money 2500 - - dw BlackbeltPic - money 2500 - - dw Rival1Pic - money 3500 - - dw ProfOakPic - money 9900 - - dw ChiefPic - money 3000 - - dw ScientistPic - money 5000 - - dw GiovanniPic - money 9900 - - dw RocketPic - money 3000 - - dw CooltrainerMPic - money 3500 - - dw CooltrainerFPic - money 3500 - - dw BrunoPic - money 9900 - - dw BrockPic - money 9900 - - dw MistyPic - money 9900 - - dw LtSurgePic - money 9900 - - dw ErikaPic - money 9900 - - dw KogaPic - money 9900 - - dw BlainePic - money 9900 - - dw SabrinaPic - money 9900 - - dw GentlemanPic - money 7000 - - dw Rival2Pic - money 6500 - - dw Rival3Pic - money 9900 - - dw LoreleiPic - money 9900 - - dw ChannelerPic - money 3000 - - dw AgathaPic - money 9900 - - dw LancePic - money 9900 diff --git a/engine/battle/unused_stats_functions.asm b/engine/battle/unused_stats_functions.asm index 55f78fd3..5174adf5 100644 --- a/engine/battle/unused_stats_functions.asm +++ b/engine/battle/unused_stats_functions.asm @@ -1,6 +1,6 @@ ; does nothing since no stats are ever selected (barring glitches) DoubleSelectedStats: - ld a, [H_WHOSETURN] + ldh a, [hWhoseTurn] and a ld a, [wPlayerStatsToDouble] ld hl, wBattleMonAttack + 1 @@ -30,7 +30,7 @@ DoubleSelectedStats: ; does nothing since no stats are ever selected (barring glitches) HalveSelectedStats: - ld a, [H_WHOSETURN] + ldh a, [hWhoseTurn] and a ld a, [wPlayerStatsToHalve] ld hl, wBattleMonAttack diff --git a/engine/battle/wild_encounters.asm b/engine/battle/wild_encounters.asm index 0285346e..d16c6515 100644 --- a/engine/battle/wild_encounters.asm +++ b/engine/battle/wild_encounters.asm @@ -7,14 +7,14 @@ TryDoWildEncounter: ld a, [wd736] and a ret nz - callab IsPlayerStandingOnDoorTileOrWarpTile + callfar IsPlayerStandingOnDoorTileOrWarpTile jr nc, .notStandingOnDoorOrWarpTile .CantEncounter ld a, $1 and a ret .notStandingOnDoorOrWarpTile - callab IsPlayerJustOutsideMap + callfar IsPlayerJustOutsideMap jr z, .CantEncounter ld a, [wRepelRemainingSteps] and a @@ -26,7 +26,7 @@ TryDoWildEncounter: ; determine if wild pokemon can appear in the half-block we're standing in ; is the bottom left tile (8,9) of the half-block we're standing in a grass/water tile? ; note that by using the bottom left tile, this prevents the "left-shore" tiles from generating grass encounters - coord hl, 8, 9 + hlcoord 8, 9 ld c, [hl] ld a, [wGrassTile] cp c @@ -40,7 +40,7 @@ TryDoWildEncounter: ; so long as the map is "indoor" and has wild pokemon defined. ; ...as long as it's not Viridian Forest or Safari Zone. ld a, [wCurMap] - cp REDS_HOUSE_1F ; is this an indoor map? + cp FIRST_INDOOR_MAP ; is this an indoor map? jr c, .CantEncounter2 ld a, [wCurMapTileset] cp FOREST ; Viridian Forest/Safari Zone @@ -49,10 +49,10 @@ TryDoWildEncounter: .CanEncounter ; compare encounter chance with a random number to determine if there will be an encounter ld b, a - ld a, [hRandomAdd] + ldh a, [hRandomAdd] cp b jr nc, .CantEncounter2 - ld a, [hRandomSub] + ldh a, [hRandomSub] ld b, a ld hl, WildMonEncounterSlotChances .determineEncounterSlot @@ -65,7 +65,7 @@ TryDoWildEncounter: ; determine which wild pokemon (grass or water) can appear in the half-block we're standing in ld c, [hl] ld hl, wGrassMons - aCoord 8, 9 + lda_coord 8, 9 cp $14 ; is the bottom left tile (8,9) of the half-block we're standing in a water tile? jr nz, .gotWildEncounterType ; else, it's treated as a grass tile by default ld hl, wWaterMons @@ -89,7 +89,7 @@ TryDoWildEncounter: .lastRepelStep ld [wRepelRemainingSteps], a ld a, TEXT_REPEL_WORE_OFF - ld [hSpriteIndexOrTextID], a + ldh [hSpriteIndexOrTextID], a call EnableAutoTextBoxDrawing call DisplayTextID .CantEncounter2 @@ -100,18 +100,4 @@ TryDoWildEncounter: xor a ret -WildMonEncounterSlotChances: -; There are 10 slots for wild pokemon, and this is the table that defines how common each of -; those 10 slots is. A random number is generated and then the first byte of each pair in this -; table is compared against that random number. If the random number is less than or equal -; to the first byte, then that slot is chosen. The second byte is double the slot number. - db $32, $00 ; 51/256 = 19.9% chance of slot 0 - db $65, $02 ; 51/256 = 19.9% chance of slot 1 - db $8C, $04 ; 39/256 = 15.2% chance of slot 2 - db $A5, $06 ; 25/256 = 9.8% chance of slot 3 - db $BE, $08 ; 25/256 = 9.8% chance of slot 4 - db $D7, $0A ; 25/256 = 9.8% chance of slot 5 - db $E4, $0C ; 13/256 = 5.1% chance of slot 6 - db $F1, $0E ; 13/256 = 5.1% chance of slot 7 - db $FC, $10 ; 11/256 = 4.3% chance of slot 8 - db $FF, $12 ; 3/256 = 1.2% chance of slot 9 +INCLUDE "data/wild/probabilities.asm" diff --git a/engine/bcd.asm b/engine/bcd.asm deleted file mode 100644 index d84e504b..00000000 --- a/engine/bcd.asm +++ /dev/null @@ -1,218 +0,0 @@ -; divide hMoney by hDivideBCDDivisor -; return output in hDivideBCDQuotient (same as hDivideBCDDivisor) -; used only to halve player money upon losing a fight -DivideBCDPredef:: -DivideBCDPredef2:: -DivideBCDPredef3:: ; only used function -DivideBCDPredef4:: - call GetPredefRegisters - -DivideBCD:: - xor a - ld [hDivideBCDBuffer], a - ld [hDivideBCDBuffer + 1], a - ld [hDivideBCDBuffer + 2], a - ld d, $1 -.mulBy10Loop -; multiply the divisor by 10 until the leading digit is nonzero -; to set up the standard long division algorithm - ld a, [hDivideBCDDivisor] - and $f0 - jr nz, .next - inc d - ld a, [hDivideBCDDivisor] - swap a - and $f0 - ld b, a - ld a, [hDivideBCDDivisor + 1] - swap a - ld [hDivideBCDDivisor + 1], a - and $f - or b - ld [hDivideBCDDivisor], a - ld a, [hDivideBCDDivisor + 1] - and $f0 - ld b, a - ld a, [hDivideBCDDivisor + 2] - swap a - ld [hDivideBCDDivisor + 2], a - and $f - or b - ld [hDivideBCDDivisor + 1], a - ld a, [hDivideBCDDivisor + 2] - and $f0 - ld [hDivideBCDDivisor + 2], a - jr .mulBy10Loop - -.next - push de - push de - call DivideBCD_getNextDigit - pop de - ld a, b - swap a - and $f0 - ld [hDivideBCDBuffer], a - dec d - jr z, .next2 - push de - call DivideBCD_divDivisorBy10 - call DivideBCD_getNextDigit - pop de - ld a, [hDivideBCDBuffer] - or b - ld [hDivideBCDBuffer], a - dec d - jr z, .next2 - push de - call DivideBCD_divDivisorBy10 - call DivideBCD_getNextDigit - pop de - ld a, b - swap a - and $f0 - ld [hDivideBCDBuffer + 1], a - dec d - jr z, .next2 - push de - call DivideBCD_divDivisorBy10 - call DivideBCD_getNextDigit - pop de - ld a, [hDivideBCDBuffer + 1] - or b - ld [hDivideBCDBuffer + 1], a - dec d - jr z, .next2 - push de - call DivideBCD_divDivisorBy10 - call DivideBCD_getNextDigit - pop de - ld a, b - swap a - and $f0 - ld [hDivideBCDBuffer + 2], a - dec d - jr z, .next2 - push de - call DivideBCD_divDivisorBy10 - call DivideBCD_getNextDigit - pop de - ld a, [hDivideBCDBuffer + 2] - or b - ld [hDivideBCDBuffer + 2], a -.next2 - ld a, [hDivideBCDBuffer] - ld [hDivideBCDQuotient], a ; the same memory location as hDivideBCDDivisor - ld a, [hDivideBCDBuffer + 1] - ld [hDivideBCDQuotient + 1], a - ld a, [hDivideBCDBuffer + 2] - ld [hDivideBCDQuotient + 2], a - pop de - ld a, $6 - sub d - and a - ret z -.divResultBy10loop - push af - call DivideBCD_divDivisorBy10 - pop af - dec a - jr nz, .divResultBy10loop - ret - -DivideBCD_divDivisorBy10: - ld a, [hDivideBCDDivisor + 2] - swap a - and $f - ld b, a - ld a, [hDivideBCDDivisor + 1] - swap a - ld [hDivideBCDDivisor + 1], a - and $f0 - or b - ld [hDivideBCDDivisor + 2], a - ld a, [hDivideBCDDivisor + 1] - and $f - ld b, a - ld a, [hDivideBCDDivisor] - swap a - ld [hDivideBCDDivisor], a - and $f0 - or b - ld [hDivideBCDDivisor + 1], a - ld a, [hDivideBCDDivisor] - and $f - ld [hDivideBCDDivisor], a - ret - -DivideBCD_getNextDigit: - ld bc, $3 -.loop - ld de, hMoney ; the dividend - ld hl, hDivideBCDDivisor - push bc - call StringCmp - pop bc - ret c - inc b - ld de, hMoney + 2 ; since SubBCD works starting from the least significant digit - ld hl, hDivideBCDDivisor + 2 - push bc - call SubBCD - pop bc - jr .loop - - -AddBCDPredef:: - call GetPredefRegisters - -AddBCD:: - and a - ld b, c -.add - ld a, [de] - adc [hl] - daa - ld [de], a - dec de - dec hl - dec c - jr nz, .add - jr nc, .done - ld a, $99 - inc de -.fill - ld [de], a - inc de - dec b - jr nz, .fill -.done - ret - - -SubBCDPredef:: - call GetPredefRegisters - -SubBCD:: - and a - ld b, c -.sub - ld a, [de] - sbc [hl] - daa - ld [de], a - dec de - dec hl - dec c - jr nz, .sub - jr nc, .done - ld a, $00 - inc de -.fill - ld [de], a - inc de - dec b - jr nz, .fill - scf -.done - ret diff --git a/engine/bg_map_attributes.asm b/engine/bg_map_attributes.asm index 90df9e27..4c50bcf8 100644 --- a/engine/bg_map_attributes.asm +++ b/engine/bg_map_attributes.asm @@ -19,37 +19,37 @@ LoadBGMapAttributes:: di ld a, $1 - ld [rVBK], a + ldh [rVBK], a push hl ld a, [hl] ld c, a ; save attribute count for later ld de, $10 add hl, de ld a, h - ld [rHDMA1], a + ldh [rHDMA1], a ld a, l - ld [rHDMA2], a + ldh [rHDMA2], a ld de, vBGMap0 ld a, d - ld [rHDMA3], a + ldh [rHDMA3], a ld a, e - ld [rHDMA4], a + ldh [rHDMA4], a - ld a, [rLCDC] + ldh a, [rLCDC] and rLCDC_ENABLE_MASK ; is LCD off? jr z, .lcdOff ; if off, transfer immediately ; wait for VBlank if LCD is on .waitForVBlankLoop1 - ld a, [rLY] + ldh a, [rLY] cp $90 jr nz, .waitForVBlankLoop1 .waitForAccessibleVRAMLoop1 - ld a, [rSTAT] + ldh a, [rSTAT] and %10 ; are we in HBlank or VBlank? jr nz, .waitForAccessibleVRAMLoop1 ; loop until we're in a safe period to transfer to VRAM .lcdOff ld a, c ; number of BG attributes to transfer, plus 1 times 16 - ld [rHDMA5], a ; initiate transfer + ldh [rHDMA5], a ; initiate transfer call Func_3082 ; update audio so it doesn't "lag" pop hl ld a, [hli] @@ -60,30 +60,30 @@ LoadBGMapAttributes:: ld d, a ; offset of the attributes add hl, de ; hl = new pointer ld a, h - ld [rHDMA1], a + ldh [rHDMA1], a ld a, l - ld [rHDMA2], a + ldh [rHDMA2], a ld de, vBGMap1 ; copy to vBGMap1 ld a, d - ld [rHDMA3], a + ldh [rHDMA3], a ld a, e - ld [rHDMA4], a + ldh [rHDMA4], a ; LCD check again - ld a, [rLCDC] + ldh a, [rLCDC] and rLCDC_ENABLE_MASK ; is LCD off? jr z, .lcdOff2 ; if off, transfer immediately ; wait for VBlank if LCD is on .waitForVBlankLoop2 - ld a, [rLY] + ldh a, [rLY] cp $90 jr nz, .waitForVBlankLoop2 .waitForAccessibleVRAMLoop2 - ld a, [rSTAT] + ldh a, [rSTAT] and %10 ; are we in HBlank or VBlank? jr nz, .waitForAccessibleVRAMLoop2 ; loop until we're in a safe period to transfer to VRAM .lcdOff2 ld a, c - ld [rHDMA5], a + ldh [rHDMA5], a pop af dec a dec a @@ -97,11 +97,11 @@ LoadBGMapAttributes:: call z, HandlePartyHPBarAttributes .done call Func_3082 - ld a, [rIF] + ldh a, [rIF] res VBLANK, a - ld [rIF], a + ldh [rIF], a xor a - ld [rVBK], a + ldh [rVBK], a ei ret diff --git a/engine/black_out.asm b/engine/black_out.asm deleted file mode 100644 index 0daa084b..00000000 --- a/engine/black_out.asm +++ /dev/null @@ -1,48 +0,0 @@ -ResetStatusAndHalveMoneyOnBlackout:: -; Reset player status on blackout. - xor a - ld [wd435], a - xor a ; gamefreak copypasting functions (double xor a) - ld [wBattleResult], a - ld [wWalkBikeSurfState], a - ld [wIsInBattle], a - ld [wMapPalOffset], a - ld [wNPCMovementScriptFunctionNum], a - ld [hJoyHeld], a - ld [wNPCMovementScriptPointerTableNum], a - ld [wFlags_0xcd60], a - - ld [hMoney], a - ld [hMoney + 1], a - ld [hMoney + 2], a - call HasEnoughMoney - jr c, .lostmoney ; never happens - - ; Halve the player's money. - ld a, [wPlayerMoney] - ld [hMoney], a - ld a, [wPlayerMoney + 1] - ld [hMoney + 1], a - ld a, [wPlayerMoney + 2] - ld [hMoney + 2], a - xor a - ld [hDivideBCDDivisor], a - ld [hDivideBCDDivisor + 1], a - ld a, 2 - ld [hDivideBCDDivisor + 2], a - predef DivideBCDPredef3 - ld a, [hDivideBCDQuotient] - ld [wPlayerMoney], a - ld a, [hDivideBCDQuotient + 1] - ld [wPlayerMoney + 1], a - ld a, [hDivideBCDQuotient + 2] - ld [wPlayerMoney + 2], a - -.lostmoney - ld hl, wd732 - set 2, [hl] - res 3, [hl] - set 6, [hl] - ld a, %11111111 - ld [wJoyIgnore], a - predef_jump HealParty diff --git a/engine/cable_club.asm b/engine/cable_club.asm deleted file mode 100755 index a8dc5d8d..00000000 --- a/engine/cable_club.asm +++ /dev/null @@ -1,984 +0,0 @@ -; performs the appropriate action when the player uses the gameboy on the table in the Colosseum or Trade Center -; In the Colosseum, it starts a battle. In the Trade Center, it displays the trade selection screen. -; Before doing either action, it swaps random numbers, trainer names and party data with the other gameboy. -CableClub_DoBattleOrTrade: - ld c, 80 - call DelayFrames - call ClearScreen - call UpdateSprites - call LoadFontTilePatterns - call LoadHpBarAndStatusTilePatterns - call LoadTrainerInfoTextBoxTiles - coord hl, 3, 8 - lb bc, 2, 12 - call CableClub_TextBoxBorder - coord hl, 4, 10 - ld de, PleaseWaitString - call PlaceString - ld hl, wPlayerNumHits - xor a - ld [hli], a - ld [hl], $50 - ; fall through - -; This is called after completing a trade. -CableClub_DoBattleOrTradeAgain: - ld hl, wSerialPlayerDataBlock - ld a, SERIAL_PREAMBLE_BYTE - ld b, 6 -.writePlayerDataBlockPreambleLoop - ld [hli], a - dec b - jr nz, .writePlayerDataBlockPreambleLoop - ld hl, wSerialRandomNumberListBlock - ld a, SERIAL_PREAMBLE_BYTE - ld b, 7 -.writeRandomNumberListPreambleLoop - ld [hli], a - dec b - jr nz, .writeRandomNumberListPreambleLoop - ld b, 10 -.generateRandomNumberListLoop - call Random - cp SERIAL_PREAMBLE_BYTE ; all the random numbers have to be less than the preamble byte - jr nc, .generateRandomNumberListLoop - ld [hli], a - dec b - jr nz, .generateRandomNumberListLoop - ld hl, wSerialPartyMonsPatchList - ld a, SERIAL_PREAMBLE_BYTE - ld [hli], a - ld [hli], a - ld [hli], a - ld b, $c8 - xor a -.zeroPlayerDataPatchListLoop - ld [hli], a - dec b - jr nz, .zeroPlayerDataPatchListLoop - ld hl, wGrassRate - ld bc, wTrainerHeaderPtr - wGrassRate -.zeroEnemyPartyLoop - xor a - ld [hli], a - dec bc - ld a, b - or c - jr nz, .zeroEnemyPartyLoop - ld hl, wPartyMons - 1 - ld de, wSerialPartyMonsPatchList + 10 - ld bc, 0 -.patchPartyMonsLoop - inc c - ld a, c - cp SERIAL_PREAMBLE_BYTE - jr z, .startPatchListPart2 - ld a, b - dec a ; are we in part 2 of the patch list? - jr nz, .checkPlayerDataByte ; jump if in part 1 -; if we're in part 2 - ld a, c - cp (wPartyMonOT - (wPartyMons - 1)) - (SERIAL_PREAMBLE_BYTE - 1) - jr z, .finishedPatchingPlayerData -.checkPlayerDataByte - inc hl - ld a, [hl] - cp SERIAL_NO_DATA_BYTE - jr nz, .patchPartyMonsLoop -; if the player data byte matches SERIAL_NO_DATA_BYTE, patch it with $FF and record the offset in the patch list - ld a, c - ld [de], a - inc de - ld [hl], $ff - jr .patchPartyMonsLoop -.startPatchListPart2 - ld a, SERIAL_PATCH_LIST_PART_TERMINATOR - ld [de], a ; end of part 1 - inc de - lb bc, 1, 0 - jr .patchPartyMonsLoop -.finishedPatchingPlayerData - ld a, SERIAL_PATCH_LIST_PART_TERMINATOR - ld [de], a ; end of part 2 - call Serial_SyncAndExchangeNybble - ld a, [hSerialConnectionStatus] - cp USING_INTERNAL_CLOCK - jr nz, .skipSendingTwoZeroBytes -; if using internal clock -; send two zero bytes for syncing purposes? - call Delay3 - xor a - ld [hSerialSendData], a - ld a, START_TRANSFER_INTERNAL_CLOCK - ld [rSC], a - call DelayFrame - xor a - ld [hSerialSendData], a - ld a, START_TRANSFER_INTERNAL_CLOCK - ld [rSC], a -.skipSendingTwoZeroBytes - call Delay3 - call StopAllMusic - ld a, (1 << SERIAL) - ld [rIE], a - ld hl, wSerialRandomNumberListBlock - ld de, wSerialOtherGameboyRandomNumberListBlock - ld bc, $11 - call Serial_ExchangeBytes - ld a, SERIAL_NO_DATA_BYTE - ld [de], a - ld hl, wSerialPlayerDataBlock - ld de, wSerialEnemyDataBlock - ld bc, $1a8 - call Serial_ExchangeBytes - ld a, SERIAL_NO_DATA_BYTE - ld [de], a - ld hl, wSerialPartyMonsPatchList - ld de, wSerialEnemyMonsPatchList - ld bc, $c8 - call Serial_ExchangeBytes - ld a, (1 << SERIAL) | (1 << TIMER) | (1 << VBLANK) - ld [rIE], a - ld a, [hSerialConnectionStatus] - cp USING_INTERNAL_CLOCK - jr z, .skipCopyingRandomNumberList ; the list generated by the gameboy clocking the connection is used by both gameboys - ld hl, wSerialOtherGameboyRandomNumberListBlock -.findStartOfRandomNumberListLoop - ld a, [hli] - and a - jr z, .findStartOfRandomNumberListLoop - cp SERIAL_PREAMBLE_BYTE - jr z, .findStartOfRandomNumberListLoop - cp SERIAL_NO_DATA_BYTE - jr z, .findStartOfRandomNumberListLoop - dec hl - ld de, wLinkBattleRandomNumberList - ld c, 10 -.copyRandomNumberListLoop - ld a, [hli] - cp SERIAL_NO_DATA_BYTE - jr z, .copyRandomNumberListLoop - ld [de], a - inc de - dec c - jr nz, .copyRandomNumberListLoop -.skipCopyingRandomNumberList - ld hl, wSerialEnemyDataBlock + 3 -.findStartOfEnemyNameLoop - ld a, [hli] - and a - jr z, .findStartOfEnemyNameLoop - cp SERIAL_PREAMBLE_BYTE - jr z, .findStartOfEnemyNameLoop - cp SERIAL_NO_DATA_BYTE - jr z, .findStartOfEnemyNameLoop - dec hl - ld de, wLinkEnemyTrainerName - ld c, NAME_LENGTH -.copyEnemyNameLoop - ld a, [hli] - cp SERIAL_NO_DATA_BYTE - jr z, .copyEnemyNameLoop - ld [de], a - inc de - dec c - jr nz, .copyEnemyNameLoop - ld de, wEnemyPartyCount - ld bc, wTrainerHeaderPtr - wEnemyPartyCount -.copyEnemyPartyLoop - ld a, [hli] - cp SERIAL_NO_DATA_BYTE - jr z, .copyEnemyPartyLoop - ld [de], a - inc de - dec bc - ld a, b - or c - jr nz, .copyEnemyPartyLoop - ld de, wSerialPartyMonsPatchList - ld hl, wPartyMons - ld c, 2 ; patch list has 2 parts -.unpatchPartyMonsLoop - ld a, [de] - inc de - and a - jr z, .unpatchPartyMonsLoop - cp SERIAL_PREAMBLE_BYTE - jr z, .unpatchPartyMonsLoop - cp SERIAL_NO_DATA_BYTE - jr z, .unpatchPartyMonsLoop - cp SERIAL_PATCH_LIST_PART_TERMINATOR - jr z, .finishedPartyMonsPatchListPart - push hl - push bc - ld b, 0 - dec a - ld c, a - add hl, bc - ld a, SERIAL_NO_DATA_BYTE - ld [hl], a - pop bc - pop hl - jr .unpatchPartyMonsLoop -.finishedPartyMonsPatchListPart - ld hl, wPartyMons + (SERIAL_PREAMBLE_BYTE - 1) - dec c ; is there another part? - jr nz, .unpatchPartyMonsLoop - ld de, wSerialEnemyMonsPatchList - ld hl, wEnemyMons - ld c, 2 ; patch list has 2 parts -.unpatchEnemyMonsLoop - ld a, [de] - inc de - and a - jr z, .unpatchEnemyMonsLoop - cp SERIAL_PREAMBLE_BYTE - jr z, .unpatchEnemyMonsLoop - cp SERIAL_NO_DATA_BYTE - jr z, .unpatchEnemyMonsLoop - cp SERIAL_PATCH_LIST_PART_TERMINATOR - jr z, .finishedEnemyMonsPatchListPart - push hl - push bc - ld b, 0 - dec a - ld c, a - add hl, bc - ld a, SERIAL_NO_DATA_BYTE - ld [hl], a - pop bc - pop hl - jr .unpatchEnemyMonsLoop -.finishedEnemyMonsPatchListPart - ld hl, wEnemyMons + (SERIAL_PREAMBLE_BYTE - 1) - dec c - jr nz, .unpatchEnemyMonsLoop - ld a, wEnemyMonOT % $100 - ld [wUnusedCF8D], a - ld a, wEnemyMonOT / $100 - ld [wUnusedCF8D + 1], a - xor a - ld [wTradeCenterPointerTableIndex], a - call StopAllMusic - ld a, [hSerialConnectionStatus] - cp USING_INTERNAL_CLOCK - ld c, 66 - call z, DelayFrames ; delay if using internal clock - ld a, [wLinkState] - cp LINK_STATE_START_BATTLE - ld a, LINK_STATE_TRADING - ld [wLinkState], a - jr nz, .trading - ld a, LINK_STATE_BATTLING - ld [wLinkState], a - ld a, OPP_SONY1 - ld [wCurOpponent], a - call ClearScreen - call Delay3 - ld b, $9 - call RunPaletteCommand - ld hl, wOptions - res 7, [hl] - ld a, [wLetterPrintingDelayFlags] - push af - xor a - ld [wLetterPrintingDelayFlags], a - predef InitOpponent - pop af - ld [wLetterPrintingDelayFlags], a - predef HealParty - jp ReturnToCableClubRoom -.trading - ld c, BANK(Music_GameCorner) - ld a, MUSIC_GAME_CORNER - call PlayMusic - jr CallCurrentTradeCenterFunction - -PleaseWaitString: - db "PLEASE WAIT!@" - -CallCurrentTradeCenterFunction: - ld hl, TradeCenterPointerTable - ld b, 0 - ld a, [wTradeCenterPointerTableIndex] - cp $ff - jp z, DisplayTitleScreen - add a - ld c, a - add hl, bc - ld a, [hli] - ld h, [hl] - ld l, a - jp hl - -TradeCenter_SelectMon: - call ClearScreen - call Delay3 - ld b, $9 - call RunPaletteCommand - call LoadTrainerInfoTextBoxTiles - call TradeCenter_DrawPartyLists - call TradeCenter_DrawCancelBox - xor a - ld hl, wSerialSyncAndExchangeNybbleReceiveData - ld [hli], a - ld [hli], a - ld [hli], a - ld [hl], a - ld [wMenuWatchMovingOutOfBounds], a - ld [wCurrentMenuItem], a - ld [wLastMenuItem], a - ld [wMenuJoypadPollCount], a - inc a - ld [wSerialExchangeNybbleSendData], a - jp .playerMonMenu -.enemyMonMenu - xor a - ld [wMenuWatchMovingOutOfBounds], a - inc a - ld [wWhichTradeMonSelectionMenu], a - ld a, D_DOWN | D_LEFT | A_BUTTON - ld [wMenuWatchedKeys], a - ld a, [wEnemyPartyCount] - ld [wMaxMenuItem], a - ld a, 9 - ld [wTopMenuItemY], a - ld a, 1 - ld [wTopMenuItemX], a -.enemyMonMenu_HandleInput - ld hl, hFlags_0xFFFA - set 1, [hl] - call HandleMenuInput - ld hl, hFlags_0xFFFA - res 1, [hl] - and a - jp z, .getNewInput - bit 0, a ; A button pressed? - jr z, .enemyMonMenu_ANotPressed -; if A button pressed - ld a, [wMaxMenuItem] - ld c, a - ld a, [wCurrentMenuItem] - cp c - jr c, .displayEnemyMonStats - ld a, [wMaxMenuItem] - dec a - ld [wCurrentMenuItem], a -.displayEnemyMonStats - ld a, INIT_ENEMYOT_LIST - ld [wInitListType], a - callab InitList ; the list isn't used - ld hl, wEnemyMons - call TradeCenter_DisplayStats - jp .getNewInput -.enemyMonMenu_ANotPressed - bit 5, a ; Left pressed? - jr z, .enemyMonMenu_LeftNotPressed -; if Left pressed, switch back to the player mon menu - xor a ; player mon menu - ld [wWhichTradeMonSelectionMenu], a - ld a, [wMenuCursorLocation] - ld l, a - ld a, [wMenuCursorLocation + 1] - ld h, a - ld a, [wTileBehindCursor] - ld [hl], a - ld a, [wCurrentMenuItem] - ld b, a - ld a, [wPartyCount] - dec a - cp b - jr nc, .playerMonMenu - ld [wCurrentMenuItem], a - jr .playerMonMenu -.enemyMonMenu_LeftNotPressed - bit 7, a ; Down pressed? - jp z, .getNewInput - jp .selectedCancelMenuItem ; jump if Down pressed -.playerMonMenu - xor a ; player mon menu - ld [wWhichTradeMonSelectionMenu], a - ld [wMenuWatchMovingOutOfBounds], a - ld a, D_DOWN | D_RIGHT | A_BUTTON - ld [wMenuWatchedKeys], a - ld a, [wPartyCount] - ld [wMaxMenuItem], a - ld a, 1 - ld [wTopMenuItemY], a - ld a, 1 - ld [wTopMenuItemX], a - coord hl, 1, 1 - lb bc, 6, 1 - call ClearScreenArea -.playerMonMenu_HandleInput - ld hl, hFlags_0xFFFA - set 1, [hl] - call HandleMenuInput - ld hl, hFlags_0xFFFA - res 1, [hl] - and a ; was anything pressed? - jr nz, .playerMonMenu_SomethingPressed - jp .getNewInput -.playerMonMenu_SomethingPressed - bit 0, a ; A button pressed? - jr z, .playerMonMenu_ANotPressed - jp .chosePlayerMon ; jump if A button pressed -; unreachable code - ld a, INIT_PLAYEROT_LIST - ld [wInitListType], a - callab InitList ; the list isn't used - call TradeCenter_DisplayStats - jp .getNewInput -.playerMonMenu_ANotPressed - bit 4, a ; Right pressed? - jr z, .playerMonMenu_RightNotPressed -; if Right pressed, switch to the enemy mon menu - ld a, $1 ; enemy mon menu - ld [wWhichTradeMonSelectionMenu], a - ld a, [wMenuCursorLocation] - ld l, a - ld a, [wMenuCursorLocation + 1] - ld h, a - ld a, [wTileBehindCursor] - ld [hl], a - ld a, [wCurrentMenuItem] - ld b, a - ld a, [wEnemyPartyCount] - dec a - cp b - jr nc, .notPastLastEnemyMon -; when switching to the enemy mon menu, if the menu selection would be past the last enemy mon, select the last enemy mon - ld [wCurrentMenuItem], a -.notPastLastEnemyMon - jp .enemyMonMenu -.playerMonMenu_RightNotPressed - bit 7, a ; Down pressed? - jr z, .getNewInput - jp .selectedCancelMenuItem ; jump if Down pressed -.getNewInput - ld a, [wWhichTradeMonSelectionMenu] - and a - jp z, .playerMonMenu_HandleInput - jp .enemyMonMenu_HandleInput -.chosePlayerMon - call SaveScreenTilesToBuffer1 - call PlaceUnfilledArrowMenuCursor - ld a, [wMaxMenuItem] - ld c, a - ld a, [wCurrentMenuItem] - cp c - jr c, .displayStatsTradeMenu - ld a, [wMaxMenuItem] - dec a -.displayStatsTradeMenu - push af - coord hl, 0, 14 - lb bc, 2, 18 - call CableClub_TextBoxBorder - coord hl, 2, 16 - ld de, .statsTrade - call PlaceString - xor a - ld [wCurrentMenuItem], a - ld [wLastMenuItem], a - ld [wMenuJoypadPollCount], a - ld [wMaxMenuItem], a - ld a, 16 - ld [wTopMenuItemY], a -.selectStatsMenuItem - ld a, " " - Coorda 11, 16 - ld a, D_RIGHT | B_BUTTON | A_BUTTON - ld [wMenuWatchedKeys], a - ld a, 1 - ld [wTopMenuItemX], a - call HandleMenuInput - bit 4, a ; Right pressed? - jr nz, .selectTradeMenuItem - bit 1, a ; B button pressed? - jr z, .displayPlayerMonStats -.cancelPlayerMonChoice - pop af - ld [wCurrentMenuItem], a - call LoadScreenTilesFromBuffer1 - jp .playerMonMenu -.selectTradeMenuItem - ld a, " " - Coorda 1, 16 - ld a, D_LEFT | B_BUTTON | A_BUTTON - ld [wMenuWatchedKeys], a - ld a, 11 - ld [wTopMenuItemX], a - call HandleMenuInput - bit 5, a ; Left pressed? - jr nz, .selectStatsMenuItem - bit 1, a ; B button pressed? - jr nz, .cancelPlayerMonChoice - jr .choseTrade -.displayPlayerMonStats - pop af - ld [wCurrentMenuItem], a - ld a, INIT_PLAYEROT_LIST - ld [wInitListType], a - callab InitList ; the list isn't used - call TradeCenter_DisplayStats - call LoadScreenTilesFromBuffer1 - jp .playerMonMenu -.choseTrade - call PlaceUnfilledArrowMenuCursor - pop af - ld [wCurrentMenuItem], a - ld [wTradingWhichPlayerMon], a - ld [wSerialExchangeNybbleSendData], a - call Serial_PrintWaitingTextAndSyncAndExchangeNybble - ld a, [wSerialSyncAndExchangeNybbleReceiveData] - cp $f - jp z, CallCurrentTradeCenterFunction ; go back to the beginning of the trade selection menu if the other person cancelled - ld [wTradingWhichEnemyMon], a - call TradeCenter_PlaceSelectedEnemyMonMenuCursor - ld a, $1 ; TradeCenter_Trade - ld [wTradeCenterPointerTableIndex], a - jp CallCurrentTradeCenterFunction -.statsTrade - db "STATS TRADE@" -.selectedCancelMenuItem - ld a, [wCurrentMenuItem] - ld b, a - ld a, [wMaxMenuItem] - cp b - jp nz, .getNewInput - ld a, [wMenuCursorLocation] - ld l, a - ld a, [wMenuCursorLocation + 1] - ld h, a - ld a, " " - ld [hl], a -.cancelMenuItem_Loop - ld a, "▶" ; filled arrow cursor - Coorda 1, 16 -.cancelMenuItem_JoypadLoop - call JoypadLowSensitivity - ld a, [hJoy5] - and a ; pressed anything? - jr z, .cancelMenuItem_JoypadLoop - bit 0, a ; A button pressed? - jr nz, .cancelMenuItem_APressed - bit 6, a ; Up pressed? - jr z, .cancelMenuItem_JoypadLoop -; if Up pressed - ld a, " " - Coorda 1, 16 - ld a, [wPartyCount] - dec a - ld [wCurrentMenuItem], a - jp .playerMonMenu -.cancelMenuItem_APressed - ld a, "▷" ; unfilled arrow cursor - Coorda 1, 16 - ld a, $f - ld [wSerialExchangeNybbleSendData], a - call Serial_PrintWaitingTextAndSyncAndExchangeNybble - ld a, [wSerialSyncAndExchangeNybbleReceiveData] - cp $f ; did the other person choose Cancel too? - jr nz, .cancelMenuItem_Loop - ; fall through - -ReturnToCableClubRoom: - call GBPalWhiteOutWithDelay3 - ld hl, wFontLoaded - ld a, [hl] - push af - push hl - res 0, [hl] - xor a - ld [wd72d], a - dec a - ld [wDestinationWarpID], a - call LoadMapData - callba ClearVariablesOnEnterMap - pop hl - pop af - ld [hl], a - call GBFadeInFromWhite - ret - -TradeCenter_DrawCancelBox: - coord hl, 11, 15 - ld a, $7e - ld bc, 2 * SCREEN_WIDTH + 9 - call FillMemory - coord hl, 0, 15 - lb bc, 1, 9 - call CableClub_TextBoxBorder - coord hl, 2, 16 - ld de, CancelTextString - jp PlaceString - -CancelTextString: - db "CANCEL@" - -TradeCenter_PlaceSelectedEnemyMonMenuCursor: - ld a, [wSerialSyncAndExchangeNybbleReceiveData] - coord hl, 1, 9 - ld bc, SCREEN_WIDTH - call AddNTimes - ld [hl], "▷" ; cursor - ret - -TradeCenter_DisplayStats: - ld a, [wCurrentMenuItem] - ld [wWhichPokemon], a - predef StatusScreen - predef StatusScreen2 - call Delay3 - ld b, $9 - call RunPaletteCommand - call GBPalNormal - call LoadTrainerInfoTextBoxTiles - call TradeCenter_DrawPartyLists - jp TradeCenter_DrawCancelBox - -TradeCenter_DrawPartyLists: - coord hl, 0, 0 - lb bc, 6, 18 - call CableClub_TextBoxBorder - coord hl, 0, 8 - lb bc, 6, 18 - call CableClub_TextBoxBorder - coord hl, 5, 0 - ld de, wPlayerName - call PlaceString - coord hl, 5, 8 - ld de, wLinkEnemyTrainerName - call PlaceString - coord hl, 2, 1 - ld de, wPartySpecies - call TradeCenter_PrintPartyListNames - coord hl, 2, 9 - ld de, wEnemyPartyMons - ; fall through - -TradeCenter_PrintPartyListNames: - ld c, $0 -.loop - ld a, [de] - cp $ff - ret z - ld [wd11e], a - push bc - push hl - push de - push hl - ld a, c - ld [$ff95], a - call GetMonName - pop hl - call PlaceString - pop de - inc de - pop hl - ld bc, 20 - add hl, bc - pop bc - inc c - jr .loop - -TradeCenter_Trade: - ld c, 100 - call DelayFrames - xor a - ld [wSerialExchangeNybbleSendData + 1], a ; unnecessary - ld [wSerialExchangeNybbleReceiveData], a - ld [wMenuWatchMovingOutOfBounds], a - ld [wMenuJoypadPollCount], a - coord hl, 0, 12 - lb bc, 4, 18 - call CableClub_TextBoxBorder - ld a, [wTradingWhichPlayerMon] - ld hl, wPartySpecies - ld c, a - ld b, 0 - add hl, bc - ld a, [hl] - ld [wd11e], a - call GetMonName - ld hl, wcd6d - ld de, wNameOfPlayerMonToBeTraded - ld bc, NAME_LENGTH - call CopyData - ld a, [wTradingWhichEnemyMon] - ld hl, wEnemyPartyMons - ld c, a - ld b, 0 - add hl, bc - ld a, [hl] - ld [wd11e], a - call GetMonName - ld hl, WillBeTradedText - coord bc, 1, 14 - call TextCommandProcessor - call SaveScreenTilesToBuffer1 - coord hl, 10, 7 - lb bc, 8, 11 - ld a, TRADE_CANCEL_MENU - ld [wTwoOptionMenuID], a - ld a, TWO_OPTION_MENU - ld [wTextBoxID], a - call DisplayTextBoxID - call LoadScreenTilesFromBuffer1 - ld a, [wCurrentMenuItem] - and a - jr z, .tradeConfirmed -; if trade cancelled - ld a, $1 - ld [wSerialExchangeNybbleSendData], a - coord hl, 0, 12 - lb bc, 4, 18 - call CableClub_TextBoxBorder - coord hl, 1, 14 - ld de, TradeCanceled - call PlaceString - call Serial_PrintWaitingTextAndSyncAndExchangeNybble - jp .tradeCancelled -.tradeConfirmed - ld a, $2 - ld [wSerialExchangeNybbleSendData], a - call Serial_PrintWaitingTextAndSyncAndExchangeNybble - ld a, [wSerialSyncAndExchangeNybbleReceiveData] - dec a ; did the other person cancel? - jr nz, .doTrade -; if the other person cancelled - coord hl, 0, 12 - lb bc, 4, 18 - call CableClub_TextBoxBorder - coord hl, 1, 14 - ld de, TradeCanceled - call PlaceString - jp .tradeCancelled -.doTrade - ld a, [wTradingWhichPlayerMon] - ld hl, wPartyMonOT - call SkipFixedLengthTextEntries - ld de, wTradedPlayerMonOT - ld bc, NAME_LENGTH - call CopyData - ld hl, wPartyMon1Species - ld a, [wTradingWhichPlayerMon] - ld bc, wPartyMon2 - wPartyMon1 - call AddNTimes - ld bc, wPartyMon1OTID - wPartyMon1 - add hl, bc - ld a, [hli] - ld [wTradedPlayerMonOTID], a - ld a, [hl] - ld [wTradedPlayerMonOTID + 1], a - ld a, [wTradingWhichEnemyMon] - ld hl, wEnemyMonOT - call SkipFixedLengthTextEntries - ld de, wTradedEnemyMonOT - ld bc, NAME_LENGTH - call CopyData - ld hl, wEnemyMons - ld a, [wTradingWhichEnemyMon] - ld bc, wEnemyMon2 - wEnemyMon1 - call AddNTimes - ld bc, wEnemyMon1OTID - wEnemyMon1 - add hl, bc - ld a, [hli] - ld [wTradedEnemyMonOTID], a - ld a, [hl] - ld [wTradedEnemyMonOTID + 1], a - ld a, [wTradingWhichPlayerMon] - ld [wWhichPokemon], a - ld hl, wPartySpecies - ld b, 0 - ld c, a - add hl, bc - ld a, [hl] - ld [wTradedPlayerMonSpecies], a - callabd_ModifyPikachuHappiness PIKAHAPPY_TRADE - xor a - ld [wRemoveMonFromBox], a - call RemovePokemon - ld a, [wTradingWhichEnemyMon] - ld c, a - ld [wWhichPokemon], a - ld hl, wEnemyPartyMons - ld d, 0 - ld e, a - add hl, de - ld a, [hl] - ld [wcf91], a - ld hl, wEnemyMons - ld a, c - ld bc, wEnemyMon2 - wEnemyMon1 - call AddNTimes - ld de, wLoadedMon - ld bc, wEnemyMon2 - wEnemyMon1 - call CopyData - call AddEnemyMonToPlayerParty - ld a, [wPartyCount] - dec a - ld [wWhichPokemon], a - ld a, $1 - ld [wForceEvolution], a - ld a, [wTradingWhichEnemyMon] - ld hl, wEnemyPartyMons - ld b, 0 - ld c, a - add hl, bc - ld a, [hl] - ld [wTradedEnemyMonSpecies], a - ld a, 10 - ld [wAudioFadeOutControl], a - ld a, BANK(Music_SafariZone) - ld [wAudioSavedROMBank], a - ld a, MUSIC_SAFARI_ZONE - ld [wNewSoundID], a - call PlaySound - ld c, 100 - call DelayFrames - call ClearScreen - call LoadHpBarAndStatusTilePatterns - xor a - ld [wUnusedCC5B], a - ld a, [hSerialConnectionStatus] - cp USING_EXTERNAL_CLOCK - jr z, .usingExternalClock - predef InternalClockTradeAnim - jr .tradeCompleted -.usingExternalClock - predef ExternalClockTradeAnim -.tradeCompleted - callab TryEvolvingMon - call ClearScreen - call LoadTrainerInfoTextBoxTiles - call Serial_PrintWaitingTextAndSyncAndExchangeNybble - ld c, 40 - call DelayFrames - call Delay3 - ld b, $9 - call RunPaletteCommand - coord hl, 0, 12 - lb bc, 4, 18 - call CableClub_TextBoxBorder - coord hl, 1, 14 - ld de, TradeCompleted - call PlaceString - predef SaveSAVtoSRAM2 - ld c, 50 - call DelayFrames - xor a - ld [wTradeCenterPointerTableIndex], a - jp CableClub_DoBattleOrTradeAgain -.tradeCancelled - ld c, 100 - call DelayFrames - xor a ; TradeCenter_SelectMon - ld [wTradeCenterPointerTableIndex], a - jp CallCurrentTradeCenterFunction - -WillBeTradedText: - TX_FAR _WillBeTradedText - db "@" - -TradeCompleted: - db "Trade completed!@" - -TradeCanceled: - db "Too bad! The trade" - next "was canceled!@" - -TradeCenterPointerTable: - dw TradeCenter_SelectMon - dw TradeCenter_Trade - -CableClub_Run: - ld a, [wLinkState] - cp LINK_STATE_START_TRADE - jr z, .doBattleOrTrade - cp LINK_STATE_START_BATTLE - jr z, .doBattleOrTrade - cp LINK_STATE_RESET ; this is never used - ret nz - predef EmptyFunc3 - jp Init -.doBattleOrTrade - call CableClub_DoBattleOrTrade - ld hl, Club_GFX - ld a, h - ld [wTilesetGfxPtr + 1], a - ld a, l - ld [wTilesetGfxPtr], a - ld a, Bank(Club_GFX) - ld [wTilesetBank], a - ld hl, Club_Coll - ld a, h - ld [wTilesetCollisionPtr + 1], a - ld a, l - ld [wTilesetCollisionPtr], a - xor a - ld [wGrassRate], a - inc a ; LINK_STATE_IN_CABLE_CLUB - ld [wLinkState], a - ld [hJoy5], a - ld a, 10 - ld [wAudioFadeOutControl], a - ld a, BANK(Music_Celadon) - ld [wAudioSavedROMBank], a - ld a, MUSIC_CELADON - ld [wNewSoundID], a - jp PlaySound - -EmptyFunc3: - ret - -Diploma_TextBoxBorder: - call GetPredefRegisters - -; b = height -; c = width -CableClub_TextBoxBorder: - push hl - ld a, $78 ; border upper left corner tile - ld [hli], a - inc a ; border top horizontal line tile - call CableClub_DrawHorizontalLine - inc a ; border upper right corner tile - ld [hl], a - pop hl - ld de, 20 - add hl, de -.loop - push hl - ld a, $7b ; border left vertical line tile - ld [hli], a - ld a, " " - call CableClub_DrawHorizontalLine - ld [hl], $77 ; border right vertical line tile - pop hl - ld de, 20 - add hl, de - dec b - jr nz, .loop - ld a, $7c ; border lower left corner tile - ld [hli], a - ld a, $76 ; border bottom horizontal line tile - call CableClub_DrawHorizontalLine - ld [hl], $7d ; border lower right corner tile - ret - -; c = width -CableClub_DrawHorizontalLine: - ld d, c -.loop - ld [hli], a - dec d - jr nz, .loop - ret - -LoadTrainerInfoTextBoxTiles: - ld de, TrainerInfoTextBoxTileGraphics - ld hl, vChars2 + $760 - lb bc, BANK(TrainerInfoTextBoxTileGraphics), (TrainerInfoTextBoxTileGraphicsEnd - TrainerInfoTextBoxTileGraphics) / $10 - jp CopyVideoData diff --git a/engine/clear_save.asm b/engine/clear_save.asm deleted file mode 100755 index f2acbf32..00000000 --- a/engine/clear_save.asm +++ /dev/null @@ -1,27 +0,0 @@ -DoClearSaveDialogue: - call ClearScreen - call RunDefaultPaletteCommand - call LoadFontTilePatterns - call LoadTextBoxTilePatterns - ld hl, ClearSaveDataText - call PrintText - ld a, B_BUTTON - ld [wJoyIgnore], a - coord hl, 14, 7 - lb bc, 8, 15 - ld a, NO_YES_MENU - ld [wTwoOptionMenuID], a - ld a, TWO_OPTION_MENU - ld [wTextBoxID], a - call DisplayTextBoxID - ld a, 0 - ld [wJoyIgnore], a - ld a, [wCurrentMenuItem] - and a - jp z, Init - callba ClearSAV - jp Init - -ClearSaveDataText: - TX_FAR _ClearSaveDataText - db "@" diff --git a/engine/debug/debug_menu.asm b/engine/debug/debug_menu.asm new file mode 100644 index 00000000..a85c9c64 --- /dev/null +++ b/engine/debug/debug_menu.asm @@ -0,0 +1,46 @@ +DebugMenu: + ret + +TestBattle: +.loop + call GBPalNormal + + ; Don't mess around + ; with obedience. + ld a, 1 << BIT_EARTHBADGE + ld [wObtainedBadges], a + + ld hl, wFlags_D733 + set BIT_TEST_BATTLE, [hl] + + ; Reset the party. + ld hl, wPartyCount + xor a + ld [hli], a + dec a + ld [hl], a + + ; Give the player a + ; level 20 Rhydon. + ld a, RHYDON + ld [wcf91], a + ld a, 20 + ld [wCurEnemyLVL], a + xor a + ld [wMonDataLocation], a + ld [wCurMap], a + call AddPartyMon + + ; Fight against a + ; level 20 Rhydon. + ld a, RHYDON + ld [wCurOpponent], a + + predef InitOpponent + + ; When the battle ends, + ; do it all again. + ld a, 1 + ld [wUpdateSpritesEnabled], a + ldh [hAutoBGTransferEnabled], a + jr .loop diff --git a/engine/debug/debug_party.asm b/engine/debug/debug_party.asm new file mode 100644 index 00000000..8545b848 --- /dev/null +++ b/engine/debug/debug_party.asm @@ -0,0 +1,24 @@ +; not IshiharaTeam +SetDebugTeam: + ld de, DebugTeam +.loop + ld a, [de] + cp -1 + ret z + ld [wcf91], a + inc de + ld a, [de] + ld [wCurEnemyLVL], a + inc de + call AddPartyMon + jr .loop + +DebugTeam: + db SNORLAX, 80 + db PERSIAN, 80 + db JIGGLYPUFF, 15 + db PIKACHU, 5 + db -1 ; end + +DebugStart: + ret diff --git a/engine/debug1.asm b/engine/debug1.asm deleted file mode 100644 index a39e8cac..00000000 --- a/engine/debug1.asm +++ /dev/null @@ -1,24 +0,0 @@ -; not IshiharaTeam -SetDebugTeam: - ld de, DebugTeam -.loop - ld a, [de] - cp $ff - ret z - ld [wcf91], a - inc de - ld a, [de] - ld [wCurEnemyLVL], a - inc de - call AddPartyMon - jr .loop - -DebugTeam: - db SNORLAX,80 - db PERSIAN,80 - db JIGGLYPUFF,15 - db PIKACHU,5 - db $FF - -EmptyFunc: - ret diff --git a/engine/diploma_3a.asm b/engine/diploma_3a.asm index f4504ad7..83a7345b 100755 --- a/engine/diploma_3a.asm +++ b/engine/diploma_3a.asm @@ -1,3 +1,5 @@ +CIRCLE_TILE_ID EQU $10 + _DisplayDiploma: call GBPalWhiteOutWithDelay3 call ClearScreen @@ -6,51 +8,51 @@ _DisplayDiploma: lb bc, BANK(SurfingPikachu3Graphics), (SurfingPikachu3GraphicsEnd - SurfingPikachu3Graphics) / $10 call CopyVideoData - coord hl, 0, 0 + hlcoord 0, 0 call Func_e9bdf - coord hl, 0, 0 + hlcoord 0, 0 call Func_e9beb - coord hl, 19, 0 + hlcoord 19, 0 call Func_e9beb ld a, $00 - coord hl, 0, 0 + hlcoord 0, 0 ld [hl], a - coord hl, 19, 0 + hlcoord 19, 0 ld [hl], a ld de, String_e9a73 - coord hl, 5, 2 + hlcoord 5, 2 call PlaceString ld de, String_e9a7d - coord hl, 3, 4 + hlcoord 3, 4 call PlaceString ld de, wPlayerName - coord hl, 10, 4 + hlcoord 10, 4 call PlaceString ld de, String_e9a84 - coord hl, 2, 6 + hlcoord 2, 6 call PlaceString ld de, String_e9ac8 - coord hl, 9, 16 + hlcoord 9, 16 call PlaceString ld b, SET_PAL_GENERIC call RunPaletteCommand ld a, $01 - ld [$ffba], a + ldh [hAutoBGTransferEnabled], a call Delay3 call GBPalNormal ret String_e9a73: - db $10, "Diploma", $10, "@" + db CIRCLE_TILE_ID, "Diploma", CIRCLE_TILE_ID, "@" String_e9a7d: db "Player@" @@ -67,29 +69,29 @@ String_e9ac8: Func_e9ad3: call ClearScreen - coord hl, 0, 17 + hlcoord 0, 17 call Func_e9bdf - coord hl, 0, 0 + hlcoord 0, 0 call Func_e9beb - coord hl, 19, 0 + hlcoord 19, 0 call Func_e9beb ld a, $00 - coord hl, 0, 17 + hlcoord 0, 17 ld [hl], a - coord hl, 19, 17 + hlcoord 19, 17 ld [hl], a ld de, Tilemap_e9b3e - coord hl, 6, 2 + hlcoord 6, 2 lb bc, 10, 12 call Diploma_Surfing_CopyBox ld de, Tilemap_e9bb6 - coord hl, 5, 13 + hlcoord 5, 13 lb bc, 1, 11 call Diploma_Surfing_CopyBox ld de, String_e9bd5 - coord hl, 2, 15 + hlcoord 2, 15 call PlaceString - coord hl, 12, 15 + hlcoord 12, 15 ld de, wPlayTimeHours lb bc, $40 | 1, 3 call PrintNumber @@ -102,7 +104,7 @@ Func_e9ad3: cp 151 ret nz ld de, TileMap_e9bc1 - coord hl, 2, 0 + hlcoord 2, 0 lb bc, 4, 5 call Diploma_Surfing_CopyBox ret diff --git a/engine/display_pokedex.asm b/engine/display_pokedex.asm deleted file mode 100644 index 96a2dd6c..00000000 --- a/engine/display_pokedex.asm +++ /dev/null @@ -1,19 +0,0 @@ -_DisplayPokedex: - ld hl, wd730 - set 6, [hl] - predef ShowPokedexData - ld hl, wd730 - res 6, [hl] - call ReloadMapData - ld c, 10 - call DelayFrames - predef IndexToPokedex - ld a, [wd11e] - dec a - ld c, a - ld b, FLAG_SET - ld hl, wPokedexSeen - predef FlagActionPredef - ld a, $1 - ld [wDoNotWaitForButtonPressAfterDisplayingText], a - ret diff --git a/engine/display_text_id_init.asm b/engine/display_text_id_init.asm deleted file mode 100644 index 0ef37370..00000000 --- a/engine/display_text_id_init.asm +++ /dev/null @@ -1,75 +0,0 @@ -; function that performs initialization for DisplayTextID -DisplayTextIDInit: - xor a - ld [wListMenuID], a - ld a, [wAutoTextBoxDrawingControl] - bit 0, a - jr nz, .skipDrawingTextBoxBorder - ld a, [hSpriteIndexOrTextID] ; text ID (or sprite ID) - and a - jr nz, .notStartMenu -; if text ID is 0 (i.e. the start menu) -; Note that the start menu text border is also drawn in the function directly -; below this, so this seems unnecessary. - CheckEvent EVENT_GOT_POKEDEX -; start menu with pokedex - coord hl, 10, 0 - lb bc, 14, 8 - jr nz, .drawTextBoxBorder -; start menu without pokedex - coord hl, 10, 0 - lb bc, 12, 8 - jr .drawTextBoxBorder -; if text ID is not 0 (i.e. not the start menu) then do a standard dialogue text box -.notStartMenu - coord hl, 0, 12 - lb bc, 4, 18 -.drawTextBoxBorder - call TextBoxBorder -.skipDrawingTextBoxBorder - ld hl, wFontLoaded - set 0, [hl] - ld hl, wFlags_0xcd60 - bit 4, [hl] - res 4, [hl] - jr nz, .skipMovingSprites - call UpdateSprites -.skipMovingSprites -; loop to copy C1X9 (direction the sprite is facing) to C2X9 for each sprite -; this is done because when you talk to an NPC, they turn to look your way -; the original direction they were facing must be restored after the dialogue is over - ld hl, wSpriteStateData1 + $19 - ld c, $0f - ld de, $0010 -.spriteFacingDirectionCopyLoop - ld a, [hl] - inc h - ld [hl], a - dec h - add hl, de - dec c - jr nz, .spriteFacingDirectionCopyLoop -; loop to force all the sprites in the middle of animation to stand still -; (so that they don't like they're frozen mid-step during the dialogue) - ld hl, wSpriteStateData1 + 2 - ld de, $0010 - ld c, e -.spriteStandStillLoop - ld a, [hl] - cp $ff ; is the sprite visible? - jr z, .nextSprite -; if it is visible - and $fc - ld [hl], a -.nextSprite - add hl, de - dec c - jr nz, .spriteStandStillLoop - ld b, $9c ; window background address - call CopyScreenTileBufferToVRAM ; transfer background in WRAM to VRAM - xor a - ld [hWY], a ; put the window on the screen - call LoadFontTilePatterns - ld a, $01 - ld [H_AUTOBGTRANSFERENABLED], a ; enable continuous WRAM to VRAM transfer each V-blank - ret diff --git a/engine/events/black_out.asm b/engine/events/black_out.asm new file mode 100644 index 00000000..6d3d91b8 --- /dev/null +++ b/engine/events/black_out.asm @@ -0,0 +1,48 @@ +ResetStatusAndHalveMoneyOnBlackout:: +; Reset player status on blackout. + xor a + ld [wd435], a + xor a ; gamefreak copypasting functions (double xor a) + ld [wBattleResult], a + ld [wWalkBikeSurfState], a + ld [wIsInBattle], a + ld [wMapPalOffset], a + ld [wNPCMovementScriptFunctionNum], a + ldh [hJoyHeld], a + ld [wNPCMovementScriptPointerTableNum], a + ld [wFlags_0xcd60], a + + ldh [hMoney], a + ldh [hMoney + 1], a + ldh [hMoney + 2], a + call HasEnoughMoney + jr c, .lostmoney ; never happens + + ; Halve the player's money. + ld a, [wPlayerMoney] + ldh [hMoney], a + ld a, [wPlayerMoney + 1] + ldh [hMoney + 1], a + ld a, [wPlayerMoney + 2] + ldh [hMoney + 2], a + xor a + ldh [hDivideBCDDivisor], a + ldh [hDivideBCDDivisor + 1], a + ld a, 2 + ldh [hDivideBCDDivisor + 2], a + predef DivideBCDPredef3 + ldh a, [hDivideBCDQuotient] + ld [wPlayerMoney], a + ldh a, [hDivideBCDQuotient + 1] + ld [wPlayerMoney + 1], a + ldh a, [hDivideBCDQuotient + 2] + ld [wPlayerMoney + 2], a + +.lostmoney + ld hl, wd732 + set 2, [hl] + res 3, [hl] + set 6, [hl] + ld a, %11111111 + ld [wJoyIgnore], a + predef_jump HealParty diff --git a/engine/events/card_key.asm b/engine/events/card_key.asm new file mode 100755 index 00000000..de5f402e --- /dev/null +++ b/engine/events/card_key.asm @@ -0,0 +1,102 @@ +PrintCardKeyText: + ld hl, SilphCoMapList + ld a, [wCurMap] + ld b, a +.silphCoMapListLoop + ld a, [hli] + cp -1 + ret z + cp b + jr nz, .silphCoMapListLoop +; does not check for tile in front of player. This might be buggy + ;predef GetTileAndCoordsInFrontOfPlayer + ld a, [wTileInFrontOfPlayer] + cp $18 + jr z, .cardKeyDoorInFrontOfPlayer + cp $24 + jr z, .cardKeyDoorInFrontOfPlayer + ld b, a + ld a, [wCurMap] + cp SILPH_CO_11F + ret nz + ld a, b + cp $5e + ret nz +.cardKeyDoorInFrontOfPlayer + ld b, CARD_KEY + call IsItemInBag + jr z, .noCardKey + xor a + ld [wPlayerMovingDirection], a + tx_pre_id CardKeySuccessText + ldh [hSpriteIndexOrTextID], a + call PrintPredefTextID + call GetCoordsInFrontOfPlayer + srl d + ld a, d + ld b, a + ld [wCardKeyDoorY], a + srl e + ld a, e + ld c, a + ld [wCardKeyDoorX], a + ld a, [wCurMap] + cp SILPH_CO_11F + jr nz, .notSilphCo11F + ld a, $3 + jr .replaceCardKeyDoorTileBlock +.notSilphCo11F + ld a, $e +.replaceCardKeyDoorTileBlock + ld [wNewTileBlockID], a + predef ReplaceTileBlock + ld hl, wCurrentMapScriptFlags + set 5, [hl] + ld a, SFX_GO_INSIDE + jp PlaySound +.noCardKey + tx_pre_id CardKeyFailText + ldh [hSpriteIndexOrTextID], a + jp PrintPredefTextID + +INCLUDE "data/events/card_key_maps.asm" + +CardKeySuccessText:: + text_far _CardKeySuccessText1 + sound_get_item_1 + text_far _CardKeySuccessText2 + text_end + +CardKeyFailText:: + text_far _CardKeyFailText + text_end + +; d = Y +; e = X +GetCoordsInFrontOfPlayer: + ld a, [wYCoord] + ld d, a + ld a, [wXCoord] + ld e, a + ld a, [wSpritePlayerStateData1FacingDirection] + and a + jr nz, .notFacingDown +; facing down + inc d + ret +.notFacingDown + cp SPRITE_FACING_UP + jr nz, .notFacingUp +; facing up + dec d + ret +.notFacingUp + cp SPRITE_FACING_LEFT + jr nz, .notFacingLeft +; facing left + dec e + ret +.notFacingLeft +; facing right + inc e + ret diff --git a/engine/events/cinnabar_lab.asm b/engine/events/cinnabar_lab.asm new file mode 100755 index 00000000..bccc95d1 --- /dev/null +++ b/engine/events/cinnabar_lab.asm @@ -0,0 +1,123 @@ +GiveFossilToCinnabarLab:: + ld hl, wd730 + set 6, [hl] + xor a + ld [wCurrentMenuItem], a + ld a, A_BUTTON | B_BUTTON + ld [wMenuWatchedKeys], a + ld a, [wFilteredBagItemsCount] + dec a + ld [wMaxMenuItem], a + ld a, 2 + ld [wTopMenuItemY], a + ld a, 1 + ld [wTopMenuItemX], a + ld a, [wFilteredBagItemsCount] + dec a + ld bc, 2 + ld hl, 3 + call AddNTimes + dec l + ld b, l + ld c, $d + hlcoord 0, 0 + call TextBoxBorder + call UpdateSprites + call PrintFossilsInBag + ld hl, wd730 + res 6, [hl] + call HandleMenuInput + bit 1, a ; pressed B? + jr nz, .cancelledGivingFossil + ld hl, wFilteredBagItems + ld a, [wCurrentMenuItem] + ld d, 0 + ld e, a + add hl, de + ld a, [hl] + ldh [hItemToRemoveID], a + cp DOME_FOSSIL + jr z, .choseDomeFossil + cp HELIX_FOSSIL + jr z, .choseHelixFossil + ld b, AERODACTYL + jr .fossilSelected +.choseHelixFossil + ld b, OMANYTE + jr .fossilSelected +.choseDomeFossil + ld b, KABUTO +.fossilSelected + ld [wFossilItem], a + ld a, b + ld [wFossilMon], a + call LoadFossilItemAndMonName + ld hl, LabFossil_610ae + call PrintText + call YesNoChoice + ld a, [wCurrentMenuItem] + and a + jr nz, .cancelledGivingFossil + ld hl, LabFossil_610b3 + call PrintText + ld a, [wFossilItem] + ldh [hItemToRemoveID], a + farcall RemoveItemByID + ld hl, LabFossil_610b8 + call PrintText + SetEvents EVENT_GAVE_FOSSIL_TO_LAB, EVENT_LAB_STILL_REVIVING_FOSSIL + ret +.cancelledGivingFossil + ld hl, LabFossil_610bd + call PrintText + ret + +LabFossil_610ae: + text_far _Lab4Text_610ae + text_end + +LabFossil_610b3: + text_far _Lab4Text_610b3 + text_end + +LabFossil_610b8: + text_far _Lab4Text_610b8 + text_end + +LabFossil_610bd: + text_far _Lab4Text_610bd + text_end + +PrintFossilsInBag: +; Prints each fossil in the player's bag on a separate line in the menu. + ld hl, wFilteredBagItems + xor a + ldh [hItemCounter], a +.loop + ld a, [hli] + cp $ff + ret z + push hl + ld [wd11e], a + call GetItemName + hlcoord 2, 2 + ldh a, [hItemCounter] + ld bc, SCREEN_WIDTH * 2 + call AddNTimes + ld de, wcd6d + call PlaceString + ld hl, hItemCounter + inc [hl] + pop hl + jr .loop + +; loads the names of the fossil item and the resulting mon +LoadFossilItemAndMonName:: + ld a, [wFossilMon] + ld [wd11e], a + call GetMonName + call CopyStringToCF4B + ld a, [wFossilItem] + ld [wd11e], a + call GetItemName + ret diff --git a/engine/events/diploma.asm b/engine/events/diploma.asm new file mode 100644 index 00000000..a5a007fa --- /dev/null +++ b/engine/events/diploma.asm @@ -0,0 +1,17 @@ +DisplayDiploma:: + call SaveScreenTilesToBuffer2 + call GBPalWhiteOutWithDelay3 + call ClearScreen + xor a + ld [wUpdateSpritesEnabled], a + ld hl, wd730 + set 6, [hl] + callfar _DisplayDiploma + call WaitForTextScrollButtonPress + ld hl, wd730 + res 6, [hl] + call GBPalWhiteOutWithDelay3 + call ReloadTilesetTilePatterns + call RestoreScreenTilesAndReloadTilePatterns + call Delay3 + jp GBPalNormal diff --git a/engine/events/display_pokedex.asm b/engine/events/display_pokedex.asm new file mode 100644 index 00000000..d657ea85 --- /dev/null +++ b/engine/events/display_pokedex.asm @@ -0,0 +1,19 @@ +_DisplayPokedex:: + ld hl, wd730 + set 6, [hl] + predef ShowPokedexData + ld hl, wd730 + res 6, [hl] + call ReloadMapData + ld c, 10 + call DelayFrames + predef IndexToPokedex + ld a, [wd11e] + dec a + ld c, a + ld b, FLAG_SET + ld hl, wPokedexSeen + predef FlagActionPredef + ld a, $1 + ld [wDoNotWaitForButtonPressAfterDisplayingText], a + ret diff --git a/engine/events/elevator.asm b/engine/events/elevator.asm new file mode 100755 index 00000000..004893a0 --- /dev/null +++ b/engine/events/elevator.asm @@ -0,0 +1,54 @@ +DisplayElevatorFloorMenu: + ld hl, wd730 + ld a, [hl] + push af + set 6, [hl] + ld hl, WhichFloorText + call PrintText + pop af + ld [wd730], a + ld hl, wItemList + ld a, l + ld [wListPointer], a + ld a, h + ld [wListPointer + 1], a + ld a, [wListScrollOffset] + push af + xor a + ld [wCurrentMenuItem], a + ld [wListScrollOffset], a + ld [wPrintItemPrices], a + ld a, SPECIALLISTMENU + ld [wListMenuID], a + call DisplayListMenuID + pop bc + ld a, b + ld [wListScrollOffset], a + ret c + ld hl, wCurrentMapScriptFlags + set 7, [hl] + ld hl, wElevatorWarpMaps + ld a, [wWhichPokemon] + add a + ld d, 0 + ld e, a + add hl, de + ld a, [hli] + ld b, a + ld a, [hl] + ld c, a + ld hl, wWarpEntries + call .UpdateWarp + +.UpdateWarp + inc hl + inc hl + ld a, b + ld [hli], a ; destination warp ID + ld a, c + ld [hli], a ; destination map ID + ret + +WhichFloorText: + text_far _WhichFloorText + text_end diff --git a/engine/events/give_pokemon.asm b/engine/events/give_pokemon.asm new file mode 100755 index 00000000..efc184f8 --- /dev/null +++ b/engine/events/give_pokemon.asm @@ -0,0 +1,87 @@ +_GivePokemon:: +; returns success in carry +; and whether the mon was added to the party in [wAddedToParty] + call EnableAutoTextBoxDrawing + xor a + ld [wAddedToParty], a + ld a, [wPartyCount] + cp PARTY_LENGTH + jr c, .addToParty + ld a, [wNumInBox] + cp MONS_PER_BOX + jr nc, .boxFull +; add to box + xor a + ld [wEnemyBattleStatus3], a + ld a, [wcf91] + ld [wEnemyMonSpecies2], a + callfar LoadEnemyMonData + call SetPokedexOwnedFlag + callfar SendNewMonToBox + ld hl, wcf4b + ld a, [wCurrentBoxNum] + and $7f + cp 9 + jr c, .singleDigitBoxNum + sub 9 + ld [hl], "1" + inc hl + add "0" + jr .next +.singleDigitBoxNum + add "1" +.next + ld [hli], a + ld [hl], "@" + ld hl, SentToBoxText + call PrintText + scf + ret +.boxFull + ld hl, BoxIsFullText + call PrintText + and a + ret +.addToParty + call SetPokedexOwnedFlag + ld hl, UnknownTerminator_f6794 + call PrintText + call AddPartyMon + ld a, 1 + ld [wDoNotWaitForButtonPressAfterDisplayingText], a + ld [wAddedToParty], a + scf + ret + +SetPokedexOwnedFlag: + ld a, [wcf91] + push af + ld [wd11e], a + predef IndexToPokedex + ld a, [wd11e] + dec a + ld c, a + ld hl, wPokedexOwned + ld b, FLAG_SET + predef FlagActionPredef + pop af + ld [wd11e], a + call GetMonName + ld hl, GotMonText + jp PrintText + +UnknownTerminator_f6794: + text_end + +GotMonText: + text_far _GotMonText + sound_get_item_1 + text_end + +SentToBoxText: + text_far _SentToBoxText + text_end + +BoxIsFullText: + text_far _BoxIsFullText + text_end diff --git a/engine/events/heal_party.asm b/engine/events/heal_party.asm new file mode 100644 index 00000000..7aaa1bd1 --- /dev/null +++ b/engine/events/heal_party.asm @@ -0,0 +1,99 @@ +HealParty: +; Restore HP and PP. + + ld hl, wPartySpecies + ld de, wPartyMon1HP +.healmon + ld a, [hli] + cp $ff + jr z, .done + + push hl + push de + + ld hl, wPartyMon1Status - wPartyMon1HP + add hl, de + xor a + ld [hl], a + + push de + ld b, NUM_MOVES ; A Pokémon has 4 moves +.pp + ld hl, wPartyMon1Moves - wPartyMon1HP + add hl, de + + ld a, [hl] + and a + jr z, .nextmove + + dec a + ld hl, wPartyMon1PP - wPartyMon1HP + add hl, de + + push hl + push de + push bc + + ld hl, Moves + ld bc, MoveEnd - Moves + call AddNTimes + ld de, wcd6d + ld a, BANK(Moves) + call FarCopyData + ld a, [wcd6d + 5] ; PP is byte 5 of move data + + pop bc + pop de + pop hl + + inc de + push bc + ld b, a + ld a, [hl] + and $c0 + add b + ld [hl], a + pop bc + +.nextmove + dec b + jr nz, .pp + pop de + + ld hl, wPartyMon1MaxHP - wPartyMon1HP + add hl, de + ld a, [hli] + ld [de], a + inc de + ld a, [hl] + ld [de], a + + pop de + pop hl + + push hl + ld bc, wPartyMon2 - wPartyMon1 + ld h, d + ld l, e + add hl, bc + ld d, h + ld e, l + pop hl + jr .healmon + +.done + xor a + ld [wWhichPokemon], a + ld [wd11e], a + + ld a, [wPartyCount] + ld b, a +.ppup + push bc + call RestoreBonusPP + pop bc + ld hl, wWhichPokemon + inc [hl] + dec b + jr nz, .ppup + ret diff --git a/engine/events/hidden_items.asm b/engine/events/hidden_items.asm new file mode 100755 index 00000000..63b95bcf --- /dev/null +++ b/engine/events/hidden_items.asm @@ -0,0 +1,172 @@ +HiddenItems: + ld hl, HiddenItemCoords + call FindHiddenItemOrCoinsIndex + ld [wHiddenItemOrCoinsIndex], a + ld hl, wObtainedHiddenItemsFlags + ld a, [wHiddenItemOrCoinsIndex] + ld c, a + ld b, FLAG_TEST + predef FlagActionPredef + ld a, c + and a + jr nz, .itemAlreadyFound + call EnableAutoTextBoxDrawing + ld a, 1 + ld [wDoNotWaitForButtonPressAfterDisplayingText], a + ld a, [wHiddenObjectFunctionArgument] ; item ID + ld [wd11e], a + call GetItemName + tx_pre_jump FoundHiddenItemText + +.itemAlreadyFound + ld a, $ff + ldh [hItemAlreadyFound], a + ret + +INCLUDE "data/events/hidden_item_coords.asm" + +FoundHiddenItemText:: + text_far _FoundHiddenItemText + text_asm + ld a, [wHiddenObjectFunctionArgument] ; item ID + ld b, a + ld c, 1 + call GiveItem + jr nc, .bagFull + ld hl, wObtainedHiddenItemsFlags + ld a, [wHiddenItemOrCoinsIndex] + ld c, a + ld b, FLAG_SET + predef FlagActionPredef + ld a, SFX_GET_ITEM_2 + call PlaySoundWaitForCurrent + call WaitForSoundToFinish + jp TextScriptEnd +.bagFull + call WaitForTextScrollButtonPress ; wait for button press + xor a + ld [wDoNotWaitForButtonPressAfterDisplayingText], a + ld hl, HiddenItemBagFullText + call PrintText + jp TextScriptEnd + +HiddenItemBagFullText:: + text_far _HiddenItemBagFullText + text_end + +HiddenCoins: + ld b, COIN_CASE + predef GetQuantityOfItemInBag + ld a, b + and a + jr z, .doNotPickUpCoins + ld hl, HiddenCoinCoords + call FindHiddenItemOrCoinsIndex + ld [wHiddenItemOrCoinsIndex], a + ld hl, wObtainedHiddenCoinsFlags + ld a, [wHiddenItemOrCoinsIndex] + ld c, a + ld b, FLAG_TEST + predef FlagActionPredef + ld a, c + and a + jr nz, .doNotPickUpCoins + xor a + ldh [hUnusedCoinsByte], a + ldh [hCoins], a + ldh [hCoins + 1], a + ld a, [wHiddenObjectFunctionArgument] + sub COIN + cp 10 + jr z, .bcd10 + cp 20 + jr z, .bcd20 + cp 40 + jr z, .bcd20 ; should be bcd40 + jr .bcd100 + +.doNotPickUpCoins + ld a, $ff + ldh [hItemAlreadyFound], a + ret + +.bcd10 + ld a, $10 + ldh [hCoins + 1], a + jr .bcdDone +.bcd20 + ld a, $20 + ldh [hCoins + 1], a + jr .bcdDone +.bcd40 ; due to a typo, this is never used + ld a, $40 + ldh [hCoins + 1], a + jr .bcdDone +.bcd100 + ld a, $1 + ldh [hCoins], a +.bcdDone + ld de, wPlayerCoins + 1 + ld hl, hCoins + 1 + ld c, $2 + predef AddBCDPredef + ld hl, wObtainedHiddenCoinsFlags + ld a, [wHiddenItemOrCoinsIndex] + ld c, a + ld b, FLAG_SET + predef FlagActionPredef + call EnableAutoTextBoxDrawing + ld a, [wPlayerCoins] + cp $99 + jr nz, .roomInCoinCase + ld a, [wPlayerCoins + 1] + cp $99 + jr nz, .roomInCoinCase + tx_pre_id DroppedHiddenCoinsText + jr .done +.roomInCoinCase + tx_pre_id FoundHiddenCoinsText +.done + jp PrintPredefTextID + +INCLUDE "data/events/hidden_coins.asm" + +FoundHiddenCoinsText:: + text_far _FoundHiddenCoinsText + sound_get_item_2 + text_end + +DroppedHiddenCoinsText:: + text_far _FoundHiddenCoins2Text + sound_get_item_2 + text_far _DroppedHiddenCoinsText + text_end + +FindHiddenItemOrCoinsIndex: + ld a, [wHiddenObjectY] + ld d, a + ld a, [wHiddenObjectX] + ld e, a + ld a, [wCurMap] + ld b, a + ld c, -1 +.loop + inc c + ld a, [hli] + cp -1 ; end of the list? + ret z ; if so, we're done here + cp b + jr nz, .next1 + ld a, [hli] + cp d + jr nz, .next2 + ld a, [hli] + cp e + jr nz, .loop + ld a, c + ret +.next1 + inc hl +.next2 + inc hl + jr .loop diff --git a/engine/events/hidden_objects/bench_guys.asm b/engine/events/hidden_objects/bench_guys.asm new file mode 100644 index 00000000..b41434ad --- /dev/null +++ b/engine/events/hidden_objects/bench_guys.asm @@ -0,0 +1,98 @@ +PrintBenchGuyText: + call EnableAutoTextBoxDrawing + ld hl, BenchGuyTextPointers + ld a, [wCurMap] + ld b, a +.loop + ld a, [hli] + cp -1 + ret z + cp b + jr z, .match + inc hl + inc hl + jr .loop +.match + ld a, [hli] + ld b, a + ld a, [wSpritePlayerStateData1FacingDirection] + cp b + jr nz, .loop ; player isn't facing the bench guy + ld a, [hl] + jp PrintPredefTextID + +INCLUDE "data/events/bench_guys.asm" + +ViridianCityPokecenterBenchGuyText:: + text_far _ViridianCityPokecenterGuyText + text_end + +PewterCityPokecenterBenchGuyText:: + text_far _PewterCityPokecenterGuyText + text_end + +CeruleanCityPokecenterBenchGuyText:: + text_far _CeruleanPokecenterGuyText + text_end + +LavenderCityPokecenterBenchGuyText:: + text_far _LavenderPokecenterGuyText + text_end + +MtMoonPokecenterBenchGuyText:: + text_far _MtMoonPokecenterBenchGuyText + text_end + +RockTunnelPokecenterBenchGuyText:: + text_far _RockTunnelPokecenterGuyText + text_end + +UnusedBenchGuyText1:: + text_far _UnusedBenchGuyText1 + text_end + +UnusedBenchGuyText2:: + text_far _UnusedBenchGuyText2 + text_end + +UnusedBenchGuyText3:: + text_far _UnusedBenchGuyText3 + text_end + +VermilionCityPokecenterBenchGuyText:: + text_far _VermilionPokecenterGuyText + text_end + +CeladonCityPokecenterBenchGuyText:: + text_far _CeladonCityPokecenterGuyText + text_end + +FuchsiaCityPokecenterBenchGuyText:: + text_far _FuchsiaCityPokecenterGuyText + text_end + +CinnabarIslandPokecenterBenchGuyText:: + text_far _CinnabarPokecenterGuyText + text_end + +SaffronCityPokecenterBenchGuyText:: + text_asm + CheckEvent EVENT_BEAT_SILPH_CO_GIOVANNI + ld hl, SaffronCityPokecenterBenchGuyText2 + jr nz, .asm_624f2 + ld hl, SaffronCityPokecenterBenchGuyText1 +.asm_624f2 + call PrintText + jp TextScriptEnd + +SaffronCityPokecenterBenchGuyText1: + text_far _SaffronCityPokecenterGuyText1 + text_end + +SaffronCityPokecenterBenchGuyText2: + text_far _SaffronCityPokecenterGuyText2 + text_end + +CeladonCityHotelText:: + text_far _CeladonCityHotelText + text_end diff --git a/engine/events/hidden_objects/bills_house_pc.asm b/engine/events/hidden_objects/bills_house_pc.asm new file mode 100644 index 00000000..bdbaff7e --- /dev/null +++ b/engine/events/hidden_objects/bills_house_pc.asm @@ -0,0 +1,131 @@ +BillsHousePC: + call EnableAutoTextBoxDrawing + ld a, [wSpritePlayerStateData1FacingDirection] + cp SPRITE_FACING_UP + ret nz + CheckEvent EVENT_LEFT_BILLS_HOUSE_AFTER_HELPING + jr nz, .displayBillsHousePokemonList + CheckEventReuseA EVENT_USED_CELL_SEPARATOR_ON_BILL + jr nz, .displayBillsHouseMonitorText + CheckEventReuseA EVENT_BILL_SAID_USE_CELL_SEPARATOR + jr nz, .doCellSeparator +.displayBillsHouseMonitorText + tx_pre_jump BillsHouseMonitorText +.doCellSeparator + ld a, $1 + ld [wDoNotWaitForButtonPressAfterDisplayingText], a + tx_pre BillsHouseInitiatedText + ld c, 32 + call DelayFrames + ld a, SFX_TINK + call PlaySound + call WaitForSoundToFinish + ld c, 80 + call DelayFrames + ld a, SFX_SHRINK + call PlaySound + call WaitForSoundToFinish + ld c, 48 + call DelayFrames + ld a, SFX_TINK + call PlaySound + call WaitForSoundToFinish + ld c, 32 + call DelayFrames + ld a, SFX_GET_ITEM_1 + call PlaySound + call WaitForSoundToFinish + call PlayDefaultMusic + SetEvent EVENT_USED_CELL_SEPARATOR_ON_BILL + ret +.displayBillsHousePokemonList + ld a, $1 + ld [wDoNotWaitForButtonPressAfterDisplayingText], a + tx_pre BillsHousePokemonList + ret + +BillsHouseMonitorText:: + text_far _BillsHouseMonitorText + text_end + +BillsHouseInitiatedText:: + text_far _BillsHouseInitiatedText + text_promptbutton + text_asm + call StopAllMusic + ld c, 16 + call DelayFrames + ld a, SFX_SWITCH + call PlaySound + call WaitForSoundToFinish + ld c, 60 + call DelayFrames + jp TextScriptEnd + +BillsHousePokemonList:: + text_asm + call SaveScreenTilesToBuffer1 + ld hl, BillsHousePokemonListText1 + call PrintText + xor a + ld [wMenuItemOffset], a ; not used + ld [wCurrentMenuItem], a + ld [wLastMenuItem], a + ld a, A_BUTTON | B_BUTTON + ld [wMenuWatchedKeys], a + ld a, 4 + ld [wMaxMenuItem], a + ld a, 2 + ld [wTopMenuItemY], a + ld a, 1 + ld [wTopMenuItemX], a +.billsPokemonLoop + ld hl, wd730 + set 6, [hl] + hlcoord 0, 0 + lb bc, 10, 9 + call TextBoxBorder + hlcoord 2, 2 + ld de, BillsMonListText + call PlaceString + ld hl, BillsHousePokemonListText2 + call PrintText + call SaveScreenTilesToBuffer2 + call HandleMenuInput + bit 1, a ; pressed b + jr nz, .cancel + ld a, [wCurrentMenuItem] + add EEVEE + cp EEVEE + jr z, .displayPokedex + cp FLAREON + jr z, .displayPokedex + cp JOLTEON + jr z, .displayPokedex + cp VAPOREON + jr z, .displayPokedex + jr .cancel +.displayPokedex + call DisplayPokedex + call LoadScreenTilesFromBuffer2 + jr .billsPokemonLoop +.cancel + ld hl, wd730 + res 6, [hl] + call LoadScreenTilesFromBuffer2 + jp TextScriptEnd + +BillsHousePokemonListText1: + text_far _BillsHousePokemonListText1 + text_end + +BillsMonListText: + db "EEVEE" + next "FLAREON" + next "JOLTEON" + next "VAPOREON" + next "CANCEL@" + +BillsHousePokemonListText2: + text_far _BillsHousePokemonListText2 + text_end diff --git a/engine/events/hidden_objects/blues_room.asm b/engine/events/hidden_objects/blues_room.asm new file mode 100644 index 00000000..bcbad556 --- /dev/null +++ b/engine/events/hidden_objects/blues_room.asm @@ -0,0 +1,13 @@ + + ret ; unused + +UnusedPredefText:: + db "@" + +PrintBookcaseText: + call EnableAutoTextBoxDrawing + tx_pre_jump BookcaseText + +BookcaseText:: + text_far _BookcaseText + text_end diff --git a/engine/events/hidden_objects/book_or_sculpture.asm b/engine/events/hidden_objects/book_or_sculpture.asm new file mode 100644 index 00000000..e04f4047 --- /dev/null +++ b/engine/events/hidden_objects/book_or_sculpture.asm @@ -0,0 +1,21 @@ +BookOrSculptureText:: + text_asm + ld hl, PokemonBooksText + ld a, [wCurMapTileset] + cp MANSION ; Celadon Mansion tileset + jr nz, .ok + lda_coord 8, 6 + cp $38 + jr nz, .ok + ld hl, DiglettSculptureText +.ok + call PrintText + jp TextScriptEnd + +PokemonBooksText: + text_far _PokemonBooksText + text_end + +DiglettSculptureText: + text_far _DiglettSculptureText + text_end diff --git a/engine/events/hidden_objects/bookshelves.asm b/engine/events/hidden_objects/bookshelves.asm new file mode 100644 index 00000000..b58444af --- /dev/null +++ b/engine/events/hidden_objects/bookshelves.asm @@ -0,0 +1,39 @@ +; prints text for bookshelves in buildings without sign events +PrintBookshelfText:: + ld a, [wSpritePlayerStateData1FacingDirection] + cp SPRITE_FACING_UP + jr nz, .noMatch +; facing up + ld a, [wCurMapTileset] + ld b, a + lda_coord 8, 7 + ld c, a + ld hl, BookshelfTileIDs +.loop + ld a, [hli] + cp $ff + jr z, .noMatch + cp b + jr nz, .nextBookshelfEntry1 + ld a, [hli] + cp c + jr nz, .nextBookshelfEntry2 + ld a, [hl] + push af + call EnableAutoTextBoxDrawing + pop af + call PrintPredefTextID + xor a + ldh [hFFDB], a + ret +.nextBookshelfEntry1 + inc hl +.nextBookshelfEntry2 + inc hl + jr .loop +.noMatch + ld a, $ff + ldh [hFFDB], a + farjp PrintCardKeyText + +INCLUDE "data/tilesets/bookshelf_tile_ids.asm" diff --git a/engine/events/hidden_objects/cinnabar_gym_quiz.asm b/engine/events/hidden_objects/cinnabar_gym_quiz.asm new file mode 100644 index 00000000..da550c76 --- /dev/null +++ b/engine/events/hidden_objects/cinnabar_gym_quiz.asm @@ -0,0 +1,246 @@ +PrintCinnabarQuiz: + ld a, [wSpritePlayerStateData1FacingDirection] + cp SPRITE_FACING_UP + ret nz + call EnableAutoTextBoxDrawing + tx_pre_jump CinnabarGymQuiz + +CinnabarGymQuiz:: + text_asm + xor a + ld [wOpponentAfterWrongAnswer], a + ld hl, wd475 + res 7, [hl] + ld a, [wHiddenObjectFunctionArgument] + push af + and $f + ldh [hGymGateIndex], a + pop af + and $f0 + swap a + ldh [hGymGateAnswer], a + ldh a, [hGymGateIndex] + ld hl, CinnabarGymQuizIntroText + cp 1 + jr z, .onFirstQuestion + ld hl, CinnabarGymQuizShortIntroText +.onFirstQuestion + call PrintText + ldh a, [hGymGateIndex] + dec a + add a + ld d, 0 + ld e, a + ld hl, CinnabarQuizQuestions + add hl, de + ld a, [hli] + ld h, [hl] + ld l, a + call PrintText + ld a, 1 + ld [wDoNotWaitForButtonPressAfterDisplayingText], a + call CinnabarGymQuiz_1ea92 + jp TextScriptEnd + +CinnabarGymQuizDummyIntroText: + text_far _CinnabarGymQuizDummyIntroText + text_end + +CinnabarGymQuizIntroText: + text_far _CinnabarGymQuizIntroText + text_end + +CinnabarGymQuizShortIntroText: + text_far _CinnabarGymQuizShortIntroText + text_end + +CinnabarQuizQuestions: + dw CinnabarQuizQuestionsText1 + dw CinnabarQuizQuestionsText2 + dw CinnabarQuizQuestionsText3 + dw CinnabarQuizQuestionsText4 + dw CinnabarQuizQuestionsText5 + dw CinnabarQuizQuestionsText6 + +CinnabarQuizQuestionsText1: + text_far _CinnabarQuizQuestionsText1 + text_end + +CinnabarQuizQuestionsText2: + text_far _CinnabarQuizQuestionsText2 + text_end + +CinnabarQuizQuestionsText3: + text_far _CinnabarQuizQuestionsText3 + text_end + +CinnabarQuizQuestionsText4: + text_far _CinnabarQuizQuestionsText4 + text_end + +CinnabarQuizQuestionsText5: + text_far _CinnabarQuizQuestionsText5 + text_end + +CinnabarQuizQuestionsText6: + text_far _CinnabarQuizQuestionsText6 + text_end + +CinnabarGymQuiz_1ea92: + call YesNoChoice + ldh a, [hGymGateAnswer] + ld c, a + ld a, [wCurrentMenuItem] + cp c + jr nz, .wrongAnswer + ld hl, wCurrentMapScriptFlags + set 5, [hl] + ldh a, [hGymGateIndex] + ldh [hBackupGymGateIndex], a + ld hl, CinnabarGymQuizCorrectText + call PrintText + ldh a, [hBackupGymGateIndex] + AdjustEventBit EVENT_CINNABAR_GYM_GATE0_UNLOCKED, 0 + ld c, a + ld b, FLAG_SET + call CinnabarGymGateFlagAction + jp UpdateCinnabarGymGateTileBlocks_ +.wrongAnswer + call WaitForSoundToFinish + ld a, SFX_DENIED + call PlaySound + call WaitForSoundToFinish + ld hl, CinnabarGymQuizIncorrectText + call PrintText + ldh a, [hGymGateIndex] + add $2 + AdjustEventBit EVENT_BEAT_CINNABAR_GYM_TRAINER_0, 2 + ld c, a + ld b, FLAG_TEST + EventFlagAddress hl, EVENT_BEAT_CINNABAR_GYM_TRAINER_0 + predef FlagActionPredef + ld a, c + and a + ret nz + ldh a, [hGymGateIndex] + add $2 + ld [wOpponentAfterWrongAnswer], a + ld hl, wd475 + set 7, [hl] + ret + +CinnabarGymQuizCorrectText: + sound_get_item_1 + text_far _CinnabarGymQuizCorrectText + text_promptbutton + text_asm + + ldh a, [hBackupGymGateIndex] + AdjustEventBit EVENT_CINNABAR_GYM_GATE0_UNLOCKED, 0 + ld c, a + ld b, FLAG_TEST + call CinnabarGymGateFlagAction + ld a, c + and a + jp nz, TextScriptEnd + call WaitForSoundToFinish + ld a, SFX_GO_INSIDE + call PlaySound + call WaitForSoundToFinish + jp TextScriptEnd + +CinnabarGymQuizIncorrectText: + text_far _CinnabarGymQuizIncorrectText + text_end + +CinnabarGymGateFlagAction: + EventFlagAddress hl, EVENT_CINNABAR_GYM_GATE0_UNLOCKED + predef_jump FlagActionPredef + +UpdateCinnabarGymGateTileBlocks_:: +; Update the overworld map with open floor blocks or locked gate blocks +; depending on event flags. + ld a, 6 + ldh [hGymGateIndex], a +.loop + ldh a, [hGymGateIndex] + dec a + add a + add a + ld d, 0 + ld e, a + ld hl, CinnabarGymGateCoords + add hl, de + ld a, [hli] + ld b, [hl] + ld c, a + inc hl + ld a, [hl] + ld [wGymGateTileBlock], a + push bc + ldh a, [hGymGateIndex] + ldh [hBackupGymGateIndex], a + AdjustEventBit EVENT_CINNABAR_GYM_GATE0_UNLOCKED, 0 + ld c, a + ld b, FLAG_TEST + call CinnabarGymGateFlagAction + ld a, c + and a + jr nz, .unlocked + ld a, [wGymGateTileBlock] + jr .next +.unlocked + ld a, $e +.next + pop bc + ld [wNewTileBlockID], a + call CinnabarGym_ReplaceTileBlock + ld hl, hGymGateIndex + dec [hl] + jr nz, .loop + callfar RedrawMapView + ret + +gym_gate_coord: MACRO + db \1, \2, \3, 0 +ENDM + +HORIZONTAL_GATE_BLOCK EQU $54 +VERTICAL_GATE_BLOCK EQU $5f + +CinnabarGymGateCoords: + ; x coord, y coord, block id + gym_gate_coord 9, 3, HORIZONTAL_GATE_BLOCK + gym_gate_coord 6, 3, HORIZONTAL_GATE_BLOCK + gym_gate_coord 6, 6, HORIZONTAL_GATE_BLOCK + gym_gate_coord 3, 8, VERTICAL_GATE_BLOCK + gym_gate_coord 2, 6, HORIZONTAL_GATE_BLOCK + gym_gate_coord 2, 3, HORIZONTAL_GATE_BLOCK + + +CinnabarGym_ReplaceTileBlock: +; basically a copy of the first half of ReplaceTileBlock +; before checking if it is necessary to redraw the map view + ld hl, wOverworldMap + ld a, [wCurMapWidth] + add $6 + ld e, a + ld d, $0 + add hl, de + add hl, de + add hl, de + ld e, $3 + add hl, de + ld e, a + ld a, b + and a + jr z, .addX +.addWidthYTimesLoop + add hl, de + dec b + jr nz, .addWidthYTimesLoop +.addX + add hl, bc + ld a, [wNewTileBlockID] + ld [hl], a + ret diff --git a/engine/events/hidden_objects/elevator.asm b/engine/events/hidden_objects/elevator.asm new file mode 100644 index 00000000..ab0f731f --- /dev/null +++ b/engine/events/hidden_objects/elevator.asm @@ -0,0 +1,3 @@ +ElevatorText:: + text_far _ElevatorText + text_end diff --git a/engine/events/hidden_objects/fanclub_pictures.asm b/engine/events/hidden_objects/fanclub_pictures.asm new file mode 100644 index 00000000..30bc72c7 --- /dev/null +++ b/engine/events/hidden_objects/fanclub_pictures.asm @@ -0,0 +1,23 @@ +FanClubPicture1: + ld a, RAPIDASH + ld [wcf91], a + call DisplayMonFrontSpriteInBox + call EnableAutoTextBoxDrawing + tx_pre FanClubPicture1Text + ret + +FanClubPicture1Text:: + text_far _FanClubPicture1Text + text_end + +FanClubPicture2: + ld a, FEAROW + ld [wcf91], a + call DisplayMonFrontSpriteInBox + call EnableAutoTextBoxDrawing + tx_pre FanClubPicture2Text + ret + +FanClubPicture2Text:: + text_far _FanClubPicture2Text + text_end diff --git a/engine/events/hidden_objects/fighting_dojo.asm b/engine/events/hidden_objects/fighting_dojo.asm new file mode 100644 index 00000000..b4f89985 --- /dev/null +++ b/engine/events/hidden_objects/fighting_dojo.asm @@ -0,0 +1,23 @@ +PrintFightingDojoText2: + call EnableAutoTextBoxDrawing + tx_pre_jump EnemiesOnEverySideText + +EnemiesOnEverySideText:: + text_far _EnemiesOnEverySideText + text_end + +PrintFightingDojoText3: + call EnableAutoTextBoxDrawing + tx_pre_jump WhatGoesAroundComesAroundText + +WhatGoesAroundComesAroundText:: + text_far _WhatGoesAroundComesAroundText + text_end + +PrintFightingDojoText: + call EnableAutoTextBoxDrawing + tx_pre_jump FightingDojoText + +FightingDojoText:: + text_far _FightingDojoText + text_end diff --git a/engine/events/hidden_objects/gym_statues.asm b/engine/events/hidden_objects/gym_statues.asm new file mode 100644 index 00000000..1c7eb970 --- /dev/null +++ b/engine/events/hidden_objects/gym_statues.asm @@ -0,0 +1,39 @@ +GymStatues: +; if in a gym and have the corresponding badge, a = GymStatueText2_id and jp PrintPredefTextID +; if in a gym and don't have the corresponding badge, a = GymStatueText1_id and jp PrintPredefTextID +; else ret + call EnableAutoTextBoxDrawing + ld a, [wSpritePlayerStateData1FacingDirection] + cp SPRITE_FACING_UP + ret nz + ld hl, MapBadgeFlags + ld a, [wCurMap] + ld b, a +.loop + ld a, [hli] + cp $ff + ret z + cp b + jr z, .match + inc hl + jr .loop +.match + ld b, [hl] + ld a, [wBeatGymFlags] + and b + cp b + tx_pre_id GymStatueText2 + jr z, .haveBadge + tx_pre_id GymStatueText1 +.haveBadge + jp PrintPredefTextID + +INCLUDE "data/maps/badge_maps.asm" + +GymStatueText1:: + text_far _GymStatueText1 + text_end + +GymStatueText2:: + text_far _GymStatueText2 + text_end diff --git a/engine/events/hidden_objects/indigo_plateau_hq.asm b/engine/events/hidden_objects/indigo_plateau_hq.asm new file mode 100644 index 00000000..e8fd0220 --- /dev/null +++ b/engine/events/hidden_objects/indigo_plateau_hq.asm @@ -0,0 +1,10 @@ +PrintIndigoPlateauHQText: + ld a, [wSpritePlayerStateData1FacingDirection] + cp SPRITE_FACING_UP + ret nz + call EnableAutoTextBoxDrawing + tx_pre_jump IndigoPlateauHQText + +IndigoPlateauHQText:: + text_far _IndigoPlateauHQText + text_end diff --git a/engine/events/hidden_objects/indigo_plateau_statues.asm b/engine/events/hidden_objects/indigo_plateau_statues.asm new file mode 100644 index 00000000..23e94fcf --- /dev/null +++ b/engine/events/hidden_objects/indigo_plateau_statues.asm @@ -0,0 +1,24 @@ +IndigoPlateauStatues:: + text_asm + ld hl, IndigoPlateauStatuesText1 + call PrintText + ld a, [wXCoord] + bit 0, a + ld hl, IndigoPlateauStatuesText2 + jr nz, .ok + ld hl, IndigoPlateauStatuesText3 +.ok + call PrintText + jp TextScriptEnd + +IndigoPlateauStatuesText1: + text_far _IndigoPlateauStatuesText1 + text_end + +IndigoPlateauStatuesText2: + text_far _IndigoPlateauStatuesText2 + text_end + +IndigoPlateauStatuesText3: + text_far _IndigoPlateauStatuesText3 + text_end diff --git a/engine/events/hidden_objects/magazines.asm b/engine/events/hidden_objects/magazines.asm new file mode 100644 index 00000000..b58636ff --- /dev/null +++ b/engine/events/hidden_objects/magazines.asm @@ -0,0 +1,8 @@ +PrintMagazinesText: + call EnableAutoTextBoxDrawing + tx_pre MagazinesText + ret + +MagazinesText:: + text_far _MagazinesText + text_end diff --git a/engine/events/hidden_objects/museum_fossils.asm b/engine/events/hidden_objects/museum_fossils.asm new file mode 100644 index 00000000..539f2c3f --- /dev/null +++ b/engine/events/hidden_objects/museum_fossils.asm @@ -0,0 +1,23 @@ +AerodactylFossil: + ld a, FOSSIL_AERODACTYL + ld [wcf91], a + call DisplayMonFrontSpriteInBox + call EnableAutoTextBoxDrawing + tx_pre AerodactylFossilText + ret + +AerodactylFossilText:: + text_far _AerodactylFossilText + text_end + +KabutopsFossil: + ld a, FOSSIL_KABUTOPS + ld [wcf91], a + call DisplayMonFrontSpriteInBox + call EnableAutoTextBoxDrawing + tx_pre KabutopsFossilText + ret + +KabutopsFossilText:: + text_far _KabutopsFossilText + text_end diff --git a/engine/events/hidden_objects/museum_fossils2.asm b/engine/events/hidden_objects/museum_fossils2.asm new file mode 100644 index 00000000..fce0f03a --- /dev/null +++ b/engine/events/hidden_objects/museum_fossils2.asm @@ -0,0 +1,28 @@ +DisplayMonFrontSpriteInBox: +; Displays a pokemon's front sprite in a pop-up window. +; [wcf91] = pokemon internal id number + ld a, 1 + ldh [hAutoBGTransferEnabled], a + call Delay3 + xor a + ldh [hWY], a + call SaveScreenTilesToBuffer1 + ld a, MON_SPRITE_POPUP + ld [wTextBoxID], a + call DisplayTextBoxID + call UpdateSprites + ld a, [wcf91] + ld [wd0b5], a + call GetMonHeader + ld de, vChars1 + $310 + call LoadMonFrontSprite + ld a, $80 + ldh [hStartTileID], a + hlcoord 10, 11 + predef AnimateSendingOutMon + call WaitForTextScrollButtonPress + call LoadScreenTilesFromBuffer1 + call Delay3 + ld a, $90 + ldh [hWY], a + ret diff --git a/engine/events/hidden_objects/new_bike.asm b/engine/events/hidden_objects/new_bike.asm new file mode 100644 index 00000000..5bce5937 --- /dev/null +++ b/engine/events/hidden_objects/new_bike.asm @@ -0,0 +1,7 @@ +PrintNewBikeText: + call EnableAutoTextBoxDrawing + tx_pre_jump NewBicycleText + +NewBicycleText:: + text_far _NewBicycleText + text_end diff --git a/engine/events/hidden_objects/oaks_lab_email.asm b/engine/events/hidden_objects/oaks_lab_email.asm new file mode 100644 index 00000000..bd4c66d7 --- /dev/null +++ b/engine/events/hidden_objects/oaks_lab_email.asm @@ -0,0 +1,11 @@ +DisplayOakLabEmailText: + ld a, [wSpritePlayerStateData1FacingDirection] + cp SPRITE_FACING_UP + ret nz + call EnableAutoTextBoxDrawing + tx_pre OakLabEmailText + ret + +OakLabEmailText:: + text_far _OakLabEmailText + text_end diff --git a/engine/events/hidden_objects/oaks_lab_posters.asm b/engine/events/hidden_objects/oaks_lab_posters.asm new file mode 100644 index 00000000..502cf951 --- /dev/null +++ b/engine/events/hidden_objects/oaks_lab_posters.asm @@ -0,0 +1,29 @@ +DisplayOakLabLeftPoster: + call EnableAutoTextBoxDrawing + tx_pre_jump PushStartText + +PushStartText:: + text_far _PushStartText + text_end + +DisplayOakLabRightPoster: + call EnableAutoTextBoxDrawing + ld hl, wPokedexOwned + ld b, wPokedexOwnedEnd - wPokedexOwned + call CountSetBits + ld a, [wNumSetBits] + cp 2 + tx_pre_id SaveOptionText + jr c, .ownLessThanTwo + ; own two or more mon + tx_pre_id StrengthsAndWeaknessesText +.ownLessThanTwo + jp PrintPredefTextID + +SaveOptionText:: + text_far _SaveOptionText + text_end + +StrengthsAndWeaknessesText:: + text_far _StrengthsAndWeaknessesText + text_end diff --git a/engine/events/hidden_objects/pokecenter_pc.asm b/engine/events/hidden_objects/pokecenter_pc.asm new file mode 100644 index 00000000..f20f40ed --- /dev/null +++ b/engine/events/hidden_objects/pokecenter_pc.asm @@ -0,0 +1,11 @@ +OpenPokemonCenterPC: + ld a, [wSpritePlayerStateData1FacingDirection] + cp SPRITE_FACING_UP + ret nz + call EnableAutoTextBoxDrawing + ld a, TRUE + ld [wAutoTextBoxDrawingControl], a + tx_pre_jump PokemonCenterPCText + +PokemonCenterPCText:: + script_pokecenter_pc diff --git a/engine/events/hidden_objects/pokemon_stuff.asm b/engine/events/hidden_objects/pokemon_stuff.asm new file mode 100644 index 00000000..267a191a --- /dev/null +++ b/engine/events/hidden_objects/pokemon_stuff.asm @@ -0,0 +1,3 @@ +PokemonStuffText:: + text_far _PokemonStuffText + text_end diff --git a/engine/events/hidden_objects/reds_room.asm b/engine/events/hidden_objects/reds_room.asm new file mode 100644 index 00000000..7b8d51a0 --- /dev/null +++ b/engine/events/hidden_objects/reds_room.asm @@ -0,0 +1,14 @@ +PrintRedSNESText: + call EnableAutoTextBoxDrawing + tx_pre_jump RedBedroomSNESText + +RedBedroomSNESText:: + text_far _RedBedroomSNESText + text_end + +OpenRedsPC: + call EnableAutoTextBoxDrawing + tx_pre_jump RedBedroomPCText + +RedBedroomPCText:: + script_players_pc diff --git a/engine/events/hidden_objects/route_15_binoculars.asm b/engine/events/hidden_objects/route_15_binoculars.asm new file mode 100644 index 00000000..9734e833 --- /dev/null +++ b/engine/events/hidden_objects/route_15_binoculars.asm @@ -0,0 +1,17 @@ +Route15GateLeftBinoculars: + ld a, [wSpritePlayerStateData1FacingDirection] + cp SPRITE_FACING_UP + ret nz + call EnableAutoTextBoxDrawing + tx_pre Route15UpstairsBinocularsText + ld a, ARTICUNO + ld [wcf91], a + call PlayCry + call DisplayMonFrontSpriteInBox + xor a + ldh [hAutoBGTransferEnabled], a + ret + +Route15UpstairsBinocularsText:: + text_far _Route15UpstairsBinocularsText + text_end diff --git a/engine/events/hidden_objects/safari_game.asm b/engine/events/hidden_objects/safari_game.asm new file mode 100644 index 00000000..5001a5d4 --- /dev/null +++ b/engine/events/hidden_objects/safari_game.asm @@ -0,0 +1,78 @@ +SafariZoneCheck:: + CheckEventHL EVENT_IN_SAFARI_ZONE ; if we are not in the Safari Zone, + jr z, SafariZoneGameStillGoing ; don't bother printing game over text + ld a, [wNumSafariBalls] + and a + jr z, SafariZoneGameOver + jr SafariZoneGameStillGoing + +SafariZoneCheckSteps:: + ld a, [wSafariSteps] + ld b, a + ld a, [wSafariSteps + 1] + ld c, a + or b + jr z, SafariZoneGameOver + dec bc + ld a, b + ld [wSafariSteps], a + ld a, c + ld [wSafariSteps + 1], a +SafariZoneGameStillGoing: + xor a + ld [wSafariZoneGameOver], a + ret + +SafariZoneGameOver: + call EnableAutoTextBoxDrawing + xor a + ld [wAudioFadeOutControl], a + call StopAllMusic + ld c, BANK(SFX_Safari_Zone_PA) + ld a, SFX_SAFARI_ZONE_PA + call PlayMusic +.waitForMusicToPlay + ld a, [wChannelSoundIDs + Ch5] + cp SFX_SAFARI_ZONE_PA + jr nz, .waitForMusicToPlay + ld a, TEXT_SAFARI_GAME_OVER + ldh [hSpriteIndexOrTextID], a + call DisplayTextID + xor a + ld [wPlayerMovingDirection], a + ld a, SAFARI_ZONE_GATE + ldh [hWarpDestinationMap], a + ld a, $3 + ld [wDestinationWarpID], a + ld a, $5 + ld [wSafariZoneGateCurScript], a + SetEvent EVENT_SAFARI_GAME_OVER + ld a, 1 + ld [wSafariZoneGameOver], a + ret + +PrintSafariGameOverText:: + xor a + ld [wJoyIgnore], a + ld hl, SafariGameOverText + jp PrintText + +SafariGameOverText: + text_asm + ld a, [wNumSafariBalls] + and a + jr z, .noMoreSafariBalls + ld hl, TimesUpText + call PrintText +.noMoreSafariBalls + ld hl, GameOverText + call PrintText + jp TextScriptEnd + +TimesUpText: + text_far _TimesUpText + text_end + +GameOverText: + text_far _GameOverText + text_end diff --git a/engine/events/hidden_objects/school_blackboard.asm b/engine/events/hidden_objects/school_blackboard.asm new file mode 100644 index 00000000..eb927292 --- /dev/null +++ b/engine/events/hidden_objects/school_blackboard.asm @@ -0,0 +1,223 @@ +PrintBlackboardLinkCableText: + call EnableAutoTextBoxDrawing + ld a, $1 + ld [wDoNotWaitForButtonPressAfterDisplayingText], a + ld a, [wHiddenObjectFunctionArgument] + call PrintPredefTextID + ret + +LinkCableHelp:: + text_asm + call SaveScreenTilesToBuffer1 + ld hl, LinkCableHelpText1 + call PrintText + xor a + ld [wMenuItemOffset], a ; not used + ld [wCurrentMenuItem], a + ld [wLastMenuItem], a + ld a, A_BUTTON | B_BUTTON + ld [wMenuWatchedKeys], a + ld a, 3 + ld [wMaxMenuItem], a + ld a, 2 + ld [wTopMenuItemY], a + ld a, 1 + ld [wTopMenuItemX], a +.linkHelpLoop + ld hl, wd730 + set 6, [hl] + hlcoord 0, 0 + lb bc, 8, 13 + call TextBoxBorder + hlcoord 2, 2 + ld de, HowToLinkText + call PlaceString + ld hl, LinkCableHelpText2 + call PrintText + call HandleMenuInput + bit 1, a ; pressed b + jr nz, .exit + ld a, [wCurrentMenuItem] + cp 3 ; pressed a on "STOP READING" + jr z, .exit + ld hl, wd730 + res 6, [hl] + ld hl, LinkCableInfoTexts + add a + ld d, 0 + ld e, a + add hl, de + ld a, [hli] + ld h, [hl] + ld l, a + call PrintText + jp .linkHelpLoop +.exit + ld hl, wd730 + res 6, [hl] + call LoadScreenTilesFromBuffer1 + jp TextScriptEnd + +LinkCableHelpText1: + text_far _LinkCableHelpText1 + text_end + +LinkCableHelpText2: + text_far _LinkCableHelpText2 + text_end + +HowToLinkText: + db "HOW TO LINK" + next "COLOSSEUM" + next "TRADE CENTER" + next "STOP READING@" + +LinkCableInfoTexts: + dw LinkCableInfoText1 + dw LinkCableInfoText2 + dw LinkCableInfoText3 + +LinkCableInfoText1: + text_far _LinkCableInfoText1 + text_end + +LinkCableInfoText2: + text_far _LinkCableInfoText2 + text_end + +LinkCableInfoText3: + text_far _LinkCableInfoText3 + text_end + +ViridianSchoolBlackboard:: + text_asm + call SaveScreenTilesToBuffer1 + ld hl, ViridianSchoolBlackboardText1 + call PrintText + xor a + ld [wMenuItemOffset], a + ld [wCurrentMenuItem], a + ld [wLastMenuItem], a + ld a, D_LEFT | D_RIGHT | A_BUTTON | B_BUTTON + ld [wMenuWatchedKeys], a + ld a, 2 + ld [wMaxMenuItem], a + ld a, 2 + ld [wTopMenuItemY], a + ld a, 1 + ld [wTopMenuItemX], a +.blackboardLoop + ld hl, wd730 + set 6, [hl] + hlcoord 0, 0 + lb bc, 6, 10 + call TextBoxBorder + hlcoord 1, 2 + ld de, StatusAilmentText1 + call PlaceString + hlcoord 6, 2 + ld de, StatusAilmentText2 + call PlaceString + ld hl, ViridianSchoolBlackboardText2 + call PrintText + call HandleMenuInput ; pressing up and down is handled in here + bit 1, a ; pressed b + jr nz, .exitBlackboard + bit 4, a ; pressed right + jr z, .didNotPressRight + ; move cursor to right column + ld a, 2 + ld [wMaxMenuItem], a + ld a, 2 + ld [wTopMenuItemY], a + ld a, 6 + ld [wTopMenuItemX], a + ld a, 3 ; in the the right column, use an offset to prevent overlap + ld [wMenuItemOffset], a + jr .blackboardLoop +.didNotPressRight + bit 5, a ; pressed left + jr z, .didNotPressLeftOrRight + ; move cursor to left column + ld a, 2 + ld [wMaxMenuItem], a + ld a, 2 + ld [wTopMenuItemY], a + ld a, 1 + ld [wTopMenuItemX], a + xor a + ld [wMenuItemOffset], a + jr .blackboardLoop +.didNotPressLeftOrRight + ld a, [wCurrentMenuItem] + ld b, a + ld a, [wMenuItemOffset] + add b + cp 5 ; cursor is pointing to "QUIT" + jr z, .exitBlackboard + ; we must have pressed a on a status condition + ; so print the text + ld hl, wd730 + res 6, [hl] + ld hl, ViridianBlackboardStatusPointers + add a + ld d, 0 + ld e, a + add hl, de + ld a, [hli] + ld h, [hl] + ld l, a + call PrintText + jp .blackboardLoop +.exitBlackboard + ld hl, wd730 + res 6, [hl] + call LoadScreenTilesFromBuffer1 + jp TextScriptEnd + +ViridianSchoolBlackboardText1: + text_far _ViridianSchoolBlackboardText1 + text_end + +ViridianSchoolBlackboardText2: + text_far _ViridianSchoolBlackboardText2 + text_end + +StatusAilmentText1: + db " SLP" + next " PSN" + next " PAR@" + +StatusAilmentText2: + db " BRN" + next " FRZ" + next " QUIT@" + + db "@" ; unused + +ViridianBlackboardStatusPointers: + dw ViridianBlackboardSleepText + dw ViridianBlackboardPoisonText + dw ViridianBlackboardPrlzText + dw ViridianBlackboardBurnText + dw ViridianBlackboardFrozenText + +ViridianBlackboardSleepText: + text_far _ViridianBlackboardSleepText + text_end + +ViridianBlackboardPoisonText: + text_far _ViridianBlackboardPoisonText + text_end + +ViridianBlackboardPrlzText: + text_far _ViridianBlackboardPrlzText + text_end + +ViridianBlackboardBurnText: + text_far _ViridianBlackboardBurnText + text_end + +ViridianBlackboardFrozenText: + text_far _ViridianBlackboardFrozenText + text_end diff --git a/engine/events/hidden_objects/school_notebooks.asm b/engine/events/hidden_objects/school_notebooks.asm new file mode 100644 index 00000000..96a44ab5 --- /dev/null +++ b/engine/events/hidden_objects/school_notebooks.asm @@ -0,0 +1,65 @@ +PrintNotebookText: + call EnableAutoTextBoxDrawing + ld a, $1 + ld [wDoNotWaitForButtonPressAfterDisplayingText], a + ld a, [wHiddenObjectFunctionArgument] + jp PrintPredefTextID + +TMNotebook:: + text_far TMNotebookText + text_waitbutton + text_end + +ViridianSchoolNotebook:: + text_asm + ld hl, ViridianSchoolNotebookText1 + call PrintText + call TurnPageSchoolNotebook + jr nz, .doneReading + ld hl, ViridianSchoolNotebookText2 + call PrintText + call TurnPageSchoolNotebook + jr nz, .doneReading + ld hl, ViridianSchoolNotebookText3 + call PrintText + call TurnPageSchoolNotebook + jr nz, .doneReading + ld hl, ViridianSchoolNotebookText4 + call PrintText + ld hl, ViridianSchoolNotebookText5 + call PrintText +.doneReading + jp TextScriptEnd + +TurnPageSchoolNotebook: + ld hl, TurnPageText + call PrintText + call YesNoChoice + ld a, [wCurrentMenuItem] + and a + ret + +TurnPageText: + text_far _TurnPageText + text_end + +ViridianSchoolNotebookText5: + text_far _ViridianSchoolNotebookText5 + text_waitbutton + text_end + +ViridianSchoolNotebookText1: + text_far _ViridianSchoolNotebookText1 + text_end + +ViridianSchoolNotebookText2: + text_far _ViridianSchoolNotebookText2 + text_end + +ViridianSchoolNotebookText3: + text_far _ViridianSchoolNotebookText3 + text_end + +ViridianSchoolNotebookText4: + text_far _ViridianSchoolNotebookText4 + text_end diff --git a/engine/events/hidden_objects/town_map.asm b/engine/events/hidden_objects/town_map.asm new file mode 100644 index 00000000..4284214f --- /dev/null +++ b/engine/events/hidden_objects/town_map.asm @@ -0,0 +1,22 @@ +TownMapText:: + text_far _TownMapText + text_promptbutton + text_asm + ld a, $1 + ld [wDoNotWaitForButtonPressAfterDisplayingText], a + ld hl, wd730 + set 6, [hl] + call GBPalWhiteOutWithDelay3 + xor a + ldh [hWY], a + inc a + ldh [hAutoBGTransferEnabled], a + call LoadFontTilePatterns + farcall DisplayTownMap + ld hl, wd730 + res 6, [hl] + ld de, TextScriptEnd + push de + ldh a, [hLoadedROMBank] + push af + jp CloseTextDisplay diff --git a/engine/events/hidden_objects/vermilion_gym_trash.asm b/engine/events/hidden_objects/vermilion_gym_trash.asm new file mode 100644 index 00000000..21dd3ee0 --- /dev/null +++ b/engine/events/hidden_objects/vermilion_gym_trash.asm @@ -0,0 +1,134 @@ +PrintTrashText: + call EnableAutoTextBoxDrawing + tx_pre_jump VermilionGymTrashText + +VermilionGymTrashText:: + text_far _VermilionGymTrashText + text_end + +GymTrashScript: + call EnableAutoTextBoxDrawing + ld a, [wHiddenObjectFunctionArgument] + ld [wGymTrashCanIndex], a + +; Don't do the trash can puzzle if it's already been done. + CheckEvent EVENT_2ND_LOCK_OPENED + jr z, .ok + + tx_pre_jump VermilionGymTrashText + +.ok + CheckEventReuseA EVENT_1ST_LOCK_OPENED + jr nz, .trySecondLock + + ld a, [wFirstLockTrashCanIndex] + ld b, a + ld a, [wGymTrashCanIndex] + cp b + jr z, .openFirstLock + + tx_pre_id VermilionGymTrashText + jr .done + +.openFirstLock +; Next can is trying for the second switch. + SetEvent EVENT_1ST_LOCK_OPENED + callfar Yellow_SampleSecondTrashCan + tx_pre_id VermilionGymTrashSuccessText1 + jr .done + +.trySecondLock + ld a, [wGymTrashCanIndex] + ld b, a + ld a, [wSecondLockTrashCanIndex] + cp b + jr z, .openSecondLock + ld a, [wSecondLockTrashCanIndex + 1] + cp b + jr z, .openSecondLock + +; Reset the cans. + ResetEvent EVENT_1ST_LOCK_OPENED + call Random + + and $e + ld [wFirstLockTrashCanIndex], a + + tx_pre_id VermilionGymTrashFailText + jr .done + +.openSecondLock +; Completed the trash can puzzle. + SetEvent EVENT_2ND_LOCK_OPENED + ld hl, wCurrentMapScriptFlags + set 6, [hl] + + tx_pre_id VermilionGymTrashSuccessText3 + +.done + jp PrintPredefTextID + +GymTrashCans: +; byte 0: mask for random number +; bytes 1-4: indices of the trash cans that can have the second lock +; Note that the mask is simply the number of valid trash can indices that +; follow. The remaining bytes are filled with -1 to pad the length of each entry +; to 5 bytes. +; This is functionally replaced with GymTrashCans3a but was never removed from source. + + db 2, 1, 3, -1, -1 ; 0 + db 3, 0, 2, 4, -1 ; 1 + db 2, 1, 5, -1, -1 ; 2 + db 3, 0, 4, 6, -1 ; 3 + db 4, 1, 3, 5, 7 ; 4 + db 3, 2, 4, 8, -1 ; 5 + db 3, 3, 7, 9, -1 ; 6 + db 4, 4, 6, 8, 10 ; 7 + db 3, 5, 7, 11, -1 ; 8 + db 3, 6, 10, 12, -1 ; 9 + db 4, 7, 9, 11, 13 ; 10 + db 3, 8, 10, 14, -1 ; 11 + db 2, 9, 13, -1, -1 ; 12 + db 3, 10, 12, 14, -1 ; 13 + db 2, 11, 13, -1, -1 ; 14 + +VermilionGymTrashSuccessText1:: + text_far _VermilionGymTrashSuccessText1 + text_asm + call WaitForSoundToFinish + ld a, SFX_SWITCH + call PlaySound + call WaitForSoundToFinish + jp TextScriptEnd + +; unused +VermilionGymTrashSuccessText2:: + text_far _VermilionGymTrashSuccessText2 + text_end + +; unused +VermilionGymTrashSuccesPlaySfx: + text_asm + call WaitForSoundToFinish + ld a, SFX_SWITCH + call PlaySound + call WaitForSoundToFinish + jp TextScriptEnd + +VermilionGymTrashSuccessText3:: + text_far _VermilionGymTrashSuccessText3 + text_asm + call WaitForSoundToFinish + ld a, SFX_GO_INSIDE + call PlaySound + call WaitForSoundToFinish + jp TextScriptEnd + +VermilionGymTrashFailText:: + text_far _VermilionGymTrashFailText + text_asm + call WaitForSoundToFinish + ld a, SFX_DENIED + call PlaySound + call WaitForSoundToFinish + jp TextScriptEnd diff --git a/engine/events/in_game_trades.asm b/engine/events/in_game_trades.asm new file mode 100755 index 00000000..a0a23dfa --- /dev/null +++ b/engine/events/in_game_trades.asm @@ -0,0 +1,350 @@ +DoInGameTradeDialogue: +; trigger the trade offer/action specified by wWhichTrade + call SaveScreenTilesToBuffer2 + ld hl, TradeMons + ld a, [wWhichTrade] + ld bc, $e + call AddNTimes + ld a, [hli] + ld [wInGameTradeGiveMonSpecies], a + ld a, [hli] + ld [wInGameTradeReceiveMonSpecies], a + ld a, [hli] + push af + ld de, wInGameTradeMonNick + ld bc, NAME_LENGTH + call CopyData + pop af + ld l, a + ld h, 0 + ld de, InGameTradeTextPointers + add hl, hl + add hl, de + ld a, [hli] + ld [wInGameTradeTextPointerTablePointer], a + ld a, [hl] + ld [wInGameTradeTextPointerTablePointer + 1], a + ld a, [wInGameTradeGiveMonSpecies] + ld de, wInGameTradeGiveMonName + call InGameTrade_GetMonName + ld a, [wInGameTradeReceiveMonSpecies] + ld de, wInGameTradeReceiveMonName + call InGameTrade_GetMonName + ld a, $4 + ld [wInGameTradeTextPointerTableIndex], a + ld b, FLAG_TEST + call InGameTrade_FlagActionPredef + ld a, c + and a + jr nz, .printText +; if the trade hasn't been done yet + ld a, $0 + ld [wInGameTradeTextPointerTableIndex], a + call .printText + ld a, $1 + ld [wInGameTradeTextPointerTableIndex], a + call YesNoChoice + ld a, [wCurrentMenuItem] + and a + jr nz, .printText + call InGameTrade_DoTrade + jr c, .printText + ld hl, TradedForText + call PrintText +.printText + ld hl, wInGameTradeTextPointerTableIndex + ld a, [hld] ; wInGameTradeTextPointerTableIndex + ld e, a + ld d, 0 + ld a, [hld] ; wInGameTradeTextPointerTablePointer + 1 + ld l, [hl] ; wInGameTradeTextPointerTablePointer + ld h, a + add hl, de + add hl, de + ld a, [hli] + ld h, [hl] + ld l, a + jp PrintText + +; copies name of species a to hl +InGameTrade_GetMonName: + push de + ld [wd11e], a + call GetMonName + ld hl, wcd6d + pop de + ld bc, NAME_LENGTH + jp CopyData + +INCLUDE "data/events/trades.asm" + +InGameTrade_DoTrade: + xor a ; NORMAL_PARTY_MENU + ld [wPartyMenuTypeOrMessageID], a + dec a + ld [wUpdateSpritesEnabled], a + call DisplayPartyMenu + push af + call InGameTrade_RestoreScreen + pop af + ld a, $1 + jp c, .tradeFailed ; jump if the player didn't select a pokemon + ld a, [wInGameTradeGiveMonSpecies] + ld b, a + ld a, [wcf91] + cp b + ld a, $2 + jr nz, .tradeFailed ; jump if the selected mon's species is not the required one + ld a, [wWhichPokemon] + ld hl, wPartyMon1Level + ld bc, wPartyMon2 - wPartyMon1 + call AddNTimes + ld a, [hl] + ld [wCurEnemyLVL], a + ld b, FLAG_SET + call InGameTrade_FlagActionPredef + ld hl, ConnectCableText + call PrintText + ld a, [wWhichPokemon] + push af + ld a, [wCurEnemyLVL] + push af + call LoadHpBarAndStatusTilePatterns + call InGameTrade_PrepareTradeData + predef InternalClockTradeAnim + pop af + ld [wCurEnemyLVL], a + pop af + ld [wWhichPokemon], a + ld a, [wInGameTradeReceiveMonSpecies] + ld [wcf91], a + xor a + ld [wMonDataLocation], a ; not used + ld [wRemoveMonFromBox], a + call RemovePokemon + ld a, $80 ; prevent the player from naming the mon + ld [wMonDataLocation], a + call AddPartyMon + call InGameTrade_CopyDataToReceivedMon + call InGameTrade_CheckForTradeEvo + call ClearScreen + call InGameTrade_RestoreScreen + farcall RedrawMapView + and a + ld a, $3 + jr .tradeSucceeded +.tradeFailed + scf +.tradeSucceeded + ld [wInGameTradeTextPointerTableIndex], a + ret + +InGameTrade_RestoreScreen: + call GBPalWhiteOutWithDelay3 + call RestoreScreenTilesAndReloadTilePatterns + call ReloadTilesetTilePatterns + call LoadScreenTilesFromBuffer2 + call Delay3 + call LoadGBPal + ld c, 10 + call DelayFrames + farjp LoadWildData + +InGameTrade_PrepareTradeData: + ld hl, wTradedPlayerMonSpecies + ld a, [wInGameTradeGiveMonSpecies] + ld [hli], a ; wTradedPlayerMonSpecies + ld a, [wInGameTradeReceiveMonSpecies] + ld [hl], a ; wTradedEnemyMonSpecies + ld hl, wPartyMonOT + ld bc, NAME_LENGTH + ld a, [wWhichPokemon] + call AddNTimes + ld de, wTradedPlayerMonOT + ld bc, NAME_LENGTH + call InGameTrade_CopyData + ld hl, InGameTrade_TrainerString + ld de, wTradedEnemyMonOT + call InGameTrade_CopyData + ld de, wLinkEnemyTrainerName + call InGameTrade_CopyData + ld hl, wPartyMon1OTID + ld bc, wPartyMon2 - wPartyMon1 + ld a, [wWhichPokemon] + call AddNTimes + ld de, wTradedPlayerMonOTID + ld bc, $2 + call InGameTrade_CopyData + call Random + ld hl, hRandomAdd + ld de, wTradedEnemyMonOTID + jp CopyData + +InGameTrade_CopyData: + push hl + push bc + call CopyData + pop bc + pop hl + ret + +InGameTrade_CopyDataToReceivedMon: + ld hl, wPartyMonNicks + ld bc, NAME_LENGTH + call InGameTrade_GetReceivedMonPointer + ld hl, wInGameTradeMonNick + ld bc, NAME_LENGTH + call CopyData + ld hl, wPartyMonOT + ld bc, NAME_LENGTH + call InGameTrade_GetReceivedMonPointer + ld hl, InGameTrade_TrainerString + ld bc, NAME_LENGTH + call CopyData + ld hl, wPartyMon1OTID + ld bc, wPartyMon2 - wPartyMon1 + call InGameTrade_GetReceivedMonPointer + ld hl, wTradedEnemyMonOTID + ld bc, $2 + jp CopyData + +; the received mon's index is (partyCount - 1), +; so this adds bc to hl (partyCount - 1) times and moves the result to de +InGameTrade_GetReceivedMonPointer: + ld a, [wPartyCount] + dec a + call AddNTimes + ld e, l + ld d, h + ret + +InGameTrade_FlagActionPredef: + ld hl, wCompletedInGameTradeFlags + ld a, [wWhichTrade] + ld c, a + predef_jump FlagActionPredef + +InGameTrade_CheckForTradeEvo: + ld a, [wInGameTradeReceiveMonSpecies] + cp KADABRA + jr z, .tradeEvo + cp GRAVELER + jr z, .tradeEvo + cp MACHOKE + jr z, .tradeEvo + cp HAUNTER + jr z, .tradeEvo + ret + +.tradeEvo + ld a, [wPartyCount] + dec a + ld [wWhichPokemon], a + ld a, $1 + ld [wForceEvolution], a + ld a, LINK_STATE_TRADING + ld [wLinkState], a + callfar EvolveTradeMon + xor a ; LINK_STATE_NONE + ld [wLinkState], a + jp PlayDefaultMusic + +InGameTrade_TrainerString: + db "@@@@@@@@@@" + +InGameTradeTextPointers: +; entries correspond to TRADE_DIALOGSET_* constants + dw TradeTextPointers1 + dw TradeTextPointers2 + dw TradeTextPointers3 + +TradeTextPointers1: + dw WannaTrade1Text + dw NoTrade1Text + dw WrongMon1Text + dw Thanks1Text + dw AfterTrade1Text + +TradeTextPointers2: + dw WannaTrade2Text + dw NoTrade2Text + dw WrongMon2Text + dw Thanks2Text + dw AfterTrade2Text + +TradeTextPointers3: + dw WannaTrade3Text + dw NoTrade3Text + dw WrongMon3Text + dw Thanks3Text + dw AfterTrade3Text + +ConnectCableText: + text_far _ConnectCableText + text_end + +TradedForText: + text_far _TradedForText + sound_get_key_item + text_pause + text_end + +WannaTrade1Text: + text_far _WannaTrade1Text + text_end + +NoTrade1Text: + text_far _NoTrade1Text + text_end + +WrongMon1Text: + text_far _WrongMon1Text + text_end + +Thanks1Text: + text_far _Thanks1Text + text_end + +AfterTrade1Text: + text_far _AfterTrade1Text + text_end + +WannaTrade2Text: + text_far _WannaTrade2Text + text_end + +NoTrade2Text: + text_far _NoTrade2Text + text_end + +WrongMon2Text: + text_far _WrongMon2Text + text_end + +Thanks2Text: + text_far _Thanks2Text + text_end + +AfterTrade2Text: + text_far _AfterTrade2Text + text_end + +WannaTrade3Text: + text_far _WannaTrade3Text + text_end + +NoTrade3Text: + text_far _NoTrade3Text + text_end + +WrongMon3Text: + text_far _WrongMon3Text + text_end + +Thanks3Text: + text_far _Thanks3Text + text_end + +AfterTrade3Text: + text_far _AfterTrade3Text + text_end diff --git a/engine/events/oaks_aide.asm b/engine/events/oaks_aide.asm new file mode 100755 index 00000000..f1801f5c --- /dev/null +++ b/engine/events/oaks_aide.asm @@ -0,0 +1,71 @@ +OaksAideScript: + ld hl, OaksAideHiText + call PrintText + call YesNoChoice + ld a, [wCurrentMenuItem] + and a + jr nz, .choseNo + ld hl, wPokedexOwned + ld b, wPokedexOwnedEnd - wPokedexOwned + call CountSetBits + ld a, [wNumSetBits] + ldh [hOaksAideNumMonsOwned], a + ld b, a + ldh a, [hOaksAideRequirement] + cp b + jr z, .giveItem + jr nc, .notEnoughOwnedMons +.giveItem + ld hl, OaksAideHereYouGoText + call PrintText + ldh a, [hOaksAideRewardItem] + ld b, a + ld c, 1 + call GiveItem + jr nc, .bagFull + ld hl, OaksAideGotItemText + call PrintText + ld a, OAKS_AIDE_GOT_ITEM + jr .done +.bagFull + ld hl, OaksAideNoRoomText + call PrintText + xor a ; OAKS_AIDE_BAG_FULL + jr .done +.notEnoughOwnedMons + ld hl, OaksAideUhOhText + call PrintText + ld a, OAKS_AIDE_NOT_ENOUGH_MONS + jr .done +.choseNo + ld hl, OaksAideComeBackText + call PrintText + ld a, OAKS_AIDE_REFUSED +.done + ldh [hOaksAideResult], a + ret + +OaksAideHiText: + text_far _OaksAideHiText + text_end + +OaksAideUhOhText: + text_far _OaksAideUhOhText + text_end + +OaksAideComeBackText: + text_far _OaksAideComeBackText + text_end + +OaksAideHereYouGoText: + text_far _OaksAideHereYouGoText + text_end + +OaksAideGotItemText: + text_far _OaksAideGotItemText + sound_get_item_1 + text_end + +OaksAideNoRoomText: + text_far _OaksAideNoRoomText + text_end diff --git a/engine/events/pewter_guys.asm b/engine/events/pewter_guys.asm new file mode 100755 index 00000000..532fa4bf --- /dev/null +++ b/engine/events/pewter_guys.asm @@ -0,0 +1,102 @@ +PewterGuys: + ld hl, wSimulatedJoypadStatesEnd + ld a, [wSimulatedJoypadStatesIndex] + dec a ; this decrement causes it to overwrite the last byte before $FF in the list + ld [wSimulatedJoypadStatesIndex], a + ld d, 0 + ld e, a + add hl, de + ld d, h + ld e, l + ld hl, PointerTable_37ce6 + ld a, [wWhichPewterGuy] + add a + ld b, 0 + ld c, a + add hl, bc + ld a, [hli] + ld h, [hl] + ld l, a + ld a, [wYCoord] + ld b, a + ld a, [wXCoord] + ld c, a +.findMatchingCoordsLoop + ld a, [hli] + cp b + jr nz, .nextEntry1 + ld a, [hli] + cp c + jr nz, .nextEntry2 + ld a, [hli] + ld h, [hl] + ld l, a +.copyMovementDataLoop + ld a, [hli] + cp $ff + ret z + ld [de], a + inc de + ld a, [wSimulatedJoypadStatesIndex] + inc a + ld [wSimulatedJoypadStatesIndex], a + jr .copyMovementDataLoop +.nextEntry1 + inc hl +.nextEntry2 + inc hl + inc hl + jr .findMatchingCoordsLoop + +PointerTable_37ce6: + dw PewterMuseumGuyCoords + dw PewterGymGuyCoords + +; these are the four coordinates of the spaces below, above, to the left and +; to the right of the museum guy, and pointers to different movements for +; the player to make to get positioned before the main movement. +PewterMuseumGuyCoords: + db 18, 27 + dw .down + db 16, 27 + dw .up + db 17, 26 + dw .left + db 17, 28 + dw .right + +.down + db D_UP, D_UP, $ff +.up + db D_RIGHT, D_LEFT, $ff +.left + db D_UP, D_RIGHT, $ff +.right + db D_UP, D_LEFT, $ff + +; these are the five coordinates which trigger the gym guy and pointers to +; different movements for the player to make to get positioned before the +; main movement +; $00 is a pause +PewterGymGuyCoords: + db 16, 34 + dw .one + db 17, 35 + dw .two + db 18, 37 + dw .three + db 19, 37 + dw .four + db 17, 36 + dw .five + +.one + db D_LEFT, D_DOWN, D_DOWN, D_RIGHT, $ff +.two + db D_LEFT, D_DOWN, D_RIGHT, D_LEFT, $ff +.three + db D_LEFT, D_LEFT, D_LEFT, $00, $00, $00, $00, $00, $00, $00, $00, $ff +.four + db D_LEFT, D_LEFT, D_UP, D_LEFT, $ff +.five + db D_LEFT, D_DOWN, D_LEFT, $00, $00, $00, $00, $00, $00, $00, $00, $ff diff --git a/engine/events/pick_up_item.asm b/engine/events/pick_up_item.asm new file mode 100644 index 00000000..548db5be --- /dev/null +++ b/engine/events/pick_up_item.asm @@ -0,0 +1,54 @@ +PickUpItem: + call EnableAutoTextBoxDrawing + + ldh a, [hSpriteIndexOrTextID] + ld b, a + ld hl, wMissableObjectList +.missableObjectsListLoop + ld a, [hli] + cp $ff + ret z + cp b + jr z, .isMissable + inc hl + jr .missableObjectsListLoop + +.isMissable + ld a, [hl] + ldh [hMissableObjectIndex], a + + ld hl, wMapSpriteExtraData + ldh a, [hSpriteIndexOrTextID] + dec a + add a + ld d, 0 + ld e, a + add hl, de + ld a, [hl] + ld b, a ; item + ld c, 1 ; quantity + call GiveItem + jr nc, .BagFull + + ldh a, [hMissableObjectIndex] + ld [wMissableObjectIndex], a + predef HideObject + ld a, 1 + ld [wDoNotWaitForButtonPressAfterDisplayingText], a + ld hl, FoundItemText + jr .print + +.BagFull + ld hl, NoMoreRoomForItemText +.print + call PrintText + ret + +FoundItemText: + text_far _FoundItemText + sound_get_item_1 + text_end + +NoMoreRoomForItemText: + text_far _NoMoreRoomForItemText + text_end diff --git a/engine/events/poison.asm b/engine/events/poison.asm new file mode 100644 index 00000000..9f3ad391 --- /dev/null +++ b/engine/events/poison.asm @@ -0,0 +1,151 @@ +ApplyOutOfBattlePoisonDamage: + ld a, [wd730] + add a + jp c, .noBlackOut ; no black out if joypad states are being simulated + ld a, [wd492] + bit 7, a + jp nz, .noBlackOut + ld a, [wd72e] + bit 6, a + jp nz, .noBlackOut + ld a, [wPartyCount] + and a + jp z, .noBlackOut + call IncrementDayCareMonExp + call Func_c4c7 + ld a, [wStepCounter] + and $3 ; is the counter a multiple of 4? + jp nz, .skipPoisonEffectAndSound ; only apply poison damage every fourth step + ld [wWhichPokemon], a + ld hl, wPartyMon1Status + ld de, wPartySpecies +.applyDamageLoop + ld a, [hl] + and (1 << PSN) + jr z, .nextMon2 ; not poisoned + dec hl + dec hl + ld a, [hld] + ld b, a + ld a, [hli] + or b + jr z, .nextMon ; already fainted +; subtract 1 from HP + ld a, [hl] + dec a + ld [hld], a + inc a + jr nz, .noBorrow +; borrow 1 from upper byte of HP + dec [hl] + inc hl + jr .nextMon +.noBorrow + ld a, [hli] + or [hl] + jr nz, .nextMon ; didn't faint from damage +; the mon fainted from the damage + push hl + inc hl + inc hl + ld [hl], a + ld a, [de] + ld [wd11e], a + push de + ld a, [wWhichPokemon] + ld hl, wPartyMonNicks + call GetPartyMonName + xor a + ld [wJoyIgnore], a + call EnableAutoTextBoxDrawing + ld a, TEXT_MON_FAINTED + ldh [hSpriteIndexOrTextID], a + call DisplayTextID + callfar IsThisPartymonStarterPikachu_Party + jr nc, .curMonNotPlayerPikachu + ld e, $3 + callfar PlayPikachuSoundClip + calladb_ModifyPikachuHappiness PIKAHAPPY_PSNFNT +.curMonNotPlayerPikachu + pop de + pop hl +.nextMon + inc hl + inc hl +.nextMon2 + inc de + ld a, [de] + inc a + jr z, .applyDamageLoopDone + ld bc, wPartyMon2 - wPartyMon1 + add hl, bc + push hl + ld hl, wWhichPokemon + inc [hl] + pop hl + jr .applyDamageLoop +.applyDamageLoopDone + ld hl, wPartyMon1Status + ld a, [wPartyCount] + ld d, a + ld e, 0 +.countPoisonedLoop + ld a, [hl] + and (1 << PSN) + or e + ld e, a + ld bc, wPartyMon2 - wPartyMon1 + add hl, bc + dec d + jr nz, .countPoisonedLoop + ld a, e + and a ; are any party members poisoned? + jr z, .skipPoisonEffectAndSound + ld b, $2 + predef ChangeBGPalColor0_4Frames ; change BG white to dark grey for 4 frames + ld a, SFX_POISONED + call PlaySound +.skipPoisonEffectAndSound + predef AnyPartyAlive + ld a, d + and a + jr nz, .noBlackOut + call EnableAutoTextBoxDrawing + ld a, TEXT_BLACKED_OUT + ldh [hSpriteIndexOrTextID], a + call DisplayTextID + ld hl, wd72e + set 5, [hl] + ld a, $ff + jr .done +.noBlackOut + xor a +.done + ld [wOutOfBattleBlackout], a + ret + +Func_c4c7: + ld a, [wStepCounter] + and a + jr nz, .asm_c4de + call Random + and $1 + jr z, .asm_c4de + calladb_ModifyPikachuHappiness $6 +.asm_c4de + ld hl, wPikachuMood + ld a, [hl] + cp $80 + jr z, .asm_c4ef + jr c, .asm_c4ea + dec a + dec a +.asm_c4ea + inc a + ld [hl], a + cp $80 + ret nz +.asm_c4ef + xor a + ld [wd49c], a + ret diff --git a/engine/events/pokecenter.asm b/engine/events/pokecenter.asm new file mode 100755 index 00000000..e007030a --- /dev/null +++ b/engine/events/pokecenter.asm @@ -0,0 +1,149 @@ +DisplayPokemonCenterDialogue_:: + ld a, [wCurMap] + cp PEWTER_POKECENTER + jr nz, .regularCenter + call CheckPikachuFollowingPlayer + jr z, .regularCenter + ld hl, LooksContentText ; if pikachu is sleeping, don't heal + call PrintText + ret +.regularCenter + call SaveScreenTilesToBuffer1 ; save screen + ld hl, PokemonCenterWelcomeText + call PrintText + ld hl, wd72e + bit 2, [hl] + set 1, [hl] + set 2, [hl] + jr nz, .skipShallWeHealYourPokemon + ld hl, ShallWeHealYourPokemonText + call PrintText +.skipShallWeHealYourPokemon + call YesNoChoicePokeCenter ; yes/no menu + call UpdateSprites + ld a, [wCurrentMenuItem] + and a + jp nz, .declinedHealing ; if the player chose No + call SetLastBlackoutMap + callfar IsStarterPikachuInOurParty + jr nc, .notHealingPlayerPikachu + call CheckPikachuFollowingPlayer + jr nz, .notHealingPlayerPikachu + call LoadCurrentMapView + call Delay3 + call UpdateSprites + callfar PikachuWalksToNurseJoy ; todo +.notHealingPlayerPikachu + ld hl, NeedYourPokemonText + call PrintText + ld c, 64 + call DelayFrames + call CheckPikachuFollowingPlayer + jr nz, .playerPikachuNotOnScreen + call DisablePikachuOverworldSpriteDrawing + callfar IsStarterPikachuInOurParty + call c, Func_6eaa +.playerPikachuNotOnScreen + lb bc, 1, 8 + call Func_6ebb + ld c, 30 + call DelayFrames + farcall AnimateHealingMachine ; do the healing machine animation + predef HealParty + xor a + ld [wAudioFadeOutControl], a + ld a, [wAudioSavedROMBank] + ld [wAudioROMBank], a + ld a, [wMapMusicSoundID] + ld [wLastMusicSoundID], a + ld [wNewSoundID], a + call PlaySound + call CheckPikachuFollowingPlayer + jr nz, .doNotReturnPikachu + callfar IsStarterPikachuInOurParty + call c, Func_6eaa + ld a, $5 + ld [wPikachuSpawnState], a + call EnablePikachuOverworldSpriteDrawing +.doNotReturnPikachu + lb bc, 1, 0 + call Func_6ebb + ld hl, PokemonFightingFitText + call PrintText + callfar IsStarterPikachuInOurParty + jr nc, .notInParty + lb bc, 15, 0 + call Func_6ebb +.notInParty + call LoadCurrentMapView + call Delay3 + call UpdateSprites + callfar ReloadWalkingTilePatterns + ld a, $1 + ldh [hSpriteIndex], a + ld a, $1 + ldh [hSpriteImageIndex], a + call SpriteFunc_34a1 + ld c, 40 + call DelayFrames + call UpdateSprites + call LoadFontTilePatterns + jr .done +.declinedHealing + call LoadScreenTilesFromBuffer1 ; restore screen +.done + ld hl, PokemonCenterFarewellText + call PrintText + call UpdateSprites + ret + +Func_6eaa: + ld a, $1 + ldh [hSpriteIndex], a + ld a, $4 + ldh [hSpriteImageIndex], a + call SpriteFunc_34a1 + ld c, 64 + call DelayFrames + ret + +Func_6ebb: + ld a, b + ldh [hSpriteIndex], a + ld a, c + ldh [hSpriteImageIndex], a + push bc + call SetSpriteFacingDirectionAndDelay + pop bc + ld a, b + ldh [hSpriteIndex], a + ld a, c + ldh [hSpriteImageIndex], a + call SpriteFunc_34a1 + ret + +PokemonCenterWelcomeText: + text_far _PokemonCenterWelcomeText + text_end + +ShallWeHealYourPokemonText: + text_pause + text_far _ShallWeHealYourPokemonText + text_end + +NeedYourPokemonText: + text_far _NeedYourPokemonText + text_end + +PokemonFightingFitText: + text_far _PokemonFightingFitText + text_end + +PokemonCenterFarewellText: + text_pause + text_far _PokemonCenterFarewellText + text_end + +LooksContentText: + text_far _LooksContentText + text_end diff --git a/engine/events/pokedex_rating.asm b/engine/events/pokedex_rating.asm new file mode 100755 index 00000000..1086257a --- /dev/null +++ b/engine/events/pokedex_rating.asm @@ -0,0 +1,138 @@ +DisplayDexRating: + ld hl, wPokedexSeen + ld b, wPokedexSeenEnd - wPokedexSeen + call CountSetBits + ld a, [wNumSetBits] + ldh [hDexRatingNumMonsSeen], a + ld hl, wPokedexOwned + ld b, wPokedexOwnedEnd - wPokedexOwned + call CountSetBits + ld a, [wNumSetBits] + ldh [hDexRatingNumMonsOwned], a + ld hl, DexRatingsTable +.findRating + ld a, [hli] + ld b, a + ldh a, [hDexRatingNumMonsOwned] + cp b + jr c, .foundRating + inc hl + inc hl + jr .findRating +.foundRating + ld a, [hli] + ld h, [hl] + ld l, a ; load text pointer into hl + CheckAndResetEventA EVENT_HALL_OF_FAME_DEX_RATING + jr nz, .hallOfFame + push hl + ld hl, DexCompletionText + call PrintText + pop hl + call PrintText + farcall PlayPokedexRatingSfx + jp WaitForTextScrollButtonPress +.hallOfFame + ld de, wDexRatingNumMonsSeen + ldh a, [hDexRatingNumMonsSeen] + ld [de], a + inc de + ldh a, [hDexRatingNumMonsOwned] + ld [de], a + inc de +.copyRatingTextLoop + ld a, [hli] + cp "@" + jr z, .doneCopying + ld [de], a + inc de + jr .copyRatingTextLoop +.doneCopying + ld [de], a + ret + +DexCompletionText: + text_far _DexCompletionText + text_end + +DexRatingsTable: + dbw 10, DexRatingText_Own0To9 + dbw 20, DexRatingText_Own10To19 + dbw 30, DexRatingText_Own20To29 + dbw 40, DexRatingText_Own30To39 + dbw 50, DexRatingText_Own40To49 + dbw 60, DexRatingText_Own50To59 + dbw 70, DexRatingText_Own60To69 + dbw 80, DexRatingText_Own70To79 + dbw 90, DexRatingText_Own80To89 + dbw 100, DexRatingText_Own90To99 + dbw 110, DexRatingText_Own100To109 + dbw 120, DexRatingText_Own110To119 + dbw 130, DexRatingText_Own120To129 + dbw 140, DexRatingText_Own130To139 + dbw 150, DexRatingText_Own140To149 + dbw NUM_POKEMON + 1, DexRatingText_Own150To151 + +DexRatingText_Own0To9: + text_far _DexRatingText_Own0To9 + text_end + +DexRatingText_Own10To19: + text_far _DexRatingText_Own10To19 + text_end + +DexRatingText_Own20To29: + text_far _DexRatingText_Own20To29 + text_end + +DexRatingText_Own30To39: + text_far _DexRatingText_Own30To39 + text_end + +DexRatingText_Own40To49: + text_far _DexRatingText_Own40To49 + text_end + +DexRatingText_Own50To59: + text_far _DexRatingText_Own50To59 + text_end + +DexRatingText_Own60To69: + text_far _DexRatingText_Own60To69 + text_end + +DexRatingText_Own70To79: + text_far _DexRatingText_Own70To79 + text_end + +DexRatingText_Own80To89: + text_far _DexRatingText_Own80To89 + text_end + +DexRatingText_Own90To99: + text_far _DexRatingText_Own90To99 + text_end + +DexRatingText_Own100To109: + text_far _DexRatingText_Own100To109 + text_end + +DexRatingText_Own110To119: + text_far _DexRatingText_Own110To119 + text_end + +DexRatingText_Own120To129: + text_far _DexRatingText_Own120To129 + text_end + +DexRatingText_Own130To139: + text_far _DexRatingText_Own130To139 + text_end + +DexRatingText_Own140To149: + text_far _DexRatingText_Own140To149 + text_end + +DexRatingText_Own150To151: + text_far _DexRatingText_Own150To151 + text_end diff --git a/engine/events/pokemart.asm b/engine/events/pokemart.asm new file mode 100755 index 00000000..c7cb8115 --- /dev/null +++ b/engine/events/pokemart.asm @@ -0,0 +1,272 @@ +DisplayPokemartDialogue_:: + ld a, [wListScrollOffset] + ld [wSavedListScrollOffset], a + call UpdateSprites + xor a + ld [wBoughtOrSoldItemInMart], a +.loop + xor a + ld [wListScrollOffset], a + ld [wCurrentMenuItem], a + ld [wPlayerMonNumber], a + inc a + ld [wPrintItemPrices], a + ld a, MONEY_BOX + ld [wTextBoxID], a + call DisplayTextBoxID + ld a, BUY_SELL_QUIT_MENU + ld [wTextBoxID], a + call DisplayTextBoxID + +; This code is useless. It copies the address of the pokemart's inventory to hl, +; but the address is never used. + ld hl, wItemListPointer + ld a, [hli] + ld l, [hl] + ld h, a + + ld a, [wMenuExitMethod] + cp CANCELLED_MENU + jp z, .done + ld a, [wChosenMenuItem] + and a ; buying? + jp z, .buyMenu + dec a ; selling? + jp z, .sellMenu + dec a ; quitting? + jp z, .done +.sellMenu + +; the same variables are set again below, so this code has no effect + xor a + ld [wPrintItemPrices], a + ld a, INIT_BAG_ITEM_LIST + ld [wInitListType], a + callfar InitList + + ld a, [wNumBagItems] + and a + jp z, .bagEmpty + ld hl, PokemonSellingGreetingText + call PrintText + call SaveScreenTilesToBuffer1 ; save screen +.sellMenuLoop + call LoadScreenTilesFromBuffer1 ; restore saved screen + ld a, MONEY_BOX + ld [wTextBoxID], a + call DisplayTextBoxID ; draw money text box + ld hl, wNumBagItems + ld a, l + ld [wListPointer], a + ld a, h + ld [wListPointer + 1], a + xor a + ld [wPrintItemPrices], a + ld [wCurrentMenuItem], a + ld a, ITEMLISTMENU + ld [wListMenuID], a + call DisplayListMenuID + jp c, .returnToMainPokemartMenu ; if the player closed the menu +.confirmItemSale ; if the player is trying to sell a specific item + call IsKeyItem + ld a, [wIsKeyItem] + and a + jr nz, .unsellableItem + ld a, [wcf91] + call IsItemHM + jr c, .unsellableItem + ld a, PRICEDITEMLISTMENU + ld [wListMenuID], a + ldh [hHalveItemPrices], a ; halve prices when selling + call DisplayChooseQuantityMenu + inc a + jr z, .sellMenuLoop ; if the player closed the choose quantity menu with the B button + ld hl, PokemartTellSellPriceText + lb bc, 14, 1 ; location that PrintText always prints to, this is useless + call PrintText + hlcoord 14, 7 + lb bc, 8, 15 + ld a, TWO_OPTION_MENU + ld [wTextBoxID], a + call DisplayTextBoxID ; yes/no menu + ld a, [wMenuExitMethod] + cp CHOSE_SECOND_ITEM + jr z, .sellMenuLoop ; if the player chose No or pressed the B button + +; The following code is supposed to check if the player chose No, but the above +; check already catches it. + ld a, [wChosenMenuItem] + dec a + jr z, .sellMenuLoop + +.sellItem + ld a, [wBoughtOrSoldItemInMart] + and a + jr nz, .skipSettingFlag1 + inc a + ld [wBoughtOrSoldItemInMart], a +.skipSettingFlag1 + call AddAmountSoldToMoney + ld hl, wNumBagItems + call RemoveItemFromInventory + jp .sellMenuLoop +.unsellableItem + ld hl, PokemartUnsellableItemText + call PrintText + jp .returnToMainPokemartMenu +.bagEmpty + ld hl, PokemartItemBagEmptyText + call PrintText + call SaveScreenTilesToBuffer1 + jp .returnToMainPokemartMenu +.buyMenu + +; the same variables are set again below, so this code has no effect + ld a, 1 + ld [wPrintItemPrices], a + ld a, INIT_OTHER_ITEM_LIST + ld [wInitListType], a + callfar InitList + + ld hl, PokemartBuyingGreetingText + call PrintText + call SaveScreenTilesToBuffer1 +.buyMenuLoop + call LoadScreenTilesFromBuffer1 + ld a, MONEY_BOX + ld [wTextBoxID], a + call DisplayTextBoxID + ld hl, wItemList + ld a, l + ld [wListPointer], a + ld a, h + ld [wListPointer + 1], a + xor a + ld [wCurrentMenuItem], a + inc a + ld [wPrintItemPrices], a + inc a ; a = 2 (PRICEDITEMLISTMENU) + ld [wListMenuID], a + call DisplayListMenuID + jr c, .returnToMainPokemartMenu ; if the player closed the menu + ld a, 99 + ld [wMaxItemQuantity], a + xor a + ldh [hHalveItemPrices], a ; don't halve item prices when buying + call DisplayChooseQuantityMenu + inc a + jr z, .buyMenuLoop ; if the player closed the choose quantity menu with the B button + ld a, [wcf91] ; item ID + ld [wd11e], a ; store item ID for GetItemName + call GetItemName + call CopyStringToCF4B ; copy name to wcf4b + ld hl, PokemartTellBuyPriceText + call PrintText + hlcoord 14, 7 + lb bc, 8, 15 + ld a, TWO_OPTION_MENU + ld [wTextBoxID], a + call DisplayTextBoxID ; yes/no menu + ld a, [wMenuExitMethod] + cp CHOSE_SECOND_ITEM + jp z, .buyMenuLoop ; if the player chose No or pressed the B button + +; The following code is supposed to check if the player chose No, but the above +; check already catches it. + ld a, [wChosenMenuItem] + dec a + jr z, .buyMenuLoop + +.buyItem + call .isThereEnoughMoney + jr c, .notEnoughMoney + ld hl, wNumBagItems + call AddItemToInventory + jr nc, .bagFull + call SubtractAmountPaidFromMoney + ld a, [wBoughtOrSoldItemInMart] + and a + jr nz, .skipSettingFlag2 + ld a, 1 + ld [wBoughtOrSoldItemInMart], a +.skipSettingFlag2 + ld a, SFX_PURCHASE + call PlaySoundWaitForCurrent + call WaitForSoundToFinish + ld hl, PokemartBoughtItemText + call PrintText + jp .buyMenuLoop +.returnToMainPokemartMenu + call LoadScreenTilesFromBuffer1 + ld a, MONEY_BOX + ld [wTextBoxID], a + call DisplayTextBoxID + ld hl, PokemartAnythingElseText + call PrintText + jp .loop +.isThereEnoughMoney + ld de, wPlayerMoney + ld hl, hMoney + ld c, 3 ; length of money in bytes + jp StringCmp +.notEnoughMoney + ld hl, PokemartNotEnoughMoneyText + call PrintText + jr .returnToMainPokemartMenu +.bagFull + ld hl, PokemartItemBagFullText + call PrintText + jr .returnToMainPokemartMenu +.done + ld hl, PokemartThankYouText + call PrintText + ld a, 1 + ld [wUpdateSpritesEnabled], a + call UpdateSprites + ld a, [wSavedListScrollOffset] + ld [wListScrollOffset], a + ret + +PokemartBuyingGreetingText: + text_far _PokemartBuyingGreetingText + text_end + +PokemartTellBuyPriceText: + text_far _PokemartTellBuyPriceText + text_end + +PokemartBoughtItemText: + text_far _PokemartBoughtItemText + text_end + +PokemartNotEnoughMoneyText: + text_far _PokemartNotEnoughMoneyText + text_end + +PokemartItemBagFullText: + text_far _PokemartItemBagFullText + text_end + +PokemonSellingGreetingText: + text_far _PokemonSellingGreetingText + text_end + +PokemartTellSellPriceText: + text_far _PokemartTellSellPriceText + text_end + +PokemartItemBagEmptyText: + text_far _PokemartItemBagEmptyText + text_end + +PokemartUnsellableItemText: + text_far _PokemartUnsellableItemText + text_end + +PokemartThankYouText: + text_far _PokemartThankYouText + text_end + +PokemartAnythingElseText: + text_far _PokemartAnythingElseText + text_end diff --git a/engine/events/prize_menu.asm b/engine/events/prize_menu.asm new file mode 100755 index 00000000..87244119 --- /dev/null +++ b/engine/events/prize_menu.asm @@ -0,0 +1,305 @@ +CeladonPrizeMenu:: + ld b, COIN_CASE + call IsItemInBag + jr nz, .havingCoinCase + ld hl, RequireCoinCaseTextPtr + jp PrintText +.havingCoinCase + ld hl, wd730 + set 6, [hl] ; disable letter-printing delay + ld hl, ExchangeCoinsForPrizesTextPtr + call PrintText +; the following are the menu settings + xor a + ld [wCurrentMenuItem], a + ld [wLastMenuItem], a + ld a, A_BUTTON | B_BUTTON + ld [wMenuWatchedKeys], a + ld a, $03 + ld [wMaxMenuItem], a + ld a, $04 + ld [wTopMenuItemY], a + ld a, $01 + ld [wTopMenuItemX], a + call PrintPrizePrice + hlcoord 0, 2 + lb bc, 8, 16 + call TextBoxBorder + call GetPrizeMenuId + call UpdateSprites + ld hl, WhichPrizeTextPtr + call PrintText + call HandleMenuInput ; menu choice handler + bit 1, a ; keypress = B (Cancel) + jr nz, .noChoice + ld a, [wCurrentMenuItem] + cp 3 ; "NO,THANKS" choice + jr z, .noChoice + call HandlePrizeChoice +.noChoice + ld hl, wd730 + res 6, [hl] + ret + +RequireCoinCaseTextPtr: + text_far _RequireCoinCaseText + text_waitbutton + text_end + +ExchangeCoinsForPrizesTextPtr: + text_far _ExchangeCoinsForPrizesText + text_end + +WhichPrizeTextPtr: + text_far _WhichPrizeText + text_end + +GetPrizeMenuId: +; determine which one among the three +; prize-texts has been selected +; using the text ID (stored in [hSpriteIndexOrTextID]) +; load the three prizes at wd13d-wd13f +; load the three prices at wd141-wd146 +; display the three prizes' names +; (distinguishing between Pokemon names +; and Items (specifically TMs) names) + ldh a, [hSpriteIndexOrTextID] + sub 3 ; prize-texts' id are 3, 4 and 5 + ld [wWhichPrizeWindow], a ; prize-texts' id (relative, i.e. 0, 1 or 2) + add a + add a + ld d, 0 + ld e, a + ld hl, PrizeDifferentMenuPtrs + add hl, de + ld a, [hli] + ld d, [hl] + ld e, a + inc hl + push hl + ld hl, wPrize1 + call CopyString + pop hl + ld a, [hli] + ld h, [hl] + ld l, a + ld de, wPrize1Price + ld bc, 6 + call CopyData + ld a, [wWhichPrizeWindow] + cp 2 ;is TM_menu? + jr nz, .putMonName + ld a, [wPrize1] + ld [wd11e], a + call GetItemName + hlcoord 2, 4 + call PlaceString + ld a, [wPrize2] + ld [wd11e], a + call GetItemName + hlcoord 2, 6 + call PlaceString + ld a, [wPrize3] + ld [wd11e], a + call GetItemName + hlcoord 2, 8 + call PlaceString + jr .putNoThanksText +.putMonName + ld a, [wPrize1] + ld [wd11e], a + call GetMonName + hlcoord 2, 4 + call PlaceString + ld a, [wPrize2] + ld [wd11e], a + call GetMonName + hlcoord 2, 6 + call PlaceString + ld a, [wPrize3] + ld [wd11e], a + call GetMonName + hlcoord 2, 8 + call PlaceString +.putNoThanksText + hlcoord 2, 10 + ld de, NoThanksText + call PlaceString +; put prices on the right side of the textbox + ld de, wPrize1Price + hlcoord 13, 5 +; reg. c: +; [low nybble] number of bytes +; [bits 765 = %100] space-padding (not zero-padding) + ld c, (1 << 7 | 2) + call PrintBCDNumber + ld de, wPrize2Price + hlcoord 13, 7 + ld c, (1 << 7 | 2) + call PrintBCDNumber + ld de, wPrize3Price + hlcoord 13, 9 + ld c, (1 << 7 | 2) + jp PrintBCDNumber + +NoThanksText: + db "NO THANKS@" + +INCLUDE "data/events/prizes.asm" + +PrintPrizePrice: + hlcoord 11, 0 + lb bc, 1, 7 + call TextBoxBorder + call UpdateSprites + hlcoord 12, 0 + ld de, .CoinString + call PlaceString + hlcoord 13, 1 + ld de, .SixSpacesString + call PlaceString + hlcoord 13, 1 + ld de, wPlayerCoins + ld c, %10000010 + call PrintBCDNumber + ret + +.CoinString: + db "COIN@" + +.SixSpacesString: + db " @" + +LoadCoinsToSubtract: + ld a, [wWhichPrize] + add a + ld d, 0 + ld e, a + ld hl, wPrize1Price + add hl, de ; get selected prize's price + xor a + ldh [hUnusedCoinsByte], a + ld a, [hli] + ldh [hCoins], a + ld a, [hl] + ldh [hCoins + 1], a + ret + +HandlePrizeChoice: + ld a, [wCurrentMenuItem] + ld [wWhichPrize], a + ld d, 0 + ld e, a + ld hl, wPrize1 + add hl, de + ld a, [hl] + ld [wd11e], a + ld a, [wWhichPrizeWindow] + cp 2 ; is prize a TM? + jr nz, .getMonName + call GetItemName + jr .givePrize +.getMonName + call GetMonName +.givePrize + ld hl, SoYouWantPrizeTextPtr + call PrintText + call YesNoChoice + ld a, [wCurrentMenuItem] ; yes/no answer (Y=0, N=1) + and a + jr nz, .printOhFineThen + call LoadCoinsToSubtract + call HasEnoughCoins + jr c, .notEnoughCoins + ld a, [wWhichPrizeWindow] + cp $02 + jr nz, .giveMon + ld a, [wd11e] + ld b, a + ld a, 1 + ld c, a + call GiveItem + jr nc, .bagFull + jr .subtractCoins +.giveMon + ld a, [wd11e] + ld [wcf91], a + push af + call GetPrizeMonLevel + ld c, a + pop af + ld b, a + call GivePokemon + +; If either the party or box was full, wait after displaying message. + push af + ld a, [wAddedToParty] + and a + call z, WaitForTextScrollButtonPress + pop af + +; If the mon couldn't be given to the player (because both the party and box +; were full), return without subtracting coins. + ret nc + +.subtractCoins + call LoadCoinsToSubtract + ld hl, hCoins + 1 + ld de, wPlayerCoins + 1 + ld c, $02 ; how many bytes + predef SubBCDPredef + jp PrintPrizePrice +.bagFull + ld hl, PrizeRoomBagIsFullTextPtr + jp PrintText +.notEnoughCoins + ld hl, SorryNeedMoreCoinsText + jp PrintText +.printOhFineThen + ld hl, OhFineThenTextPtr + jp PrintText + +UnknownPrizeData: +; XXX what's this? + db $00,$01,$00,$01,$00,$01,$00,$00,$01 + +HereYouGoTextPtr: + text_far _HereYouGoText + text_waitbutton + text_end + +SoYouWantPrizeTextPtr: + text_far _SoYouWantPrizeText + text_end + +SorryNeedMoreCoinsText: + text_far _SorryNeedMoreCoinsText + text_waitbutton + text_end + +PrizeRoomBagIsFullTextPtr: + text_far _OopsYouDontHaveEnoughRoomText + text_waitbutton + text_end + +OhFineThenTextPtr: + text_far _OhFineThenText + text_waitbutton + text_end + +GetPrizeMonLevel: + ld a, [wcf91] + ld b, a + ld hl, PrizeMonLevelDictionary +.loop + ld a, [hli] + cp b + jr z, .matchFound + inc hl + jr .loop +.matchFound + ld a, [hl] + ld [wCurEnemyLVL], a + ret + +INCLUDE "data/events/prize_mon_levels.asm" diff --git a/engine/events/saffron_guards.asm b/engine/events/saffron_guards.asm new file mode 100755 index 00000000..bf30b8c5 --- /dev/null +++ b/engine/events/saffron_guards.asm @@ -0,0 +1,15 @@ +RemoveGuardDrink:: + ld hl, GuardDrinksList +.drinkLoop + ld a, [hli] + ldh [hItemToRemoveID], a + and a + ret z + push hl + ld b, a + call IsItemInBag + pop hl + jr z, .drinkLoop + farjp RemoveItemByID + +INCLUDE "data/items/guard_drink_items.asm" diff --git a/engine/events/set_blackout_map.asm b/engine/events/set_blackout_map.asm new file mode 100644 index 00000000..e8460240 --- /dev/null +++ b/engine/events/set_blackout_map.asm @@ -0,0 +1,25 @@ +SetLastBlackoutMap: +; Set the map to return to when +; blacking out or using Teleport or Dig. +; Safari rest houses don't count. + + push hl + ld hl, SafariZoneRestHouses + ld a, [wCurMap] + ld b, a +.loop + ld a, [hli] + cp -1 + jr z, .notresthouse + cp b + jr nz, .loop + jr .done + +.notresthouse + ld a, [wLastMap] + ld [wLastBlackoutMap], a +.done + pop hl + ret + +INCLUDE "data/maps/rest_house_maps.asm" diff --git a/engine/events/starter_dex.asm b/engine/events/starter_dex.asm new file mode 100755 index 00000000..7cfe9af2 --- /dev/null +++ b/engine/events/starter_dex.asm @@ -0,0 +1,9 @@ +; this function temporarily makes the starters (and Ivysaur) seen +; so that the full Pokedex information gets displayed in Oak's lab +StarterDex: + ld a, 1 << (DEX_BULBASAUR - 1) | 1 << (DEX_IVYSAUR - 1) | 1 << (DEX_CHARMANDER - 1) | 1 << (DEX_SQUIRTLE - 1) + ld [wPokedexOwned], a + predef ShowPokedexData + xor a + ld [wPokedexOwned], a + ret diff --git a/engine/events/vending_machine.asm b/engine/events/vending_machine.asm new file mode 100755 index 00000000..6ff6a5e4 --- /dev/null +++ b/engine/events/vending_machine.asm @@ -0,0 +1,132 @@ +VendingMachineMenu:: + ld hl, VendingMachineText1 + call PrintText + ld a, MONEY_BOX + ld [wTextBoxID], a + call DisplayTextBoxID + xor a + ld [wCurrentMenuItem], a + ld [wLastMenuItem], a + ld a, A_BUTTON | B_BUTTON + ld [wMenuWatchedKeys], a + ld a, 3 + ld [wMaxMenuItem], a + ld a, 5 + ld [wTopMenuItemY], a + ld a, 1 + ld [wTopMenuItemX], a + ld hl, wd730 + set 6, [hl] + hlcoord 0, 3 + lb bc, 8, 12 + call TextBoxBorder + call UpdateSprites + hlcoord 2, 5 + ld de, DrinkText + call PlaceString + hlcoord 9, 6 + ld de, DrinkPriceText + call PlaceString + ld hl, wd730 + res 6, [hl] + call HandleMenuInput + bit 1, a ; pressed B? + jr nz, .notThirsty + ld a, [wCurrentMenuItem] + cp 3 ; chose Cancel? + jr z, .notThirsty + xor a + ldh [hMoney], a + ldh [hMoney + 2], a + ld a, $2 + ldh [hMoney + 1], a + call HasEnoughMoney + jr nc, .enoughMoney + ld hl, VendingMachineText4 + jp PrintText +.enoughMoney + call LoadVendingMachineItem + ldh a, [hVendingMachineItem] + ld b, a + ld c, 1 + call GiveItem + jr nc, .BagFull + + ld b, 60 ; number of times to play the "brrrrr" sound +.playDeliverySound + ld c, 2 + call DelayFrames + push bc + ld a, SFX_PUSH_BOULDER + call PlaySound + pop bc + dec b + jr nz, .playDeliverySound + + ld hl, VendingMachineText5 + call PrintText + ld hl, hVendingMachinePrice + 2 + ld de, wPlayerMoney + 2 + ld c, $3 + predef SubBCDPredef + ld a, MONEY_BOX + ld [wTextBoxID], a + jp DisplayTextBoxID +.BagFull + ld hl, VendingMachineText6 + jp PrintText +.notThirsty + ld hl, VendingMachineText7 + jp PrintText + +VendingMachineText1: + text_far _VendingMachineText1 + text_end + +DrinkText: + db "FRESH WATER" + next "SODA POP" + next "LEMONADE" + next "CANCEL@" + +DrinkPriceText: + db "¥200" + next "¥300" + next "¥350" + next "@" + +VendingMachineText4: + text_far _VendingMachineText4 + text_end + +VendingMachineText5: + text_far _VendingMachineText5 + text_end + +VendingMachineText6: + text_far _VendingMachineText6 + text_end + +VendingMachineText7: + text_far _VendingMachineText7 + text_end + +LoadVendingMachineItem: + ld hl, VendingPrices + ld a, [wCurrentMenuItem] + add a + add a + ld d, 0 + ld e, a + add hl, de + ld a, [hli] + ldh [hVendingMachineItem], a + ld a, [hli] + ldh [hVendingMachinePrice], a + ld a, [hli] + ldh [hVendingMachinePrice + 1], a + ld a, [hl] + ldh [hVendingMachinePrice + 2], a + ret + +INCLUDE "data/items/vending_prices.asm" diff --git a/engine/evolution.asm b/engine/evolution.asm deleted file mode 100755 index 7277e991..00000000 --- a/engine/evolution.asm +++ /dev/null @@ -1,156 +0,0 @@ -EvolveMon: - push hl - push de - push bc - ld a, [wcf91] - push af - ld a, [wd0b5] - push af - xor a - ld [wLowHealthAlarm], a - ld [wChannelSoundIDs + Ch5], a - call StopAllMusic - ld a, $1 - ld [H_AUTOBGTRANSFERENABLED], a - ld a, SFX_TINK - call PlaySound - call Delay3 - xor a - ld [H_AUTOBGTRANSFERENABLED], a - ld [hTilesetType], a - ld a, [wEvoOldSpecies] - ld [wWholeScreenPaletteMonSpecies], a - ld c, 0 - call EvolutionSetWholeScreenPalette - ld a, [wEvoNewSpecies] - ld [wcf91], a - ld [wd0b5], a - call Evolution_LoadPic - ld de, vFrontPic - ld hl, vBackPic - ld bc, 7 * 7 - call CopyVideoData - ld a, [wEvoOldSpecies] - ld [wcf91], a - ld [wd0b5], a - call Evolution_LoadPic - ld a, $1 - ld [H_AUTOBGTRANSFERENABLED], a - ld a, [wEvoOldSpecies] - call PlayCry - call WaitForSoundToFinish - ld c, BANK(Music_SafariZone) - ld a, MUSIC_SAFARI_ZONE - call PlayMusic - ld c, 80 - call DelayFrames - ld c, 1 ; set PAL_BLACK instead of mon palette - call EvolutionSetWholeScreenPalette - lb bc, $1, $10 -.animLoop - push bc - call Evolution_CheckForCancel - jr c, .evolutionCancelled - call Evolution_BackAndForthAnim - pop bc - inc b - dec c - dec c - jr nz, .animLoop - xor a - ld [wEvoCancelled], a - ld a, $31 - ld [wEvoMonTileOffset], a - call Evolution_ChangeMonPic ; show the new species pic - ld a, [wEvoNewSpecies] -.done - ld [wWholeScreenPaletteMonSpecies], a - call StopAllMusic - ld a, [wWholeScreenPaletteMonSpecies] - call PlayCry - ld c, 0 - call EvolutionSetWholeScreenPalette - pop af - ld [wd0b5], a - pop af - ld [wcf91], a - pop bc - pop de - pop hl - ld a, [wEvoCancelled] - and a - ret z - scf - ret -.evolutionCancelled - pop bc - ld a, 1 - ld [wEvoCancelled], a - ld a, [wEvoOldSpecies] - jr .done - -EvolutionSetWholeScreenPalette: - ld b, SET_PAL_POKEMON_WHOLE_SCREEN - jp RunPaletteCommand - -Evolution_LoadPic: - call GetMonHeader - coord hl, 7, 2 - jp LoadFlippedFrontSpriteByMonIndex - -Evolution_BackAndForthAnim: -; show the mon change back and forth between the new and old species b times - ld a, $31 - ld [wEvoMonTileOffset], a - call Evolution_ChangeMonPic - ld a, -$31 - ld [wEvoMonTileOffset], a - call Evolution_ChangeMonPic - dec b - jr nz, Evolution_BackAndForthAnim - ret - -Evolution_ChangeMonPic: - push bc - xor a - ld [H_AUTOBGTRANSFERENABLED], a - coord hl, 7, 2 - lb bc, 7, 7 - ld de, SCREEN_WIDTH - 7 -.loop - push bc -.innerLoop - ld a, [wEvoMonTileOffset] - add [hl] - ld [hli], a - dec c - jr nz, .innerLoop - pop bc - add hl, de - dec b - jr nz, .loop - ld a, 1 - ld [H_AUTOBGTRANSFERENABLED], a - call Delay3 - pop bc - ret - -Evolution_CheckForCancel: - call DelayFrame - push bc - call JoypadLowSensitivity - ld a, [hJoy5] - pop bc - and B_BUTTON - jr nz, .pressedB -.notAllowedToCancel - dec c - jr nz, Evolution_CheckForCancel - and a - ret -.pressedB - ld a, [wForceEvolution] - and a - jr nz, .notAllowedToCancel - scf - ret diff --git a/engine/evos_moves.asm b/engine/evos_moves.asm deleted file mode 100755 index 8ec2c4c7..00000000 --- a/engine/evos_moves.asm +++ /dev/null @@ -1,668 +0,0 @@ -; try to evolve the mon in [wWhichPokemon] -TryEvolvingMon: -EvolveTradeMon: - ld hl, wCanEvolveFlags - xor a - ld [hl], a - ld a, [wWhichPokemon] - ld c, a - ld b, FLAG_SET - call Evolution_FlagAction - -; this is only called after battle -; it is supposed to do level up evolutions, though there is a bug that allows item evolutions to occur -EvolutionAfterBattle: - ld a, [hTilesetType] - push af - xor a - ld [wEvolutionOccurred], a - dec a - ld [wWhichPokemon], a - push hl - push bc - push de - ld hl, wPartyCount - push hl - -Evolution_PartyMonLoop: ; loop over party mons - ld hl, wWhichPokemon - inc [hl] - pop hl - inc hl - ld a, [hl] - cp $ff ; have we reached the end of the party? - jp z, .done - ld [wEvoOldSpecies], a - push hl - ld a, [wWhichPokemon] - ld c, a - ld hl, wCanEvolveFlags - ld b, FLAG_TEST - call Evolution_FlagAction - ld a, c - and a ; is the mon's bit set? - jp z, Evolution_PartyMonLoop ; if not, go to the next mon - ld a, [wEvoOldSpecies] - dec a - ld b, 0 - ld hl, EvosMovesPointerTable - add a - rl b - ld c, a - add hl, bc - ld a, [hli] - ld h, [hl] - ld l, a - push hl - ld a, [wcf91] - push af - xor a ; PLAYER_PARTY_DATA - ld [wMonDataLocation], a - call LoadMonData - pop af - ld [wcf91], a - pop hl - -.evoEntryLoop ; loop over evolution entries - ld a, [hli] - and a ; have we reached the end of the evolution data? - jr z, Evolution_PartyMonLoop - ld b, a ; evolution type - cp EV_TRADE - jr z, .checkTradeEvo -; not trade evolution - ld a, [wLinkState] - cp LINK_STATE_TRADING - jr z, Evolution_PartyMonLoop ; if trading, go the next mon - ld a, b - cp EV_ITEM - jr z, .checkItemEvo - ld a, [wForceEvolution] - and a - jr nz, Evolution_PartyMonLoop - ld a, b - cp EV_LEVEL - jr z, .checkLevel -.checkTradeEvo - ld a, [wLinkState] - cp LINK_STATE_TRADING - jp nz, .nextEvoEntry1 ; if not trading, go to the next evolution entry - ld a, [hli] ; level requirement - ld b, a - ld a, [wLoadedMonLevel] - cp b ; is the mon's level greater than the evolution requirement? - jp c, Evolution_PartyMonLoop ; if so, go the next mon - jr .doEvolution -.checkItemEvo - ld a, [wIsInBattle] ; are we in battle? - and a - ld a, [hli] - jp nz, .nextEvoEntry1 ; don't evolve if we're in a battle as wcf91 could be holding the last mon sent out - - ld b, a ; evolution item - ld a, [wcf91] ; last item used - cp b ; was the evolution item in this entry used? - jp nz, .nextEvoEntry1 ; if not, go to the next evolution entry -.checkLevel - ld a, [hli] ; level requirement - ld b, a - ld a, [wLoadedMonLevel] - cp b ; is the mon's level greater than the evolution requirement? - jp c, .nextEvoEntry2 ; if so, go the next evolution entry -.doEvolution - ld [wCurEnemyLVL], a - ld a, 1 - ld [wEvolutionOccurred], a - push hl - ld a, [hl] - ld [wEvoNewSpecies], a - ld a, [wWhichPokemon] - ld hl, wPartyMonNicks - call GetPartyMonName - call CopyStringToCF4B - ld hl, IsEvolvingText - call PrintText - ld c, 50 - call DelayFrames - xor a - ld [H_AUTOBGTRANSFERENABLED], a - coord hl, 0, 0 - lb bc, 12, 20 - call ClearScreenArea - ld a, $1 - ld [H_AUTOBGTRANSFERENABLED], a - ld a, $ff - ld [wUpdateSpritesEnabled], a - call ClearSprites - callab EvolveMon - jp c, CancelledEvolution - ld hl, EvolvedText - call PrintText - pop hl - ld a, [hl] - ld [wd0b5], a - ld [wLoadedMonSpecies], a - ld [wEvoNewSpecies], a - ld a, MONSTER_NAME - ld [wNameListType], a - ld a, BANK(MonsterNames) ; bank is not used for monster names - ld [wPredefBank], a - call GetName - push hl - ld hl, IntoText - call PrintText_NoCreatingTextBox - ld a, SFX_GET_ITEM_2 - call PlaySoundWaitForCurrent - call WaitForSoundToFinish - ld c, 40 - call DelayFrames - call ClearScreen - call RenameEvolvedMon - ld a, [wd11e] - push af - ld a, [wd0b5] - ld [wd11e], a - predef IndexToPokedex - ld a, [wd11e] - dec a - ld hl, BaseStats - ld bc, MonBaseStatsEnd - MonBaseStats - call AddNTimes - ld de, wMonHeader - call CopyData - ld a, [wd0b5] - ld [wMonHIndex], a - pop af - ld [wd11e], a - ld hl, wLoadedMonHPExp - 1 - ld de, wLoadedMonStats - ld b, $1 - call CalcStats - ld a, [wWhichPokemon] - ld hl, wPartyMon1 - ld bc, wPartyMon2 - wPartyMon1 - call AddNTimes - ld e, l - ld d, h - push hl - push bc - ld bc, wPartyMon1MaxHP - wPartyMon1 - add hl, bc - ld a, [hli] - ld b, a - ld c, [hl] - ld hl, wLoadedMonMaxHP + 1 - ld a, [hld] - sub c - ld c, a - ld a, [hl] - sbc b - ld b, a - ld hl, wLoadedMonHP + 1 - ld a, [hl] - add c - ld [hld], a - ld a, [hl] - adc b - ld [hl], a - dec hl - pop bc - call CopyData - ld a, [wd0b5] - ld [wd11e], a - xor a - ld [wMonDataLocation], a - call LearnMoveFromLevelUp - pop hl - predef SetPartyMonTypes - ld a, [wIsInBattle] - and a - call z, Evolution_ReloadTilesetTilePatterns - predef IndexToPokedex - ld a, [wd11e] - dec a - ld c, a - ld b, FLAG_SET - ld hl, wPokedexOwned - push bc - call Evolution_FlagAction - pop bc - ld hl, wPokedexSeen - call Evolution_FlagAction - pop de - pop hl - ld a, [wLoadedMonSpecies] - ld [hl], a - push hl - ld l, e - ld h, d - jr .nextEvoEntry2 - -.nextEvoEntry1 - inc hl - -.nextEvoEntry2 - inc hl - jp .evoEntryLoop - -.done - pop de - pop bc - pop hl - pop af - ld [hTilesetType], a - ld a, [wLinkState] - cp LINK_STATE_TRADING - ret z - ld a, [wIsInBattle] - and a - ret nz - ld a, [wEvolutionOccurred] - and a - call nz, PlayDefaultMusic - ret - -RenameEvolvedMon: -; Renames the mon to its new, evolved form's standard name unless it had a -; nickname, in which case the nickname is kept. - ld a, [wd0b5] - push af - ld a, [wMonHIndex] - ld [wd0b5], a - call GetName - pop af - ld [wd0b5], a - ld hl, wcd6d - ld de, wcf4b -.compareNamesLoop - ld a, [de] - inc de - cp [hl] - inc hl - ret nz - cp "@" - jr nz, .compareNamesLoop - ld a, [wWhichPokemon] - ld bc, NAME_LENGTH - ld hl, wPartyMonNicks - call AddNTimes - push hl - call GetName - ld hl, wcd6d - pop de - jp CopyData - -CancelledEvolution: - ld hl, StoppedEvolvingText - call PrintText - call ClearScreen - pop hl - call Evolution_ReloadTilesetTilePatterns - jp Evolution_PartyMonLoop - -EvolvedText: - TX_FAR _EvolvedText - db "@" - -IntoText: - TX_FAR _IntoText - db "@" - -StoppedEvolvingText: - TX_FAR _StoppedEvolvingText - db "@" - -IsEvolvingText: - TX_FAR _IsEvolvingText - db "@" - -Evolution_ReloadTilesetTilePatterns: - ld a, [wLinkState] - cp LINK_STATE_TRADING - ret z - jp ReloadTilesetTilePatterns - -LearnMoveFromLevelUp: - ld a, [wd11e] ; species - ld [wcf91], a - call GetMonLearnset -.learnSetLoop ; loop over the learn set until we reach a move that is learnt at the current level or the end of the list - ld a, [hli] - and a ; have we reached the end of the learn set? - jr z, .done ; if we've reached the end of the learn set, jump - ld b, a ; level the move is learnt at - ld a, [wCurEnemyLVL] - cp b ; is the move learnt at the mon's current level? - ld a, [hli] ; move ID - jr nz, .learnSetLoop - ld d, a ; ID of move to learn - ld a, [wMonDataLocation] - and a - jr nz, .next -; If [wMonDataLocation] is 0 (PLAYER_PARTY_DATA), get the address of the mon's -; current moves in party data. Every call to this function sets -; [wMonDataLocation] to 0 because other data locations are not supported. -; If it is not 0, this function will not work properly. - ld hl, wPartyMon1Moves - ld a, [wWhichPokemon] - ld bc, wPartyMon2 - wPartyMon1 - call AddNTimes -.next - ld b, NUM_MOVES -.checkCurrentMovesLoop ; check if the move to learn is already known - ld a, [hli] - cp d - jr z, .done ; if already known, jump - dec b - jr nz, .checkCurrentMovesLoop - ld a, d - ld [wMoveNum], a - ld [wd11e], a - call GetMoveName - call CopyStringToCF4B - predef LearnMove - ld a, b - and a - jr z, .done - callab IsThisPartymonStarterPikachu_Party - jr nc, .done - ld a, [wMoveNum] - cp THUNDERBOLT - jr z, .foundThunderOrThunderbolt - cp THUNDER - jr nz, .done -.foundThunderOrThunderbolt - ld a, $5 - ld [wd49c], a - ld a, $85 - ld [wPikachuMood], a -.done - ld a, [wcf91] - ld [wd11e], a - ret - -Func_3b079: - ld a, [wcf91] - push af - call Func_3b0a2 - jr c, .asm_3b09c - - call Func_3b10f - jr nc, .asm_3b096 - - call Func_3b0a2 - jr c, .asm_3b09c - - call Func_3b10f - jr nc, .asm_3b096 - - call Func_3b0a2 - jr c, .asm_3b09c -.asm_3b096 - pop af - ld [wcf91], a - and a - ret -.asm_3b09c - pop af - ld [wcf91], a - scf - ret - -Func_3b0a2: -; XXX what is wcf91 entering this function? - ld a, [wd11e] - ld [wMoveNum], a - predef CanLearnTM - ld a, c - and a - jr nz, .asm_3b0ec - ld hl, Pointer_3b0ee - ld a, [wcf91] - ld de, $1 - call IsInArray - jr c, .asm_3b0d2 - ld a, $ff - ld [wMonHGrowthRate], a - ld a, [wd11e] - ld hl, wMonHMoves - ld de, $1 - call IsInArray - jr c, .asm_3b0ec -.asm_3b0d2 - ld a, [wd11e] - ld d, a - call GetMonLearnset -.loop - ld a, [hli] - and a - jr z, .asm_3b0ea - ld b, a - ld a, [wCurEnemyLVL] - cp b - jr c, .asm_3b0ea - ld a, [hli] - cp d - jr z, .asm_3b0ec - jr .loop -.asm_3b0ea - and a - ret -.asm_3b0ec - scf - ret - -Pointer_3b0ee: - db NIDOKING - db IVYSAUR - db EXEGGUTOR - db GENGAR - db NIDOQUEEN - db ARCANINE - db GYARADOS - db BLASTOISE - db GOLEM - db DRAGONITE - db NINETALES - db DRAGONAIR - db KABUTOPS - db OMASTAR - db JIGGLYPUFF - db FLAREON - db JOLTEON - db VAPOREON - db BEEDRILL - db BUTTERFREE - db MACHAMP - db CLOYSTER - db CLEFABLE - db ALAKAZAM - db STARMIE - db VENUSAUR - db TENTACRUEL - db CHARMELEON - db WARTORTLE - db CHARIZARD - db VILEPLUME - db VICTREEBEL - db $ff - -Func_3b10f: - ld c, $0 -.asm_3b111 - ld hl, EvosMovesPointerTable - ld b, $0 - add hl, bc - add hl, bc - ld a, [hli] - ld h, [hl] - ld l, a -.asm_3b11b - ld a, [hli] - and a - jr z, .asm_3b130 - cp $2 - jr nz, .asm_3b124 - inc hl -.asm_3b124 - inc hl - ld a, [wcf91] - cp [hl] - jr z, .asm_3b138 - inc hl - ld a, [hl] - and a - jr nz, .asm_3b11b -.asm_3b130 - inc c - ld a, c - cp VICTREEBEL - jr c, .asm_3b111 - and a - ret -.asm_3b138 - inc c - ld a, c - ld [wcf91], a - scf - ret - -; writes the moves a mon has at level [wCurEnemyLVL] to [de] -; move slots are being filled up sequentially and shifted if all slots are full -WriteMonMoves: - call GetPredefRegisters - push hl - push de - push bc - call GetMonLearnset - jr .firstMove -.nextMove - pop de -.nextMove2 - inc hl -.firstMove - ld a, [hli] ; read level of next move in learnset - and a - jp z, .done ; end of list - ld b, a - ld a, [wCurEnemyLVL] - cp b - jp c, .done ; mon level < move level (assumption: learnset is sorted by level) - ld a, [wLearningMovesFromDayCare] - and a - jr z, .skipMinLevelCheck - ld a, [wDayCareStartLevel] - cp b - jr nc, .nextMove2 ; min level >= move level - -.skipMinLevelCheck - -; check if the move is already known - push de - ld c, NUM_MOVES -.alreadyKnowsCheckLoop - ld a, [de] - inc de - cp [hl] - jr z, .nextMove - dec c - jr nz, .alreadyKnowsCheckLoop - -; try to find an empty move slot - pop de - push de - ld c, NUM_MOVES -.findEmptySlotLoop - ld a, [de] - and a - jr z, .writeMoveToSlot2 - inc de - dec c - jr nz, .findEmptySlotLoop - -; no empty move slots found - pop de - push de - push hl - ld h, d - ld l, e - call WriteMonMoves_ShiftMoveData ; shift all moves one up (deleting move 1) - ld a, [wLearningMovesFromDayCare] - and a - jr z, .writeMoveToSlot - -; shift PP as well if learning moves from day care - push de - ld bc, wPartyMon1PP - (wPartyMon1Moves + 3) - add hl, bc - ld d, h - ld e, l - call WriteMonMoves_ShiftMoveData ; shift all move PP data one up - pop de - -.writeMoveToSlot - pop hl -.writeMoveToSlot2 - ld a, [hl] - ld [de], a - ld a, [wLearningMovesFromDayCare] - and a - jr z, .nextMove - -; write move PP value if learning moves from day care - push hl - ld a, [hl] - ld hl, wPartyMon1PP - wPartyMon1Moves - add hl, de - push hl - dec a - ld hl, Moves - ld bc, MoveEnd - Moves - call AddNTimes - ld de, wBuffer - ld a, BANK(Moves) - call FarCopyData - ld a, [wBuffer + 5] - pop hl - ld [hl], a - pop hl - jr .nextMove - -.done - pop bc - pop de - pop hl - ret - -; shifts all move data one up (freeing 4th move slot) -WriteMonMoves_ShiftMoveData: - ld c, NUM_MOVES - 1 -.loop - inc de - ld a, [de] - ld [hli], a - dec c - jr nz, .loop - ret - -Evolution_FlagAction: - predef_jump FlagActionPredef - -GetMonLearnset: - ld hl, EvosMovesPointerTable - ld b, 0 - ld a, [wcf91] - dec a - ld c, a - add hl, bc - add hl, bc - ld a, [hli] - ld h, [hl] - ld l, a -.skipEvolutionDataLoop ; loop to skip past the evolution data, which comes before the move data - ld a, [hli] - and a ; have we reached the end of the evolution data? - jr nz, .skipEvolutionDataLoop ; if not, jump back up - ret - -INCLUDE "data/evos_moves.asm" diff --git a/engine/experience.asm b/engine/experience.asm deleted file mode 100755 index 2efc13de..00000000 --- a/engine/experience.asm +++ /dev/null @@ -1,160 +0,0 @@ -; calculates the level a mon should be based on its current exp -CalcLevelFromExperience: - ld a, [wLoadedMonSpecies] - ld [wd0b5], a - call GetMonHeader - ld d, $1 ; init level to 1 -.loop - inc d ; increment level - call CalcExperience - push hl - ld hl, wLoadedMonExp + 2 ; current exp -; compare exp needed for level d with current exp - ld a, [hExperience + 2] - ld c, a - ld a, [hld] - sub c - ld a, [hExperience + 1] - ld c, a - ld a, [hld] - sbc c - ld a, [hExperience] - ld c, a - ld a, [hl] - sbc c - pop hl - jr nc, .loop ; if exp needed for level d is not greater than exp, try the next level - dec d ; since the exp was too high on the last loop iteration, go back to the previous value and return - ret - -; calculates the amount of experience needed for level d -CalcExperience: - ld a, [wMonHGrowthRate] - add a - add a - ld c, a - ld b, 0 - ld hl, GrowthRateTable - add hl, bc - call CalcDSquared - ld a, d - ld [H_MULTIPLIER], a - call Multiply - ld a, [hl] - and $f0 - swap a - ld [H_MULTIPLIER], a - call Multiply - ld a, [hli] - and $f - ld [H_DIVISOR], a - ld b, $4 - call Divide - ld a, [H_QUOTIENT + 1] - push af - ld a, [H_QUOTIENT + 2] - push af - ld a, [H_QUOTIENT + 3] - push af - call CalcDSquared - ld a, [hl] - and $7f - ld [H_MULTIPLIER], a - call Multiply - ld a, [H_PRODUCT + 1] - push af - ld a, [H_PRODUCT + 2] - push af - ld a, [H_PRODUCT + 3] - push af - ld a, [hli] - push af - xor a - ld [H_MULTIPLICAND], a - ld [H_MULTIPLICAND + 1], a - ld a, d - ld [H_MULTIPLICAND + 2], a - ld a, [hli] - ld [H_MULTIPLIER], a - call Multiply - ld b, [hl] - ld a, [H_PRODUCT + 3] - sub b - ld [H_PRODUCT + 3], a - ld b, $0 - ld a, [H_PRODUCT + 2] - sbc b - ld [H_PRODUCT + 2], a - ld a, [H_PRODUCT + 1] - sbc b - ld [H_PRODUCT + 1], a -; The difference of the linear term and the constant term consists of 3 bytes -; starting at H_PRODUCT + 1. Below, hExperience (an alias of that address) will -; be used instead for the further work of adding or subtracting the squared -; term and adding the cubed term. - pop af - and $80 - jr nz, .subtractSquaredTerm ; check sign - pop bc - ld a, [hExperience + 2] - add b - ld [hExperience + 2], a - pop bc - ld a, [hExperience + 1] - adc b - ld [hExperience + 1], a - pop bc - ld a, [hExperience] - adc b - ld [hExperience], a - jr .addCubedTerm -.subtractSquaredTerm - pop bc - ld a, [hExperience + 2] - sub b - ld [hExperience + 2], a - pop bc - ld a, [hExperience + 1] - sbc b - ld [hExperience + 1], a - pop bc - ld a, [hExperience] - sbc b - ld [hExperience], a -.addCubedTerm - pop bc - ld a, [hExperience + 2] - add b - ld [hExperience + 2], a - pop bc - ld a, [hExperience + 1] - adc b - ld [hExperience + 1], a - pop bc - ld a, [hExperience] - adc b - ld [hExperience], a - ret - -; calculates d*d -CalcDSquared: - xor a - ld [H_MULTIPLICAND], a - ld [H_MULTIPLICAND + 1], a - ld a, d - ld [H_MULTIPLICAND + 2], a - ld [H_MULTIPLIER], a - jp Multiply - -; each entry has the following scheme: -; %AAAABBBB %SCCCCCCC %DDDDDDDD %EEEEEEEE -; resulting in -; (a*n^3)/b + sign*c*n^2 + d*n - e -; where sign = -1 <=> S=1 -GrowthRateTable: - db $11,$00,$00,$00 ; medium fast n^3 - db $34,$0A,$00,$1E ; (unused?) 3/4 n^3 + 10 n^2 - 30 - db $34,$14,$00,$46 ; (unused?) 3/4 n^3 + 20 n^2 - 70 - db $65,$8F,$64,$8C ; medium slow: 6/5 n^3 - 15 n^2 + 100 n - 140 - db $45,$00,$00,$00 ; fast: 4/5 n^3 - db $54,$00,$00,$00 ; slow: 5/4 n^3 diff --git a/engine/game_corner_slots.asm b/engine/game_corner_slots.asm deleted file mode 100755 index 3c5b3a10..00000000 --- a/engine/game_corner_slots.asm +++ /dev/null @@ -1,54 +0,0 @@ -StartSlotMachine: - ld a, [wHiddenObjectFunctionArgument] - cp $fd - jr z, .printOutOfOrder - cp $fe - jr z, .printOutToLunch - cp $ff - jr z, .printSomeonesKeys - callba AbleToPlaySlotsCheck - ld a, [wCanPlaySlots] - and a - ret z - ld a, [wLuckySlotHiddenObjectIndex] - ld b, a - ld a, [wHiddenObjectIndex] - inc a - cp b - jr z, .match - ld a, 253 - jr .next -.match - ld a, 250 -.next - ld [wSlotMachineSevenAndBarModeChance], a - ld a, [H_LOADEDROMBANK] - ld [wSlotMachineSavedROMBank], a - call PromptUserToPlaySlots - ret -.printOutOfOrder - tx_pre_id GameCornerOutOfOrderText - jr .printText -.printOutToLunch - tx_pre_id GameCornerOutToLunchText - jr .printText -.printSomeonesKeys - tx_pre_id GameCornerSomeonesKeysText -.printText - push af - call EnableAutoTextBoxDrawing - pop af - call PrintPredefTextID - ret - -GameCornerOutOfOrderText: - TX_FAR _GameCornerOutOfOrderText - db "@" - -GameCornerOutToLunchText: - TX_FAR _GameCornerOutToLunchText - db "@" - -GameCornerSomeonesKeysText: - TX_FAR _GameCornerSomeonesKeysText - db "@" diff --git a/engine/game_corner_slots2.asm b/engine/game_corner_slots2.asm deleted file mode 100755 index 6bbaf72d..00000000 --- a/engine/game_corner_slots2.asm +++ /dev/null @@ -1,31 +0,0 @@ -AbleToPlaySlotsCheck: - ld a, [wSpriteStateData1 + 2] - and $8 - jr z, .done ; not able - ld b, COIN_CASE - predef GetQuantityOfItemInBag - ld a, b - and a - ld b, (GameCornerCoinCaseText_id - TextPredefs) / 2 + 1 - jr z, .printCoinCaseRequired - ld hl, wPlayerCoins - ld a, [hli] - or [hl] - jr nz, .done ; able to play - ld b, (GameCornerNoCoinsText_id - TextPredefs) / 2 + 1 -.printCoinCaseRequired - call EnableAutoTextBoxDrawing - ld a, b - call PrintPredefTextID - xor a -.done - ld [wCanPlaySlots], a - ret - -GameCornerCoinCaseText: - TX_FAR _GameCornerCoinCaseText - db "@" - -GameCornerNoCoinsText: - TX_FAR _GameCornerNoCoinsText - db "@" diff --git a/engine/gamefreak.asm b/engine/gamefreak.asm deleted file mode 100755 index 5472a56e..00000000 --- a/engine/gamefreak.asm +++ /dev/null @@ -1,263 +0,0 @@ -LoadShootingStarGraphics: - ld a, $f9 - ld [rOBP0], a - ld a, $a4 - ld [rOBP1], a - call UpdateGBCPal_OBP0 - call UpdateGBCPal_OBP1 - ld de, AnimationTileset2 + $30 ; star tile (top left quadrant) - ld hl, vChars1 + $200 - lb bc, BANK(AnimationTileset2), $01 - call CopyVideoData - ld de, AnimationTileset2 + $130 ; star tile (bottom left quadrant) - ld hl, vChars1 + $210 - lb bc, BANK(AnimationTileset2), $01 - call CopyVideoData - ld de, FallingStar - ld hl, vChars1 + $220 - lb bc, BANK(FallingStar), (FallingStarEnd - FallingStar) / $10 - call CopyVideoData - ld hl, GameFreakLogoOAMData - ld de, wOAMBuffer + $60 - ld bc, GameFreakLogoOAMDataEnd - GameFreakLogoOAMData - call CopyData - ld hl, GameFreakShootingStarOAMData - ld de, wOAMBuffer - ld bc, GameFreakShootingStarOAMDataEnd - GameFreakShootingStarOAMData - jp CopyData - -AnimateShootingStar: - call LoadShootingStarGraphics - ld a, SFX_SHOOTING_STAR - call PlaySound - -; Move the big star down and left across the screen. - ld hl, wOAMBuffer - lb bc, $a0, $4 -.bigStarLoop - push hl - push bc -.bigStarInnerLoop - ld a, [hl] ; Y - add 4 - ld [hli], a - ld a, [hl] ; X - add -4 - ld [hli], a - inc hl - inc hl - dec c - jr nz, .bigStarInnerLoop - ld c, 1 - call CheckForUserInterruption - pop bc - pop hl - ret c - ld a, [hl] - cp 80 - jr nz, .next - jr .bigStarLoop -.next - cp b - jr nz, .bigStarLoop - -; Clear big star OAM. - ld hl, wOAMBuffer - ld c, 4 - ld de, 4 -.clearOAMLoop - ld [hl], 160 - add hl, de - dec c - jr nz, .clearOAMLoop - -; Make Gamefreak logo flash. - ld b, 3 -.flashLogoLoop - ld hl, rOBP0 - rrc [hl] - rrc [hl] - call UpdateGBCPal_OBP0 - ld c, 10 - call CheckForUserInterruption - ret c - dec b - jr nz, .flashLogoLoop - -; Copy 24 instances of the small stars OAM data. -; Note that their coordinates put them off-screen. - ld de, wOAMBuffer - ld a, 24 -.initSmallStarsOAMLoop - push af - ld hl, SmallStarsOAM - ld bc, SmallStarsOAMEnd - SmallStarsOAM - call CopyData - pop af - dec a - jr nz, .initSmallStarsOAMLoop - -; Animate the small stars falling from the Gamefreak logo. - xor a - ld [wMoveDownSmallStarsOAMCount], a - ld hl, SmallStarsWaveCoordsPointerTable - ld c, 6 -.smallStarsLoop - ld a, [hli] - ld e, a - ld a, [hli] - ld d, a - push bc - push hl - ld hl, wOAMBuffer + $50 - ld c, 4 -.smallStarsInnerLoop ; introduce new wave of 4 small stars OAM entries - ld a, [de] - cp $ff - jr z, .next2 - ld [hli], a ; Y - inc de - ld a, [de] - ld [hli], a ; X - inc de - inc hl - push bc - ld a, [de] - ld b,a - ld a, [hl] - and $f0 - or b - ld [hl], a - inc de - pop bc - inc hl - dec c - jr nz, .smallStarsInnerLoop - ld a, [wMoveDownSmallStarsOAMCount] - cp 24 - jr z, .next2 - add 6 ; should be 4, but the extra 2 aren't visible on screen - ld [wMoveDownSmallStarsOAMCount], a -.next2 - call MoveDownSmallStars - push af - -; shift the existing OAM entries down to make room for the next wave - ld hl, wOAMBuffer + $10 - ld de, wOAMBuffer - ld bc, $50 - call CopyData - - pop af - pop hl - pop bc - ret c - dec c - jr nz, .smallStarsLoop - and a - ret - -SmallStarsOAM: - db $00,$00,$A2,$90 -SmallStarsOAMEnd: - -SmallStarsWaveCoordsPointerTable: - dw SmallStarsWave1Coords - dw SmallStarsWave2Coords - dw SmallStarsWave3Coords - dw SmallStarsWave4Coords - dw SmallStarsEmptyWave - dw SmallStarsEmptyWave - -; The stars that fall from the Gamefreak logo come in 4 waves of 4 OAM entries. -; These arrays contain the Y and X coordinates of each OAM entry. - -SmallStarsWave1Coords: - db $68,$30 - db $05,$68 - db $40,$05 - db $68,$58 - db $04,$68 - db $78,$07 - -SmallStarsWave2Coords: - db $68,$38 - db $05,$68 - db $48,$06 - db $68,$60 - db $04,$68 - db $70,$07 - -SmallStarsWave3Coords: - db $68,$34 - db $05,$68 - db $4c,$06 - db $68,$54 - db $06,$68 - db $64,$07 - -SmallStarsWave4Coords: - db $68,$3c - db $05,$68 - db $5c,$04 - db $68,$6c - db $07,$68 - db $74,$07 - -SmallStarsEmptyWave: - db $FF - -MoveDownSmallStars: - ld b, 8 -.loop - ld hl, wOAMBuffer + $5c - ld a, [wMoveDownSmallStarsOAMCount] - ld de, -4 - ld c, a -.innerLoop - inc [hl] ; Y - add hl, de - dec c - jr nz, .innerLoop -; Toggle the palette so that the lower star in the small stars tile blinks in -; and out. - ld a, [rOBP1] - xor %10100000 - ld [rOBP1], a - call UpdateGBCPal_OBP1 - ld c, 3 - call CheckForUserInterruption - ret c - dec b - jr nz, .loop - ret - -GameFreakLogoOAMData: - db $48,$50,$8D,$00 - db $48,$58,$8E,$00 - db $50,$50,$8F,$00 - db $50,$58,$90,$00 - db $58,$50,$91,$00 - db $58,$58,$92,$00 - db $60,$30,$80,$00 - db $60,$38,$81,$00 - db $60,$40,$82,$00 - db $60,$48,$83,$00 - db $60,$50,$93,$00 - db $60,$58,$84,$00 - db $60,$60,$85,$00 - db $60,$68,$83,$00 - db $60,$70,$81,$00 - db $60,$78,$86,$00 -GameFreakLogoOAMDataEnd: - -GameFreakShootingStarOAMData: - db $00,$A0,$A0,$14 - db $00,$A8,$A0,$34 - db $08,$A0,$A1,$14 - db $08,$A8,$A1,$34 -GameFreakShootingStarOAMDataEnd: - -FallingStar: - INCBIN "gfx/falling_star.2bpp" -FallingStarEnd: diff --git a/engine/get_bag_item_quantity.asm b/engine/get_bag_item_quantity.asm deleted file mode 100644 index f10df1a0..00000000 --- a/engine/get_bag_item_quantity.asm +++ /dev/null @@ -1,18 +0,0 @@ -GetQuantityOfItemInBag: -; In: b = item ID -; Out: b = how many of that item are in the bag - call GetPredefRegisters - ld hl, wNumBagItems -.loop - inc hl - ld a, [hli] - cp $ff - jr z, .notInBag - cp b - jr nz, .loop - ld a, [hl] - ld b, a - ret -.notInBag - ld b, 0 - ret diff --git a/engine/gfx/hp_bar.asm b/engine/gfx/hp_bar.asm new file mode 100755 index 00000000..b47b1fbd --- /dev/null +++ b/engine/gfx/hp_bar.asm @@ -0,0 +1,268 @@ +HPBarLength: + call GetPredefRegisters + +; calculates bc * 48 / de, the number of pixels the HP bar has +; the result is always at least 1 +GetHPBarLength: + push hl + xor a + ld hl, hMultiplicand + ld [hli], a + ld a, b + ld [hli], a + ld a, c + ld [hli], a + ld [hl], $30 + call Multiply ; 48 * bc (hp bar is 48 pixels long) + ld a, d + and a + jr z, .maxHPSmaller256 + srl d ; make HP in de fit into 1 byte by dividing by 4 + rr e + srl d + rr e + ldh a, [hMultiplicand+1] + ld b, a + ldh a, [hMultiplicand+2] + srl b ; divide multiplication result as well + rr a + srl b + rr a + ldh [hMultiplicand+2], a + ld a, b + ldh [hMultiplicand+1], a +.maxHPSmaller256 + ld a, e + ldh [hDivisor], a + ld b, $4 + call Divide + ldh a, [hMultiplicand+2] + ld e, a ; e = bc * 48 / de (num of pixels of HP bar) + pop hl + and a + ret nz + ld e, $1 ; make result at least 1 + ret + +; predef $48 +UpdateHPBar: +UpdateHPBar2: + push hl + ld hl, wHPBarOldHP + ld a, [hli] + ld c, a ; old HP into bc + ld a, [hli] + ld b, a + ld a, [hli] + ld e, a ; new HP into de + ld d, [hl] + pop hl + push de + push bc + call UpdateHPBar_CalcHPDifference + ld a, e + ld [wHPBarHPDifference+1], a + ld a, d + ld [wHPBarHPDifference], a + pop bc + pop de + call UpdateHPBar_CompareNewHPToOldHP + ret z + ld a, $ff + jr c, .HPdecrease + ld a, $1 +.HPdecrease + ld [wHPBarDelta], a + call GetPredefRegisters + ld a, [wHPBarNewHP] + ld e, a + ld a, [wHPBarNewHP+1] + ld d, a +.animateHPBarLoop + push de + ld a, [wHPBarOldHP] + ld c, a + ld a, [wHPBarOldHP+1] + ld b, a + call UpdateHPBar_CompareNewHPToOldHP + jr z, .animateHPBarDone + jr nc, .HPIncrease +; HP decrease + dec bc ; subtract 1 HP + ld a, c + ld [wHPBarNewHP], a + ld a, b + ld [wHPBarNewHP+1], a + call UpdateHPBar_CalcOldNewHPBarPixels + ld a, e + sub d ; calc pixel difference + jr .ok +.HPIncrease + inc bc ; add 1 HP + ld a, c + ld [wHPBarNewHP], a + ld a, b + ld [wHPBarNewHP+1], a + call UpdateHPBar_CalcOldNewHPBarPixels + ld a, d + sub e ; calc pixel difference +.ok + call UpdateHPBar_PrintHPNumber + and a + jr z, .noPixelDifference + call UpdateHPBar_AnimateHPBar +.noPixelDifference + ld a, [wHPBarNewHP] + ld [wHPBarOldHP], a + ld a, [wHPBarNewHP+1] + ld [wHPBarOldHP+1], a + pop de + jr .animateHPBarLoop +.animateHPBarDone + pop de + ld a, e + ld [wHPBarOldHP], a + ld a, d + ld [wHPBarOldHP+1], a + or e + jr z, .monFainted + call UpdateHPBar_CalcOldNewHPBarPixels + ld d, e +.monFainted + call UpdateHPBar_PrintHPNumber + ld a, $1 + call UpdateHPBar_AnimateHPBar + jp Delay3 + +; animates the HP bar going up or down for (a) ticks (two waiting frames each) +; stops prematurely if bar is filled up +; e: current health (in pixels) to start with +UpdateHPBar_AnimateHPBar: + push hl +.barAnimationLoop + push af + push de + ld d, $6 + call DrawHPBar + ld c, 2 + call DelayFrames + pop de + ld a, [wHPBarDelta] ; +1 or -1 + add e + cp $31 + jr nc, .barFilledUp + ld e, a + pop af + dec a + jr nz, .barAnimationLoop + pop hl + ret +.barFilledUp + pop af + pop hl + ret + +; compares old HP and new HP and sets c and z flags accordingly +UpdateHPBar_CompareNewHPToOldHP: + ld a, d + sub b + ret nz + ld a, e + sub c + ret + +; calcs HP difference between bc and de (into de) +UpdateHPBar_CalcHPDifference: + ld a, d + sub b + jr c, .oldHPGreater + jr z, .testLowerByte +.newHPGreater + ld a, e + sub c + ld e, a + ld a, d + sbc b + ld d, a + ret +.oldHPGreater + ld a, c + sub e + ld e, a + ld a, b + sbc d + ld d, a + ret +.testLowerByte + ld a, e + sub c + jr c, .oldHPGreater + jr nz, .newHPGreater + ld de, $0 + ret + +UpdateHPBar_PrintHPNumber: + push af + push de + ld a, [wHPBarType] + and a + jr z, .done ; don't print number in enemy HUD +; convert from little-endian to big-endian for PrintNumber + ld a, [wHPBarOldHP] + ld [wHPBarTempHP + 1], a + ld a, [wHPBarOldHP + 1] + ld [wHPBarTempHP], a + push hl + ld de, $15 + ldh a, [hFlagsFFFA] + bit 0, a + jr z, .next + ld de, $9 +.next + add hl, de + push hl + ld a, " " + ld [hli], a + ld [hli], a + ld [hli], a + pop hl + ld de, wHPBarTempHP + lb bc, 2, 3 + call PrintNumber + call DelayFrame + pop hl +.done + pop de + pop af + ret + +; calcs number of HP bar pixels for old and new HP value +; d: new pixels +; e: old pixels +UpdateHPBar_CalcOldNewHPBarPixels: + push hl + ld hl, wHPBarMaxHP + ld a, [hli] ; max HP into de + ld e, a + ld a, [hli] + ld d, a + ld a, [hli] ; old HP into bc + ld c, a + ld a, [hli] + ld b, a + ld a, [hli] ; new HP into hl + ld h, [hl] + ld l, a + push hl + push de + call GetHPBarLength ; calc num pixels for old HP + ld a, e + pop de + pop bc + push af + call GetHPBarLength ; calc num pixels for new HP + pop af + ld d, e + ld e, a + pop hl + ret diff --git a/engine/gfx/load_pokedex_tiles.asm b/engine/gfx/load_pokedex_tiles.asm new file mode 100755 index 00000000..a3f69171 --- /dev/null +++ b/engine/gfx/load_pokedex_tiles.asm @@ -0,0 +1,11 @@ +; Loads tile patterns for tiles used in the pokedex. +LoadPokedexTilePatterns: + call LoadHpBarAndStatusTilePatterns + ld de, PokedexTileGraphics + ld hl, vChars2 tile $60 + lb bc, BANK(PokedexTileGraphics), (PokedexTileGraphicsEnd - PokedexTileGraphics) / $10 + call CopyVideoData + ld de, PokeballTileGraphics + ld hl, vChars2 tile $72 + lb bc, BANK(PokeballTileGraphics), 1 + jp CopyVideoData ; load pokeball tile for marking caught mons diff --git a/engine/gfx/mon_icons.asm b/engine/gfx/mon_icons.asm new file mode 100755 index 00000000..6e2cf0ba --- /dev/null +++ b/engine/gfx/mon_icons.asm @@ -0,0 +1,307 @@ +AnimatePartyMon_ForceSpeed1: + xor a + ld [wCurrentMenuItem], a + ld b, a + inc a + jr GetAnimationSpeed + +; wPartyMenuHPBarColors contains the party mon's health bar colors +; 0: green +; 1: yellow +; 2: red +AnimatePartyMon:: + ld hl, wPartyMenuHPBarColors + ld a, [wCurrentMenuItem] + ld c, a + ld b, 0 + add hl, bc + ld a, [hl] + +GetAnimationSpeed: + ld c, a + ld hl, PartyMonSpeeds + add hl, bc + ld a, [wOnSGB] + xor $1 + add [hl] + ld c, a + add a + ld b, a + ld a, [wAnimCounter] + and a + jr z, .resetSprites + cp c + jr z, .animateSprite +.incTimer + inc a + cp b + jr nz, .skipResetTimer + xor a ; reset timer +.skipResetTimer + ld [wAnimCounter], a + jp DelayFrame +.resetSprites + push bc + ld hl, wMonPartySpritesSavedOAM + ld de, wOAMBuffer + ld bc, $60 + call CopyData + pop bc + xor a + jr .incTimer +.animateSprite + push bc + ld hl, wOAMBuffer + $02 ; OAM tile id + ld bc, $10 + ld a, [wCurrentMenuItem] + call AddNTimes + ld c, ICONOFFSET + ld a, [hl] + cp ICON_BALL << 2 + jr z, .editCoords + cp ICON_HELIX << 2 + jr nz, .editTileIDS +; ICON_BALL and ICON_HELIX only shake up and down +.editCoords + dec hl + dec hl ; dec hl to the OAM y coord + ld c, $1 ; amount to increase the y coord by +; otherwise, load a second sprite frame +.editTileIDS + ld b, $4 + ld de, $4 +.loop + ld a, [hl] + add c + ld [hl], a + add hl, de + dec b + jr nz, .loop + pop bc + ld a, c + jr .incTimer + +; Party mon animations cycle between 2 frames. +; The members of the PartyMonSpeeds array specify the number of V-blanks +; that each frame lasts for green HP, yellow HP, and red HP in order. +; On the naming screen, the yellow HP speed is always used. +PartyMonSpeeds: + db 5, 16, 32 + +LoadMonPartySpriteGfx: +; Load mon party sprite tile patterns into VRAM during V-blank. + ld hl, MonPartySpritePointers + ld a, $1e + +LoadAnimSpriteGfx: +; Load animated sprite tile patterns into VRAM during V-blank. hl is the address +; of an array of structures that contain arguments for CopyVideoData and a is +; the number of structures in the array. + ld bc, $0 +.loop + push af + push bc + push hl + add hl, bc + ld a, [hli] + ld e, a + ld a, [hli] + ld d, a + ld a, [hli] + ld c, a + ld a, [hli] + ld b, a + ld a, [hli] + ld h, [hl] + ld l, a + call CopyVideoData + pop hl + pop bc + ld a, $6 + add c + ld c, a + pop af + dec a + jr nz, .loop + ret + +LoadMonPartySpriteGfxWithLCDDisabled: +; Load mon party sprite tile patterns into VRAM immediately by disabling the +; LCD. + call DisableLCD + ld hl, MonPartySpritePointers + ld a, $1e + ld bc, $0 +.loop + push af + push bc + push hl + add hl, bc + ld a, [hli] + ld e, a + ld a, [hli] + ld d, a + push de + ld a, [hli] + ld c, a + swap c + ld b, $0 + ld a, [hli] + ld e, [hl] + inc hl + ld d, [hl] + pop hl + call FarCopyData + pop hl + pop bc + ld a, $6 + add c + ld c, a + pop af + dec a + jr nz, .loop + jp EnableLCD + +INCLUDE "data/icon_pointers.asm" + +WriteMonPartySpriteOAMByPartyIndex: +; Write OAM blocks for the party mon in [hPartyMonIndex]. + push hl + push de + push bc + ldh a, [hPartyMonIndex] + cp $ff + jr z, .asm_7191f + ld hl, wPartySpecies + ld e, a + ld d, 0 + add hl, de + ld a, [hl] + call GetPartyMonSpriteID + ld [wOAMBaseTile], a + call WriteMonPartySpriteOAM + pop bc + pop de + pop hl + ret + +.asm_7191f + ld hl, wOAMBuffer + ld de, wMonPartySpritesSavedOAM + ld bc, $60 + call CopyData + pop bc + pop de + pop hl + ret + +WriteMonPartySpriteOAMBySpecies: +; Write OAM blocks for the party sprite of the species in +; [wMonPartySpriteSpecies]. + xor a + ldh [hPartyMonIndex], a + ld a, [wMonPartySpriteSpecies] + call GetPartyMonSpriteID + ld [wOAMBaseTile], a + jr WriteMonPartySpriteOAM + +UnusedPartyMonSpriteFunction: +; This function is unused and doesn't appear to do anything useful. It looks +; like it may have been intended to load the tile patterns and OAM data for +; the mon party sprite associated with the species in [wcf91]. +; However, its calculations are off and it loads garbage data. + ld a, [wcf91] + call GetPartyMonSpriteID + push af + ld hl, vSprites tile $00 + call .LoadTilePatterns + pop af + add $5A + ld hl, vSprites tile $04 + call .LoadTilePatterns + xor a + ld [wMonPartySpriteSpecies], a + jr WriteMonPartySpriteOAMBySpecies + +.LoadTilePatterns + push hl + add a + ld c, a + ld b, 0 + ld hl, MonPartySpritePointers + add hl, bc + add hl, bc + add hl, bc + ld a, [hli] + ld e, a + ld a, [hli] + ld d, a + ld a, [hli] + ld c, a + ld a, [hli] + ld b, a + pop hl + jp CopyVideoData + +WriteMonPartySpriteOAM: +; Write the OAM blocks for the first animation frame into the OAM buffer and +; make a copy at wMonPartySpritesSavedOAM. + push af + ld c, $10 + ld h, HIGH(wOAMBuffer) + ldh a, [hPartyMonIndex] + swap a + ld l, a + add $10 + ld b, a + pop af + cp ICON_HELIX << 2 + jr z, .helix + call WriteSymmetricMonPartySpriteOAM + jr .makeCopy +.helix + call WriteAsymmetricMonPartySpriteOAM +; Make a copy of the OAM buffer with the first animation frame written so that +; we can flip back to it from the second frame by copying it back. +.makeCopy + ld hl, wOAMBuffer + ld de, wMonPartySpritesSavedOAM + ld bc, $60 + jp CopyData + +GetPartyMonSpriteID: + ld [wd11e], a + predef IndexToPokedex + ld a, [wd11e] + ld c, a + dec a + srl a + ld hl, MonPartyData + ld e, a + ld d, 0 + add hl, de + ld a, [hl] + bit 0, c + jr nz, .skipSwap + swap a ; use lower nybble if pokedex num is even +.skipSwap + and $f0 + srl a ; value == ICON constant << 2 + srl a + ret + +INCLUDE "data/pokemon/menu_icons.asm" + +INC_FRAME_1 EQUS "0, $20" +INC_FRAME_2 EQUS "$20, $20" + +BugIconFrame1: INCBIN "gfx/icons/bug.2bpp", INC_FRAME_1 +PlantIconFrame1: INCBIN "gfx/icons/plant.2bpp", INC_FRAME_1 +BugIconFrame2: INCBIN "gfx/icons/bug.2bpp", INC_FRAME_2 +PlantIconFrame2: INCBIN "gfx/icons/plant.2bpp", INC_FRAME_2 +SnakeIconFrame1: INCBIN "gfx/icons/snake.2bpp", INC_FRAME_1 +QuadrupedIconFrame1: INCBIN "gfx/icons/quadruped.2bpp", INC_FRAME_1 +SnakeIconFrame2: INCBIN "gfx/icons/snake.2bpp", INC_FRAME_2 +QuadrupedIconFrame2: INCBIN "gfx/icons/quadruped.2bpp", INC_FRAME_2 + +TradeBubbleIconGFX: INCBIN "gfx/trade/bubble.2bpp" diff --git a/engine/gfx/oam_dma.asm b/engine/gfx/oam_dma.asm new file mode 100644 index 00000000..fe93e90d --- /dev/null +++ b/engine/gfx/oam_dma.asm @@ -0,0 +1,28 @@ +WriteDMACodeToHRAM:: +; Since no other memory is available during OAM DMA, +; DMARoutine is copied to HRAM and executed there. + ld c, LOW(hDMARoutine) + ld b, DMARoutineEnd - DMARoutine + ld hl, DMARoutine +.copy + ld a, [hli] + ldh [c], a + inc c + dec b + jr nz, .copy + ret + +DMARoutine: +LOAD "OAM DMA", HRAM +hDMARoutine:: + ; initiate DMA + ld a, HIGH(wOAMBuffer) + ldh [rDMA], a + ; wait for DMA to finish + ld a, $28 +.wait + dec a + jr nz, .wait + ret +ENDL +DMARoutineEnd: diff --git a/engine/gfx/palettes.asm b/engine/gfx/palettes.asm new file mode 100755 index 00000000..dd723afa --- /dev/null +++ b/engine/gfx/palettes.asm @@ -0,0 +1,1117 @@ +_RunPaletteCommand: + call GetPredefRegisters + ld a, b + cp SET_PAL_DEFAULT + jr nz, .not_default + ld a, [wDefaultPaletteCommand] +.not_default + cp SET_PAL_PARTY_MENU_HP_BARS + jp z, UpdatePartyMenuBlkPacket + ld l, a + ld h, 0 + add hl, hl + ld de, SetPalFunctions + add hl, de + ld a, [hli] + ld h, [hl] + ld l, a + ld de, SendSGBPackets + push de + jp hl + +SetPal_Black: + ld hl, PalPacket_Black + ld de, BlkPacket_Battle + ret + +; uses PalPacket_Empty to build a packet based on mon IDs and health color +SetPal_Battle: + ld hl, PalPacket_Empty + ld de, wPalPacket + ld bc, $10 + call CopyData + ;ld a, [wPlayerBattleStatus3] + ld hl, wBattleMonSpecies + ld a, [hl] + and a + jr z, .asm_71ef9 + ld hl, wPartyMon1 + ld a, [wPlayerMonNumber] + ld bc, wPartyMon2 - wPartyMon1 + call AddNTimes +.asm_71ef9 + call DeterminePaletteID + ld b, a + ;ld a, [wEnemyBattleStatus3] + ld hl, wEnemyMonSpecies2 + call DeterminePaletteID + ld c, a + ld hl, wPalPacket + 1 + ld a, [wPlayerHPBarColor] + add PAL_GREENBAR + ld [hli], a + inc hl + ld a, [wEnemyHPBarColor] + add PAL_GREENBAR + ld [hli], a + inc hl + ld a, b + ld [hli], a + inc hl + ld a, c + ld [hl], a + ld hl, wPalPacket + ld de, BlkPacket_Battle + ld a, SET_PAL_BATTLE + ld [wDefaultPaletteCommand], a + ret + +SetPal_TownMap: + ld hl, PalPacket_TownMap + ld de, BlkPacket_WholeScreen + ret + +; uses PalPacket_Empty to build a packet based the mon ID +SetPal_StatusScreen: + ld hl, PalPacket_Empty + ld de, wPalPacket + ld bc, $10 + call CopyData + ld a, [wcf91] + cp NUM_POKEMON_INDEXES + 1 + jr c, .pokemon + ld a, $1 ; not pokemon +.pokemon + call DeterminePaletteIDOutOfBattle + push af + ld hl, wPalPacket + 1 + ld a, [wStatusScreenHPBarColor] + add PAL_GREENBAR + ld [hli], a + inc hl + pop af + ld [hl], a + ld hl, wPalPacket + ld de, BlkPacket_StatusScreen + ret + +SetPal_PartyMenu: + ld hl, PalPacket_PartyMenu + ld de, wPartyMenuBlkPacket + ret + +SetPal_Pokedex: + ld hl, PalPacket_Pokedex + ld de, wPalPacket + ld bc, $10 + call CopyData + ld a, [wcf91] + call DeterminePaletteIDOutOfBattle + ld hl, wPalPacket + 3 + ld [hl], a + ld hl, wPalPacket + ld de, BlkPacket_Pokedex + ret + +SetPal_Slots: + ld hl, PalPacket_Slots + ld de, BlkPacket_Slots + ret + +SetPal_Titlescreen: + ld hl, PalPacket_Titlescreen + ld de, BlkPacket_Titlescreen + ret + +; used mostly for menus and the Oak intro +SetPal_Generic: + ld hl, PalPacket_Generic + ld de, BlkPacket_WholeScreen + ret + +SetPal_NidorinoIntro: + ld hl, PalPacket_NidorinoIntro + ld de, BlkPacket_NidorinoIntro + ret + +SetPal_GameFreakIntro: + ld hl, PalPacket_GameFreakIntro + ld de, BlkPacket_GameFreakIntro + ld a, SET_PAL_GENERIC + ld [wDefaultPaletteCommand], a + ret + +; uses PalPacket_Empty to build a packet based on the current map +SetPal_Overworld: + ld hl, PalPacket_Empty + ld de, wPalPacket + ld bc, $10 + call CopyData + ld a, [wCurMapTileset] + cp CEMETERY + jr z, .PokemonTowerOrAgatha + cp CAVERN + jr z, .caveOrBruno + ld a, [wCurMap] + cp FIRST_INDOOR_MAP + jr c, .townOrRoute + cp CERULEAN_CAVE_2F + jr c, .normalDungeonOrBuilding + cp CERULEAN_CAVE_1F + 1 + jr c, .caveOrBruno + cp LORELEIS_ROOM + jr z, .Lorelei + cp BRUNOS_ROOM + jr z, .caveOrBruno + cp TRADE_CENTER + jr z, .trade_center_colosseum + cp COLOSSEUM + jr z, .trade_center_colosseum +.normalDungeonOrBuilding + ld a, [wLastMap] ; town or route that current dungeon or building is located +.townOrRoute + cp NUM_CITY_MAPS + jr c, .town + ld a, PAL_ROUTE - 1 +.town + inc a ; a town's palette ID is its map ID + 1 + ld hl, wPalPacket + 1 + ld [hld], a + ld de, BlkPacket_WholeScreen + ld a, SET_PAL_OVERWORLD + ld [wDefaultPaletteCommand], a + ret +.PokemonTowerOrAgatha + ld a, PAL_GREYMON - 1 + jr .town +.caveOrBruno + ld a, PAL_CAVE - 1 + jr .town +.Lorelei + xor a + jr .town +.trade_center_colosseum + ld a, PAL_GREYMON - 1 + jr .town + +; used when a Pokemon is the only thing on the screen +; such as evolution, trading and the Hall of Fame +SetPal_PokemonWholeScreen: + push bc + ld hl, PalPacket_Empty + ld de, wPalPacket + ld bc, $10 + call CopyData + pop bc + ld a, c + and a + ld a, PAL_BLACK + jr nz, .next + ld a, [wWholeScreenPaletteMonSpecies] + call DeterminePaletteIDOutOfBattle +.next + ld [wPalPacket + 1], a + ld hl, wPalPacket + ld de, BlkPacket_WholeScreen + ret + +SetPal_TrainerCard: + ld hl, BlkPacket_TrainerCard + ld de, wTrainerCardBlkPacket + ld bc, $40 + call CopyData + ld de, BadgeBlkDataLengths + ld hl, wTrainerCardBlkPacket + 2 + ld a, [wObtainedBadges] + ld c, NUM_BADGES +.badgeLoop + srl a + push af + jr c, .haveBadge +; The player doens't have the badge, so zero the badge's blk data. + push bc + ld a, [de] + ld c, a + xor a +.zeroBadgeDataLoop + ld [hli], a + dec c + jr nz, .zeroBadgeDataLoop + pop bc + jr .nextBadge +.haveBadge +; The player does have the badge, so skip past the badge's blk data. + ld a, [de] +.skipBadgeDataLoop + inc hl + dec a + jr nz, .skipBadgeDataLoop +.nextBadge + pop af + inc de + dec c + jr nz, .badgeLoop + ld hl, PalPacket_TrainerCard + ld de, wTrainerCardBlkPacket + ret + +SendUnknownPalPacket_7205d:: + ld hl, UnknownPalPacket_72811 + ld de, BlkPacket_WholeScreen + ret + +SendUnknownPalPacket_72064:: + ld hl, UnknownPalPacket_72821 + ld de, UnknownPacket_72751 + ret + +SetPalFunctions: +; entries correspond to SET_PAL_* constants + dw SetPal_Black + dw SetPal_Battle + dw SetPal_TownMap + dw SetPal_StatusScreen + dw SetPal_Pokedex + dw SetPal_Slots + dw SetPal_Titlescreen + dw SetPal_NidorinoIntro + dw SetPal_Generic + dw SetPal_Overworld + dw SetPal_PartyMenu + dw SetPal_PokemonWholeScreen + dw SetPal_GameFreakIntro + dw SetPal_TrainerCard + dw SendUnknownPalPacket_7205d + dw SendUnknownPalPacket_72064 + +; The length of the blk data of each badge on the Trainer Card. +; The Rainbow Badge has 3 entries because of its many colors. +BadgeBlkDataLengths: + db 6 ; Boulder Badge + db 6 ; Cascade Badge + db 6 ; Thunder Badge + db 6 * 3 ; Rainbow Badge + db 6 ; Soul Badge + db 6 ; Marsh Badge + db 6 ; Volcano Badge + db 6 ; Earth Badge + +DeterminePaletteID: + ld a, [hl] +DeterminePaletteIDOutOfBattle: + ld [wd11e], a + and a ; is the mon index 0? + jr z, .skipDexNumConversion + push bc + predef IndexToPokedex + pop bc + ld a, [wd11e] +.skipDexNumConversion + ld e, a + ld d, 0 + ld hl, MonsterPalettes ; not just for Pokemon, Trainers use it too + add hl, de + ld a, [hl] + ret + +YellowIntroPaletteAction:: + ld a, e + and a + jr nz, .asm_720bd + ld hl, PalPacket_Generic + ldh a, [hGBC] + and a + jp z, SendSGBPacket + jp InitGBCPalettes + +.asm_720bd + ld hl, UnknownPalPacket_72811 + ldh a, [hGBC] + and a + jp z, SendSGBPacket + call InitGBCPalettes + ld hl, PalPacket_Generic + inc hl + ld a, [hli] + call GetGBCBasePalAddress + ld a, e + ld [wGBCBasePalPointers + 2], a + ld a, d + ld [wGBCBasePalPointers + 2 + 1], a + xor a ; CONVERT_BGP + call DMGPalToGBCPal + ld a, 1 + call TransferCurBGPData + ret + +LoadOverworldPikachuFrontpicPalettes:: + ld hl, PalPacket_Empty + ld de, wPalPacket + ld bc, $10 + call CopyData + call GetPal_Pikachu + ld hl, wPartyMenuBlkPacket + ld [hl], a + ld hl, wPartyMenuBlkPacket + 2 + ld a, $26 + ld [hl], a + ld hl, wPalPacket + ldh a, [hGBC] + and a + jr nz, .cgb_1 + call SendSGBPacket + jr .okay_1 + +.cgb_1 + call InitGBCPalettes +.okay_1 + ld hl, BlkPacket_WholeScreen + ld de, wPalPacket + ld bc, $10 + call CopyData + ld hl, wPartyMenuBlkPacket + 2 + ld a, $5 + ld [hli], a + ld a, $7 + ld [hli], a + ld a, $6 + ld [hli], a + ld a, $b + ld [hli], a + ld a, $a + ld [hl], a + ld hl, wPalPacket + ldh a, [hGBC] + and a + jr nz, .cgb_2 + call SendSGBPacket + jr .okay_2 + +.cgb_2 + call InitGBCPalettes +.okay_2 + ret + +GetPal_Pikachu:: +; similar to SetPal_Overworld + ld a, [wCurMapTileset] + cp CEMETERY + jr z, .PokemonTowerOrAgatha + cp CAVERN + jr z, .caveOrBruno + ld a, [wCurMap] + cp REDS_HOUSE_1F + jr c, .townOrRoute + cp CERULEAN_CAVE_2F + jr c, .normalDungeonOrBuilding + cp NAME_RATERS_HOUSE + jr c, .caveOrBruno + cp LORELEIS_ROOM + jr z, .Lorelei + cp BRUNOS_ROOM + jr z, .caveOrBruno + cp TRADE_CENTER + jr z, .battleOrTradeCenter + cp COLOSSEUM + jr z, .battleOrTradeCenter +.normalDungeonOrBuilding + ld a, [wLastMap] ; town or route that current dungeon or building is located +.townOrRoute + cp SAFFRON_CITY + 1 + jr c, .town + ld a, PAL_ROUTE - 1 +.town + inc a ; a town's pallete ID is its map ID + 1 + ret + +.PokemonTowerOrAgatha + ld a, PAL_GREYMON - 1 + jr .town + +.caveOrBruno + ld a, PAL_CAVE - 1 + jr .town + +.Lorelei + xor a ; PAL_PALLET - 1 + jr .town + +.battleOrTradeCenter + ld a, PAL_GREYMON - 1 + jr .town + +InitPartyMenuBlkPacket: + ld hl, BlkPacket_PartyMenu + ld de, wPartyMenuBlkPacket + ld bc, $30 + jp CopyData + +UpdatePartyMenuBlkPacket: +; Update the blk packet with the palette of the HP bar that is +; specified in [wWhichPartyMenuHPBar]. + ld hl, wPartyMenuHPBarColors + ld a, [wWhichPartyMenuHPBar] + ld e, a + ld d, 0 + add hl, de + ld e, l + ld d, h + ld a, [de] + and a + ld e, (1 << 2) | 1 ; green + jr z, .next + dec a + ld e, (2 << 2) | 2 ; yellow + jr z, .next + ld e, (3 << 2) | 3 ; red +.next + push de + ld hl, wPartyMenuBlkPacket + 8 + 1 + ld bc, 6 + ld a, [wWhichPartyMenuHPBar] + call AddNTimes + pop de + ld [hl], e + ret + +SendSGBPacket: + ld a, 1 + ldh [hDisableJoypadPolling], a ; don't poll joypad while sending packet + call _SendSGBPacket + xor a + ldh [hDisableJoypadPolling], a + ret + +_SendSGBPacket: +;check number of packets + ld a, [hl] + and $07 + ret z +; store number of packets in B + ld b, a +.loop2 +; save B for later use + push bc +; send RESET signal (P14=LOW, P15=LOW) + xor a + ldh [rJOYP], a +; set P14=HIGH, P15=HIGH + ld a, $30 + ldh [rJOYP], a +;load length of packets (16 bytes) + ld b, $10 +.nextByte +;set bit counter (8 bits per byte) + ld e, $08 +; get next byte in the packet + ld a, [hli] + ld d, a +.nextBit0 + bit 0, d +; if 0th bit is not zero set P14=HIGH, P15=LOW (send bit 1) + ld a, $10 + jr nz, .next0 +; else (if 0th bit is zero) set P14=LOW, P15=HIGH (send bit 0) + ld a, $20 +.next0 + ldh [rJOYP], a +; must set P14=HIGH,P15=HIGH between each "pulse" + ld a, $30 + ldh [rJOYP], a +; rotation will put next bit in 0th position (so we can always use command +; "bit 0, d" to fetch the bit that has to be sent) + rr d +; decrease bit counter so we know when we have sent all 8 bits of current byte + dec e + jr nz, .nextBit0 + dec b + jr nz, .nextByte +; send bit 1 as a "stop bit" (end of parameter data) + ld a, $20 + ldh [rJOYP], a +; set P14=HIGH,P15=HIGH + ld a, $30 + ldh [rJOYP], a +; wait for about 70000 cycles + call Wait7000 +; restore (previously pushed) number of packets + pop bc + dec b +; return if there are no more packets + ret z +; else send 16 more bytes + jr .loop2 + +LoadSGB: + xor a + ld [wOnSGB], a + call CheckSGB + jr c, .onSGB + ldh a, [hGBC] + and a + jr z, .onDMG + ld a, $1 + ld [wOnSGB], a +.onDMG + ret +.onSGB + ld a, $1 + ld [wOnSGB], a + di + call PrepareSuperNintendoVRAMTransfer + ei + ld a, 1 + ld [wCopyingSGBTileData], a + ld de, ChrTrnPacket + ld hl, SGBBorderGraphics + call CopyGfxToSuperNintendoVRAM + xor a + ld [wCopyingSGBTileData], a + ld de, PctTrnPacket + ld hl, BorderPalettes + call CopyGfxToSuperNintendoVRAM + xor a + ld [wCopyingSGBTileData], a + ld de, PalTrnPacket + ld hl, SuperPalettes + call CopyGfxToSuperNintendoVRAM + call ClearVram + ld hl, MaskEnCancelPacket + jp SendSGBPacket + +PrepareSuperNintendoVRAMTransfer: + ld hl, .packetPointers + ld c, 9 +.loop + push bc + ld a, [hli] + push hl + ld h, [hl] + ld l, a + call SendSGBPacket + pop hl + inc hl + pop bc + dec c + jr nz, .loop + ret + +.packetPointers +; Only the first packet is needed. + dw MaskEnFreezePacket + dw DataSnd_728a1 + dw DataSnd_728b1 + dw DataSnd_728c1 + dw DataSnd_728d1 + dw DataSnd_728e1 + dw DataSnd_728f1 + dw DataSnd_72901 + dw DataSnd_72911 + +CheckSGB: +; Returns whether the game is running on an SGB in carry. + ld hl, MltReq2Packet + call SendSGBPacket + call Wait7000 + ldh a, [rJOYP] + and $3 + cp $3 + jr nz, .isSGB + ld a, $20 + ldh [rJOYP], a + ldh a, [rJOYP] + ldh a, [rJOYP] + call Wait7000 + call Wait7000 + ld a, $30 + ldh [rJOYP], a + call Wait7000 + call Wait7000 + ld a, $10 + ldh [rJOYP], a + ldh a, [rJOYP] + ldh a, [rJOYP] + ldh a, [rJOYP] + ldh a, [rJOYP] + ldh a, [rJOYP] + ldh a, [rJOYP] + call Wait7000 + call Wait7000 + ld a, $30 + ldh [rJOYP], a + ldh a, [rJOYP] + ldh a, [rJOYP] + ldh a, [rJOYP] + call Wait7000 + call Wait7000 + ldh a, [rJOYP] + and $3 + cp $3 + jr nz, .isSGB + call SendMltReq1Packet + and a + ret +.isSGB + call SendMltReq1Packet + scf + ret + +SendMltReq1Packet: + ld hl, MltReq1Packet + call SendSGBPacket + jp Wait7000 + +CopyGfxToSuperNintendoVRAM: + di + push de + call DisableLCD + ld a, $e4 + ldh [rBGP], a + call _UpdateGBCPal_BGP_CheckDMG + ld de, vChars1 + ld a, [wCopyingSGBTileData] + and a + jr z, .notCopyingTileData + call CopySGBBorderTiles + jr .next +.notCopyingTileData + ld bc, $1000 + call CopyData +.next + ld hl, vBGMap0 + ld de, $c + ld a, $80 + ld c, $d +.loop + ld b, $14 +.innerLoop + ld [hli], a + inc a + dec b + jr nz, .innerLoop + add hl, de + dec c + jr nz, .loop + ld a, $e3 + ldh [rLCDC], a + pop hl + call SendSGBPacket + xor a + ldh [rBGP], a + call _UpdateGBCPal_BGP_CheckDMG + ei + ret + +Wait7000: +; Each loop takes 9 cycles so this routine actually waits 63000 cycles. + ld de, 7000 +.loop + nop + nop + nop + dec de + ld a, d + or e + jr nz, .loop + ret + +SendSGBPackets: + ldh a, [hGBC] + and a + jr z, .notGBC + push de + call InitGBCPalettes + pop hl + call InitGBCPalettes + ldh a, [rLCDC] + and rLCDC_ENABLE_MASK + ret z + call Delay3 + ret +.notGBC + push de + call SendSGBPacket + pop hl + jp SendSGBPacket + +InitGBCPalettes: + ld a, [hl] + and $f8 + cp $20 + jp z, TranslatePalPacketToBGMapAttributes + + inc hl + +index = 0 + + REPT NUM_ACTIVE_PALS + IF index > 0 + pop hl + ENDC + + ld a, [hli] + inc hl + + IF index < (NUM_ACTIVE_PALS + -1) + push hl + ENDC + + call GetGBCBasePalAddress + ld a, e + ld [wGBCBasePalPointers + index * 2], a + ld a, d + ld [wGBCBasePalPointers + index * 2 + 1], a + + xor a ; CONVERT_BGP + call DMGPalToGBCPal + ld a, index + call TransferCurBGPData + + ld a, CONVERT_OBP0 + call DMGPalToGBCPal + ld a, index + call TransferCurOBPData + + ld a, CONVERT_OBP1 + call DMGPalToGBCPal + ld a, index + 4 + call TransferCurOBPData + +index = index + 1 + ENDR + + ret + +GetGBCBasePalAddress:: +; Input: a = palette ID +; Output: de = palette address + push hl + ld l, a + xor a + ld h, a + add hl, hl + add hl, hl + add hl, hl + ld de, GBCBasePalettes + add hl, de + ld a, l + ld e, a + ld a, h + ld d, a + pop hl + ret + +DMGPalToGBCPal:: +; Populate wGBCPal with colors from a base palette, selected using one of the +; DMG palette registers. +; Input: +; a = which DMG palette register +; de = address of GBC base palette + and a + jr nz, .notBGP + ldh a, [rBGP] + ld [wLastBGP], a + jr .convert +.notBGP + dec a + jr nz, .notOBP0 + ldh a, [rOBP0] + ld [wLastOBP0], a + jr .convert +.notOBP0 + ldh a, [rOBP1] + ld [wLastOBP1], a +.convert +color_index = 0 + REPT NUM_COLORS + ld b, a + and %11 + call .GetColorAddress + ld a, [hli] + ld [wGBCPal + color_index * 2], a + ld a, [hl] + ld [wGBCPal + color_index * 2 + 1], a + + IF color_index < (NUM_COLORS + -1) + ld a, b + rrca + rrca + ENDC + +color_index = color_index + 1 + ENDR + ret + +.GetColorAddress: + add a + ld l, a + xor a + ld h, a + add hl, de + ret + +TransferCurBGPData:: + push de + add a + add a + add a + or $80 ; auto-increment + ldh [rBGPI], a + ld de, rBGPD + ld hl, wGBCPal + ld b, %10 ; mask for non-V-blank/non-H-blank STAT mode + ldh a, [rLCDC] + and rLCDC_ENABLE_MASK + jr nz, .lcdEnabled + rept NUM_COLORS + call TransferPalColorLCDDisabled + endr + jr .done +.lcdEnabled + rept NUM_COLORS + call TransferPalColorLCDEnabled + endr +.done + pop de + ret + +BufferBGPPal:: +; Copy wGBCPal to palette a in wBGPPalsBuffer. + push de + add a + add a + add a + ld l, a + xor a + ld h, a + ld de, wBGPPalsBuffer + add hl, de + ld de, wGBCPal + ld c, PAL_SIZE +.loop + ld a, [de] + ld [hli], a + inc de + dec c + jr nz, .loop + pop de + ret + +TransferBGPPals:: +; Transfer the buffered BG palettes. + ldh a, [rLCDC] + and rLCDC_ENABLE_MASK + jr z, .lcdDisabled + di +.waitLoop + ldh a, [rLY] + cp 144 + jr c, .waitLoop +.lcdDisabled + call .DoTransfer + ei + ret + +.DoTransfer: + xor a + or $80 ; auto-increment + ldh [rBGPI], a + ld de, rBGPD + ld hl, wBGPPalsBuffer + ld c, 4 * PAL_SIZE +.loop + ld a, [hli] + ld [de], a + dec c + jr nz, .loop + ret + +TransferCurOBPData: + push de + add a + add a + add a + or $80 ; auto-increment + ldh [rOBPI], a + ld de, rOBPD + ld hl, wGBCPal + ld b, %10 ; mask for non-V-blank/non-H-blank STAT mode + ldh a, [rLCDC] + and rLCDC_ENABLE_MASK + jr nz, .lcdEnabled + rept NUM_COLORS + call TransferPalColorLCDDisabled + endr + jr .done +.lcdEnabled + rept NUM_COLORS + call TransferPalColorLCDEnabled + endr +.done + pop de + ret + +TransferPalColorLCDEnabled: +; Transfer a palette color while the LCD is enabled. + +; In case we're already in H-blank or V-blank, wait for it to end. This is a +; precaution so that the transfer doesn't extend past the blanking period. + ldh a, [rSTAT] + and b + jr z, TransferPalColorLCDEnabled + +; Wait for H-blank or V-blank to begin. +.notInBlankingPeriod + ldh a, [rSTAT] + and b + jr nz, .notInBlankingPeriod +; fall through + +TransferPalColorLCDDisabled: +; Transfer a palette color while the LCD is disabled. + ld a, [hli] + ld [de], a + ld a, [hli] + ld [de], a + ret + +_UpdateGBCPal_BGP_CheckDMG:: + ldh a, [hGBC] + and a + ret z +; fall through + +_UpdateGBCPal_BGP:: +index = 0 + + REPT NUM_ACTIVE_PALS + ld a, [wGBCBasePalPointers + index * 2] + ld e, a + ld a, [wGBCBasePalPointers + index * 2 + 1] + ld d, a + xor a ; CONVERT_BGP + call DMGPalToGBCPal + ld a, index + call BufferBGPPal + +index = index + 1 + ENDR + + call TransferBGPPals + ret + +_UpdateGBCPal_OBP:: +index = 0 + + REPT NUM_ACTIVE_PALS + ld a, [wGBCBasePalPointers + index * 2] + ld e, a + ld a, [wGBCBasePalPointers + index * 2 + 1] + ld d, a + ld a, c + call DMGPalToGBCPal + ld a, c + dec a + rlca + rlca + + IF index > 0 + IF index == 1 + inc a + ELSE + add index + ENDC + ENDC + + call TransferCurOBPData + +index = index + 1 + ENDR + + ret + +TranslatePalPacketToBGMapAttributes:: +; translate the SGB pal packets into something usable for the GBC + push hl + pop de + ld hl, PalPacketPointers + ld a, [hli] + ld c, a +.loop + ld a, e +.innerLoop + cp [hl] + jr z, .checkHighByte + inc hl + inc hl + dec c + jr nz, .innerLoop + ret +.checkHighByte +; the low byte of pointer matched, so check the high byte + inc hl + ld a, d + cp [hl] + jr z, .foundMatchingPointer + inc hl + dec c + jr nz, .loop + ret +.foundMatchingPointer + farcall LoadBGMapAttributes + ret + +PalPacketPointers:: + db (palPacketPointersEnd - palPacketPointers) / 2 +palPacketPointers: + dw BlkPacket_WholeScreen + dw BlkPacket_Battle + dw BlkPacket_StatusScreen + dw BlkPacket_Pokedex + dw BlkPacket_Slots + dw BlkPacket_Titlescreen + dw BlkPacket_NidorinoIntro + dw wPartyMenuBlkPacket + dw wTrainerCardBlkPacket + dw BlkPacket_GameFreakIntro + dw wPalPacket + dw UnknownPacket_72751 +palPacketPointersEnd: + +CopySGBBorderTiles: +; SGB tile data is stored in a 4BPP planar format. +; Each tile is 32 bytes. The first 16 bytes contain bit planes 1 and 2, while +; the second 16 bytes contain bit planes 3 and 4. +; This function converts 2BPP planar data into this format by mapping +; 2BPP colors 0-3 to 4BPP colors 0-3. 4BPP colors 4-15 are not used. + ld b, 128 +.tileLoop +; Copy bit planes 1 and 2 of the tile data. + ld c, 16 +.copyLoop + ld a, [hli] + ld [de], a + inc de + dec c + jr nz, .copyLoop + +; Zero bit planes 3 and 4. + ld c, 16 + xor a +.zeroLoop + ld [de], a + inc de + dec c + jr nz, .zeroLoop + + dec b + jr nz, .tileLoop + ret + +INCLUDE "data/sgb/sgb_packets.asm" + +INCLUDE "data/pokemon/palettes.asm" + +INCLUDE "data/sgb/sgb_palettes.asm" + +INCLUDE "data/sgb/sgb_border.asm" diff --git a/engine/gfx/screen_effects.asm b/engine/gfx/screen_effects.asm new file mode 100644 index 00000000..973a951a --- /dev/null +++ b/engine/gfx/screen_effects.asm @@ -0,0 +1,73 @@ +; inverts the BGP for 4 (6 on CGB due to lag) frames +ChangeBGPalColor0_4Frames: + call GetPredefRegisters ; leftover of red/blue, has no use here + ldh a, [rBGP] + xor $ff + ldh [rBGP], a + call UpdateGBCPal_BGP + ld c, 4 + call DelayFrames + ldh a, [rBGP] + xor $ff + ldh [rBGP], a + call UpdateGBCPal_BGP + ret + +PredefShakeScreenVertically: +; Moves the window down and then back in a sequence of progressively smaller +; numbers of pixels, starting at b. + call GetPredefRegisters + ld a, 1 + ld [wDisableVBlankWYUpdate], a + xor a +.loop + ldh [hMutateWY], a + call .MutateWY + call .MutateWY + dec b + ld a, b + jr nz, .loop + xor a + ld [wDisableVBlankWYUpdate], a + ret + +.MutateWY + ldh a, [hMutateWY] + xor b + ldh [hMutateWY], a + ldh [rWY], a + ld c, 3 + jp DelayFrames + +PredefShakeScreenHorizontally: +; Moves the window right and then back in a sequence of progressively smaller +; numbers of pixels, starting at b. + call GetPredefRegisters + xor a +.loop + ldh [hMutateWX], a + call .MutateWX + ld c, 1 + call DelayFrames + call .MutateWX + dec b + ld a, b + jr nz, .loop + +; restore normal WX + ld a, 7 + ldh [rWX], a + ret + +.MutateWX + ldh a, [hMutateWX] + xor b + ldh [hMutateWX], a + bit 7, a + jr z, .skipZeroing + xor a ; zero a if it's negative +.skipZeroing + add 7 + ldh [rWX], a + ld c, 4 + jp DelayFrames diff --git a/engine/gfx/sprite_oam.asm b/engine/gfx/sprite_oam.asm new file mode 100644 index 00000000..01b2c412 --- /dev/null +++ b/engine/gfx/sprite_oam.asm @@ -0,0 +1,232 @@ +PrepareOAMData:: +; Determine OAM data for currently visible +; sprites and write it to wOAMBuffer. +; Yellow code has been changed to use registers more efficiently +; as well as tweaking the code to show gbc palettes + + ld a, [wUpdateSpritesEnabled] + dec a + jr z, .updateEnabled + + cp -1 + ret nz + ld [wUpdateSpritesEnabled], a + jp HideSprites + +.updateEnabled + xor a + ldh [hOAMBufferOffset], a + +.spriteLoop + ldh [hSpriteOffset2], a + + ld e, a + ld d, HIGH(wSpriteStateData1) + + ld a, [de] ; [x#SPRITESTATEDATA1_PICTUREID] + and a + jp z, .nextSprite + + inc e + inc e + ld a, [de] ; [x#SPRITESTATEDATA1_IMAGEINDEX] + ld [wd5cd], a + cp $ff ; off-screen (don't draw) + jr nz, .visible + + call GetSpriteScreenXY + jr .nextSprite + +.visible + cp $a0 ; is the sprite unchanging like an item ball or boulder? + jr c, .usefacing + +; unchanging + ld a, $0 + jr .next + +.usefacing + and $f + +.next +; read the entry from the table + ld c, a + ld b, 0 + ld hl, SpriteFacingAndAnimationTable + add hl, bc + add hl, bc + ld a, [hli] + ld h, [hl] + ld l, a +; get sprite priority + push de + inc d + ld a, e + add $5 + ld e, a + ld a, [de] ; [x#SPRITESTATEDATA2_GRASSPRIORITY] + and $80 + ldh [hSpritePriority], a ; temp store sprite priority + pop de + + + call GetSpriteScreenXY + + ldh a, [hOAMBufferOffset] + add [hl] + cp $a0 + jr z, .hidden + jr nc, .asm_4a41 +.hidden + call Func_4a7b + ld [wd5cd], a + ldh a, [hOAMBufferOffset] + + ld e, a + ld d, HIGH(wOAMBuffer) + +.tileLoop + ld a, [hli] + ld c, a +.loop + ldh a, [hSpriteScreenY] ; temp for sprite Y position + add $10 ; Y=16 is top of screen (Y=0 is invisible) + add [hl] ; add Y offset from table + ld [de], a ; write new sprite OAM Y position + inc hl + inc e + ldh a, [hSpriteScreenX] ; temp for sprite X position + add $8 ; X=8 is left of screen (X=0 is invisible) + add [hl] ; add X offset from table + ld [de], a + inc hl + inc e + ld a, [wd5cd] + add [hl] + cp $80 + jr c, .asm_4a1c + ld b, a + ldh a, [hFFFC] + add b +.asm_4a1c + ld [de], a ; tile id + inc hl + inc e + ld a, [hl] + bit 1, a ; is the tile allowed to set the sprite priority bit? + jr z, .skipPriority + ldh a, [hSpritePriority] + or [hl] +.skipPriority + and $f0 + bit 4, a ; OBP0 or OBP1 + jr z, .spriteusesOBP0 + or %100 ; palettes 4-7 are OBP1 +.spriteusesOBP0 + ld [de], a + inc hl + inc e + dec c + jr nz, .loop + + ld a, e + ldh [hOAMBufferOffset], a +.nextSprite + ldh a, [hSpriteOffset2] + add $10 + cp LOW($100) + jp nz, .spriteLoop + + ; Clear unused OAM. +.asm_4a41 + ld a, [wd736] + bit 6, a ; jumping down ledge or fishing animation? + ld c, $a0 + jr z, .clear + +; Don't clear the last 4 entries because they are used for the shadow in the +; jumping down ledge animation and the rod in the fishing animation. + ld c, $90 + +.clear + ldh a, [hOAMBufferOffset] + cp c + ret nc + ld l, a + ld h, wOAMBuffer / $100 + ld a, c + ld de, $4 ; entry size + ld b, $a0 +.clearLoop + ld [hl], b + add hl, de + cp l + jr nz, .clearLoop + ret + +GetSpriteScreenXY: + inc e + inc e + ld a, [de] ; [x#SPRITESTATEDATA1_YPIXELS] + ldh [hSpriteScreenY], a + inc e + inc e + ld a, [de] ; [x#SPRITESTATEDATA1_XPIXELS] + ldh [hSpriteScreenX], a + ld a, 4 + add e + ld e, a + ldh a, [hSpriteScreenY] + add 4 + and $f0 + ld [de], a ; [x#SPRITESTATEDATA1_YADJUSTED] + inc e + ldh a, [hSpriteScreenX] + and $f0 + ld [de], a ; [x#SPRITESTATEDATA1_XADJUSTED] + ret + +Func_4a7b: + push bc + ld a, [wd5cd] ; temp copy of [x#SPRITESTATEDATA1_IMAGEINDEX] + swap a ; high nybble determines sprite used (0 is always player sprite, next are some npcs) + and $f + + ; Sprites $a and $b have one face (and therefore 4 tiles instead of 12). + ; As a result, sprite $b's tile offset is less than normal. + cp $b + jr nz, .notFourTileSprite + ld a, $a * 12 + 4 ; $7c + jr .done + +.notFourTileSprite + ; a *= 12 + add a + add a + ld c, a + add a + add c +.done + pop bc + ret + +INCLUDE "engine/gfx/oam_dma.asm" + +_IsTilePassable:: + ld hl, wTilesetCollisionPtr ; pointer to list of passable tiles + ld a, [hli] + ld h, [hl] + ld l, a ; hl now points to passable tiles +.loop + ld a, [hli] + cp a, $ff + jr z, .tileNotPassable + cp c + jr nz, .loop + xor a + ret +.tileNotPassable + scf + ret + +INCLUDE "data/tilesets/collision_tile_ids.asm" diff --git a/engine/give_pokemon.asm b/engine/give_pokemon.asm deleted file mode 100755 index 6fdca2ef..00000000 --- a/engine/give_pokemon.asm +++ /dev/null @@ -1,87 +0,0 @@ -_GivePokemon: -; returns success in carry -; and whether the mon was added to the party in [wAddedToParty] - call EnableAutoTextBoxDrawing - xor a - ld [wAddedToParty], a - ld a, [wPartyCount] - cp PARTY_LENGTH - jr c, .addToParty - ld a, [wNumInBox] - cp MONS_PER_BOX - jr nc, .boxFull -; add to box - xor a - ld [wEnemyBattleStatus3], a - ld a, [wcf91] - ld [wEnemyMonSpecies2], a - callab LoadEnemyMonData - call SetPokedexOwnedFlag - callab SendNewMonToBox - ld hl, wcf4b - ld a, [wCurrentBoxNum] - and $7f - cp 9 - jr c, .singleDigitBoxNum - sub 9 - ld [hl], "1" - inc hl - add "0" - jr .next -.singleDigitBoxNum - add "1" -.next - ld [hli], a - ld [hl], "@" - ld hl, SetToBoxText - call PrintText - scf - ret -.boxFull - ld hl, BoxIsFullText - call PrintText - and a - ret -.addToParty - call SetPokedexOwnedFlag - ld hl, UnknownTerminator_f6794 - call PrintText - call AddPartyMon - ld a, 1 - ld [wDoNotWaitForButtonPressAfterDisplayingText], a - ld [wAddedToParty], a - scf - ret - -SetPokedexOwnedFlag: - ld a, [wcf91] - push af - ld [wd11e], a - predef IndexToPokedex - ld a, [wd11e] - dec a - ld c, a - ld hl, wPokedexOwned - ld b, FLAG_SET - predef FlagActionPredef - pop af - ld [wd11e], a - call GetMonName - ld hl, GotMonText - jp PrintText - -UnknownTerminator_f6794: - db "@" - -GotMonText: - TX_FAR _GotMonText - TX_SFX_ITEM_1 - db "@" - -SetToBoxText: - TX_FAR _SetToBoxText - db "@" - -BoxIsFullText: - TX_FAR _BoxIsFullText - db "@" diff --git a/engine/hall_of_fame.asm b/engine/hall_of_fame.asm deleted file mode 100755 index 39a7a2e3..00000000 --- a/engine/hall_of_fame.asm +++ /dev/null @@ -1,303 +0,0 @@ -AnimateHallOfFame: - call HoFFadeOutScreenAndMusic - call ClearScreen - ld c, 100 - call DelayFrames - call LoadFontTilePatterns - call LoadTextBoxTilePatterns - call DisableLCD - ld hl, vBGMap0 - ld bc, $800 - ld a, " " - call FillMemory - call EnableLCD - ld hl, rLCDC - set 3, [hl] - xor a - ld hl, wHallOfFame - ld bc, HOF_TEAM - call FillMemory - xor a - ld [wUpdateSpritesEnabled], a - ld [hTilesetType], a - ld [wSpriteFlipped], a - ld [wLetterPrintingDelayFlags], a ; no delay - ld [wHoFMonOrPlayer], a ; mon - inc a - ld [H_AUTOBGTRANSFERENABLED], a - ld hl, wNumHoFTeams - ld a, [hl] - inc a - jr z, .skipInc ; don't wrap around to 0 - inc [hl] -.skipInc - ld a, $90 - ld [hWY], a - ld c, BANK(Music_HallOfFame) - ld a, MUSIC_HALL_OF_FAME - call PlayMusic - ld hl, wPartySpecies - ld c, $ff -.partyMonLoop - ld a, [hli] - cp $ff - jr z, .doneShowingParty - inc c - push hl - push bc - ld [wHoFMonSpecies], a - ld a, c - ld [wHoFPartyMonIndex], a - ld hl, wPartyMon1Level - ld bc, wPartyMon2 - wPartyMon1 - call AddNTimes - ld a, [hl] - ld [wHoFMonLevel], a - call HoFShowMonOrPlayer - call HoFDisplayAndRecordMonInfo - ld c, 80 - call DelayFrames - coord hl, 2, 13 - lb bc, 3, 14 - call TextBoxBorder - coord hl, 4, 15 - ld de, HallOfFameText - call PlaceString - ld c, 180 - call DelayFrames - call GBFadeOutToWhite - pop bc - pop hl - jr .partyMonLoop -.doneShowingParty - ld a, c - inc a - ld hl, wHallOfFame - ld bc, HOF_MON - call AddNTimes - ld [hl], $ff - callab SaveHallOfFameTeams ; useless since in same bank - xor a - ld [wHoFMonSpecies], a - inc a - ld [wHoFMonOrPlayer], a ; player - call HoFShowMonOrPlayer - call HoFDisplayPlayerStats - call HoFFadeOutScreenAndMusic - xor a - ld [hWY], a - ld hl, rLCDC - res 3, [hl] - ret - -HallOfFameText: - db "HALL OF FAME@" - -HoFShowMonOrPlayer: - call ClearScreen - ld a, $d0 - ld [hSCY], a - ld a, $c0 - ld [hSCX], a - ld a, [wHoFMonSpecies] - ld [wcf91], a - ld [wd0b5], a - ld [wBattleMonSpecies2], a - ld [wWholeScreenPaletteMonSpecies], a - ld a, [wHoFMonOrPlayer] - and a - jr z, .showMon -; show player - call HoFLoadPlayerPics - jr .next1 -.showMon - coord hl, 12, 5 - call GetMonHeader - call LoadFrontSpriteByMonIndex - predef LoadMonBackPic -.next1 - ld b, SET_PAL_POKEMON_WHOLE_SCREEN - ld c, 0 - call RunPaletteCommand - ld a, %11100100 - ld [rBGP], a - call UpdateGBCPal_BGP - ld c, $31 ; back pic - call HoFLoadMonPlayerPicTileIDs - ld d, $a0 - ld e, 4 - ld a, [wOnSGB] - and a - jr z, .next2 - sla e ; scroll more slowly on SGB -.next2 - call .ScrollPic ; scroll back pic left - xor a - ld [hSCY], a - ld c, a ; front pic - call HoFLoadMonPlayerPicTileIDs - ld d, 0 - ld e, -4 -; scroll front pic right - -.ScrollPic - call DelayFrame - ld a, [hSCX] - add e - ld [hSCX], a - cp d - jr nz, .ScrollPic - ret - -HoFDisplayAndRecordMonInfo: - ld a, [wHoFPartyMonIndex] - ld hl, wPartyMonNicks - call GetPartyMonName - call HoFDisplayMonInfo - ld a, [wHoFPartyMonIndex] - ld [wWhichPokemon], a - callab IsThisPartymonStarterPikachu_Party - jr nc, .asm_70336 - ld e, $22 - callab PlayPikachuSoundClip - jr .asm_7033c -.asm_70336 - ld a,[wHoFMonSpecies] - call PlayCry -.asm_7033c - jp HoFRecordMonInfo - -Func_7033f: - call HoFDisplayMonInfo - ld a,[wHoFMonSpecies] - jp PlayCry - -HoFDisplayMonInfo: - coord hl, 0, 2 - lb bc, 9, 10 - call TextBoxBorder - coord hl, 2, 6 - ld de, HoFMonInfoText - call PlaceString - coord hl, 1, 4 - ld de, wcd6d - call PlaceString - ld a, [wHoFMonLevel] - coord hl, 8, 7 - call PrintLevelCommon - ld a, [wHoFMonSpecies] - ld [wd0b5], a - coord hl, 3, 9 - predef PrintMonType - ret - -HoFMonInfoText: - db "LEVEL/" - next "TYPE1/" - next "TYPE2/@" - -HoFLoadPlayerPics: - ld de, RedPicFront - ld a, BANK(RedPicFront) - call UncompressSpriteFromDE - ld a,$0 - call SwitchSRAMBankAndLatchClockData - ld hl, sSpriteBuffer1 - ld de, sSpriteBuffer0 - ld bc, $310 - call CopyData - call PrepareRTCDataAndDisableSRAM - ld de, vFrontPic - call InterlaceMergeSpriteBuffers - ld de, RedPicBack - ld a, BANK(RedPicBack) - call UncompressSpriteFromDE - predef ScaleSpriteByTwo - ld de, vBackPic - call InterlaceMergeSpriteBuffers - ld c, $1 - -HoFLoadMonPlayerPicTileIDs: -; c = base tile ID - ld b, 0 - coord hl, 12, 5 - predef_jump CopyTileIDsFromList - -HoFDisplayPlayerStats: - SetEvent EVENT_HALL_OF_FAME_DEX_RATING - predef DisplayDexRating - coord hl, 0, 4 - lb bc, 6, 10 - call TextBoxBorder - coord hl, 5, 0 - lb bc, 2, 9 - call TextBoxBorder - coord hl, 7, 2 - ld de, wPlayerName - call PlaceString - coord hl, 1, 6 - ld de, HoFPlayTimeText - call PlaceString - coord hl, 5, 7 - ld de, wPlayTimeHours - lb bc, 1, 3 - call PrintNumber - ld [hl], $6d - inc hl - ld de, wPlayTimeMinutes - lb bc, LEADING_ZEROES | 1, 2 - call PrintNumber - coord hl, 1, 9 - ld de, HoFMoneyText - call PlaceString - coord hl, 4, 10 - ld de, wPlayerMoney - ld c, $a3 - call PrintBCDNumber - ld hl, DexSeenOwnedText - call HoFPrintTextAndDelay - ld hl, DexRatingText - call HoFPrintTextAndDelay - ld hl, wDexRatingText - -HoFPrintTextAndDelay: - call PrintText - ld c, 120 - jp DelayFrames - -HoFPlayTimeText: - db "PLAY TIME@" - -HoFMoneyText: - db "MONEY@" - -DexSeenOwnedText: - TX_FAR _DexSeenOwnedText - db "@" - -DexRatingText: - TX_FAR _DexRatingText - db "@" - -HoFRecordMonInfo: - ld hl, wHallOfFame - ld bc, HOF_MON - ld a, [wHoFPartyMonIndex] - call AddNTimes - ld a, [wHoFMonSpecies] - ld [hli], a - ld a, [wHoFMonLevel] - ld [hli], a - ld e, l - ld d, h - ld hl, wcd6d - ld bc, NAME_LENGTH - jp CopyData - -HoFFadeOutScreenAndMusic: - ld a, 10 - ld [wAudioFadeOutCounterReloadValue], a - ld [wAudioFadeOutCounter], a - ld a, $ff - ld [wAudioFadeOutControl], a - jp GBFadeOutToWhite diff --git a/engine/heal_party.asm b/engine/heal_party.asm deleted file mode 100644 index 7aaa1bd1..00000000 --- a/engine/heal_party.asm +++ /dev/null @@ -1,99 +0,0 @@ -HealParty: -; Restore HP and PP. - - ld hl, wPartySpecies - ld de, wPartyMon1HP -.healmon - ld a, [hli] - cp $ff - jr z, .done - - push hl - push de - - ld hl, wPartyMon1Status - wPartyMon1HP - add hl, de - xor a - ld [hl], a - - push de - ld b, NUM_MOVES ; A Pokémon has 4 moves -.pp - ld hl, wPartyMon1Moves - wPartyMon1HP - add hl, de - - ld a, [hl] - and a - jr z, .nextmove - - dec a - ld hl, wPartyMon1PP - wPartyMon1HP - add hl, de - - push hl - push de - push bc - - ld hl, Moves - ld bc, MoveEnd - Moves - call AddNTimes - ld de, wcd6d - ld a, BANK(Moves) - call FarCopyData - ld a, [wcd6d + 5] ; PP is byte 5 of move data - - pop bc - pop de - pop hl - - inc de - push bc - ld b, a - ld a, [hl] - and $c0 - add b - ld [hl], a - pop bc - -.nextmove - dec b - jr nz, .pp - pop de - - ld hl, wPartyMon1MaxHP - wPartyMon1HP - add hl, de - ld a, [hli] - ld [de], a - inc de - ld a, [hl] - ld [de], a - - pop de - pop hl - - push hl - ld bc, wPartyMon2 - wPartyMon1 - ld h, d - ld l, e - add hl, bc - ld d, h - ld e, l - pop hl - jr .healmon - -.done - xor a - ld [wWhichPokemon], a - ld [wd11e], a - - ld a, [wPartyCount] - ld b, a -.ppup - push bc - call RestoreBonusPP - pop bc - ld hl, wWhichPokemon - inc [hl] - dec b - jr nz, .ppup - ret diff --git a/engine/hidden_object_functions14.asm b/engine/hidden_object_functions14.asm deleted file mode 100755 index 04f9cb35..00000000 --- a/engine/hidden_object_functions14.asm +++ /dev/null @@ -1,100 +0,0 @@ -PrintNotebookText: - call EnableAutoTextBoxDrawing - ld a, $1 - ld [wDoNotWaitForButtonPressAfterDisplayingText], a - ld a, [wHiddenObjectFunctionArgument] - jp PrintPredefTextID - -TMNotebook: - TX_FAR TMNotebookText - TX_WAIT - db "@" - -ViridianSchoolNotebook: - TX_ASM - ld hl, ViridianSchoolNotebookText1 - call PrintText - call TurnPageSchoolNotebook - jr nz, .doneReading - ld hl, ViridianSchoolNotebookText2 - call PrintText - call TurnPageSchoolNotebook - jr nz, .doneReading - ld hl, ViridianSchoolNotebookText3 - call PrintText - call TurnPageSchoolNotebook - jr nz, .doneReading - ld hl, ViridianSchoolNotebookText4 - call PrintText - ld hl, ViridianSchoolNotebookText5 - call PrintText -.doneReading - jp TextScriptEnd - -TurnPageSchoolNotebook: - ld hl, TurnPageText - call PrintText - call YesNoChoice - ld a, [wCurrentMenuItem] - and a - ret - -TurnPageText: - TX_FAR _TurnPageText - db "@" - -ViridianSchoolNotebookText5: - TX_FAR _ViridianSchoolNotebookText5 - TX_WAIT - db "@" - -ViridianSchoolNotebookText1: - TX_FAR _ViridianSchoolNotebookText1 - db "@" - -ViridianSchoolNotebookText2: - TX_FAR _ViridianSchoolNotebookText2 - db "@" - -ViridianSchoolNotebookText3: - TX_FAR _ViridianSchoolNotebookText3 - db "@" - -ViridianSchoolNotebookText4: - TX_FAR _ViridianSchoolNotebookText4 - db "@" - -PrintFightingDojoText2: - call EnableAutoTextBoxDrawing - tx_pre_jump EnemiesOnEverySideText - -EnemiesOnEverySideText: - TX_FAR _EnemiesOnEverySideText - db "@" - -PrintFightingDojoText3: - call EnableAutoTextBoxDrawing - tx_pre_jump WhatGoesAroundComesAroundText - -WhatGoesAroundComesAroundText: - TX_FAR _WhatGoesAroundComesAroundText - db "@" - -PrintFightingDojoText: - call EnableAutoTextBoxDrawing - tx_pre_jump FightingDojoText - -FightingDojoText: - TX_FAR _FightingDojoText - db "@" - -PrintIndigoPlateauHQText: - ld a, [wSpritePlayerStateData1FacingDirection] - cp SPRITE_FACING_UP - ret nz - call EnableAutoTextBoxDrawing - tx_pre_jump IndigoPlateauHQText - -IndigoPlateauHQText: - TX_FAR _IndigoPlateauHQText - db "@" diff --git a/engine/hidden_object_functions17.asm b/engine/hidden_object_functions17.asm deleted file mode 100755 index 8775fd39..00000000 --- a/engine/hidden_object_functions17.asm +++ /dev/null @@ -1,466 +0,0 @@ -PrintRedSNESText: - call EnableAutoTextBoxDrawing - tx_pre_jump RedBedroomSNESText - -RedBedroomSNESText: - TX_FAR _RedBedroomSNESText - db "@" - -OpenRedsPC: - call EnableAutoTextBoxDrawing - tx_pre_jump RedBedroomPCText - -RedBedroomPCText: - TX_PLAYERS_PC - -Route15GateLeftBinoculars: - ld a, [wSpritePlayerStateData1FacingDirection] - cp SPRITE_FACING_UP - ret nz - call EnableAutoTextBoxDrawing - tx_pre Route15UpstairsBinocularsText - ld a, ARTICUNO - ld [wcf91], a - call PlayCry - call DisplayMonFrontSpriteInBox - xor a - ld [H_AUTOBGTRANSFERENABLED], a - ret - -Route15UpstairsBinocularsText: - TX_FAR _Route15UpstairsBinocularsText - db "@" - -AerodactylFossil: - ld a, FOSSIL_AERODACTYL - ld [wcf91], a - call DisplayMonFrontSpriteInBox - call EnableAutoTextBoxDrawing - tx_pre AerodactylFossilText - ret - -AerodactylFossilText: - TX_FAR _AerodactylFossilText - db "@" - -KabutopsFossil: - ld a, FOSSIL_KABUTOPS - ld [wcf91], a - call DisplayMonFrontSpriteInBox - call EnableAutoTextBoxDrawing - tx_pre KabutopsFossilText - ret - -KabutopsFossilText: - TX_FAR _KabutopsFossilText - db "@" - -FanClubPicture1: - ld a, RAPIDASH - ld [wcf91], a - call DisplayMonFrontSpriteInBox - call EnableAutoTextBoxDrawing - tx_pre FanClubPicture1Text - ret - -FanClubPicture1Text: - TX_FAR _FanClubPicture1Text - db "@" - -FanClubPicture2: - ld a, FEAROW - ld [wcf91], a - call DisplayMonFrontSpriteInBox - call EnableAutoTextBoxDrawing - tx_pre FanClubPicture2Text - ret - -FanClubPicture2Text: - TX_FAR _FanClubPicture2Text - db "@" - -DisplayMonFrontSpriteInBox: -; Displays a pokemon's front sprite in a pop-up window. -; [wcf91] = pokemon internal id number - ld a, 1 - ld [H_AUTOBGTRANSFERENABLED], a - call Delay3 - xor a - ld [hWY], a - call SaveScreenTilesToBuffer1 - ld a, MON_SPRITE_POPUP - ld [wTextBoxID], a - call DisplayTextBoxID - call UpdateSprites - ld a, [wcf91] - ld [wd0b5], a - call GetMonHeader - ld de, vChars1 + $310 - call LoadMonFrontSprite - ld a, $80 - ld [hStartTileID], a - coord hl, 10, 11 - predef AnimateSendingOutMon - call WaitForTextScrollButtonPress - call LoadScreenTilesFromBuffer1 - call Delay3 - ld a, $90 - ld [hWY], a - ret - -PrintBlackboardLinkCableText: - call EnableAutoTextBoxDrawing - ld a, $1 - ld [wDoNotWaitForButtonPressAfterDisplayingText], a - ld a, [wHiddenObjectFunctionArgument] - call PrintPredefTextID - ret - -LinkCableHelp: - TX_ASM - call SaveScreenTilesToBuffer1 - ld hl, LinkCableHelpText1 - call PrintText - xor a - ld [wMenuItemOffset], a ; not used - ld [wCurrentMenuItem], a - ld [wLastMenuItem], a - ld a, A_BUTTON | B_BUTTON - ld [wMenuWatchedKeys], a - ld a, 3 - ld [wMaxMenuItem], a - ld a, 2 - ld [wTopMenuItemY], a - ld a, 1 - ld [wTopMenuItemX], a -.linkHelpLoop - ld hl, wd730 - set 6, [hl] - coord hl, 0, 0 - lb bc, 8, 13 - call TextBoxBorder - coord hl, 2, 2 - ld de, HowToLinkText - call PlaceString - ld hl, LinkCableHelpText2 - call PrintText - call HandleMenuInput - bit 1, a ; pressed b - jr nz, .exit - ld a, [wCurrentMenuItem] - cp 3 ; pressed a on "STOP READING" - jr z, .exit - ld hl, wd730 - res 6, [hl] - ld hl, LinkCableInfoTexts - add a - ld d, 0 - ld e, a - add hl, de - ld a, [hli] - ld h, [hl] - ld l, a - call PrintText - jp .linkHelpLoop -.exit - ld hl, wd730 - res 6, [hl] - call LoadScreenTilesFromBuffer1 - jp TextScriptEnd - -LinkCableHelpText1: - TX_FAR _LinkCableHelpText1 - db "@" - -LinkCableHelpText2: - TX_FAR _LinkCableHelpText2 - db "@" - -HowToLinkText: - db "HOW TO LINK" - next "COLOSSEUM" - next "TRADE CENTER" - next "STOP READING@" - -LinkCableInfoTexts: - dw LinkCableInfoText1 - dw LinkCableInfoText2 - dw LinkCableInfoText3 - -LinkCableInfoText1: - TX_FAR _LinkCableInfoText1 - db "@" - -LinkCableInfoText2: - TX_FAR _LinkCableInfoText2 - db "@" - -LinkCableInfoText3: - TX_FAR _LinkCableInfoText3 - db "@" - -ViridianSchoolBlackboard: - TX_ASM - call SaveScreenTilesToBuffer1 - ld hl, ViridianSchoolBlackboardText1 - call PrintText - xor a - ld [wMenuItemOffset], a - ld [wCurrentMenuItem], a - ld [wLastMenuItem], a - ld a, D_LEFT | D_RIGHT | A_BUTTON | B_BUTTON - ld [wMenuWatchedKeys], a - ld a, 2 - ld [wMaxMenuItem], a - ld a, 2 - ld [wTopMenuItemY], a - ld a, 1 - ld [wTopMenuItemX], a -.blackboardLoop - ld hl, wd730 - set 6, [hl] - coord hl, 0, 0 - lb bc, 6, 10 - call TextBoxBorder - coord hl, 1, 2 - ld de, StatusAilmentText1 - call PlaceString - coord hl, 6, 2 - ld de, StatusAilmentText2 - call PlaceString - ld hl, ViridianSchoolBlackboardText2 - call PrintText - call HandleMenuInput ; pressing up and down is handled in here - bit 1, a ; pressed b - jr nz, .exitBlackboard - bit 4, a ; pressed right - jr z, .didNotPressRight - ; move cursor to right column - ld a, 2 - ld [wMaxMenuItem], a - ld a, 2 - ld [wTopMenuItemY], a - ld a, 6 - ld [wTopMenuItemX], a - ld a, 3 ; in the the right column, use an offset to prevent overlap - ld [wMenuItemOffset], a - jr .blackboardLoop -.didNotPressRight - bit 5, a ; pressed left - jr z, .didNotPressLeftOrRight - ; move cursor to left column - ld a, 2 - ld [wMaxMenuItem], a - ld a, 2 - ld [wTopMenuItemY], a - ld a, 1 - ld [wTopMenuItemX], a - xor a - ld [wMenuItemOffset], a - jr .blackboardLoop -.didNotPressLeftOrRight - ld a, [wCurrentMenuItem] - ld b, a - ld a, [wMenuItemOffset] - add b - cp 5 ; cursor is pointing to "QUIT" - jr z, .exitBlackboard - ; we must have pressed a on a status condition - ; so print the text - ld hl, wd730 - res 6, [hl] - ld hl, ViridianBlackboardStatusPointers - add a - ld d, 0 - ld e, a - add hl, de - ld a, [hli] - ld h, [hl] - ld l, a - call PrintText - jp .blackboardLoop -.exitBlackboard - ld hl, wd730 - res 6, [hl] - call LoadScreenTilesFromBuffer1 - jp TextScriptEnd - -ViridianSchoolBlackboardText1: - TX_FAR _ViridianSchoolBlackboardText1 - db "@" - -ViridianSchoolBlackboardText2: - TX_FAR _ViridianSchoolBlackboardText2 - db "@" - -StatusAilmentText1: - db " SLP" - next " PSN" - next " PAR@" - -StatusAilmentText2: - db " BRN" - next " FRZ" - next " QUIT@@" - -ViridianBlackboardStatusPointers: - dw ViridianBlackboardSleepText - dw ViridianBlackboardPoisonText - dw ViridianBlackboardPrlzText - dw ViridianBlackboardBurnText - dw ViridianBlackboardFrozenText - -ViridianBlackboardSleepText: - TX_FAR _ViridianBlackboardSleepText - db "@" - -ViridianBlackboardPoisonText: - TX_FAR _ViridianBlackboardPoisonText - db "@" - -ViridianBlackboardPrlzText: - TX_FAR _ViridianBlackboardPrlzText - db "@" - -ViridianBlackboardBurnText: - TX_FAR _ViridianBlackboardBurnText - db "@" - -ViridianBlackboardFrozenText: - TX_FAR _ViridianBlackboardFrozenText - db "@" - -PrintTrashText: - call EnableAutoTextBoxDrawing - tx_pre_jump VermilionGymTrashText - -VermilionGymTrashText: - TX_FAR _VermilionGymTrashText - db "@" - -GymTrashScript: - call EnableAutoTextBoxDrawing - ld a, [wHiddenObjectFunctionArgument] - ld [wGymTrashCanIndex], a - -; Don't do the trash can puzzle if it's already been done. - CheckEvent EVENT_2ND_LOCK_OPENED - jr z, .ok - - tx_pre_jump VermilionGymTrashText - -.ok - CheckEventReuseA EVENT_1ST_LOCK_OPENED - jr nz, .trySecondLock - - ld a, [wFirstLockTrashCanIndex] - ld b, a - ld a, [wGymTrashCanIndex] - cp b - jr z, .openFirstLock - - tx_pre_id VermilionGymTrashText - jr .done - -.openFirstLock -; Next can is trying for the second switch. - SetEvent EVENT_1ST_LOCK_OPENED - callab Yellow_SampleSecondTrashCan - tx_pre_id VermilionGymTrashSuccessText1 - jr .done - -.trySecondLock - ld a, [wGymTrashCanIndex] - ld b, a - ld a, [wSecondLockTrashCanIndex] - cp b - jr z, .openSecondLock - ld a, [wSecondLockTrashCanIndex + 1] - cp b - jr z, .openSecondLock - -; Reset the cans. - ResetEvent EVENT_1ST_LOCK_OPENED - call Random - - and $e - ld [wFirstLockTrashCanIndex], a - - tx_pre_id VermilionGymTrashFailText - jr .done - -.openSecondLock -; Completed the trash can puzzle. - SetEvent EVENT_2ND_LOCK_OPENED - ld hl, wCurrentMapScriptFlags - set 6, [hl] - - tx_pre_id VermilionGymTrashSuccessText3 - -.done - jp PrintPredefTextID - -GymTrashCans: -; byte 0: mask for random number -; bytes 1-4: indices of the trash cans that can have the second lock -; Note that the mask is simply the number of valid trash can indices that -; follow. The remaining bytes are filled with -1 to pad the length of each entry -; to 5 bytes. -; This is functionally replaced with GymTrashCans3a but was never removed from source. - - db 2, 1, 3, -1, -1 ; 0 - db 3, 0, 2, 4, -1 ; 1 - db 2, 1, 5, -1, -1 ; 2 - db 3, 0, 4, 6, -1 ; 3 - db 4, 1, 3, 5, 7 ; 4 - db 3, 2, 4, 8, -1 ; 5 - db 3, 3, 7, 9, -1 ; 6 - db 4, 4, 6, 8, 10 ; 7 - db 3, 5, 7, 11, -1 ; 8 - db 3, 6, 10, 12, -1 ; 9 - db 4, 7, 9, 11, 13 ; 10 - db 3, 8, 10, 14, -1 ; 11 - db 2, 9, 13, -1, -1 ; 12 - db 3, 10, 12, 14, -1 ; 13 - db 2, 11, 13, -1, -1 ; 14 - -VermilionGymTrashSuccessText1: - TX_FAR _VermilionGymTrashSuccessText1 - TX_ASM - call WaitForSoundToFinish - ld a, SFX_SWITCH - call PlaySound - call WaitForSoundToFinish - jp TextScriptEnd - -; unused -VermilionGymTrashSuccessText2: - TX_FAR _VermilionGymTrashSuccessText2 - db "@" - -; unused -VermilionGymTrashSuccesPlaySfx: - TX_ASM - call WaitForSoundToFinish - ld a, SFX_SWITCH - call PlaySound - call WaitForSoundToFinish - jp TextScriptEnd - -VermilionGymTrashSuccessText3: - TX_FAR _VermilionGymTrashSuccessText3 - TX_ASM - call WaitForSoundToFinish - ld a, SFX_GO_INSIDE - call PlaySound - call WaitForSoundToFinish - jp TextScriptEnd - -VermilionGymTrashFailText: - TX_FAR _VermilionGymTrashFailText - TX_ASM - call WaitForSoundToFinish - ld a, SFX_DENIED - call PlaySound - call WaitForSoundToFinish - jp TextScriptEnd diff --git a/engine/hidden_object_functions18.asm b/engine/hidden_object_functions18.asm deleted file mode 100755 index 3fd5dd47..00000000 --- a/engine/hidden_object_functions18.asm +++ /dev/null @@ -1,204 +0,0 @@ -GymStatues: -; if in a gym and have the corresponding badge, a = GymStatueText2_id and jp PrintPredefTextID -; if in a gym and don’t have the corresponding badge, a = GymStatueText1_id and jp PrintPredefTextID -; else ret - call EnableAutoTextBoxDrawing - ld a, [wSpritePlayerStateData1FacingDirection] - cp SPRITE_FACING_UP - ret nz - ld hl, .BadgeFlags - ld a, [wCurMap] - ld b, a -.loop - ld a, [hli] - cp $ff - ret z - cp b - jr z, .match - inc hl - jr .loop -.match - ld b, [hl] - ld a, [wBeatGymFlags] - and b - cp b - tx_pre_id GymStatueText2 - jr z, .haveBadge - tx_pre_id GymStatueText1 -.haveBadge - jp PrintPredefTextID - -.BadgeFlags: - db PEWTER_GYM, %00000001 - db CERULEAN_GYM, %00000010 - db VERMILION_GYM, %00000100 - db CELADON_GYM, %00001000 - db FUCHSIA_GYM, %00010000 - db SAFFRON_GYM, %00100000 - db CINNABAR_GYM, %01000000 - db VIRIDIAN_GYM, %10000000 - db $ff - -GymStatueText1: - TX_FAR _GymStatueText1 - db "@" - -GymStatueText2: - TX_FAR _GymStatueText2 - db "@" - -PrintBenchGuyText: - call EnableAutoTextBoxDrawing - ld hl, BenchGuyTextPointers - ld a, [wCurMap] - ld b, a -.loop - ld a, [hli] - cp $ff - ret z - cp b - jr z, .match - inc hl - inc hl - jr .loop -.match - ld a, [hli] - ld b, a - ld a, [wSpritePlayerStateData1FacingDirection] - cp b - jr nz, .loop ; player isn't facing left at the bench guy - ld a, [hl] - jp PrintPredefTextID - -; format: db map id, player sprite facing direction, text id of PredefTextIDPointerTable -BenchGuyTextPointers: - db VIRIDIAN_POKECENTER, SPRITE_FACING_LEFT - db_tx_pre ViridianCityPokecenterBenchGuyText - db PEWTER_POKECENTER, SPRITE_FACING_LEFT - db_tx_pre PewterCityPokecenterBenchGuyText - db CERULEAN_POKECENTER, SPRITE_FACING_LEFT - db_tx_pre CeruleanCityPokecenterBenchGuyText - db LAVENDER_POKECENTER, SPRITE_FACING_LEFT - db_tx_pre LavenderCityPokecenterBenchGuyText - db VERMILION_POKECENTER, SPRITE_FACING_LEFT - db_tx_pre VermilionCityPokecenterBenchGuyText - db CELADON_POKECENTER, SPRITE_FACING_LEFT - db_tx_pre CeladonCityPokecenterBenchGuyText - db CELADON_HOTEL, SPRITE_FACING_LEFT - db_tx_pre CeladonCityHotelText - db FUCHSIA_POKECENTER, SPRITE_FACING_LEFT - db_tx_pre FuchsiaCityPokecenterBenchGuyText - db CINNABAR_POKECENTER, SPRITE_FACING_LEFT - db_tx_pre CinnabarIslandPokecenterBenchGuyText - db SAFFRON_POKECENTER, SPRITE_FACING_LEFT - db_tx_pre SaffronCityPokecenterBenchGuyText - db MT_MOON_POKECENTER, SPRITE_FACING_LEFT - db_tx_pre MtMoonPokecenterBenchGuyText - db ROCK_TUNNEL_POKECENTER, SPRITE_FACING_LEFT - db_tx_pre RockTunnelPokecenterBenchGuyText - db SAFARI_ZONE_WEST_REST_HOUSE,SPRITE_FACING_LEFT - db_tx_pre UnusedBenchGuyText1 - db SAFARI_ZONE_EAST_REST_HOUSE,SPRITE_FACING_LEFT - db_tx_pre UnusedBenchGuyText2 - db SAFARI_ZONE_NORTH_REST_HOUSE,SPRITE_FACING_LEFT - db_tx_pre UnusedBenchGuyText3 - db $FF - -ViridianCityPokecenterBenchGuyText: - TX_FAR _ViridianCityPokecenterGuyText - db "@" - -PewterCityPokecenterBenchGuyText: - TX_FAR _PewterCityPokecenterGuyText - db "@" - -CeruleanCityPokecenterBenchGuyText: - TX_FAR _CeruleanPokecenterGuyText - db "@" - -LavenderCityPokecenterBenchGuyText: - TX_FAR _LavenderPokecenterGuyText - db "@" - -MtMoonPokecenterBenchGuyText: - TX_FAR _MtMoonPokecenterBenchGuyText - db "@" - -RockTunnelPokecenterBenchGuyText: - TX_FAR _RockTunnelPokecenterGuyText - db "@" - -UnusedBenchGuyText1: - TX_FAR _UnusedBenchGuyText1 - db "@" - -UnusedBenchGuyText2: - TX_FAR _UnusedBenchGuyText2 - db "@" - -UnusedBenchGuyText3: - TX_FAR _UnusedBenchGuyText3 - db "@" - -VermilionCityPokecenterBenchGuyText: - TX_FAR _VermilionPokecenterGuyText - db "@" - -CeladonCityPokecenterBenchGuyText: - TX_FAR _CeladonCityPokecenterGuyText - db "@" - -FuchsiaCityPokecenterBenchGuyText: - TX_FAR _FuchsiaCityPokecenterGuyText - db "@" - -CinnabarIslandPokecenterBenchGuyText: - TX_FAR _CinnabarPokecenterGuyText - db "@" - -SaffronCityPokecenterBenchGuyText: - TX_ASM - CheckEvent EVENT_BEAT_SILPH_CO_GIOVANNI - ld hl, SaffronCityPokecenterBenchGuyText2 - jr nz, .asm_624f2 - ld hl, SaffronCityPokecenterBenchGuyText1 -.asm_624f2 - call PrintText - jp TextScriptEnd - -SaffronCityPokecenterBenchGuyText1: - TX_FAR _SaffronCityPokecenterGuyText1 - db "@" - -SaffronCityPokecenterBenchGuyText2: - TX_FAR _SaffronCityPokecenterGuyText2 - db "@" - -CeladonCityHotelText: - TX_FAR _CeladonCityHotelText - db "@" - - ret - -UnusedPredefText: - db "@" - -PrintBookcaseText: - call EnableAutoTextBoxDrawing - tx_pre_jump BookcaseText - -BookcaseText: - TX_FAR _BookcaseText - db "@" - -OpenPokemonCenterPC: - ld a, [wSpritePlayerStateData1FacingDirection] - cp SPRITE_FACING_UP ; check to see if player is facing up - ret nz - call EnableAutoTextBoxDrawing - ld a, $1 - ld [wAutoTextBoxDrawingControl], a - tx_pre_jump PokemonCenterPCText - -PokemonCenterPCText: - TX_POKECENTER_PC diff --git a/engine/hidden_object_functions3.asm b/engine/hidden_object_functions3.asm deleted file mode 100755 index 11aecd5b..00000000 --- a/engine/hidden_object_functions3.asm +++ /dev/null @@ -1,153 +0,0 @@ -; prints text for bookshelves in buildings without sign events -PrintBookshelfText: - ld a, [wSpritePlayerStateData1FacingDirection] ; player's sprite facing direction - cp SPRITE_FACING_UP - jr nz, .noMatch -; facing up - ld a, [wCurMapTileset] - ld b, a - aCoord 8, 7 - ld c, a - ld hl, BookshelfTileIDs -.loop - ld a, [hli] - cp $ff - jr z, .noMatch - cp b - jr nz, .nextBookshelfEntry1 - ld a, [hli] - cp c - jr nz, .nextBookshelfEntry2 - ld a, [hl] - push af - call EnableAutoTextBoxDrawing - pop af - call PrintPredefTextID - xor a - ld [$ffdb], a - ret -.nextBookshelfEntry1 - inc hl -.nextBookshelfEntry2 - inc hl - jr .loop -.noMatch - ld a, $ff - ld [$ffdb], a - jpba PrintCardKeyText - -; format: db tileset id, bookshelf tile id, text id -BookshelfTileIDs: - db PLATEAU, $30 - db_tx_pre IndigoPlateauStatues - db HOUSE, $3D - db_tx_pre TownMapText - db HOUSE, $1E - db_tx_pre BookOrSculptureText - db MANSION, $32 - db_tx_pre BookOrSculptureText - db REDS_HOUSE_1, $32 - db_tx_pre BookOrSculptureText - db LAB, $28 - db_tx_pre BookOrSculptureText - db LOBBY, $16 - db_tx_pre ElevatorText - db GYM, $1D - db_tx_pre BookOrSculptureText - db DOJO, $1D - db_tx_pre BookOrSculptureText - db GATE, $22 - db_tx_pre BookOrSculptureText - db MART, $54 - db_tx_pre PokemonStuffText - db MART, $55 - db_tx_pre PokemonStuffText - db POKECENTER, $54 - db_tx_pre PokemonStuffText - db POKECENTER, $55 - db_tx_pre PokemonStuffText - db LOBBY, $50 - db_tx_pre PokemonStuffText - db LOBBY, $52 - db_tx_pre PokemonStuffText - db SHIP, $36 - db_tx_pre BookOrSculptureText - db $FF - -IndigoPlateauStatues: - TX_ASM - ld hl, IndigoPlateauStatuesText1 - call PrintText - ld a, [wXCoord] - bit 0, a - ld hl, IndigoPlateauStatuesText2 - jr nz, .ok - ld hl, IndigoPlateauStatuesText3 -.ok - call PrintText - jp TextScriptEnd - -IndigoPlateauStatuesText1: - TX_FAR _IndigoPlateauStatuesText1 - db "@" - -IndigoPlateauStatuesText2: - TX_FAR _IndigoPlateauStatuesText2 - db "@" - -IndigoPlateauStatuesText3: - TX_FAR _IndigoPlateauStatuesText3 - db "@" - -BookOrSculptureText: - TX_ASM - ld hl, PokemonBooksText - ld a, [wCurMapTileset] - cp MANSION ; Celadon Mansion tileset - jr nz, .ok - aCoord 8, 6 - cp $38 - jr nz, .ok - ld hl, DiglettSculptureText -.ok - call PrintText - jp TextScriptEnd - -PokemonBooksText: - TX_FAR _PokemonBooksText - db "@" - -DiglettSculptureText: - TX_FAR _DiglettSculptureText - db "@" - -ElevatorText: - TX_FAR _ElevatorText - db "@" - -TownMapText: - TX_FAR _TownMapText - TX_BLINK - TX_ASM - ld a, $1 - ld [wDoNotWaitForButtonPressAfterDisplayingText], a - ld hl, wd730 - set 6, [hl] - call GBPalWhiteOutWithDelay3 - xor a - ld [hWY], a - inc a - ld [H_AUTOBGTRANSFERENABLED], a - call LoadFontTilePatterns - callba DisplayTownMap - ld hl, wd730 - res 6, [hl] - ld de, TextScriptEnd - push de - ld a, [H_LOADEDROMBANK] - push af - jp CloseTextDisplay - -PokemonStuffText: - TX_FAR _PokemonStuffText - db "@" diff --git a/engine/hidden_object_functions7.asm b/engine/hidden_object_functions7.asm deleted file mode 100755 index 2498c167..00000000 --- a/engine/hidden_object_functions7.asm +++ /dev/null @@ -1,510 +0,0 @@ -PrintNewBikeText: - call EnableAutoTextBoxDrawing - tx_pre_jump NewBicycleText - -NewBicycleText: - TX_FAR _NewBicycleText - db "@" - -DisplayOakLabLeftPoster: - call EnableAutoTextBoxDrawing - tx_pre_jump PushStartText - -PushStartText: - TX_FAR _PushStartText - db "@" - -DisplayOakLabRightPoster: - call EnableAutoTextBoxDrawing - ld hl, wPokedexOwned - ld b, wPokedexOwnedEnd - wPokedexOwned - call CountSetBits - ld a, [wNumSetBits] - cp 2 - tx_pre_id SaveOptionText - jr c, .ownLessThanTwo - ; own two or more mon - tx_pre_id StrengthsAndWeaknessesText -.ownLessThanTwo - jp PrintPredefTextID - -SaveOptionText: - TX_FAR _SaveOptionText - db "@" - -StrengthsAndWeaknessesText: - TX_FAR _StrengthsAndWeaknessesText - db "@" - -SafariZoneCheck: - CheckEventHL EVENT_IN_SAFARI_ZONE ; if we are not in the Safari Zone, - jr z, SafariZoneGameStillGoing ; don't bother printing game over text - ld a, [wNumSafariBalls] - and a - jr z, SafariZoneGameOver - jr SafariZoneGameStillGoing - -SafariZoneCheckSteps: - ld a, [wSafariSteps] - ld b, a - ld a, [wSafariSteps + 1] - ld c, a - or b - jr z, SafariZoneGameOver - dec bc - ld a, b - ld [wSafariSteps], a - ld a, c - ld [wSafariSteps + 1], a -SafariZoneGameStillGoing: - xor a - ld [wSafariZoneGameOver], a - ret - -SafariZoneGameOver: - call EnableAutoTextBoxDrawing - xor a - ld [wAudioFadeOutControl], a - call StopAllMusic - ld c, BANK(SFX_Safari_Zone_PA) - ld a, SFX_SAFARI_ZONE_PA - call PlayMusic -.waitForMusicToPlay - ld a, [wChannelSoundIDs + Ch5] - cp SFX_SAFARI_ZONE_PA - jr nz, .waitForMusicToPlay - ld a, TEXT_SAFARI_GAME_OVER - ld [hSpriteIndexOrTextID], a - call DisplayTextID - xor a - ld [wPlayerMovingDirection], a - ld a, SAFARI_ZONE_GATE - ld [hWarpDestinationMap], a - ld a, $3 - ld [wDestinationWarpID], a - ld a, $5 - ld [wSafariZoneGateCurScript], a - SetEvent EVENT_SAFARI_GAME_OVER - ld a, 1 - ld [wSafariZoneGameOver], a - ret - -PrintSafariGameOverText: - xor a - ld [wJoyIgnore], a - ld hl, SafariGameOverText - jp PrintText - -SafariGameOverText: - TX_ASM - ld a, [wNumSafariBalls] - and a - jr z, .noMoreSafariBalls - ld hl, TimesUpText - call PrintText -.noMoreSafariBalls - ld hl, GameOverText - call PrintText - jp TextScriptEnd - -TimesUpText: - TX_FAR _TimesUpText - db "@" - -GameOverText: - TX_FAR _GameOverText - db "@" - -PrintCinnabarQuiz: - ld a, [wSpritePlayerStateData1FacingDirection] - cp SPRITE_FACING_UP - ret nz - call EnableAutoTextBoxDrawing - tx_pre_jump CinnabarGymQuiz - -CinnabarGymQuiz: - TX_ASM - xor a - ld [wOpponentAfterWrongAnswer], a - ld hl, wd475 - res 7, [hl] - ld a, [wHiddenObjectFunctionArgument] - push af - and $f - ld [hGymGateIndex], a - pop af - and $f0 - swap a - ld [$ffdc], a - ld a, [hGymGateIndex] - ld hl, CinnabarGymQuizIntroText - cp 1 - jr z, .onFirstQuestion - ld hl, CinnabarGymQuizShortIntroText -.onFirstQuestion - call PrintText - ld a, [hGymGateIndex] - dec a - add a - ld d, 0 - ld e, a - ld hl, CinnabarQuizQuestions - add hl, de - ld a, [hli] - ld h, [hl] - ld l, a - call PrintText - ld a, 1 - ld [wDoNotWaitForButtonPressAfterDisplayingText], a - call CinnabarGymQuiz_1ea92 - jp TextScriptEnd - -CinnabarGymQuizDummyIntroText: - TX_FAR _CinnabarGymQuizDummyIntroText - db "@" - -CinnabarGymQuizIntroText: - TX_FAR _CinnabarGymQuizIntroText - db "@" - -CinnabarGymQuizShortIntroText: - TX_FAR _CinnabarGymQuizShortIntroText - db "@" - -CinnabarQuizQuestions: - dw CinnabarQuizQuestionsText1 - dw CinnabarQuizQuestionsText2 - dw CinnabarQuizQuestionsText3 - dw CinnabarQuizQuestionsText4 - dw CinnabarQuizQuestionsText5 - dw CinnabarQuizQuestionsText6 - -CinnabarQuizQuestionsText1: - TX_FAR _CinnabarQuizQuestionsText1 - db "@" - -CinnabarQuizQuestionsText2: - TX_FAR _CinnabarQuizQuestionsText2 - db "@" - -CinnabarQuizQuestionsText3: - TX_FAR _CinnabarQuizQuestionsText3 - db "@" - -CinnabarQuizQuestionsText4: - TX_FAR _CinnabarQuizQuestionsText4 - db "@" - -CinnabarQuizQuestionsText5: - TX_FAR _CinnabarQuizQuestionsText5 - db "@" - -CinnabarQuizQuestionsText6: - TX_FAR _CinnabarQuizQuestionsText6 - db "@" - -CinnabarGymQuiz_1ea92: - call YesNoChoice - ld a, [$ffdc] - ld c, a - ld a, [wCurrentMenuItem] - cp c - jr nz, .wrongAnswer - ld hl, wCurrentMapScriptFlags - set 5, [hl] - ld a, [hGymGateIndex] - ld [$ffe0], a - ld hl, CinnabarGymQuizCorrectText - call PrintText - ld a, [$ffe0] - AdjustEventBit EVENT_CINNABAR_GYM_GATE0_UNLOCKED, 0 - ld c, a - ld b, FLAG_SET - call CinnabarGymGateFlagAction - jp UpdateCinnabarGymGateTileBlocks_ -.wrongAnswer - call WaitForSoundToFinish - ld a, SFX_DENIED - call PlaySound - call WaitForSoundToFinish - ld hl, CinnabarGymQuizIncorrectText - call PrintText - ld a, [hGymGateIndex] - add $2 - AdjustEventBit EVENT_BEAT_CINNABAR_GYM_TRAINER_0, 2 - ld c, a - ld b, FLAG_TEST - EventFlagAddress hl, EVENT_BEAT_CINNABAR_GYM_TRAINER_0 - predef FlagActionPredef - ld a, c - and a - ret nz - ld a, [hGymGateIndex] - add $2 - ld [wOpponentAfterWrongAnswer], a - ld hl, wd475 - set 7, [hl] - ret - -CinnabarGymQuizCorrectText: - TX_SFX_ITEM_1 - TX_FAR _CinnabarGymQuizCorrectText - TX_BLINK - TX_ASM - - ld a, [$ffe0] - AdjustEventBit EVENT_CINNABAR_GYM_GATE0_UNLOCKED, 0 - ld c, a - ld b, FLAG_TEST - call CinnabarGymGateFlagAction - ld a, c - and a - jp nz, TextScriptEnd - call WaitForSoundToFinish - ld a, SFX_GO_INSIDE - call PlaySound - call WaitForSoundToFinish - jp TextScriptEnd - -CinnabarGymQuizIncorrectText: - TX_FAR _CinnabarGymQuizIncorrectText - db "@" - -CinnabarGymGateFlagAction: - EventFlagAddress hl, EVENT_CINNABAR_GYM_GATE0_UNLOCKED - predef_jump FlagActionPredef - -UpdateCinnabarGymGateTileBlocks_: -; Update the overworld map with open floor blocks or locked gate blocks -; depending on event flags. - ld a, 6 - ld [hGymGateIndex], a -.loop - ld a, [hGymGateIndex] - dec a - add a - add a - ld d, 0 - ld e, a - ld hl, CinnabarGymGateCoords - add hl, de - ld a, [hli] - ld b, [hl] - ld c, a - inc hl - ld a, [hl] - ld [wGymGateTileBlock], a - push bc - ld a, [hGymGateIndex] - ld [$ffe0], a - AdjustEventBit EVENT_CINNABAR_GYM_GATE0_UNLOCKED, 0 - ld c, a - ld b, FLAG_TEST - call CinnabarGymGateFlagAction - ld a, c - and a - jr nz, .unlocked - ld a, [wGymGateTileBlock] - jr .next -.unlocked - ld a, $e -.next - pop bc - ld [wNewTileBlockID], a - call CinnabarGym_ReplaceTileBlock - ld hl, hGymGateIndex - dec [hl] - jr nz, .loop - callab RedrawMapView - ret - -CinnabarGymGateCoords: - ; format: x-coord, y-coord, direction, padding - ; direction: $54 = horizontal gate, $5f = vertical gate - db $09,$03,$54,$00 - db $06,$03,$54,$00 - db $06,$06,$54,$00 - db $03,$08,$5f,$00 - db $02,$06,$54,$00 - db $02,$03,$54,$00 - - -CinnabarGym_ReplaceTileBlock: -; basically a copy of the first half of ReplaceTileBlock -; before checking if it is necessary to redraw the map view - ld hl, wOverworldMap - ld a, [wCurMapWidth] - add $6 - ld e, a - ld d, $0 - add hl, de - add hl, de - add hl, de - ld e, $3 - add hl, de - ld e, a - ld a, b - and a - jr z, .addX -.addWidthYTimesLoop - add hl, de - dec b - jr nz, .addWidthYTimesLoop -.addX - add hl, bc - ld a, [wNewTileBlockID] - ld [hl], a - ret - -PrintMagazinesText: - call EnableAutoTextBoxDrawing - tx_pre MagazinesText - ret - -MagazinesText: - TX_FAR _MagazinesText - db "@" - -BillsHousePC: - call EnableAutoTextBoxDrawing - ld a, [wSpritePlayerStateData1FacingDirection] - cp SPRITE_FACING_UP - ret nz - CheckEvent EVENT_LEFT_BILLS_HOUSE_AFTER_HELPING - jr nz, .displayBillsHousePokemonList - CheckEventReuseA EVENT_USED_CELL_SEPARATOR_ON_BILL - jr nz, .displayBillsHouseMonitorText - CheckEventReuseA EVENT_BILL_SAID_USE_CELL_SEPARATOR - jr nz, .doCellSeparator -.displayBillsHouseMonitorText - tx_pre_jump BillsHouseMonitorText -.doCellSeparator - ld a, $1 - ld [wDoNotWaitForButtonPressAfterDisplayingText], a - tx_pre BillsHouseInitiatedText - ld c, 32 - call DelayFrames - ld a, SFX_TINK - call PlaySound - call WaitForSoundToFinish - ld c, 80 - call DelayFrames - ld a, SFX_SHRINK - call PlaySound - call WaitForSoundToFinish - ld c, 48 - call DelayFrames - ld a, SFX_TINK - call PlaySound - call WaitForSoundToFinish - ld c, 32 - call DelayFrames - ld a, SFX_GET_ITEM_1 - call PlaySound - call WaitForSoundToFinish - call PlayDefaultMusic - SetEvent EVENT_USED_CELL_SEPARATOR_ON_BILL - ret -.displayBillsHousePokemonList - ld a, $1 - ld [wDoNotWaitForButtonPressAfterDisplayingText], a - tx_pre BillsHousePokemonList - ret - -BillsHouseMonitorText: - TX_FAR _BillsHouseMonitorText - db "@" - -BillsHouseInitiatedText: - TX_FAR _BillsHouseInitiatedText - TX_BLINK - TX_ASM - call StopAllMusic - ld c, 16 - call DelayFrames - ld a, SFX_SWITCH - call PlaySound - call WaitForSoundToFinish - ld c, 60 - call DelayFrames - jp TextScriptEnd - -BillsHousePokemonList: - TX_ASM - call SaveScreenTilesToBuffer1 - ld hl, BillsHousePokemonListText1 - call PrintText - xor a - ld [wMenuItemOffset], a ; not used - ld [wCurrentMenuItem], a - ld [wLastMenuItem], a - ld a, A_BUTTON | B_BUTTON - ld [wMenuWatchedKeys], a - ld a, 4 - ld [wMaxMenuItem], a - ld a, 2 - ld [wTopMenuItemY], a - ld a, 1 - ld [wTopMenuItemX], a -.billsPokemonLoop - ld hl, wd730 - set 6, [hl] - coord hl, 0, 0 - lb bc, 10, 9 - call TextBoxBorder - coord hl, 2, 2 - ld de, BillsMonListText - call PlaceString - ld hl, BillsHousePokemonListText2 - call PrintText - call SaveScreenTilesToBuffer2 - call HandleMenuInput - bit 1, a ; pressed b - jr nz, .cancel - ld a, [wCurrentMenuItem] - add EEVEE - cp EEVEE - jr z, .displayPokedex - cp FLAREON - jr z, .displayPokedex - cp JOLTEON - jr z, .displayPokedex - cp VAPOREON - jr z, .displayPokedex - jr .cancel -.displayPokedex - call DisplayPokedex - call LoadScreenTilesFromBuffer2 - jr .billsPokemonLoop -.cancel - ld hl, wd730 - res 6, [hl] - call LoadScreenTilesFromBuffer2 - jp TextScriptEnd - -BillsHousePokemonListText1: - TX_FAR _BillsHousePokemonListText1 - db "@" - -BillsMonListText: - db "EEVEE" - next "FLAREON" - next "JOLTEON" - next "VAPOREON" - next "CANCEL@" - -BillsHousePokemonListText2: - TX_FAR _BillsHousePokemonListText2 - db "@" - -DisplayOakLabEmailText: - ld a, [wSpritePlayerStateData1FacingDirection] - cp SPRITE_FACING_UP - ret nz - call EnableAutoTextBoxDrawing - tx_pre OakLabEmailText - ret - -OakLabEmailText: - TX_FAR _OakLabEmailText - db "@" diff --git a/engine/hp_bar.asm b/engine/hp_bar.asm deleted file mode 100755 index 566a7b61..00000000 --- a/engine/hp_bar.asm +++ /dev/null @@ -1,268 +0,0 @@ -HPBarLength: - call GetPredefRegisters - -; calculates bc * 48 / de, the number of pixels the HP bar has -; the result is always at least 1 -GetHPBarLength: - push hl - xor a - ld hl, H_MULTIPLICAND - ld [hli], a - ld a, b - ld [hli], a - ld a, c - ld [hli], a - ld [hl], $30 - call Multiply ; 48 * bc (hp bar is 48 pixels long) - ld a, d - and a - jr z, .maxHPSmaller256 - srl d ; make HP in de fit into 1 byte by dividing by 4 - rr e - srl d - rr e - ld a, [H_MULTIPLICAND+1] - ld b, a - ld a, [H_MULTIPLICAND+2] - srl b ; divide multiplication result as well - rr a - srl b - rr a - ld [H_MULTIPLICAND+2], a - ld a, b - ld [H_MULTIPLICAND+1], a -.maxHPSmaller256 - ld a, e - ld [H_DIVISOR], a - ld b, $4 - call Divide - ld a, [H_MULTIPLICAND+2] - ld e, a ; e = bc * 48 / de (num of pixels of HP bar) - pop hl - and a - ret nz - ld e, $1 ; make result at least 1 - ret - -; predef $48 -UpdateHPBar: -UpdateHPBar2: - push hl - ld hl, wHPBarOldHP - ld a, [hli] - ld c, a ; old HP into bc - ld a, [hli] - ld b, a - ld a, [hli] - ld e, a ; new HP into de - ld d, [hl] - pop hl - push de - push bc - call UpdateHPBar_CalcHPDifference - ld a, e - ld [wHPBarHPDifference+1], a - ld a, d - ld [wHPBarHPDifference], a - pop bc - pop de - call UpdateHPBar_CompareNewHPToOldHP - ret z - ld a, $ff - jr c, .HPdecrease - ld a, $1 -.HPdecrease - ld [wHPBarDelta], a - call GetPredefRegisters - ld a, [wHPBarNewHP] - ld e, a - ld a, [wHPBarNewHP+1] - ld d, a -.animateHPBarLoop - push de - ld a, [wHPBarOldHP] - ld c, a - ld a, [wHPBarOldHP+1] - ld b, a - call UpdateHPBar_CompareNewHPToOldHP - jr z, .animateHPBarDone - jr nc, .HPIncrease -; HP decrease - dec bc ; subtract 1 HP - ld a, c - ld [wHPBarNewHP], a - ld a, b - ld [wHPBarNewHP+1], a - call UpdateHPBar_CalcOldNewHPBarPixels - ld a, e - sub d ; calc pixel difference - jr .ok -.HPIncrease - inc bc ; add 1 HP - ld a, c - ld [wHPBarNewHP], a - ld a, b - ld [wHPBarNewHP+1], a - call UpdateHPBar_CalcOldNewHPBarPixels - ld a, d - sub e ; calc pixel difference -.ok - call UpdateHPBar_PrintHPNumber - and a - jr z, .noPixelDifference - call UpdateHPBar_AnimateHPBar -.noPixelDifference - ld a, [wHPBarNewHP] - ld [wHPBarOldHP], a - ld a, [wHPBarNewHP+1] - ld [wHPBarOldHP+1], a - pop de - jr .animateHPBarLoop -.animateHPBarDone - pop de - ld a, e - ld [wHPBarOldHP], a - ld a, d - ld [wHPBarOldHP+1], a - or e - jr z, .monFainted - call UpdateHPBar_CalcOldNewHPBarPixels - ld d, e -.monFainted - call UpdateHPBar_PrintHPNumber - ld a, $1 - call UpdateHPBar_AnimateHPBar - jp Delay3 - -; animates the HP bar going up or down for (a) ticks (two waiting frames each) -; stops prematurely if bar is filled up -; e: current health (in pixels) to start with -UpdateHPBar_AnimateHPBar: - push hl -.barAnimationLoop - push af - push de - ld d, $6 - call DrawHPBar - ld c, 2 - call DelayFrames - pop de - ld a, [wHPBarDelta] ; +1 or -1 - add e - cp $31 - jr nc, .barFilledUp - ld e, a - pop af - dec a - jr nz, .barAnimationLoop - pop hl - ret -.barFilledUp - pop af - pop hl - ret - -; compares old HP and new HP and sets c and z flags accordingly -UpdateHPBar_CompareNewHPToOldHP: - ld a, d - sub b - ret nz - ld a, e - sub c - ret - -; calcs HP difference between bc and de (into de) -UpdateHPBar_CalcHPDifference: - ld a, d - sub b - jr c, .oldHPGreater - jr z, .testLowerByte -.newHPGreater - ld a, e - sub c - ld e, a - ld a, d - sbc b - ld d, a - ret -.oldHPGreater - ld a, c - sub e - ld e, a - ld a, b - sbc d - ld d, a - ret -.testLowerByte - ld a, e - sub c - jr c, .oldHPGreater - jr nz, .newHPGreater - ld de, $0 - ret - -UpdateHPBar_PrintHPNumber: - push af - push de - ld a, [wHPBarType] - and a - jr z, .done ; don't print number in enemy HUD -; convert from little-endian to big-endian for PrintNumber - ld a, [wHPBarOldHP] - ld [wHPBarTempHP + 1], a - ld a, [wHPBarOldHP + 1] - ld [wHPBarTempHP], a - push hl - ld de, $15 - ld a, [hFlags_0xFFFA] - bit 0, a - jr z, .next - ld de, $9 -.next - add hl, de - push hl - ld a, " " - ld [hli], a - ld [hli], a - ld [hli], a - pop hl - ld de, wHPBarTempHP - lb bc, 2, 3 - call PrintNumber - call DelayFrame - pop hl -.done - pop de - pop af - ret - -; calcs number of HP bar pixels for old and new HP value -; d: new pixels -; e: old pixels -UpdateHPBar_CalcOldNewHPBarPixels: - push hl - ld hl, wHPBarMaxHP - ld a, [hli] ; max HP into de - ld e, a - ld a, [hli] - ld d, a - ld a, [hli] ; old HP into bc - ld c, a - ld a, [hli] - ld b, a - ld a, [hli] ; new HP into hl - ld h, [hl] - ld l, a - push hl - push de - call GetHPBarLength ; calc num pixels for old HP - ld a, e - pop de - pop bc - push af - call GetHPBarLength ; calc num pixels for new HP - pop af - ld d, e - ld e, a - pop hl - ret diff --git a/engine/in_game_trades.asm b/engine/in_game_trades.asm deleted file mode 100755 index 720920df..00000000 --- a/engine/in_game_trades.asm +++ /dev/null @@ -1,350 +0,0 @@ -DoInGameTradeDialogue: -; trigger the trade offer/action specified by wWhichTrade - call SaveScreenTilesToBuffer2 - ld hl, TradeMons - ld a, [wWhichTrade] - ld bc, $e - call AddNTimes - ld a, [hli] - ld [wInGameTradeGiveMonSpecies], a - ld a, [hli] - ld [wInGameTradeReceiveMonSpecies], a - ld a, [hli] - push af - ld de, wInGameTradeMonNick - ld bc, NAME_LENGTH - call CopyData - pop af - ld l, a - ld h, 0 - ld de, InGameTradeTextPointers - add hl, hl - add hl, de - ld a, [hli] - ld [wInGameTradeTextPointerTablePointer], a - ld a, [hl] - ld [wInGameTradeTextPointerTablePointer + 1], a - ld a, [wInGameTradeGiveMonSpecies] - ld de, wInGameTradeGiveMonName - call InGameTrade_GetMonName - ld a, [wInGameTradeReceiveMonSpecies] - ld de, wInGameTradeReceiveMonName - call InGameTrade_GetMonName - ld a, $4 - ld [wInGameTradeTextPointerTableIndex], a - ld b, FLAG_TEST - call InGameTrade_FlagActionPredef - ld a, c - and a - jr nz, .printText -; if the trade hasn't been done yet - ld a, $0 - ld [wInGameTradeTextPointerTableIndex], a - call .printText - ld a, $1 - ld [wInGameTradeTextPointerTableIndex], a - call YesNoChoice - ld a, [wCurrentMenuItem] - and a - jr nz, .printText - call InGameTrade_DoTrade - jr c, .printText - ld hl, TradedForText - call PrintText -.printText - ld hl, wInGameTradeTextPointerTableIndex - ld a, [hld] ; wInGameTradeTextPointerTableIndex - ld e, a - ld d, 0 - ld a, [hld] ; wInGameTradeTextPointerTablePointer + 1 - ld l, [hl] ; wInGameTradeTextPointerTablePointer - ld h, a - add hl, de - add hl, de - ld a, [hli] - ld h, [hl] - ld l, a - jp PrintText - -; copies name of species a to hl -InGameTrade_GetMonName: - push de - ld [wd11e], a - call GetMonName - ld hl, wcd6d - pop de - ld bc, NAME_LENGTH - jp CopyData - -INCLUDE "data/trades.asm" - -InGameTrade_DoTrade: - xor a ; NORMAL_PARTY_MENU - ld [wPartyMenuTypeOrMessageID], a - dec a - ld [wUpdateSpritesEnabled], a - call DisplayPartyMenu - push af - call InGameTrade_RestoreScreen - pop af - ld a, $1 - jp c, .tradeFailed ; jump if the player didn't select a pokemon - ld a, [wInGameTradeGiveMonSpecies] - ld b, a - ld a, [wcf91] - cp b - ld a, $2 - jr nz, .tradeFailed ; jump if the selected mon's species is not the required one - ld a, [wWhichPokemon] - ld hl, wPartyMon1Level - ld bc, wPartyMon2 - wPartyMon1 - call AddNTimes - ld a, [hl] - ld [wCurEnemyLVL], a - ld b, FLAG_SET - call InGameTrade_FlagActionPredef - ld hl, ConnectCableText - call PrintText - ld a, [wWhichPokemon] - push af - ld a, [wCurEnemyLVL] - push af - call LoadHpBarAndStatusTilePatterns - call InGameTrade_PrepareTradeData - predef InternalClockTradeAnim - pop af - ld [wCurEnemyLVL], a - pop af - ld [wWhichPokemon], a - ld a, [wInGameTradeReceiveMonSpecies] - ld [wcf91], a - xor a - ld [wMonDataLocation], a ; not used - ld [wRemoveMonFromBox], a - call RemovePokemon - ld a, $80 ; prevent the player from naming the mon - ld [wMonDataLocation], a - call AddPartyMon - call InGameTrade_CopyDataToReceivedMon - call InGameTrade_CheckForTradeEvo - call ClearScreen - call InGameTrade_RestoreScreen - callba RedrawMapView - and a - ld a, $3 - jr .tradeSucceeded -.tradeFailed - scf -.tradeSucceeded - ld [wInGameTradeTextPointerTableIndex], a - ret - -InGameTrade_RestoreScreen: - call GBPalWhiteOutWithDelay3 - call RestoreScreenTilesAndReloadTilePatterns - call ReloadTilesetTilePatterns - call LoadScreenTilesFromBuffer2 - call Delay3 - call LoadGBPal - ld c, 10 - call DelayFrames - jpba LoadWildData - -InGameTrade_PrepareTradeData: - ld hl, wTradedPlayerMonSpecies - ld a, [wInGameTradeGiveMonSpecies] - ld [hli], a ; wTradedPlayerMonSpecies - ld a, [wInGameTradeReceiveMonSpecies] - ld [hl], a ; wTradedEnemyMonSpecies - ld hl, wPartyMonOT - ld bc, NAME_LENGTH - ld a, [wWhichPokemon] - call AddNTimes - ld de, wTradedPlayerMonOT - ld bc, NAME_LENGTH - call InGameTrade_CopyData - ld hl, InGameTrade_TrainerString - ld de, wTradedEnemyMonOT - call InGameTrade_CopyData - ld de, wLinkEnemyTrainerName - call InGameTrade_CopyData - ld hl, wPartyMon1OTID - ld bc, wPartyMon2 - wPartyMon1 - ld a, [wWhichPokemon] - call AddNTimes - ld de, wTradedPlayerMonOTID - ld bc, $2 - call InGameTrade_CopyData - call Random - ld hl, hRandomAdd - ld de, wTradedEnemyMonOTID - jp CopyData - -InGameTrade_CopyData: - push hl - push bc - call CopyData - pop bc - pop hl - ret - -InGameTrade_CopyDataToReceivedMon: - ld hl, wPartyMonNicks - ld bc, NAME_LENGTH - call InGameTrade_GetReceivedMonPointer - ld hl, wInGameTradeMonNick - ld bc, NAME_LENGTH - call CopyData - ld hl, wPartyMonOT - ld bc, NAME_LENGTH - call InGameTrade_GetReceivedMonPointer - ld hl, InGameTrade_TrainerString - ld bc, NAME_LENGTH - call CopyData - ld hl, wPartyMon1OTID - ld bc, wPartyMon2 - wPartyMon1 - call InGameTrade_GetReceivedMonPointer - ld hl, wTradedEnemyMonOTID - ld bc, $2 - jp CopyData - -; the received mon's index is (partyCount - 1), -; so this adds bc to hl (partyCount - 1) times and moves the result to de -InGameTrade_GetReceivedMonPointer: - ld a, [wPartyCount] - dec a - call AddNTimes - ld e, l - ld d, h - ret - -InGameTrade_FlagActionPredef: - ld hl,wCompletedInGameTradeFlags - ld a,[wWhichTrade] - ld c,a - predef_jump FlagActionPredef - -InGameTrade_CheckForTradeEvo: - ld a,[wInGameTradeReceiveMonSpecies] - cp KADABRA - jr z,.tradeEvo - cp GRAVELER - jr z,.tradeEvo - cp MACHOKE - jr z,.tradeEvo - cp HAUNTER - jr z,.tradeEvo - ret - -.tradeEvo - ld a,[wPartyCount] - dec a - ld [wWhichPokemon],a - ld a,$1 - ld [wForceEvolution],a - ld a,LINK_STATE_TRADING - ld [wLinkState],a - callab EvolveTradeMon - xor a ; LINK_STATE_NONE - ld [wLinkState],a - jp PlayDefaultMusic - -InGameTrade_TrainerString: - ; "TRAINER@@@@@@@@@@" - db $5d, "@@@@@@@@@@" - -InGameTradeTextPointers: - dw TradeTextPointers1 - dw TradeTextPointers2 - dw TradeTextPointers3 - -TradeTextPointers1: - dw WannaTrade1Text - dw NoTrade1Text - dw WrongMon1Text - dw Thanks1Text - dw AfterTrade1Text - -TradeTextPointers2: - dw WannaTrade2Text - dw NoTrade2Text - dw WrongMon2Text - dw Thanks2Text - dw AfterTrade2Text - -TradeTextPointers3: - dw WannaTrade3Text - dw NoTrade3Text - dw WrongMon3Text - dw Thanks3Text - dw AfterTrade3Text - -ConnectCableText: - TX_FAR _ConnectCableText - db "@" - -TradedForText: - TX_FAR _TradedForText - TX_SFX_KEY_ITEM - TX_DELAY - db "@" - -WannaTrade1Text: - TX_FAR _WannaTrade1Text - db "@" - -NoTrade1Text: - TX_FAR _NoTrade1Text - db "@" - -WrongMon1Text: - TX_FAR _WrongMon1Text - db "@" - -Thanks1Text: - TX_FAR _Thanks1Text - db "@" - -AfterTrade1Text: - TX_FAR _AfterTrade1Text - db "@" - -WannaTrade2Text: - TX_FAR _WannaTrade2Text - db "@" - -NoTrade2Text: - TX_FAR _NoTrade2Text - db "@" - -WrongMon2Text: - TX_FAR _WrongMon2Text - db "@" - -Thanks2Text: - TX_FAR _Thanks2Text - db "@" - -AfterTrade2Text: - TX_FAR _AfterTrade2Text - db "@" - -WannaTrade3Text: - TX_FAR _WannaTrade3Text - db "@" - -NoTrade3Text: - TX_FAR _NoTrade3Text - db "@" - -WrongMon3Text: - TX_FAR _WrongMon3Text - db "@" - -Thanks3Text: - TX_FAR _Thanks3Text - db "@" - -AfterTrade3Text: - TX_FAR _AfterTrade3Text - db "@" diff --git a/engine/init_player_data.asm b/engine/init_player_data.asm deleted file mode 100644 index 5883547c..00000000 --- a/engine/init_player_data.asm +++ /dev/null @@ -1,60 +0,0 @@ -InitPlayerData: -InitPlayerData2: - - call Random - ld a, [hRandomSub] - ld [wPlayerID], a - - call Random - ld a, [hRandomAdd] - ld [wPlayerID + 1], a - - ld a, $ff - ld [wUnusedD71B], a - - ld a, 90 ; initialize happiness to 90 - ld [wPikachuHappiness], a - ld a, $80 - ld [wPikachuMood], a ; initialize mood - - ld hl, wPartyCount - call InitializeEmptyList - ld hl, wNumInBox - call InitializeEmptyList - ld hl, wNumBagItems - call InitializeEmptyList - ld hl, wNumBoxItems - call InitializeEmptyList - -START_MONEY EQU $3000 - ld hl, wPlayerMoney + 1 - ld a, START_MONEY / $100 - ld [hld], a - xor a - ld [hli], a - inc hl - ld [hl], a - - ld [wMonDataLocation], a - - ld hl, wObtainedBadges - ld [hli], a - - ld [hl], a - - ld hl, wPlayerCoins - ld [hli], a - ld [hl], a - - ld hl, wGameProgressFlags - ld bc, wGameProgressFlagsEnd - wGameProgressFlags - call FillMemory ; clear all game progress flags - - jp InitializeMissableObjectsFlags - -InitializeEmptyList: - xor a ; count - ld [hli], a - dec a ; terminator - ld [hl], a - ret diff --git a/engine/intro.asm b/engine/intro.asm deleted file mode 100755 index 00e892da..00000000 --- a/engine/intro.asm +++ /dev/null @@ -1,164 +0,0 @@ -const_value = -1 - const MOVE_NIDORINO_RIGHT - const MOVE_GENGAR_RIGHT - const MOVE_GENGAR_LEFT - -ANIMATION_END EQU 80 - -const_value = 3 - const GENGAR_INTRO_TILES1 - const GENGAR_INTRO_TILES2 - const GENGAR_INTRO_TILES3 - -PlayIntro: - xor a - ld [hJoyHeld], a - inc a - ld [H_AUTOBGTRANSFERENABLED], a - call PlayShootingStar - callab PlayIntroScene - xor a - ld [hSCX], a - ld [H_AUTOBGTRANSFERENABLED], a - call ClearSprites - call DelayFrame - ret - -InitIntroNidorinoOAM: - ld hl, wOAMBuffer - ld d, 0 -.loop - push bc - ld a, [wBaseCoordY] - ld e, a -.innerLoop - ld a, e - add 8 - ld e, a - ld [hli], a ; Y - ld a, [wBaseCoordX] - ld [hli], a ; X - ld a, d - ld [hli], a ; tile - ld a, OAM_BEHIND_BG - ld [hli], a ; attributes - inc d - dec c - jr nz, .innerLoop - ld a, [wBaseCoordX] - add 8 - ld [wBaseCoordX], a - pop bc - dec b - jr nz, .loop - ret - -IntroClearScreen: - ld hl, vBGMap1 - ld bc, BG_MAP_WIDTH * SCREEN_HEIGHT - jr IntroClearCommon - -IntroClearMiddleOfScreen: -; clear the area of the tile map between the black bars on the top and bottom - coord hl, 0, 4 - ld bc, SCREEN_WIDTH * 10 - -IntroClearCommon: - ld [hl], 0 - inc hl - dec bc - ld a, b - or c - jr nz, IntroClearCommon - ret - -IntroPlaceBlackTiles: - ld a, 1 -.loop - ld [hli], a - dec c - jr nz, .loop - ret - -CopyTileIDsFromList_ZeroBaseTileID: - ld c, 0 - predef_jump CopyTileIDsFromList - -PlayShootingStar: - ld b, SET_PAL_GAME_FREAK_INTRO - call RunPaletteCommand - callba LoadCopyrightAndTextBoxTiles - ldPal a, BLACK, DARK_GRAY, LIGHT_GRAY, WHITE - ld [rBGP], a - call UpdateGBCPal_BGP - ld c, 180 - call DelayFrames - call ClearScreen - call DisableLCD - xor a - ld [wCurOpponent], a - call IntroDrawBlackBars -; write the black and white tiles - ld hl, vChars2 - ld bc, $10 - xor a - call FillMemory - ld hl, vChars2 + $10 - ld bc, $10 - ld a, $ff - call FillMemory -; copy gamefreak logo and others - ld hl, GameFreakIntro - ld de, vChars2 + $600 - ld bc, GameFreakIntroEnd - GameFreakIntro - ld a, BANK(GameFreakIntro) - call FarCopyData - ld hl, GameFreakIntro - ld de, vChars1 - ld bc, GameFreakIntroEnd - GameFreakIntro - ld a, BANK(GameFreakIntro) - call FarCopyData - - call EnableLCD - ld hl, rLCDC - res 5, [hl] - set 3, [hl] - ld c, 64 - call DelayFrames - callba AnimateShootingStar - push af - pop af - jr c, .next ; skip the delay if the user interrupted the animation - ld c, 40 - call DelayFrames -.next - call IntroClearMiddleOfScreen - call ClearSprites - jp Delay3 - -IntroDrawBlackBars: -; clear the screen and draw black bars on the top and bottom - call IntroClearScreen - coord hl, 0, 0 - ld c, SCREEN_WIDTH * 4 - call IntroPlaceBlackTiles - coord hl, 0, 14 - ld c, SCREEN_WIDTH * 4 - call IntroPlaceBlackTiles - ld hl, vBGMap1 - ld c, BG_MAP_WIDTH * 4 - call IntroPlaceBlackTiles - ld hl, vBGMap1 + BG_MAP_WIDTH * 14 - ld c, BG_MAP_WIDTH * 4 - jp IntroPlaceBlackTiles - -EmptyFunc4: - ret - -GameFreakIntro: - INCBIN "gfx/gamefreak_intro.2bpp" - INCBIN "gfx/gamefreak_logo.2bpp" - rept 16 - db $00 ; blank tile - endr -GameFreakIntroEnd: diff --git a/engine/items/get_bag_item_quantity.asm b/engine/items/get_bag_item_quantity.asm new file mode 100644 index 00000000..f10df1a0 --- /dev/null +++ b/engine/items/get_bag_item_quantity.asm @@ -0,0 +1,18 @@ +GetQuantityOfItemInBag: +; In: b = item ID +; Out: b = how many of that item are in the bag + call GetPredefRegisters + ld hl, wNumBagItems +.loop + inc hl + ld a, [hli] + cp $ff + jr z, .notInBag + cp b + jr nz, .loop + ld a, [hl] + ld b, a + ret +.notInBag + ld b, 0 + ret diff --git a/engine/items/inventory.asm b/engine/items/inventory.asm index 58bcf7e9..c2e0b2b4 100644 --- a/engine/items/inventory.asm +++ b/engine/items/inventory.asm @@ -4,7 +4,7 @@ ; [wcf91] = item ID ; [wItemQuantity] = item quantity ; sets carry flag if successful, unsets carry flag if unsuccessful -AddItemToInventory_: +AddItemToInventory_:: ld a, [wItemQuantity] ; a = item quantity push af push bc @@ -12,10 +12,10 @@ AddItemToInventory_: push hl push hl ld d, PC_ITEM_CAPACITY ; how many items the PC can hold - ld a, wNumBagItems & $FF + ld a, LOW(wNumBagItems) cp l jr nz, .checkIfInventoryFull - ld a, wNumBagItems >> 8 + ld a, HIGH(wNumBagItems) cp h jr nz, .checkIfInventoryFull ; if the destination is the bag @@ -98,7 +98,7 @@ AddItemToInventory_: ; hl = address of inventory (either wNumBagItems or wNumBoxItems) ; [wWhichPokemon] = index (within the inventory) of the item to remove ; [wItemQuantity] = quantity to remove -RemoveItemFromInventory_: +RemoveItemFromInventory_:: push hl inc hl ld a, [wWhichPokemon] ; index (within the inventory) of the item being removed diff --git a/engine/items/item_effects.asm b/engine/items/item_effects.asm new file mode 100755 index 00000000..b1b458ab --- /dev/null +++ b/engine/items/item_effects.asm @@ -0,0 +1,3186 @@ +UseItem_:: + ld a, 1 + ld [wActionResultOrTookBattleTurn], a ; initialise to success value + ld a, [wcf91] ;contains item_ID + cp HM01 + jp nc, ItemUseTMHM + ld hl, ItemUsePtrTable + dec a + add a + ld c, a + ld b, 0 + add hl, bc + ld a, [hli] + ld h, [hl] + ld l, a + jp hl + +ItemUsePtrTable: +; entries correspond to item ids + dw ItemUseBall ; MASTER_BALL + dw ItemUseBall ; ULTRA_BALL + dw ItemUseBall ; GREAT_BALL + dw ItemUseBall ; POKE_BALL + dw ItemUseTownMap ; TOWN_MAP + dw ItemUseBicycle ; BICYCLE + dw ItemUseSurfboard ; out-of-battle Surf effect + dw ItemUseBall ; SAFARI_BALL + dw ItemUsePokedex ; POKEDEX + dw ItemUseEvoStone ; MOON_STONE + dw ItemUseMedicine ; ANTIDOTE + dw ItemUseMedicine ; BURN_HEAL + dw ItemUseMedicine ; ICE_HEAL + dw ItemUseMedicine ; AWAKENING + dw ItemUseMedicine ; PARLYZ_HEAL + dw ItemUseMedicine ; FULL_RESTORE + dw ItemUseMedicine ; MAX_POTION + dw ItemUseMedicine ; HYPER_POTION + dw ItemUseMedicine ; SUPER_POTION + dw ItemUseMedicine ; POTION + dw ItemUseBait ; BOULDERBADGE + dw ItemUseRock ; CASCADEBADGE + dw UnusableItem ; THUNDERBADGE + dw UnusableItem ; RAINBOWBADGE + dw UnusableItem ; SOULBADGE + dw UnusableItem ; MARSHBADGE + dw UnusableItem ; VOLCANOBADGE + dw UnusableItem ; EARTHBADGE + dw ItemUseEscapeRope ; ESCAPE_ROPE + dw ItemUseRepel ; REPEL + dw UnusableItem ; OLD_AMBER + dw ItemUseEvoStone ; FIRE_STONE + dw ItemUseEvoStone ; THUNDER_STONE + dw ItemUseEvoStone ; WATER_STONE + dw ItemUseVitamin ; HP_UP + dw ItemUseVitamin ; PROTEIN + dw ItemUseVitamin ; IRON + dw ItemUseVitamin ; CARBOS + dw ItemUseVitamin ; CALCIUM + dw ItemUseVitamin ; RARE_CANDY + dw UnusableItem ; DOME_FOSSIL + dw UnusableItem ; HELIX_FOSSIL + dw UnusableItem ; SECRET_KEY + dw UnusableItem + dw UnusableItem ; BIKE_VOUCHER + dw ItemUseXAccuracy ; X_ACCURACY + dw ItemUseEvoStone ; LEAF_STONE + dw ItemUseCardKey ; CARD_KEY + dw UnusableItem ; NUGGET + dw UnusableItem ; ??? PP_UP + dw ItemUsePokedoll ; POKE_DOLL + dw ItemUseMedicine ; FULL_HEAL + dw ItemUseMedicine ; REVIVE + dw ItemUseMedicine ; MAX_REVIVE + dw ItemUseGuardSpec ; GUARD_SPEC + dw ItemUseSuperRepel ; SUPER_REPL + dw ItemUseMaxRepel ; MAX_REPEL + dw ItemUseDireHit ; DIRE_HIT + dw UnusableItem ; COIN + dw ItemUseMedicine ; FRESH_WATER + dw ItemUseMedicine ; SODA_POP + dw ItemUseMedicine ; LEMONADE + dw UnusableItem ; S_S_TICKET + dw UnusableItem ; GOLD_TEETH + dw ItemUseXStat ; X_ATTACK + dw ItemUseXStat ; X_DEFEND + dw ItemUseXStat ; X_SPEED + dw ItemUseXStat ; X_SPECIAL + dw ItemUseCoinCase ; COIN_CASE + dw ItemUseOaksParcel ; OAKS_PARCEL + dw ItemUseItemfinder ; ITEMFINDER + dw UnusableItem ; SILPH_SCOPE + dw ItemUsePokeflute ; POKE_FLUTE + dw UnusableItem ; LIFT_KEY + dw UnusableItem ; EXP_ALL + dw ItemUseOldRod ; OLD_ROD + dw ItemUseGoodRod ; GOOD_ROD + dw ItemUseSuperRod ; SUPER_ROD + dw ItemUsePPUp ; PP_UP (real one) + dw ItemUsePPRestore ; ETHER + dw ItemUsePPRestore ; MAX_ETHER + dw ItemUsePPRestore ; ELIXER + dw ItemUsePPRestore ; MAX_ELIXER + +ItemUseBall: + +; Balls can't be used out of battle. + ld a, [wIsInBattle] + and a + jp z, ItemUseNotTime + +; Balls can't catch trainers' Pokémon. + dec a + jp nz, ThrowBallAtTrainerMon + +; If this is for the old man battle, skip checking if the party & box are full. + ld a, [wBattleType] + cp BATTLE_TYPE_OLD_MAN + jr z, .canUseBall + cp BATTLE_TYPE_PIKACHU + jr z, .canUseBall + + ld a, [wPartyCount] ; is party full? + cp PARTY_LENGTH + jr nz, .canUseBall + ld a, [wNumInBox] ; is box full? + cp MONS_PER_BOX + jp z, BoxFullCannotThrowBall + +.canUseBall + xor a + ld [wCapturedMonSpecies], a + + ld a, [wBattleType] + cp BATTLE_TYPE_SAFARI + jr nz, .skipSafariZoneCode + +.safariZone + ld hl, wNumSafariBalls + dec [hl] ; remove a Safari Ball + +.skipSafariZoneCode + call RunDefaultPaletteCommand + + ld a, $43 ; successful capture value + ld [wPokeBallAnimData], a + + call LoadScreenTilesFromBuffer1 + ld hl, ItemUseText00 + call PrintText + +; If the player is fighting an unidentified ghost, set the value that indicates +; the Pokémon can't be caught and skip the capture calculations. + callfar IsGhostBattle + ld b, $10 ; can't be caught value + jp z, .setAnimData + + ld a, [wBattleType] + cp BATTLE_TYPE_OLD_MAN + jr z, .oldManBattle + cp BATTLE_TYPE_PIKACHU + jr z, .oldManBattle ; pikachu battle technically old man battle + jr .notOldManBattle + +.oldManBattle + ld hl, wGrassRate + ld de, wPlayerName + ld bc, NAME_LENGTH + call CopyData ; save the player's name in the Wild Monster data (part of the Cinnabar Island Missingno. glitch) + ld a, [wBattleType] + cp BATTLE_TYPE_OLD_MAN + jp nz, .captured + ld a, $1 + ld [wCapturedMonSpecies], a + CheckEvent EVENT_02F + ld b, $63 + jp nz, .setAnimData + jp .captured +.notOldManBattle +; If the player is fighting the ghost Marowak, set the value that indicates the +; Pokémon can't be caught and skip the capture calculations. + ld a, [wCurMap] + cp POKEMON_TOWER_6F + jr nz, .loop + ld a, [wEnemyMonSpecies2] + cp RESTLESS_SOUL + ld b, $10 ; can't be caught value + jp z, .setAnimData + +; Get the first random number. Let it be called Rand1. +; Rand1 must be within a certain range according the kind of ball being thrown. +; The ranges are as follows. +; Poké Ball: [0, 255] +; Great Ball: [0, 200] +; Ultra/Safari Ball: [0, 150] +; Loop until an acceptable number is found. + +.loop + call Random + ld b, a + +; Get the item ID. + ld hl, wcf91 + ld a, [hl] + +; The Master Ball always succeeds. + cp MASTER_BALL + jp z, .captured + +; Anything will do for the basic Poké Ball. + cp POKE_BALL + jr z, .checkForAilments + +; If it's a Great/Ultra/Safari Ball and Rand1 is greater than 200, try again. + ld a, 200 + cp b + jr c, .loop + +; Less than or equal to 200 is good enough for a Great Ball. + ld a, [hl] + cp GREAT_BALL + jr z, .checkForAilments + +; If it's an Ultra/Safari Ball and Rand1 is greater than 150, try again. + ld a, 150 + cp b + jr c, .loop + +.checkForAilments +; Pokémon can be caught more easily with a status ailment. +; Depending on the status ailment, a certain value will be subtracted from +; Rand1. Let this value be called Status. +; The larger Status is, the more easily the Pokémon can be caught. +; no status ailment: Status = 0 +; Burn/Paralysis/Poison: Status = 12 +; Freeze/Sleep: Status = 25 +; If Status is greater than Rand1, the Pokémon will be caught for sure. + ld a, [wEnemyMonStatus] + and a + jr z, .skipAilmentValueSubtraction ; no ailments + and 1 << FRZ | SLP + ld c, 12 + jr z, .notFrozenOrAsleep + ld c, 25 +.notFrozenOrAsleep + ld a, b + sub c + jp c, .captured + ld b, a + +.skipAilmentValueSubtraction + push bc ; save (Rand1 - Status) + +; Calculate MaxHP * 255. + xor a + ldh [hMultiplicand], a + ld hl, wEnemyMonMaxHP + ld a, [hli] + ldh [hMultiplicand + 1], a + ld a, [hl] + ldh [hMultiplicand + 2], a + ld a, 255 + ldh [hMultiplier], a + call Multiply + +; Determine BallFactor. It's 8 for Great Balls and 12 for the others. + ld a, [wcf91] + cp GREAT_BALL + ld a, 12 + jr nz, .skip1 + ld a, 8 + +.skip1 +; Note that the results of all division operations are floored. + +; Calculate (MaxHP * 255) / BallFactor. + ldh [hDivisor], a + ld b, 4 ; number of bytes in dividend + call Divide + +; Divide the enemy's current HP by 4. HP is not supposed to exceed 999 so +; the result should fit in a. If the division results in a quotient of 0, +; change it to 1. + ld hl, wEnemyMonHP + ld a, [hli] + ld b, a + ld a, [hl] + srl b + rr a + srl b + rr a + and a + jr nz, .skip2 + inc a + +.skip2 + +; Let W = ((MaxHP * 255) / BallFactor) / max(HP / 4, 1). Calculate W. + ldh [hDivisor], a + ld b, 4 + call Divide + +; If W > 255, store 255 in [hQuotient + 3]. +; Let X = min(W, 255) = [hQuotient + 3]. + ldh a, [hQuotient + 2] + and a + jr z, .skip3 + ld a, 255 + ldh [hQuotient + 3], a + +.skip3 + pop bc ; b = Rand1 - Status + +; If Rand1 - Status > CatchRate, the ball fails to capture the Pokémon. + ld a, [wEnemyMonActualCatchRate] + cp b + jr c, .failedToCapture + +; If W > 255, the ball captures the Pokémon. + ldh a, [hQuotient + 2] + and a + jr nz, .captured + + call Random ; Let this random number be called Rand2. + +; If Rand2 > X, the ball fails to capture the Pokémon. + ld b, a + ldh a, [hQuotient + 3] + cp b + jr c, .failedToCapture + +.captured + jr .skipShakeCalculations + +.failedToCapture + ldh a, [hQuotient + 3] + ld [wPokeBallCaptureCalcTemp], a ; Save X. + +; Calculate CatchRate * 100. + xor a + ldh [hMultiplicand], a + ldh [hMultiplicand + 1], a + ld a, [wEnemyMonActualCatchRate] + ldh [hMultiplicand + 2], a + ld a, 100 + ldh [hMultiplier], a + call Multiply + +; Determine BallFactor2. +; Poké Ball: BallFactor2 = 255 +; Great Ball: BallFactor2 = 200 +; Ultra/Safari Ball: BallFactor2 = 150 + ld a, [wcf91] + ld b, 255 + cp POKE_BALL + jr z, .skip4 + ld b, 200 + cp GREAT_BALL + jr z, .skip4 + ld b, 150 + cp ULTRA_BALL + jr z, .skip4 + +.skip4 + +; Let Y = (CatchRate * 100) / BallFactor2. Calculate Y. + ld a, b + ldh [hDivisor], a + ld b, 4 + call Divide + +; If Y > 255, there are 3 shakes. +; Note that this shouldn't be possible. +; The maximum value of Y is (255 * 100) / 150 = 170. + ldh a, [hQuotient + 2] + and a + ld b, $63 ; 3 shakes + jr nz, .setAnimData + +; Calculate X * Y. + ld a, [wPokeBallCaptureCalcTemp] + ldh [hMultiplier], a + call Multiply + +; Calculate (X * Y) / 255. + ld a, 255 + ldh [hDivisor], a + ld b, 4 + call Divide + +; Determine Status2. +; no status ailment: Status2 = 0 +; Burn/Paralysis/Poison: Status2 = 5 +; Freeze/Sleep: Status2 = 10 + ld a, [wEnemyMonStatus] + and a + jr z, .skip5 + and 1 << FRZ | SLP + ld b, 5 + jr z, .addAilmentValue + ld b, 10 + +.addAilmentValue +; If the Pokémon has a status ailment, add Status2. + ldh a, [hQuotient + 3] + add b + ldh [hQuotient + 3], a + +.skip5 +; Finally determine the number of shakes. +; Let Z = ((X * Y) / 255) + Status2 = [hQuotient + 3]. +; The number of shakes depend on the range Z is in. +; 0 ≤ Z < 10: 0 shakes (the ball misses) +; 10 ≤ Z < 30: 1 shake +; 30 ≤ Z < 70: 2 shakes +; 70 ≤ Z: 3 shakes + ldh a, [hQuotient + 3] + cp 10 + ld b, $20 + jr c, .setAnimData + cp 30 + ld b, $61 + jr c, .setAnimData + cp 70 + ld b, $62 + jr c, .setAnimData + ld b, $63 + +.setAnimData + ld a, b + ld [wPokeBallAnimData], a + +.skipShakeCalculations + ld c, 20 + call DelayFrames + +; Do the animation. + ld a, TOSS_ANIM + ld [wAnimationID], a + xor a + ldh [hWhoseTurn], a + ld [wAnimationType], a + ld [wDamageMultipliers], a + ld a, [wWhichPokemon] + push af + ld a, [wcf91] + push af + predef MoveAnimation + pop af + ld [wcf91], a + pop af + ld [wWhichPokemon], a + +; Determine the message to display from the animation. + ld a, [wPokeBallAnimData] + cp $10 + ld hl, ItemUseBallText00 + jp z, .printMessage + cp $20 + ld hl, ItemUseBallText01 + jp z, .printMessage + cp $61 + ld hl, ItemUseBallText02 + jp z, .printMessage + cp $62 + ld hl, ItemUseBallText03 + jp z, .printMessage + cp $63 + ld hl, ItemUseBallText04 + jp z, .printMessage + +; Save current HP. + ld hl, wEnemyMonHP + ld a, [hli] + push af + ld a, [hli] + push af + +; Save status ailment. + inc hl + ld a, [hl] + push af + + push hl + +; If the Pokémon is transformed, the Pokémon is assumed to be a Ditto. +; This is a bug because a wild Pokémon could have used Transform via +; Mirror Move even though the only wild Pokémon that knows Transform is Ditto. + ld hl, wEnemyBattleStatus3 + bit TRANSFORMED, [hl] + jr z, .notTransformed + ld a, DITTO + ld [wEnemyMonSpecies2], a + jr .skip6 + +.notTransformed +; If the Pokémon is not transformed, set the transformed bit and copy the +; DVs to wTransformedEnemyMonOriginalDVs so that LoadEnemyMonData won't generate +; new DVs. + set TRANSFORMED, [hl] + ld hl, wTransformedEnemyMonOriginalDVs + ld a, [wEnemyMonDVs] + ld [hli], a + ld a, [wEnemyMonDVs + 1] + ld [hl], a + +.skip6 + ld a, [wcf91] + push af + ld a, [wEnemyMonSpecies2] + ld [wcf91], a + ld a, [wEnemyMonLevel] + ld [wCurEnemyLVL], a + callfar LoadEnemyMonData + pop af + ld [wcf91], a + pop hl + pop af + ld [hld], a + dec hl + pop af + ld [hld], a + pop af + ld [hl], a + ld a, [wEnemyMonSpecies] + ld [wCapturedMonSpecies], a + ld [wcf91], a + ld [wd11e], a + ld a, [wBattleType] + cp BATTLE_TYPE_OLD_MAN ; is this the old man battle? + jp z, .oldManCaughtMon ; if so, don't give the player the caught Pokémon + cp BATTLE_TYPE_PIKACHU + jr z, .oldManCaughtMon ; same with Pikachu battle + ld hl, ItemUseBallText05 + call PrintText + +; Add the caught Pokémon to the Pokédex. + predef IndexToPokedex + ld a, [wd11e] + dec a + ld c, a + ld b, FLAG_TEST + ld hl, wPokedexOwned + predef FlagActionPredef + ld a, c + push af + ld a, [wd11e] + dec a + ld c, a + ld b, FLAG_SET + predef FlagActionPredef + pop af + + and a ; was the Pokémon already in the Pokédex? + jr nz, .skipShowingPokedexData ; if so, don't show the Pokédex data + + ld hl, ItemUseBallText06 + call PrintText + call ClearSprites + ld a, [wEnemyMonSpecies] + ld [wd11e], a + predef ShowPokedexData + +.skipShowingPokedexData + ld a, $1 + ld [wd49c], a + ld a, $85 + ld [wPikachuMood], a + ld a, [wPartyCount] + cp PARTY_LENGTH ; is party full? + jr z, .sendToBox + xor a ; PLAYER_PARTY_DATA + ld [wMonDataLocation], a + call ClearSprites + ld hl, .emptyString + call PrintText + call AddPartyMon + jr .done + +.sendToBox + call ClearSprites + call SendNewMonToBox + ld hl, ItemUseBallText07 + CheckEvent EVENT_MET_BILL + jr nz, .printTransferredToPCText + ld hl, ItemUseBallText08 +.printTransferredToPCText + call PrintText + jr .done + +.oldManCaughtMon + ld hl, ItemUseBallText05 + +.printMessage + call PrintText + call ClearSprites + +.done + ld a, [wBattleType] + and a ; is this the old man battle? + ret nz ; if so, don't remove a ball from the bag + +; Remove a ball from the bag. + ld hl, wNumBagItems + inc a + ld [wItemQuantity], a + jp RemoveItemFromInventory + +.emptyString + db "@" + +ItemUseBallText00: +;"It dodged the thrown ball!" +;"This pokemon can't be caught" + text_far _ItemUseBallText00 + text_end +ItemUseBallText01: +;"You missed the pokemon!" + text_far _ItemUseBallText01 + text_end +ItemUseBallText02: +;"Darn! The pokemon broke free!" + text_far _ItemUseBallText02 + text_end +ItemUseBallText03: +;"Aww! It appeared to be caught!" + text_far _ItemUseBallText03 + text_end +ItemUseBallText04: +;"Shoot! It was so close too!" + text_far _ItemUseBallText04 + text_end +ItemUseBallText05: +;"All right! {MonName} was caught!" +;play sound + text_far _ItemUseBallText05 + sound_caught_mon + text_promptbutton + text_end +ItemUseBallText07: +;"X was transferred to Bill's PC" + text_far _ItemUseBallText07 + text_end +ItemUseBallText08: +;"X was transferred to someone's PC" + text_far _ItemUseBallText08 + text_end + +ItemUseBallText06: +;"New DEX data will be added..." +;play sound + text_far _ItemUseBallText06 + sound_dex_page_added + text_promptbutton + text_end + +ItemUseTownMap: + ld a, [wIsInBattle] + and a + jp nz, ItemUseNotTime + farjp DisplayTownMap + +ItemUseBicycle: + ld a, [wIsInBattle] + and a + jp nz, ItemUseNotTime + ld a, [wWalkBikeSurfState] + ld [wWalkBikeSurfStateCopy], a + cp 2 ; is the player surfing? + jp z, ItemUseNotTime + dec a ; is player already bicycling? + jr nz, .tryToGetOnBike +.getOffBike + call ItemUseReloadOverworldData + xor a + ld [wWalkBikeSurfState], a ; change player state to walking + ld a, $00 + ld [wPikachuSpawnState], a + call PlayDefaultMusic ; play walking music + ld hl, GotOffBicycleText + jp PrintText + +.tryToGetOnBike + call IsBikeRidingAllowed + jp nc, NoCyclingAllowedHere + call ItemUseReloadOverworldData + xor a ; no keys pressed + ldh [hJoyHeld], a ; current joypad state + ld a, $1 + ld [wWalkBikeSurfState], a ; change player state to bicycling + call PlayDefaultMusic ; play bike riding music + xor a + ld [wWalkBikeSurfState], a + ld hl, GotOnBicycleText + call PrintText + ld a, $1 + ld [wWalkBikeSurfState], a + ret + +; used for Surf out-of-battle effect +ItemUseSurfboard: + ld a, [wWalkBikeSurfState] + ld [wWalkBikeSurfStateCopy], a + cp 2 ; is the player already surfing? + jr z, .tryToStopSurfing +.tryToSurf + call IsNextTileShoreOrWater + jp nc, SurfingAttemptFailed + ld hl, TilePairCollisionsWater + call CheckForTilePairCollisions + jp c, SurfingAttemptFailed +.surf + call .makePlayerMoveForward + ld hl, wd730 + set 7, [hl] + ld a, 2 + ld [wWalkBikeSurfState], a ; change player state to surfing + call PlayDefaultMusic ; play surfing music + ld hl, SurfingGotOnText + jp PrintText + +.tryToStopSurfing + xor a + ldh [hSpriteIndexOrTextID], a + ld d, 16 ; talking range in pixels (normal range) + call IsSpriteInFrontOfPlayer2 + res 7, [hl] + ldh a, [hSpriteIndexOrTextID] + and a ; is there a sprite in the way? + jr nz, .cannotStopSurfing + ld hl, TilePairCollisionsWater + call CheckForTilePairCollisions + jr c, .cannotStopSurfing + ld a, [wTileInFrontOfPlayer] + ld c, a + call IsTilePassable + jr nc, .stopSurfing +.cannotStopSurfing + ld hl, SurfingNoPlaceToGetOffText + jp PrintText + +.stopSurfing + call .makePlayerMoveForward + ld a, $3 + ld [wPikachuSpawnState], a + ld hl, wPikachuOverworldStateFlags + set 5, [hl] + ld hl, wd730 + set 7, [hl] + xor a + ld [wWalkBikeSurfState], a ; change player state to walking + dec a + ld [wJoyIgnore], a + call PlayDefaultMusic ; play walking music + call GBPalWhiteOutWithDelay3 + jp LoadWalkingPlayerSpriteGraphics + +; uses a simulated button press to make the player move forward +.makePlayerMoveForward + ld a, [wPlayerDirection] ; direction the player is going + bit PLAYER_DIR_BIT_UP, a + ld b, D_UP + jr nz, .storeSimulatedButtonPress + bit PLAYER_DIR_BIT_DOWN, a + ld b, D_DOWN + jr nz, .storeSimulatedButtonPress + bit PLAYER_DIR_BIT_LEFT, a + ld b, D_LEFT + jr nz, .storeSimulatedButtonPress + ld b, D_RIGHT +.storeSimulatedButtonPress + ld a, b + ld [wSimulatedJoypadStatesEnd], a + xor a + ld [wWastedByteCD39], a + inc a + ld [wSimulatedJoypadStatesIndex], a + ret + +SurfingGotOnText: + text_far _SurfingGotOnText + text_end + +SurfingNoPlaceToGetOffText: + text_far _SurfingNoPlaceToGetOffText + text_end + +ItemUsePokedex: + predef_jump ShowPokedexMenu + +ItemUseEvoStone: + ld a, [wIsInBattle] + and a + jp nz, ItemUseNotTime + ld a, [wWhichPokemon] + push af + ld a, [wcf91] + ld [wEvoStoneItemID], a + push af + ld a, EVO_STONE_PARTY_MENU + ld [wPartyMenuTypeOrMessageID], a + ld a, $ff + ld [wUpdateSpritesEnabled], a + call DisplayPartyMenu + ld a, [wcf91] + ld [wLoadedMon], a + pop bc + jr c, .canceledItemUse + ld a, b + ld [wcf91], a + call Func_d85d + jr nc, .noEffect + callfar IsThisPartymonStarterPikachu_Party + jr nc, .notPlayerPikachu + ld e, $1b + callfar PlayPikachuSoundClip + ld a, [wWhichPokemon] + ld hl, wPartyMonNicks + call GetPartyMonName + ld hl, RefusingText + call PrintText + ld a, $4 + ld [wd49c], a + ld a, $82 + ld [wPikachuMood], a + jr .canceledItemUse + +.notPlayerPikachu + ld a, SFX_HEAL_AILMENT + call PlaySoundWaitForCurrent + call WaitForSoundToFinish + ld a, $01 + ld [wForceEvolution], a + callfar TryEvolvingMon ; try to evolve pokemon + pop af + ld [wWhichPokemon], a + ld hl, wNumBagItems + ld a, 1 ; remove 1 stone + ld [wItemQuantity], a + jp RemoveItemFromInventory + +.noEffect + call ItemUseNoEffect +.canceledItemUse + xor a + ld [wActionResultOrTookBattleTurn], a ; item not used + pop af + ret + +Func_d85d: + ld hl, EvosMovesPointerTable + ld a, [wLoadedMon] + dec a + ld c, a + ld b, $0 + add hl, bc + add hl, bc + ld de, wcd6d + ld a, BANK(TryEvolvingMon) + ld bc, $2 + call FarCopyData + ld hl, wcd6d + ld a, [hli] + ld h, [hl] + ld l, a + ld de, wcd6d + ld a, BANK(TryEvolvingMon) + ld bc, 13 + call FarCopyData + ld hl, wcd6d +.loop + ld a, [hli] + and a + jr z, .cannotEvolveWithUsedStone + inc hl + inc hl + cp EV_ITEM + jr nz, .loop + dec hl + dec hl + ld b, [hl] + ld a, [wcf91] + inc hl + inc hl + inc hl + cp b + jr nz, .loop + scf + ret + +.cannotEvolveWithUsedStone + and a + ret + +RefusingText: + text_far _RefusingText + text_end + +ItemUseVitamin: + ld a, [wIsInBattle] + and a + jp nz, ItemUseNotTime + +ItemUseMedicine: + ld a, [wPartyCount] + and a + jp z, Func_e4bf + ld a, [wWhichPokemon] + push af + ld a, [wcf91] + push af + ld a, USE_ITEM_PARTY_MENU + ld [wPartyMenuTypeOrMessageID], a + ld a, $ff + ld [wUpdateSpritesEnabled], a + ld a, [wPseudoItemID] + and a ; using Softboiled? + jr z, .notUsingSoftboiled +; if using softboiled + call GoBackToPartyMenu + jr .getPartyMonDataAddress +.notUsingSoftboiled + call DisplayPartyMenu +.getPartyMonDataAddress + jp c, .canceledItemUse + ld hl, wPartyMons + ld bc, wPartyMon2 - wPartyMon1 + ld a, [wWhichPokemon] + call AddNTimes + ld a, [wWhichPokemon] + ld [wUsedItemOnWhichPokemon], a + ld d, a + ld a, [wcf91] + ld e, a + ld [wd0b5], a + pop af + push af + cp $28 + jr nc, .asm_d906 + push hl + push de + callabd_ModifyPikachuHappiness PIKAHAPPY_USEDITEM + pop de + pop hl +.asm_d906 + pop af + ld [wcf91], a + pop af + ld [wWhichPokemon], a + ld a, [wPseudoItemID] + and a ; using Softboiled? + jr z, .checkItemType +; if using softboiled + ld a, [wWhichPokemon] + cp d ; is the pokemon trying to use softboiled on itself? + jr z, ItemUseMedicine ; if so, force another choice +.checkItemType + ld a, [wcf91] + cp REVIVE + jr nc, .healHP ; if it's a Revive or Max Revive + cp FULL_HEAL + jr z, .cureStatusAilment ; if it's a Full Heal + cp HP_UP + jp nc, .useVitamin ; if it's a vitamin or Rare Candy + cp FULL_RESTORE + jr nc, .healHP ; if it's a Full Restore or one of the potions +; fall through if it's one of the status-specific healing items +.cureStatusAilment + ld bc, wPartyMon1Status - wPartyMon1 + add hl, bc ; hl now points to status + ld a, [wcf91] + lb bc, ANTIDOTE_MSG, 1 << PSN + cp ANTIDOTE + jr z, .checkMonStatus + lb bc, BURN_HEAL_MSG, 1 << BRN + cp BURN_HEAL + jr z, .checkMonStatus + lb bc, ICE_HEAL_MSG, 1 << FRZ + cp ICE_HEAL + jr z, .checkMonStatus + lb bc, AWAKENING_MSG, SLP + cp AWAKENING + jr z, .checkMonStatus + lb bc, PARALYZ_HEAL_MSG, 1 << PAR + cp PARLYZ_HEAL + jr z, .checkMonStatus + lb bc, FULL_HEAL_MSG, $ff ; Full Heal +.checkMonStatus + ld a, [hl] ; pokemon's status + and c ; does the pokemon have a status ailment the item can cure? + jp z, .healingItemNoEffect +; if the pokemon has a status the item can heal + xor a + ld [hl], a ; remove the status ailment in the party data + ld a, b + ld [wPartyMenuTypeOrMessageID], a ; the message to display for the item used + ld a, [wPlayerMonNumber] + cp d ; is pokemon the item was used on active in battle? + jp nz, .doneHealing +; if it is active in battle + xor a + ld [wBattleMonStatus], a ; remove the status ailment in the in-battle pokemon data + push hl + ld hl, wPlayerBattleStatus3 + res BADLY_POISONED, [hl] ; heal Toxic status + pop hl + ld bc, wPartyMon1Stats - wPartyMon1Status + add hl, bc ; hl now points to party stats + ld de, wBattleMonStats + ld bc, NUM_STATS * 2 + call CopyData ; copy party stats to in-battle stat data + predef DoubleOrHalveSelectedStats + jp .doneHealing + +.healHP + inc hl ; hl = address of current HP + ld a, [hli] + ld b, a + ld [wHPBarOldHP+1], a + ld a, [hl] + ld c, a + ld [wHPBarOldHP], a ; current HP stored at wHPBarOldHP (2 bytes, big-endian) + or b + jr nz, .notFainted +.fainted + ld a, [wcf91] + cp REVIVE + jr z, .updateInBattleFaintedData + cp MAX_REVIVE + jr z, .updateInBattleFaintedData + jp .healingItemNoEffect + +.updateInBattleFaintedData + ld a, [wWhichPokemon] + push af + ld a, [wUsedItemOnWhichPokemon] + ld [wWhichPokemon], a + push hl + push de + push bc + callfar Func_2fd6a + pop bc + pop de + pop hl + pop af + ld [wWhichPokemon], a + + ld a, [wIsInBattle] + and a + jr z, .compareCurrentHPToMaxHP + push hl + push de + push bc + ld a, [wUsedItemOnWhichPokemon] + ld c, a + ld hl, wPartyFoughtCurrentEnemyFlags + ld b, FLAG_TEST + predef FlagActionPredef + ld a, c + and a + jr z, .next + ld a, [wUsedItemOnWhichPokemon] + ld c, a + ld hl, wPartyGainExpFlags + ld b, FLAG_SET + predef FlagActionPredef +.next + pop bc + pop de + pop hl + jr .compareCurrentHPToMaxHP + +.notFainted + ld a, [wcf91] + cp REVIVE + jp z, .healingItemNoEffect + cp MAX_REVIVE + jp z, .healingItemNoEffect +.compareCurrentHPToMaxHP + push hl + push bc + ld bc, wPartyMon1MaxHP - (wPartyMon1HP + 1) + add hl, bc ; hl now points to max HP + pop bc + ld a, [hli] + cp b + jr nz, .skipComparingLSB ; no need to compare the LSB's if the MSB's don't match + ld a, [hl] + cp c +.skipComparingLSB + pop hl + jr nz, .notFullHP +.fullHP ; if the pokemon's current HP equals its max HP + ld a, [wcf91] + cp FULL_RESTORE + jp nz, .healingItemNoEffect + inc hl + inc hl + ld a, [hld] ; status ailment + and a ; does the pokemon have a status ailment? + jp z, .healingItemNoEffect + ld a, FULL_HEAL + ld [wcf91], a + dec hl + dec hl + dec hl + jp .cureStatusAilment + +.notFullHP ; if the pokemon's current HP doesn't equal its max HP + xor a + ld [wLowHealthAlarm], a ;disable low health alarm + ld [wChannelSoundIDs + Ch5], a + push hl + push de + ld bc, wPartyMon1MaxHP - (wPartyMon1HP + 1) + add hl, bc ; hl now points to max HP + ld a, [hli] + ld [wHPBarMaxHP+1], a + ld a, [hl] + ld [wHPBarMaxHP], a ; max HP stored at wHPBarMaxHP (2 bytes, big-endian) + ld a, [wPseudoItemID] + and a ; using Softboiled? + jp z, .notUsingSoftboiled2 +; if using softboiled + ld hl, wHPBarMaxHP + ld a, [hli] + push af + ld a, [hli] + push af + ld a, [hli] + push af + ld a, [hl] + push af + ld hl, wPartyMon1MaxHP + ld a, [wWhichPokemon] + ld bc, wPartyMon2 - wPartyMon1 + call AddNTimes + ld a, [hli] + ld [wHPBarMaxHP + 1], a + ldh [hDividend], a + ld a, [hl] + ld [wHPBarMaxHP], a + ldh [hDividend + 1], a + ld a, 5 + ldh [hDivisor], a + ld b, 2 ; number of bytes + call Divide ; get 1/5 of max HP of pokemon that used Softboiled + ld bc, (wPartyMon1HP + 1) - (wPartyMon1MaxHP + 1) + add hl, bc ; hl now points to LSB of current HP of pokemon that used Softboiled +; subtract 1/5 of max HP from current HP of pokemon that used Softboiled + ldh a, [hQuotient + 3] + push af + ld b, a + ld a, [hl] + ld [wHPBarOldHP], a + sub b + ld [hld], a + ld [wHPBarNewHP], a + ldh a, [hQuotient + 2] + ld b, a + ld a, [hl] + ld [wHPBarOldHP+1], a + sbc b + ld [hl], a + ld [wHPBarNewHP+1], a + hlcoord 4, 1 + ld a, [wWhichPokemon] + ld bc, 2 * SCREEN_WIDTH + call AddNTimes ; calculate coordinates of HP bar of pokemon that used Softboiled + ld a, SFX_HEAL_HP + call PlaySoundWaitForCurrent + ldh a, [hFlagsFFFA] + set 0, a + ldh [hFlagsFFFA], a + ld a, $02 + ld [wHPBarType], a + predef UpdateHPBar2 ; animate HP bar decrease of pokemon that used Softboiled + ldh a, [hFlagsFFFA] + res 0, a + ldh [hFlagsFFFA], a + pop af + ld b, a ; store heal amount (1/5 of max HP) + ld hl, wHPBarOldHP + 1 + pop af + ld [hld], a + pop af + ld [hld], a + pop af + ld [hld], a + pop af + ld [hl], a + jr .addHealAmount + +.notUsingSoftboiled2 + ld a, [wcf91] + cp SODA_POP + ld b, 60 ; Soda Pop heal amount + jr z, .addHealAmount + ld b, 80 ; Lemonade heal amount + jr nc, .addHealAmount + cp FRESH_WATER + ld b, 50 ; Fresh Water heal amount + jr z, .addHealAmount + cp SUPER_POTION + ld b, 200 ; Hyper Potion heal amount + jr c, .addHealAmount + ld b, 50 ; Super Potion heal amount + jr z, .addHealAmount + ld b, 20 ; Potion heal amount +.addHealAmount + pop de + pop hl + ld a, [hl] + add b + ld [hld], a + ld [wHPBarNewHP], a + ld a, [hl] + ld [wHPBarNewHP+1], a + jr nc, .noCarry + inc [hl] + ld a, [hl] + ld [wHPBarNewHP + 1], a +.noCarry + push de + inc hl + ld d, h + ld e, l ; de now points to current HP + ld hl, (wPartyMon1MaxHP + 1) - (wPartyMon1HP + 1) + add hl, de ; hl now points to max HP + ld a, [wcf91] + cp REVIVE + jr z, .setCurrentHPToHalfMaxHP + ld a, [hld] + ld b, a + ld a, [de] + sub b + dec de + ld b, [hl] + ld a, [de] + sbc b + jr nc, .setCurrentHPToMaxHp ; if current HP exceeds max HP after healing + ld a, [wcf91] + cp HYPER_POTION + jr c, .setCurrentHPToMaxHp ; if using a Full Restore or Max Potion + cp MAX_REVIVE + jr z, .setCurrentHPToMaxHp ; if using a Max Revive + jr .updateInBattleData + +.setCurrentHPToHalfMaxHP + dec hl + dec de + ld a, [hli] + srl a + ld [de], a + ld [wHPBarNewHP+1], a + ld a, [hl] + rr a + inc de + ld [de], a + ld [wHPBarNewHP], a + dec de + jr .doneHealingPartyHP + +.setCurrentHPToMaxHp + ld a, [hli] + ld [de], a + ld [wHPBarNewHP+1], a + inc de + ld a, [hl] + ld [de], a + ld [wHPBarNewHP], a + dec de +.doneHealingPartyHP ; done updating the pokemon's current HP in the party data structure + ld a, [wcf91] + cp FULL_RESTORE + jr nz, .updateInBattleData + ld bc, wPartyMon1Status - (wPartyMon1MaxHP + 1) + add hl, bc + xor a + ld [hl], a ; remove the status ailment in the party data +.updateInBattleData + ld h, d + ld l, e + pop de + ld a, [wPlayerMonNumber] + cp d ; is pokemon the item was used on active in battle? + jr nz, .calculateHPBarCoords +; copy party HP to in-battle HP + ld a, [hli] + ld [wBattleMonHP], a + ld a, [hld] + ld [wBattleMonHP + 1], a + ld a, [wcf91] + cp FULL_RESTORE + jr nz, .calculateHPBarCoords + xor a + ld [wBattleMonStatus], a ; remove the status ailment in the in-battle pokemon data +.calculateHPBarCoords + ld hl, wOAMBuffer + $90 + ld bc, 2 * SCREEN_WIDTH + inc d +.calculateHPBarCoordsLoop + add hl, bc + dec d + jr nz, .calculateHPBarCoordsLoop + jr .doneHealing + +.healingItemNoEffect + call ItemUseNoEffect + jp .done + +.doneHealing + ld a, [wPseudoItemID] + and a ; using Softboiled? + jr nz, .skipRemovingItem ; no item to remove if using Softboiled + push hl + call RemoveUsedItem + pop hl +.skipRemovingItem + ld a, [wcf91] + cp FULL_RESTORE + jr c, .playStatusAilmentCuringSound + cp FULL_HEAL + jr z, .playStatusAilmentCuringSound + ld a, SFX_HEAL_HP + call PlaySoundWaitForCurrent + ldh a, [hFlagsFFFA] + set 0, a + ldh [hFlagsFFFA], a + ld a, $02 + ld [wHPBarType], a + predef UpdateHPBar2 ; animate the HP bar lengthening + ldh a, [hFlagsFFFA] + res 0, a + ldh [hFlagsFFFA], a + ld a, REVIVE_MSG + ld [wPartyMenuTypeOrMessageID], a + ld a, [wcf91] + cp REVIVE + jr z, .showHealingItemMessage + cp MAX_REVIVE + jr z, .showHealingItemMessage + ld a, POTION_MSG + ld [wPartyMenuTypeOrMessageID], a + jr .showHealingItemMessage + +.playStatusAilmentCuringSound + ld a, SFX_HEAL_AILMENT + call PlaySoundWaitForCurrent +.showHealingItemMessage + xor a + ldh [hAutoBGTransferEnabled], a + call ClearScreen + dec a + ld [wUpdateSpritesEnabled], a + call RedrawPartyMenu ; redraws the party menu and displays the message + ld a, 1 + ldh [hAutoBGTransferEnabled], a + ld c, 50 + call DelayFrames + call WaitForTextScrollButtonPress + jr .done + +.canceledItemUse + xor a + ld [wActionResultOrTookBattleTurn], a ; item use failed + pop af + pop af +.done + ld a, [wPseudoItemID] + and a ; using Softboiled? + ret nz ; if so, return + call GBPalWhiteOut + call z, RunDefaultPaletteCommand + ld a, [wIsInBattle] + and a + ret nz + jp ReloadMapData + +.useVitamin + push hl + ld a, [hl] + ld [wd0b5], a + ld [wd11e], a + ld bc, wPartyMon1Level - wPartyMon1 + add hl, bc ; hl now points to level + ld a, [hl] ; a = level + ld [wCurEnemyLVL], a ; store level + call GetMonHeader + push de + ld a, d + ld hl, wPartyMonNicks + call GetPartyMonName + pop de + pop hl + ld a, [wcf91] + cp RARE_CANDY + jp z, .useRareCandy + push hl + sub HP_UP + add a + ld bc, wPartyMon1HPExp - wPartyMon1 + add hl, bc + add l + ld l, a + jr nc, .noCarry2 + inc h +.noCarry2 + ld a, 10 + ld b, a + ld a, [hl] ; a = MSB of stat experience of the appropriate stat + cp 100 ; is there already at least 25600 (256 * 100) stat experience? + jr nc, .vitaminNoEffect ; if so, vitamins can't add any more + add b ; add 2560 (256 * 10) stat experience + jr nc, .noCarry3 ; a carry should be impossible here, so this will always jump + ld a, 255 +.noCarry3 + ld [hl], a + pop hl + call .recalculateStats + ld hl, VitaminText + ld a, [wcf91] + sub HP_UP - 1 + ld c, a +.statNameLoop ; loop to get the address of the name of the stat the vitamin increases + dec c + jr z, .gotStatName +.statNameInnerLoop + ld a, [hli] + ld b, a + ld a, $50 + cp b + jr nz, .statNameInnerLoop + jr .statNameLoop + +.gotStatName + ld de, wcf4b + ld bc, 10 + call CopyData ; copy the stat's name to wcf4b + ld a, SFX_HEAL_AILMENT + call PlaySound + ld hl, VitaminStatRoseText + call PrintText + jp RemoveUsedItem + +.vitaminNoEffect + pop hl + ld hl, VitaminNoEffectText + call PrintText + jp GBPalWhiteOut + +.recalculateStats + ld bc, wPartyMon1Stats - wPartyMon1 + add hl, bc + ld d, h + ld e, l ; de now points to stats + ld bc, (wPartyMon1Exp + 2) - wPartyMon1Stats + add hl, bc ; hl now points to LSB of experience + ld b, 1 + jp CalcStats ; recalculate stats +.useRareCandy + push hl + ld bc, wPartyMon1Level - wPartyMon1 + add hl, bc ; hl now points to level + ld a, [hl] ; a = level + cp MAX_LEVEL + jr z, .vitaminNoEffect ; can't raise level above 100 + inc a + ld [hl], a ; store incremented level + ld [wCurEnemyLVL], a + push hl + push de + ld d, a + callfar CalcExperience ; calculate experience for next level and store it at hExperience + pop de + pop hl + ld bc, wPartyMon1Exp - wPartyMon1Level + add hl, bc ; hl now points to MSB of experience +; update experience to minimum for new level + ldh a, [hExperience] + ld [hli], a + ldh a, [hExperience + 1] + ld [hli], a + ldh a, [hExperience + 2] + ld [hl], a + pop hl + ld a, [wWhichPokemon] + push af + ld a, [wcf91] + push af + push de + push hl + ld bc, wPartyMon1MaxHP - wPartyMon1 + add hl, bc ; hl now points to MSB of max HP + ld a, [hli] + ld b, a + ld c, [hl] + pop hl + push bc + push hl + call .recalculateStats + pop hl + ld bc, (wPartyMon1MaxHP + 1) - wPartyMon1 + add hl, bc ; hl now points to LSB of max HP + pop bc + ld a, [hld] + sub c + ld c, a + ld a, [hl] + sbc b + ld b, a ; bc = the amount of max HP gained from leveling up +; add the amount gained to the current HP + ld de, (wPartyMon1HP + 1) - wPartyMon1MaxHP + add hl, de ; hl now points to LSB of current HP + ld a, [hl] + add c + ld [hld], a + ld a, [hl] + adc b + ld [hl], a + ld a, RARE_CANDY_MSG + ld [wPartyMenuTypeOrMessageID], a + call RedrawPartyMenu + pop de + ld a, d + ld [wWhichPokemon], a + ld a, e + ld [wd11e], a + xor a ; PLAYER_PARTY_DATA + ld [wMonDataLocation], a + call LoadMonData + ld d, $01 + callfar PrintStatsBox ; display new stats text box + call WaitForTextScrollButtonPress ; wait for button press + xor a ; PLAYER_PARTY_DATA + ld [wMonDataLocation], a + predef LearnMoveFromLevelUp ; learn level up move, if any + + xor a + ld [wForceEvolution], a + callabd_ModifyPikachuHappiness PIKAHAPPY_LEVELUP + ld a, [wWhichPokemon] + push af + ld a, [wUsedItemOnWhichPokemon] + ld [wWhichPokemon], a + callfar Func_2fd6a ; evolve pokemon, if appropriate + pop af + ld [wWhichPokemon], a + + callfar TryEvolvingMon + ld a, $01 + ld [wUpdateSpritesEnabled], a + pop af + ld [wcf91], a + pop af + ld [wWhichPokemon], a + jp RemoveUsedItem + +VitaminStatRoseText: + text_far _VitaminStatRoseText + text_end + +VitaminNoEffectText: + text_far _VitaminNoEffectText + text_end + +VitaminText: + db "HEALTH@" + db "ATTACK@" + db "DEFENSE@" + db "SPEED@" + db "SPECIAL@" + +ItemUseBait: + ld hl, ThrewBaitText + call PrintText + ld hl, wEnemyMonActualCatchRate ; catch rate + srl [hl] ; halve catch rate + ld a, BAIT_ANIM + ld hl, wSafariBaitFactor ; bait factor + ld de, wSafariEscapeFactor ; escape factor + jr BaitRockCommon + +ItemUseRock: + ld hl, ThrewRockText + call PrintText + ld hl, wEnemyMonActualCatchRate ; catch rate + ld a, [hl] + add a ; double catch rate + jr nc, .noCarry + ld a, $ff +.noCarry + ld [hl], a + ld a, ROCK_ANIM + ld hl, wSafariEscapeFactor ; escape factor + ld de, wSafariBaitFactor ; bait factor + +BaitRockCommon: + ld [wAnimationID], a + xor a + ld [wAnimationType], a + ldh [hWhoseTurn], a + ld [de], a ; zero escape factor (for bait), zero bait factor (for rock) +.randomLoop ; loop until a random number less than 5 is generated + call Random + and 7 + cp 5 + jr nc, .randomLoop + inc a ; increment the random number, giving a range from 1 to 5 inclusive + ld b, a + ld a, [hl] + add b ; increase bait factor (for bait), increase escape factor (for rock) + jr nc, .noCarry + ld a, $ff +.noCarry + ld [hl], a + predef MoveAnimation ; do animation + ld c, 70 + jp DelayFrames + +ThrewBaitText: + text_far _ThrewBaitText + text_end + +ThrewRockText: + text_far _ThrewRockText + text_end + +; also used for Dig out-of-battle effect +ItemUseEscapeRope: + ld a, [wIsInBattle] + and a + jr nz, .notUsable + ld a, [wCurMap] + cp AGATHAS_ROOM + jr z, .notUsable + cp BILLS_HOUSE + jr z, .notUsable + cp POKEMON_FAN_CLUB + jr z, .notUsable + ld a, [wCurMapTileset] + ld b, a + ld hl, EscapeRopeTilesets +.loop + ld a, [hli] + cp $ff + jr z, .notUsable + cp b + jr nz, .loop + ld hl, wd732 + set 3, [hl] + set 6, [hl] + call Func_1510 + ld hl, wd72e + res 4, [hl] + ResetEvent EVENT_IN_SAFARI_ZONE + xor a + ld [wNumSafariBalls], a + ld [wSafariZoneGateCurScript], a + inc a + ld [wEscapedFromBattle], a + ld [wActionResultOrTookBattleTurn], a ; item used + ld a, [wPseudoItemID] + and a ; using Dig? + ret nz ; if so, return + call ItemUseReloadOverworldData + ld c, 30 + call DelayFrames + jp RemoveUsedItem + +.notUsable + jp ItemUseNotTime + +INCLUDE "data/tilesets/escape_rope_tilesets.asm" + +ItemUseRepel: + ld b, 100 + +ItemUseRepelCommon: + ld a, [wIsInBattle] + and a + jp nz, ItemUseNotTime + ld a, b + ld [wRepelRemainingSteps], a + jp PrintItemUseTextAndRemoveItem + +; handles X Accuracy item +ItemUseXAccuracy: + ld a, [wIsInBattle] + and a + jp z, ItemUseNotTime + ld hl, wPlayerBattleStatus2 + set USING_X_ACCURACY, [hl] ; X Accuracy bit + callabd_ModifyPikachuHappiness PIKAHAPPY_USEDXITEM + jp PrintItemUseTextAndRemoveItem + +; This function is bugged and never works. It always jumps to ItemUseNotTime. +; The Card Key is handled in a different way. +ItemUseCardKey: + xor a + ld [wUnusedD71F], a + call GetTileAndCoordsInFrontOfPlayer + ld a, [GetTileAndCoordsInFrontOfPlayer] + cp $18 + jr nz, .next0 + ld hl, CardKeyTable1 + jr .next1 + +.next0 + cp $24 + jr nz, .next2 + ld hl, CardKeyTable2 + jr .next1 + +.next2 + cp $5e + jp nz, ItemUseNotTime + ld hl, CardKeyTable3 +.next1 + ld a, [wCurMap] + ld b, a +.loop + ld a, [hli] + cp -1 + jp z, ItemUseNotTime + cp b + jr nz, .nextEntry1 + ld a, [hli] + cp d + jr nz, .nextEntry2 + ld a, [hli] + cp e + jr nz, .nextEntry3 + ld a, [hl] + ld [wUnusedD71F], a + jr .done + +.nextEntry1 + inc hl +.nextEntry2 + inc hl +.nextEntry3 + inc hl + jr .loop + +.done + ld hl, ItemUseText00 + call PrintText + ld hl, wd728 + set 7, [hl] + ret + +INCLUDE "data/events/card_key_coords.asm" + +ItemUsePokedoll: + ld a, [wIsInBattle] + dec a + jp nz, ItemUseNotTime + ld a, $01 + ld [wEscapedFromBattle], a + jp PrintItemUseTextAndRemoveItem + +ItemUseGuardSpec: + ld a, [wIsInBattle] + and a + jp z, ItemUseNotTime + + ld a, [wWhichPokemon] + push af + ld a, [wPlayerMonNumber] + ld [wWhichPokemon], a + callabd_ModifyPikachuHappiness PIKAHAPPY_USEDXITEM + pop af + ld [wWhichPokemon], a + + ld hl, wPlayerBattleStatus2 + set PROTECTED_BY_MIST, [hl] ; Mist bit + jp PrintItemUseTextAndRemoveItem + +ItemUseSuperRepel: + ld b, 200 + jp ItemUseRepelCommon + +ItemUseMaxRepel: + ld b, 250 + jp ItemUseRepelCommon + +ItemUseDireHit: + ld a, [wIsInBattle] + and a + jp z, ItemUseNotTime + + ld a, [wWhichPokemon] + push af + ld a, [wPlayerMonNumber] + ld [wWhichPokemon], a + callabd_ModifyPikachuHappiness PIKAHAPPY_USEDXITEM + pop af + ld [wWhichPokemon], a + + ld hl, wPlayerBattleStatus2 + set GETTING_PUMPED, [hl] ; Focus Energy bit + jp PrintItemUseTextAndRemoveItem + +ItemUseXStat: + ld a, [wIsInBattle] + and a + jr nz, .inBattle + call ItemUseNotTime + ld a, 2 + ld [wActionResultOrTookBattleTurn], a ; item not used + ret + +.inBattle + ld hl, wPlayerMoveNum + ld a, [hli] + push af ; save [wPlayerMoveNum] + ld a, [hl] + push af ; save [wPlayerMoveEffect] + push hl + ld a, [wcf91] + sub X_ATTACK - ATTACK_UP1_EFFECT + ld [hl], a ; store player move effect + call PrintItemUseTextAndRemoveItem + ld a, XSTATITEM_ANIM ; X stat item animation ID + ld [wPlayerMoveNum], a + call LoadScreenTilesFromBuffer1 ; restore saved screen + call Delay3 + xor a + ldh [hWhoseTurn], a ; set turn to player's turn + farcall StatModifierUpEffect ; do stat increase move + + ld a, [wWhichPokemon] + push af + ld a, [wPlayerMonNumber] + ld [wWhichPokemon], a + callabd_ModifyPikachuHappiness PIKAHAPPY_USEDXITEM + pop af + ld [wWhichPokemon], a + + pop hl + pop af + ld [hld], a ; restore [wPlayerMoveEffect] + pop af + ld [hl], a ; restore [wPlayerMoveNum] + ret + +ItemUsePokeflute: + ld a, [wIsInBattle] + and a + jr nz, .inBattle +; if not in battle + call ItemUseReloadOverworldData + ld a, [wCurMap] + cp ROUTE_12 + jr nz, .notRoute12 + CheckEvent EVENT_BEAT_ROUTE12_SNORLAX + jr nz, .noSnorlaxOrPikachuToWakeUp +; if the player hasn't beaten Route 12 Snorlax + ld hl, Route12SnorlaxFluteCoords + call ArePlayerCoordsInArray + jr nc, .noSnorlaxOrPikachuToWakeUp + ld hl, PlayedFluteHadEffectText + call PrintText + SetEvent EVENT_FIGHT_ROUTE12_SNORLAX + ret + +.notRoute12 + cp ROUTE_16 + jr nz, .notRoute16 + CheckEvent EVENT_BEAT_ROUTE16_SNORLAX + jr nz, .noSnorlaxOrPikachuToWakeUp +; if the player hasn't beaten Route 16 Snorlax + ld hl, Route16SnorlaxFluteCoords + call ArePlayerCoordsInArray + jr nc, .noSnorlaxOrPikachuToWakeUp + ld hl, PlayedFluteHadEffectText + call PrintText + SetEvent EVENT_FIGHT_ROUTE16_SNORLAX + ret + +.notRoute16 + cp PEWTER_POKECENTER + jr nz, .noSnorlaxOrPikachuToWakeUp + call CheckPikachuFollowingPlayer + jr z, .noSnorlaxOrPikachuToWakeUp + callfar IsPikachuRightNextToPlayer + jr nc, .noSnorlaxOrPikachuToWakeUp + ld hl, PlayedFluteHadEffectText + call PrintText + call ItemUseReloadOverworldData + ldpikaemotion e, PikachuEmotion26 + callfar PlaySpecificPikachuEmotion + ret + +.noSnorlaxOrPikachuToWakeUp + ld hl, PlayedFluteNoEffectText + jp PrintText + +.inBattle + xor a + ld [wWereAnyMonsAsleep], a + ld b, ~SLP & $ff + ld hl, wPartyMon1Status + call WakeUpEntireParty + ld a, [wIsInBattle] + dec a ; is it a trainer battle? + jr z, .skipWakingUpEnemyParty +; if it's a trainer battle + ld hl, wEnemyMon1Status + call WakeUpEntireParty +.skipWakingUpEnemyParty + ld hl, wBattleMonStatus + ld a, [hl] + and b ; remove Sleep status + ld [hl], a + ld hl, wEnemyMonStatus + ld a, [hl] + ld c, a + and b ; remove Sleep status + ld [hl], a + ld a, c + and SLP + jr z, .asm_e063 + ld a, $1 + ld [wWereAnyMonsAsleep], a +.asm_e063 + call LoadScreenTilesFromBuffer2 ; restore saved screen + ld a, [wWereAnyMonsAsleep] + and a ; were any pokemon asleep before playing the flute? + ld hl, PlayedFluteNoEffectText + jp z, PrintText ; if no pokemon were asleep +; if some pokemon were asleep + ld hl, PlayedFluteHadEffectText + call PrintText + ld a, [wLowHealthAlarm] + and $80 + jr nz, .skipMusic + call WaitForSoundToFinish ; wait for sound to end + farcall Music_PokeFluteInBattle ; play in-battle pokeflute music +.musicWaitLoop ; wait for music to finish playing + ld a, [wChannelSoundIDs + Ch7] + and a ; music off? + jr nz, .musicWaitLoop +.skipMusic + ld hl, FluteWokeUpText + jp PrintText + +; wakes up all party pokemon +; INPUT: +; hl must point to status of first pokemon in party (player's or enemy's) +; b must equal ~SLP +; [wWereAnyMonsAsleep] should be initialized to 0 +; OUTPUT: +; [wWereAnyMonsAsleep]: set to 1 if any pokemon were asleep +WakeUpEntireParty: + ld de, 44 + ld c, 6 +.loop + ld a, [hl] + push af + and SLP ; is pokemon asleep? + jr z, .notAsleep + ld a, 1 + ld [wWereAnyMonsAsleep], a ; indicate that a pokemon had to be woken up +.notAsleep + pop af + and b ; remove Sleep status + ld [hl], a + add hl, de + dec c + jr nz, .loop + ret + +Route12SnorlaxFluteCoords: + dbmapcoord 9, 62 ; one space West of Snorlax + dbmapcoord 10, 61 ; one space North of Snorlax + dbmapcoord 10, 63 ; one space South of Snorlax + dbmapcoord 11, 62 ; one space East of Snorlax + db -1 ; end + +Route16SnorlaxFluteCoords: + dbmapcoord 27, 10 ; one space East of Snorlax + dbmapcoord 25, 10 ; one space West of Snorlax + db -1 ; end + +PlayedFluteNoEffectText: + text_far _PlayedFluteNoEffectText + text_end + +FluteWokeUpText: + text_far _FluteWokeUpText + text_end + +PlayedFluteHadEffectText: + text_far _PlayedFluteHadEffectText + text_promptbutton + text_asm + ld a, [wIsInBattle] + and a + jr nz, .done +; play out-of-battle pokeflute music + call StopAllMusic + ld a, SFX_POKEFLUTE + ld c, BANK(SFX_Pokeflute) + call PlayMusic +.musicWaitLoop ; wait for music to finish playing + ld a, [wChannelSoundIDs + Ch3] + cp SFX_POKEFLUTE + jr z, .musicWaitLoop + call PlayDefaultMusic ; start playing normal music again +.done + jp TextScriptEnd ; end text + +ItemUseCoinCase: + ld a, [wIsInBattle] + and a + jp nz, ItemUseNotTime + ld hl, CoinCaseNumCoinsText + jp PrintText + +CoinCaseNumCoinsText: + text_far _CoinCaseNumCoinsText + text_end + +ItemUseOldRod: + call FishingInit + jp c, ItemUseNotTime + lb bc, 5, MAGIKARP + ld a, $1 ; set bite + jr RodResponse + +ItemUseGoodRod: + call FishingInit + jp c, ItemUseNotTime +.RandomLoop + call Random + srl a + jr c, .SetBite + and %11 + cp 2 + jr nc, .RandomLoop + ; choose which monster appears + ld hl, GoodRodMons + add a + ld c, a + ld b, 0 + add hl, bc + ld b, [hl] + inc hl + ld c, [hl] + and a +.SetBite + ld a, 0 + rla + xor 1 + jr RodResponse + +INCLUDE "data/wild/good_rod.asm" + +ItemUseSuperRod: + call FishingInit + jp c, ItemUseNotTime + callfar ReadSuperRodData + ld c, e + ld b, d + ld a, $2 + ld [wRodResponse], a + ld a, c + and a ; are there fish in the map? + jr z, DoNotGenerateFishingEncounter ; if not, do not generate an encounter + ld a, $1 + ld [wRodResponse], a + call Random + and $1 + jr nz, RodResponse + xor a + ld [wRodResponse], a + jr DoNotGenerateFishingEncounter + +RodResponse: + ld [wRodResponse], a + + dec a ; is there a bite? + jr nz, DoNotGenerateFishingEncounter + ; if yes, store level and species data + ld a, 1 + ld [wMoveMissed], a + ld a, b ; level + ld [wCurEnemyLVL], a + ld a, c ; species + ld [wCurOpponent], a + +DoNotGenerateFishingEncounter: + ld hl, wWalkBikeSurfState + ld a, [hl] ; store the value in a + push af + push hl + ld [hl], 0 + farcall FishingAnim + pop hl + pop af + ld [hl], a + ret + +; checks if fishing is possible and if so, runs initialization code common to all rods +; unsets carry if fishing is possible, sets carry if not +FishingInit: + ld a, [wIsInBattle] + and a + jr z, .notInBattle + scf ; can't fish during battle + ret + +.notInBattle + call IsNextTileShoreOrWater + jr nc, .cannotFish + ld a, [wWalkBikeSurfState] + cp 2 ; Surfing? + jr z, .cannotFish + call ItemUseReloadOverworldData + ld hl, ItemUseText00 + call PrintText + ld a, SFX_HEAL_AILMENT + call PlaySound + ld a, $2 + ld [wd49c], a + ld a, $81 + ld [wPikachuMood], a + ld c, 80 + call DelayFrames + and a + ret + +.cannotFish + scf ; can't fish when surfing + ret + +ItemUseOaksParcel: + jp ItemUseNotYoursToUse + +ItemUseItemfinder: + ld a, [wIsInBattle] + and a + jp nz, ItemUseNotTime + call ItemUseReloadOverworldData + farcall HiddenItemNear ; check for hidden items + ld hl, ItemfinderFoundNothingText + jr nc, .printText ; if no hidden items + ld c, 4 +.loop + ld a, SFX_HEALING_MACHINE + call PlaySoundWaitForCurrent + ld a, SFX_PURCHASE + call PlaySoundWaitForCurrent + dec c + jr nz, .loop + ld hl, ItemfinderFoundItemText +.printText + jp PrintText + +ItemfinderFoundItemText: + text_far _ItemfinderFoundItemText + text_end + +ItemfinderFoundNothingText: + text_far _ItemfinderFoundNothingText + text_end + +ItemUsePPUp: + ld a, [wIsInBattle] + and a + jp nz, ItemUseNotTime + +ItemUsePPRestore: + ld a, [wWhichPokemon] + push af + ld a, [wcf91] + ld [wPPRestoreItem], a +.chooseMon + xor a + ld [wUpdateSpritesEnabled], a + ld a, USE_ITEM_PARTY_MENU + ld [wPartyMenuTypeOrMessageID], a + call DisplayPartyMenu + jr nc, .chooseMove + jp .itemNotUsed + +.chooseMove + ld a, [wIsInBattle] + and a + jr z, .usePPItem + ld a, [wWhichPokemon] + ld b, a + ld a, [wPlayerMonNumber] + cp b + jr nz, .usePPItem + ld a, [wPlayerBattleStatus3] + bit TRANSFORMED, a + jr z, .usePPItem + call ItemUseNotTime + jp .itemNotUsed + +.usePPItem + ld a, [wPPRestoreItem] + cp ELIXER + jp nc, .useElixir ; if Elixir or Max Elixir + ld a, $02 + ld [wMoveMenuType], a + ld hl, RaisePPWhichTechniqueText + ld a, [wPPRestoreItem] + cp ETHER ; is it a PP Up? + jr c, .printWhichTechniqueMessage ; if so, print the raise PP message + ld hl, RestorePPWhichTechniqueText ; otherwise, print the restore PP message +.printWhichTechniqueMessage + call PrintText + xor a + ld [wPlayerMoveListIndex], a + callfar MoveSelectionMenu ; move selection menu + ld a, 0 + ld [wPlayerMoveListIndex], a + jr nz, .chooseMon + ld hl, wPartyMon1Moves + ld bc, wPartyMon2 - wPartyMon1 + call GetSelectedMoveOffset + push hl + ld a, [hl] + ld [wd11e], a + call GetMoveName + call CopyStringToCF4B ; copy name to wcf4b + pop hl + ld a, [wPPRestoreItem] + cp ETHER + jr nc, .useEther ; if Ether or Max Ether +.usePPUp + ld bc, wPartyMon1PP - wPartyMon1Moves + add hl, bc + ld a, [hl] ; move PP + cp 3 << 6 ; have 3 PP Ups already been used? + jr c, .PPNotMaxedOut + ld hl, PPMaxedOutText + call PrintText + jr .chooseMove + +.PPNotMaxedOut + ld a, [hl] + add 1 << 6 ; increase PP Up count by 1 + ld [hl], a + ld a, 1 ; 1 PP Up used + ld [wd11e], a + call RestoreBonusPP ; add the bonus PP to current PP + ld a, SFX_HEAL_AILMENT + call PlaySound + ld hl, PPIncreasedText + call PrintText +.done + pop af + ld [wWhichPokemon], a + call GBPalWhiteOut + call RunDefaultPaletteCommand + jp RemoveUsedItem + +.afterRestoringPP ; after using a (Max) Ether/Elixir + ld a, [wWhichPokemon] + ld b, a + ld a, [wPlayerMonNumber] + cp b ; is the pokemon whose PP was restored active in battle? + jr nz, .skipUpdatingInBattleData + ld hl, wPartyMon1PP + ld bc, wPartyMon2 - wPartyMon1 + call AddNTimes + ld de, wBattleMonPP + ld bc, 4 + call CopyData ; copy party data to in-battle data +.skipUpdatingInBattleData + ld a, SFX_HEAL_AILMENT + call PlaySound + ld hl, PPRestoredText + call PrintText + jr .done + +.useEther + call .restorePP + jr nz, .afterRestoringPP + jp .noEffect + +; unsets zero flag if PP was restored, sets zero flag if not +; however, this is bugged for Max Ethers and Max Elixirs (see below) +.restorePP + xor a ; PLAYER_PARTY_DATA + ld [wMonDataLocation], a + call GetMaxPP + ld hl, wPartyMon1Moves + ld bc, wPartyMon2 - wPartyMon1 + call GetSelectedMoveOffset + ld bc, wPartyMon1PP - wPartyMon1Moves + add hl, bc ; hl now points to move's PP + ld a, [wMaxPP] + ld b, a + ld a, [wPPRestoreItem] + cp MAX_ETHER + jr z, .fullyRestorePP + ld a, [hl] ; move PP + and %00111111 ; lower 6 bit bits store current PP + cp b ; does current PP equal max PP? + ret z ; if so, return + add 10 ; increase current PP by 10 +; b holds the max PP amount and b will hold the new PP amount. +; So, if the new amount meets or exceeds the max amount, +; cap the amount to the max amount by leaving b unchanged. +; Otherwise, store the new amount in b. + cp b ; does the new amount meet or exceed the maximum? + jr nc, .storeNewAmount + ld b, a +.storeNewAmount + ld a, [hl] ; move PP + and %11000000 ; PP Up counter bits + add b + ld [hl], a + ret + +.fullyRestorePP + ld a, [hl] ; move PP +; Note that this code has a bug. It doesn't mask out the upper two bits, which +; are used to count how many PP Ups have been used on the move. So, Max Ethers +; and Max Elixirs will not be detected as having no effect on a move with full +; PP if the move has had any PP Ups used on it. + cp b ; does current PP equal max PP? + ret z + jr .storeNewAmount + +.useElixir +; decrement the item ID so that ELIXER becomes ETHER and MAX_ELIXER becomes MAX_ETHER + ld hl, wPPRestoreItem + dec [hl] + dec [hl] + xor a + ld hl, wCurrentMenuItem + ld [hli], a + ld [hl], a ; zero the counter for number of moves that had their PP restored + ld b, 4 +; loop through each move and restore PP +.elixirLoop + push bc + ld hl, wPartyMon1Moves + ld bc, wPartyMon2 - wPartyMon1 + call GetSelectedMoveOffset + ld a, [hl] + and a ; does the current slot have a move? + jr z, .nextMove + call .restorePP + jr z, .nextMove +; if some PP was restored + ld hl, wTileBehindCursor ; counter for number of moves that had their PP restored + inc [hl] +.nextMove + ld hl, wCurrentMenuItem + inc [hl] + pop bc + dec b + jr nz, .elixirLoop + ld a, [wTileBehindCursor] + and a ; did any moves have their PP restored? + jp nz, .afterRestoringPP +.noEffect + call ItemUseNoEffect +.itemNotUsed + call GBPalWhiteOut + call RunDefaultPaletteCommand + pop af + xor a + ld [wActionResultOrTookBattleTurn], a ; item use failed + ret + +RaisePPWhichTechniqueText: + text_far _RaisePPWhichTechniqueText + text_end + +RestorePPWhichTechniqueText: + text_far _RestorePPWhichTechniqueText + text_end + +PPMaxedOutText: + text_far _PPMaxedOutText + text_end + +PPIncreasedText: + text_far _PPIncreasedText + text_end + +PPRestoredText: + text_far _PPRestoredText + text_end + +; for items that can't be used from the Item menu +UnusableItem: + jp ItemUseNotTime + +ItemUseTMHM: + ld a, [wIsInBattle] + and a + jp nz, ItemUseNotTime + ld a, [wcf91] + sub TM01 ; underflows below 0 for HM items (before TM items) + push af + jr nc, .skipAdding + add NUM_TMS + NUM_HMS ; adjust HM IDs to come after TM IDs +.skipAdding + inc a + ld [wd11e], a + predef TMToMove ; get move ID from TM/HM ID + ld a, [wd11e] + ld [wMoveNum], a + call GetMoveName + call CopyStringToCF4B ; copy name to wcf4b + pop af + ld hl, BootedUpTMText + jr nc, .printBootedUpMachineText + ld hl, BootedUpHMText +.printBootedUpMachineText + call PrintText + ld hl, TeachMachineMoveText + call PrintText + hlcoord 14, 7 + lb bc, 8, 15 + ld a, TWO_OPTION_MENU + ld [wTextBoxID], a + call DisplayTextBoxID ; yes/no menu + ld a, [wCurrentMenuItem] + and a + jr z, .useMachine + ld a, 2 + ld [wActionResultOrTookBattleTurn], a ; item not used + ret + +.useMachine + ld a, [wWhichPokemon] + push af + ld a, [wcf91] + push af +.chooseMon + ld hl, wcf4b + ld de, wTempMoveNameBuffer + ld bc, 14 + call CopyData ; save the move name because DisplayPartyMenu will overwrite it + ld a, $ff + ld [wUpdateSpritesEnabled], a + ld a, TMHM_PARTY_MENU + ld [wPartyMenuTypeOrMessageID], a + call DisplayPartyMenu + push af + ld hl, wTempMoveNameBuffer + ld de, wcf4b + ld bc, 14 + call CopyData + pop af + jr nc, .checkIfAbleToLearnMove +; if the player canceled teaching the move + pop af + pop af + call GBPalWhiteOutWithDelay3 + call ClearSprites + call RunDefaultPaletteCommand + jp LoadScreenTilesFromBuffer1 ; restore saved screen +.checkIfAbleToLearnMove + predef CanLearnTM ; check if the pokemon can learn the move + push bc + ld a, [wWhichPokemon] + ld hl, wPartyMonNicks + call GetPartyMonName + pop bc + ld a, c + and a ; can the pokemon learn the move? + jr nz, .checkIfAlreadyLearnedMove +; if the pokemon can't learn the move + ld a, SFX_DENIED + call PlaySoundWaitForCurrent + ld hl, MonCannotLearnMachineMoveText + call PrintText + jr .chooseMon + +.checkIfAlreadyLearnedMove + callfar CheckIfMoveIsKnown ; check if the pokemon already knows the move + jr c, .chooseMon + predef LearnMove ; teach move + ld a, [wWhichPokemon] + ld d, a + pop af + ld [wcf91], a + pop af + ld [wWhichPokemon], a + ld a, b + and a + ret z + + ld a, [wWhichPokemon] + push af + ld a, d + ld [wWhichPokemon], a + callabd_ModifyPikachuHappiness PIKAHAPPY_USEDTMHM + callfar IsThisPartymonStarterPikachu_Party + jr nc, .notTeachingThunderboltOrThunderToPikachu + ld a, [wcf91] + cp TM_THUNDERBOLT ; are we teaching thunderbolt to the player pikachu? + jr z, .teachingThunderboltOrThunderToPlayerPikachu + cp TM_THUNDER ; are we teaching thunder then? + jr nz, .notTeachingThunderboltOrThunderToPikachu +.teachingThunderboltOrThunderToPlayerPikachu + ld a, $5 + ld [wd49c], a + ld a, $85 + ld [wPikachuMood], a +.notTeachingThunderboltOrThunderToPikachu + pop af + ld [wWhichPokemon], a + + ld a, [wcf91] + call IsItemHM + ret c + jp RemoveUsedItem + +BootedUpTMText: + text_far _BootedUpTMText + text_end + +BootedUpHMText: + text_far _BootedUpHMText + text_end + +TeachMachineMoveText: + text_far _TeachMachineMoveText + text_end + +MonCannotLearnMachineMoveText: + text_far _MonCannotLearnMachineMoveText + text_end + +PrintItemUseTextAndRemoveItem: + ld hl, ItemUseText00 + call PrintText + ld a, SFX_HEAL_AILMENT + call PlaySound + call WaitForTextScrollButtonPress ; wait for button press + +RemoveUsedItem: + ld hl, wNumBagItems + ld a, 1 ; one item + ld [wItemQuantity], a + jp RemoveItemFromInventory + +ItemUseNoEffect: + ld hl, ItemUseNoEffectText + jr ItemUseFailed + +ItemUseNotTime: + ld hl, ItemUseNotTimeText + jr ItemUseFailed + +ItemUseNotYoursToUse: + ld hl, ItemUseNotYoursToUseText + jr ItemUseFailed + +Func_e4bf: + ld a, $2 + ld [wActionResultOrTookBattleTurn], a + ld hl, DontHavePokemonText + jp PrintText + +ThrowBallAtTrainerMon: + call RunDefaultPaletteCommand + call LoadScreenTilesFromBuffer1 ; restore saved screen + call Delay3 + ld a, TOSS_ANIM + ld [wAnimationID], a + predef MoveAnimation ; do animation + ld hl, ThrowBallAtTrainerMonText1 + call PrintText + ld hl, ThrowBallAtTrainerMonText2 + call PrintText + jr RemoveUsedItem + +NoCyclingAllowedHere: + ld hl, NoCyclingAllowedHereText + jr ItemUseFailed + +BoxFullCannotThrowBall: + ld hl, BoxFullCannotThrowBallText + jr ItemUseFailed + +SurfingAttemptFailed: + ld hl, NoSurfingHereText + +ItemUseFailed: + xor a + ld [wActionResultOrTookBattleTurn], a ; item use failed + jp PrintText + +ItemUseNotTimeText: + text_far _ItemUseNotTimeText + text_end + +ItemUseNotYoursToUseText: + text_far _ItemUseNotYoursToUseText + text_end + +ItemUseNoEffectText: + text_far _ItemUseNoEffectText + text_end + +ThrowBallAtTrainerMonText1: + text_far _ThrowBallAtTrainerMonText1 + text_end + +ThrowBallAtTrainerMonText2: + text_far _ThrowBallAtTrainerMonText2 + text_end + +NoCyclingAllowedHereText: + text_far _NoCyclingAllowedHereText + text_end + +NoSurfingHereText: + text_far _NoSurfingHereText + text_end + +BoxFullCannotThrowBallText: + text_far _BoxFullCannotThrowBallText + text_end + +DontHavePokemonText: + text_far _DontHavePokemonText + text_end + +ItemUseText00: + text_far _ItemUseText001 + text_low + text_far _ItemUseText002 + text_end + +GotOnBicycleText: + text_far _GotOnBicycleText1 + text_low + text_far _GotOnBicycleText2 + text_end + +GotOffBicycleText: + text_far _GotOffBicycleText1 + text_low + text_far _GotOffBicycleText2 + text_end + +; restores bonus PP (from PP Ups) when healing at a pokemon center +; also, when a PP Up is used, it increases the current PP by one PP Up bonus +; INPUT: +; [wWhichPokemon] = index of pokemon in party +; [wCurrentMenuItem] = index of move (when using a PP Up) +RestoreBonusPP: + ld hl, wPartyMon1Moves + ld bc, wPartyMon2 - wPartyMon1 + ld a, [wWhichPokemon] + call AddNTimes + push hl + ld de, wNormalMaxPPList - 1 + predef LoadMovePPs ; loads the normal max PP of each of the pokemon's moves to wNormalMaxPPList + pop hl + ld c, wPartyMon1PP - wPartyMon1Moves + ld b, 0 + add hl, bc ; hl now points to move 1 PP + ld de, wNormalMaxPPList + ld b, 0 ; initialize move counter to zero +; loop through the pokemon's moves +.loop + inc b + ld a, b + cp 5 ; reached the end of the pokemon's moves? + ret z ; if so, return + ld a, [wUsingPPUp] + dec a ; using a PP Up? + jr nz, .skipMenuItemIDCheck +; if using a PP Up, check if this is the move it's being used on + ld a, [wCurrentMenuItem] + inc a + cp b + jr nz, .nextMove +.skipMenuItemIDCheck + ld a, [hl] + and %11000000 ; have any PP Ups been used? + call nz, AddBonusPP ; if so, add bonus PP +.nextMove + inc hl + inc de + jr .loop + +; adds bonus PP from PP Ups to current PP +; 1/5 of normal max PP (capped at 7) is added for each PP Up +; INPUT: +; [de] = normal max PP +; [hl] = move PP +AddBonusPP: + push bc + ld a, [de] ; normal max PP of move + ldh [hDividend + 3], a + xor a + ldh [hDividend], a + ldh [hDividend + 1], a + ldh [hDividend + 2], a + ld a, 5 + ldh [hDivisor], a + ld b, 4 + call Divide + ld a, [hl] ; move PP + ld b, a + swap a + and %00001111 + srl a + srl a + ld c, a ; c = number of PP Ups used +.loop + ldh a, [hQuotient + 3] + cp 8 ; is the amount greater than or equal to 8? + jr c, .addAmount + ld a, 7 ; cap the amount at 7 +.addAmount + add b + ld b, a + ld a, [wUsingPPUp] + dec a ; is the player using a PP Up right now? + jr z, .done ; if so, only add the bonus once + dec c + jr nz, .loop +.done + ld [hl], b + pop bc + ret + +; gets max PP of a pokemon's move (including PP from PP Ups) +; INPUT: +; [wWhichPokemon] = index of pokemon within party/box +; [wMonDataLocation] = pokemon source +; 00: player's party +; 01: enemy's party +; 02: current box +; 03: daycare +; 04: player's in-battle pokemon +; [wCurrentMenuItem] = move index +; OUTPUT: +; [wMaxPP] = max PP +GetMaxPP: + ld a, [wMonDataLocation] + and a + ld hl, wPartyMon1Moves + ld bc, wPartyMon2 - wPartyMon1 + jr z, .sourceWithMultipleMon + ld hl, wEnemyMon1Moves + dec a + jr z, .sourceWithMultipleMon + ld hl, wBoxMon1Moves + ld bc, wBoxMon2 - wBoxMon1 + dec a + jr z, .sourceWithMultipleMon + ld hl, wDayCareMonMoves + dec a + jr z, .sourceWithOneMon + ld hl, wBattleMonMoves ; player's in-battle pokemon +.sourceWithOneMon + call GetSelectedMoveOffset2 + jr .next + +.sourceWithMultipleMon + call GetSelectedMoveOffset +.next + ld a, [hl] + dec a + push hl + ld hl, Moves + ld bc, MoveEnd - Moves + call AddNTimes + ld de, wcd6d + ld a, BANK(Moves) + call FarCopyData + ld de, wcd6d + 5 ; PP is byte 5 of move data + ld a, [de] + ld b, a ; b = normal max PP + pop hl + push bc + ld bc, wPartyMon1PP - wPartyMon1Moves ; PP offset if not player's in-battle pokemon data + ld a, [wMonDataLocation] + cp 4 ; player's in-battle pokemon? + jr nz, .addPPOffset + ld bc, wBattleMonPP - wBattleMonMoves ; PP offset if player's in-battle pokemon data +.addPPOffset + add hl, bc + ld a, [hl] ; a = current PP + and %11000000 ; get PP Up count + pop bc + or b ; place normal max PP in 6 lower bits of a + ld h, d + ld l, e + inc hl ; hl = wcd73 + ld [hl], a + xor a ; add the bonus for the existing PP Up count + ld [wUsingPPUp], a + call AddBonusPP ; add bonus PP from PP Ups + ld a, [hl] + and %00111111 ; mask out the PP Up count + ld [wMaxPP], a ; store max PP + ret + +GetSelectedMoveOffset: + ld a, [wWhichPokemon] + call AddNTimes + +GetSelectedMoveOffset2: + ld a, [wCurrentMenuItem] + ld c, a + ld b, 0 + add hl, bc + ret + +; confirms the item toss and then tosses the item +; INPUT: +; hl = address of inventory (either wNumBagItems or wNumBoxItems) +; [wcf91] = item ID +; [wWhichPokemon] = index of item within inventory +; [wItemQuantity] = quantity to toss +; OUTPUT: +; clears carry flag if the item is tossed, sets carry flag if not +TossItem_:: + push hl + ld a, [wcf91] + call IsItemHM + pop hl + jr c, .tooImportantToToss + push hl + call IsKeyItem_ + ld a, [wIsKeyItem] + pop hl + and a + jr nz, .tooImportantToToss + push hl + ld a, [wcf91] + ld [wd11e], a + call GetItemName + call CopyStringToCF4B ; copy name to wcf4b + ld hl, IsItOKToTossItemText + call PrintText + hlcoord 14, 7 + lb bc, 8, 15 + ld a, TWO_OPTION_MENU + ld [wTextBoxID], a + call DisplayTextBoxID ; yes/no menu + ld a, [wMenuExitMethod] + cp CHOSE_SECOND_ITEM + pop hl + scf + ret z ; return if the player chose No +; if the player chose Yes + push hl + ld a, [wWhichPokemon] + call RemoveItemFromInventory + ld a, [wcf91] + ld [wd11e], a + call GetItemName + call CopyStringToCF4B ; copy name to wcf4b + ld hl, ThrewAwayItemText + call PrintText + pop hl + and a + ret + +.tooImportantToToss + push hl + ld hl, TooImportantToTossText + call PrintText + pop hl + scf + ret + +ThrewAwayItemText: + text_far _ThrewAwayItemText + text_end + +IsItOKToTossItemText: + text_far _IsItOKToTossItemText + text_end + +TooImportantToTossText: + text_far _TooImportantToTossText + text_end + +; checks if an item is a key item +; INPUT: +; [wcf91] = item ID +; OUTPUT: +; [wIsKeyItem] = result +; 00: item is not key item +; 01: item is key item +IsKeyItem_:: + ld a, $01 + ld [wIsKeyItem], a + ld a, [wcf91] + cp HM01 ; is the item an HM or TM? + jr nc, .checkIfItemIsHM +; if the item is not an HM or TM + push af + ld hl, KeyItemBitfield + ld de, wBuffer + ld bc, 15 ; only 11 bytes are actually used + call CopyData + pop af + dec a + ld c, a + ld hl, wBuffer + ld b, FLAG_TEST + predef FlagActionPredef + ld a, c + and a + ret nz +.checkIfItemIsHM + ld a, [wcf91] + call IsItemHM + ret c + xor a + ld [wIsKeyItem], a + ret + +INCLUDE "data/items/key_items.asm" + +SendNewMonToBox: + ld de, wNumInBox + ld a, [de] + inc a + ld [de], a + ld a, [wcf91] + ld [wd0b5], a + ld c, a +.asm_e6f5 + inc de + ld a, [de] + ld b, a + ld a, c + ld c, b + ld [de], a + cp $ff + jr nz, .asm_e6f5 + call GetMonHeader + ld hl, wBoxMonOT + ld bc, NAME_LENGTH + ld a, [wNumInBox] + dec a + jr z, .asm_e732 + dec a + call AddNTimes + push hl + ld bc, NAME_LENGTH + add hl, bc + ld d, h + ld e, l + pop hl + ld a, [wNumInBox] + dec a + ld b, a +.asm_e71f + push bc + push hl + ld bc, NAME_LENGTH + call CopyData + pop hl + ld d, h + ld e, l + ld bc, -NAME_LENGTH + add hl, bc + pop bc + dec b + jr nz, .asm_e71f +.asm_e732 + ld hl, wPlayerName + ld de, wBoxMonOT + ld bc, NAME_LENGTH + call CopyData + ld a, [wNumInBox] + dec a + jr z, .asm_e76e + ld hl, wBoxMonNicks + ld bc, NAME_LENGTH + dec a + call AddNTimes + push hl + ld bc, NAME_LENGTH + add hl, bc + ld d, h + ld e, l + pop hl + ld a, [wNumInBox] + dec a + ld b, a +.asm_e75b + push bc + push hl + ld bc, NAME_LENGTH + call CopyData + pop hl + ld d, h + ld e, l + ld bc, -NAME_LENGTH + add hl, bc + pop bc + dec b + jr nz, .asm_e75b +.asm_e76e + ld hl, wBoxMonNicks + ld a, NAME_MON_SCREEN + ld [wNamingScreenType], a + predef AskName + ld a, [wNumInBox] + dec a + jr z, .asm_e7ab + ld hl, wBoxMons + ld bc, wBoxMon2 - wBoxMon1 + dec a + call AddNTimes + push hl + ld bc, wBoxMon2 - wBoxMon1 + add hl, bc + ld d, h + ld e, l + pop hl + ld a, [wNumInBox] + dec a + ld b, a +.asm_e798 + push bc + push hl + ld bc, wBoxMon2 - wBoxMon1 + call CopyData + pop hl + ld d, h + ld e, l + ld bc, wBoxMon1 - wBoxMon2 + add hl, bc + pop bc + dec b + jr nz, .asm_e798 +.asm_e7ab + ld a, [wEnemyMonLevel] + ld [wEnemyMonBoxLevel], a + ld hl, wEnemyMon + ld de, wBoxMon1 + ld bc, wEnemyMonDVs - wEnemyMon + call CopyData + ld hl, wPlayerID + ld a, [hli] + ld [de], a + inc de + ld a, [hl] + ld [de], a + inc de + push de + ld a, [wCurEnemyLVL] + ld d, a + callfar CalcExperience + pop de + ldh a, [hExperience] + ld [de], a + inc de + ldh a, [hExperience + 1] + ld [de], a + inc de + ldh a, [hExperience + 2] + ld [de], a + inc de + xor a + ld b, NUM_STATS * 2 +.asm_e7e3 + ld [de], a + inc de + dec b + jr nz, .asm_e7e3 + ld hl, wEnemyMonDVs + ld a, [hli] + ld [de], a + inc de + ld a, [hli] + ld [de], a + ld hl, wEnemyMonPP + ld b, NUM_MOVES +.asm_e7f5 + ld a, [hli] + inc de + ld [de], a + dec b + jr nz, .asm_e7f5 + ld a, [wcf91] + cp KADABRA + jr nz, .notKadabra + ld a, $60 ; twistedspoon in gsc + ld [wBoxMon1CatchRate], a +.notKadabra + ret + +; checks if the tile in front of the player is a shore or water tile +; used for surfing and fishing +; unsets carry if it is, sets carry if not +IsNextTileShoreOrWater:: + ld a, [wCurMapTileset] + ld hl, WaterTilesets + ld de, 1 + call IsInArray ; does the current map allow surfing? + ret nc ; if not, return + ld hl, WaterTile + ld a, [wCurMapTileset] + cp SHIP_PORT ; Vermilion Dock tileset + jr z, .skipShoreTiles ; if it's the Vermilion Dock tileset + cp GYM ; eastern shore tile in Safari Zone + jr z, .skipShoreTiles + cp DOJO ; usual eastern shore tile + jr z, .skipShoreTiles + ld hl, ShoreTiles +.skipShoreTiles + ld a, [wTileInFrontOfPlayer] + ld de, $1 + call IsInArray + ret + +INCLUDE "data/tilesets/water_tilesets.asm" + +; shore tiles +ShoreTiles: + db $48, $32 +WaterTile: + db $14 + db $ff ; terminator + +; reloads map view and processes sprite data +; for items that cause the overworld to be displayed +ItemUseReloadOverworldData: + call LoadCurrentMapView + jp UpdateSprites + +; creates a list at wBuffer of maps where the mon in [wd11e] can be found. +; this is used by the pokedex to display locations the mon can be found on the map. +FindWildLocationsOfMon: + ld hl, WildDataPointers + ld de, wBuffer + ld c, $0 +.loop + inc hl + ld a, [hld] + inc a + jr z, .done + push hl + ld a, [hli] + ld h, [hl] + ld l, a + ld a, [hli] + and a + call nz, CheckMapForMon ; land + ld a, [hli] + and a + call nz, CheckMapForMon ; water + pop hl + inc hl + inc hl + inc c + jr .loop +.done + ld a, $ff ; list terminator + ld [de], a + ret + +CheckMapForMon: + inc hl + ld b, $a +.loop + ld a, [wd11e] + cp [hl] + jr nz, .nextEntry + ld a, c + ld [de], a + inc de +.nextEntry + inc hl + inc hl + dec b + jr nz, .loop + dec hl + ret diff --git a/engine/items/items.asm b/engine/items/items.asm deleted file mode 100755 index e935f292..00000000 --- a/engine/items/items.asm +++ /dev/null @@ -1,3235 +0,0 @@ -UseItem_: - ld a, 1 - ld [wActionResultOrTookBattleTurn], a ; initialise to success value - ld a, [wcf91] ;contains item_ID - cp HM_01 - jp nc, ItemUseTMHM - ld hl, ItemUsePtrTable - dec a - add a - ld c, a - ld b, 0 - add hl, bc - ld a, [hli] - ld h, [hl] - ld l, a - jp hl - -ItemUsePtrTable: - dw ItemUseBall ; MASTER_BALL - dw ItemUseBall ; ULTRA_BALL - dw ItemUseBall ; GREAT_BALL - dw ItemUseBall ; POKE_BALL - dw ItemUseTownMap ; TOWN_MAP - dw ItemUseBicycle ; BICYCLE - dw ItemUseSurfboard ; out-of-battle Surf effect - dw ItemUseBall ; SAFARI_BALL - dw ItemUsePokedex ; POKEDEX - dw ItemUseEvoStone ; MOON_STONE - dw ItemUseMedicine ; ANTIDOTE - dw ItemUseMedicine ; BURN_HEAL - dw ItemUseMedicine ; ICE_HEAL - dw ItemUseMedicine ; AWAKENING - dw ItemUseMedicine ; PARLYZ_HEAL - dw ItemUseMedicine ; FULL_RESTORE - dw ItemUseMedicine ; MAX_POTION - dw ItemUseMedicine ; HYPER_POTION - dw ItemUseMedicine ; SUPER_POTION - dw ItemUseMedicine ; POTION - dw ItemUseBait ; BOULDERBADGE - dw ItemUseRock ; CASCADEBADGE - dw UnusableItem ; THUNDERBADGE - dw UnusableItem ; RAINBOWBADGE - dw UnusableItem ; SOULBADGE - dw UnusableItem ; MARSHBADGE - dw UnusableItem ; VOLCANOBADGE - dw UnusableItem ; EARTHBADGE - dw ItemUseEscapeRope ; ESCAPE_ROPE - dw ItemUseRepel ; REPEL - dw UnusableItem ; OLD_AMBER - dw ItemUseEvoStone ; FIRE_STONE - dw ItemUseEvoStone ; THUNDER_STONE - dw ItemUseEvoStone ; WATER_STONE - dw ItemUseVitamin ; HP_UP - dw ItemUseVitamin ; PROTEIN - dw ItemUseVitamin ; IRON - dw ItemUseVitamin ; CARBOS - dw ItemUseVitamin ; CALCIUM - dw ItemUseVitamin ; RARE_CANDY - dw UnusableItem ; DOME_FOSSIL - dw UnusableItem ; HELIX_FOSSIL - dw UnusableItem ; SECRET_KEY - dw UnusableItem - dw UnusableItem ; BIKE_VOUCHER - dw ItemUseXAccuracy ; X_ACCURACY - dw ItemUseEvoStone ; LEAF_STONE - dw ItemUseCardKey ; CARD_KEY - dw UnusableItem ; NUGGET - dw UnusableItem ; ??? PP_UP - dw ItemUsePokedoll ; POKE_DOLL - dw ItemUseMedicine ; FULL_HEAL - dw ItemUseMedicine ; REVIVE - dw ItemUseMedicine ; MAX_REVIVE - dw ItemUseGuardSpec ; GUARD_SPEC - dw ItemUseSuperRepel ; SUPER_REPL - dw ItemUseMaxRepel ; MAX_REPEL - dw ItemUseDireHit ; DIRE_HIT - dw UnusableItem ; COIN - dw ItemUseMedicine ; FRESH_WATER - dw ItemUseMedicine ; SODA_POP - dw ItemUseMedicine ; LEMONADE - dw UnusableItem ; S_S_TICKET - dw UnusableItem ; GOLD_TEETH - dw ItemUseXStat ; X_ATTACK - dw ItemUseXStat ; X_DEFEND - dw ItemUseXStat ; X_SPEED - dw ItemUseXStat ; X_SPECIAL - dw ItemUseCoinCase ; COIN_CASE - dw ItemUseOaksParcel ; OAKS_PARCEL - dw ItemUseItemfinder ; ITEMFINDER - dw UnusableItem ; SILPH_SCOPE - dw ItemUsePokeflute ; POKE_FLUTE - dw UnusableItem ; LIFT_KEY - dw UnusableItem ; EXP_ALL - dw ItemUseOldRod ; OLD_ROD - dw ItemUseGoodRod ; GOOD_ROD - dw ItemUseSuperRod ; SUPER_ROD - dw ItemUsePPUp ; PP_UP (real one) - dw ItemUsePPRestore ; ETHER - dw ItemUsePPRestore ; MAX_ETHER - dw ItemUsePPRestore ; ELIXER - dw ItemUsePPRestore ; MAX_ELIXER - -ItemUseBall: - -; Balls can't be used out of battle. - ld a, [wIsInBattle] - and a - jp z, ItemUseNotTime - -; Balls can't catch trainers' Pokémon. - dec a - jp nz, ThrowBallAtTrainerMon - -; If this is for the old man battle, skip checking if the party & box are full. - ld a, [wBattleType] - cp BATTLE_TYPE_OLD_MAN - jr z, .canUseBall - cp BATTLE_TYPE_PIKACHU - jr z, .canUseBall - - ld a, [wPartyCount] ; is party full? - cp PARTY_LENGTH - jr nz, .canUseBall - ld a, [wNumInBox] ; is box full? - cp MONS_PER_BOX - jp z, BoxFullCannotThrowBall - -.canUseBall - xor a - ld [wCapturedMonSpecies], a - - ld a, [wBattleType] - cp BATTLE_TYPE_SAFARI - jr nz, .skipSafariZoneCode - -.safariZone - ld hl, wNumSafariBalls - dec [hl] ; remove a Safari Ball - -.skipSafariZoneCode - call RunDefaultPaletteCommand - - ld a, $43 ; successful capture value - ld [wPokeBallAnimData], a - - call LoadScreenTilesFromBuffer1 - ld hl, ItemUseText00 - call PrintText - -; If the player is fighting an unidentified ghost, set the value that indicates -; the Pokémon can't be caught and skip the capture calculations. - callab IsGhostBattle - ld b, $10 ; can't be caught value - jp z, .setAnimData - - ld a, [wBattleType] - cp BATTLE_TYPE_OLD_MAN - jr z, .oldManBattle - cp BATTLE_TYPE_PIKACHU - jr z, .oldManBattle ; pikachu battle technically old man battle - jr .notOldManBattle - -.oldManBattle - ld hl, wGrassRate - ld de, wPlayerName - ld bc, NAME_LENGTH - call CopyData ; save the player's name in the Wild Monster data (part of the Cinnabar Island Missingno. glitch) - ld a, [wBattleType] - cp BATTLE_TYPE_OLD_MAN - jp nz,.captured - ld a,$1 - ld [wCapturedMonSpecies], a - CheckEvent EVENT_02F - ld b, $63 - jp nz,.setAnimData - jp .captured -.notOldManBattle -; If the player is fighting the ghost Marowak, set the value that indicates the -; Pokémon can't be caught and skip the capture calculations. - ld a, [wCurMap] - cp POKEMON_TOWER_6F - jr nz, .loop - ld a, [wEnemyMonSpecies2] - cp RESTLESS_SOUL - ld b, $10 ; can't be caught value - jp z, .setAnimData - -; Get the first random number. Let it be called Rand1. -; Rand1 must be within a certain range according the kind of ball being thrown. -; The ranges are as follows. -; Poké Ball: [0, 255] -; Great Ball: [0, 200] -; Ultra/Safari Ball: [0, 150] -; Loop until an acceptable number is found. - -.loop - call Random - ld b, a - -; Get the item ID. - ld hl, wcf91 - ld a, [hl] - -; The Master Ball always succeeds. - cp MASTER_BALL - jp z, .captured - -; Anything will do for the basic Poké Ball. - cp POKE_BALL - jr z, .checkForAilments - -; If it's a Great/Ultra/Safari Ball and Rand1 is greater than 200, try again. - ld a, 200 - cp b - jr c, .loop - -; Less than or equal to 200 is good enough for a Great Ball. - ld a, [hl] - cp GREAT_BALL - jr z, .checkForAilments - -; If it's an Ultra/Safari Ball and Rand1 is greater than 150, try again. - ld a, 150 - cp b - jr c, .loop - -.checkForAilments -; Pokémon can be caught more easily with a status ailment. -; Depending on the status ailment, a certain value will be subtracted from -; Rand1. Let this value be called Status. -; The larger Status is, the more easily the Pokémon can be caught. -; no status ailment: Status = 0 -; Burn/Paralysis/Poison: Status = 12 -; Freeze/Sleep: Status = 25 -; If Status is greater than Rand1, the Pokémon will be caught for sure. - ld a, [wEnemyMonStatus] - and a - jr z, .skipAilmentValueSubtraction ; no ailments - and 1 << FRZ | SLP - ld c, 12 - jr z, .notFrozenOrAsleep - ld c, 25 -.notFrozenOrAsleep - ld a, b - sub c - jp c, .captured - ld b, a - -.skipAilmentValueSubtraction - push bc ; save (Rand1 - Status) - -; Calculate MaxHP * 255. - xor a - ld [H_MULTIPLICAND], a - ld hl, wEnemyMonMaxHP - ld a, [hli] - ld [H_MULTIPLICAND + 1], a - ld a, [hl] - ld [H_MULTIPLICAND + 2], a - ld a, 255 - ld [H_MULTIPLIER], a - call Multiply - -; Determine BallFactor. It's 8 for Great Balls and 12 for the others. - ld a, [wcf91] - cp GREAT_BALL - ld a, 12 - jr nz, .skip1 - ld a, 8 - -.skip1 -; Note that the results of all division operations are floored. - -; Calculate (MaxHP * 255) / BallFactor. - ld [H_DIVISOR], a - ld b, 4 ; number of bytes in dividend - call Divide - -; Divide the enemy's current HP by 4. HP is not supposed to exceed 999 so -; the result should fit in a. If the division results in a quotient of 0, -; change it to 1. - ld hl, wEnemyMonHP - ld a, [hli] - ld b, a - ld a, [hl] - srl b - rr a - srl b - rr a - and a - jr nz, .skip2 - inc a - -.skip2 - -; Let W = ((MaxHP * 255) / BallFactor) / max(HP / 4, 1). Calculate W. - ld [H_DIVISOR], a - ld b, 4 - call Divide - -; If W > 255, store 255 in [H_QUOTIENT + 3]. -; Let X = min(W, 255) = [H_QUOTIENT + 3]. - ld a, [H_QUOTIENT + 2] - and a - jr z, .skip3 - ld a, 255 - ld [H_QUOTIENT + 3], a - -.skip3 - pop bc ; b = Rand1 - Status - -; If Rand1 - Status > CatchRate, the ball fails to capture the Pokémon. - ld a, [wEnemyMonActualCatchRate] - cp b - jr c, .failedToCapture - -; If W > 255, the ball captures the Pokémon. - ld a, [H_QUOTIENT + 2] - and a - jr nz, .captured - - call Random ; Let this random number be called Rand2. - -; If Rand2 > X, the ball fails to capture the Pokémon. - ld b, a - ld a, [H_QUOTIENT + 3] - cp b - jr c, .failedToCapture - -.captured - jr .skipShakeCalculations - -.failedToCapture - ld a, [H_QUOTIENT + 3] - ld [wPokeBallCaptureCalcTemp], a ; Save X. - -; Calculate CatchRate * 100. - xor a - ld [H_MULTIPLICAND], a - ld [H_MULTIPLICAND + 1], a - ld a, [wEnemyMonActualCatchRate] - ld [H_MULTIPLICAND + 2], a - ld a, 100 - ld [H_MULTIPLIER], a - call Multiply - -; Determine BallFactor2. -; Poké Ball: BallFactor2 = 255 -; Great Ball: BallFactor2 = 200 -; Ultra/Safari Ball: BallFactor2 = 150 - ld a, [wcf91] - ld b, 255 - cp POKE_BALL - jr z, .skip4 - ld b, 200 - cp GREAT_BALL - jr z, .skip4 - ld b, 150 - cp ULTRA_BALL - jr z, .skip4 - -.skip4 - -; Let Y = (CatchRate * 100) / BallFactor2. Calculate Y. - ld a, b - ld [H_DIVISOR], a - ld b, 4 - call Divide - -; If Y > 255, there are 3 shakes. -; Note that this shouldn't be possible. -; The maximum value of Y is (255 * 100) / 150 = 170. - ld a, [H_QUOTIENT + 2] - and a - ld b, $63 ; 3 shakes - jr nz, .setAnimData - -; Calculate X * Y. - ld a, [wPokeBallCaptureCalcTemp] - ld [H_MULTIPLIER], a - call Multiply - -; Calculate (X * Y) / 255. - ld a, 255 - ld [H_DIVISOR], a - ld b, 4 - call Divide - -; Determine Status2. -; no status ailment: Status2 = 0 -; Burn/Paralysis/Poison: Status2 = 5 -; Freeze/Sleep: Status2 = 10 - ld a, [wEnemyMonStatus] - and a - jr z, .skip5 - and 1 << FRZ | SLP - ld b, 5 - jr z, .addAilmentValue - ld b, 10 - -.addAilmentValue -; If the Pokémon has a status ailment, add Status2. - ld a, [H_QUOTIENT + 3] - add b - ld [H_QUOTIENT + 3], a - -.skip5 -; Finally determine the number of shakes. -; Let Z = ((X * Y) / 255) + Status2 = [H_QUOTIENT + 3]. -; The number of shakes depend on the range Z is in. -; 0 ≤ Z < 10: 0 shakes (the ball misses) -; 10 ≤ Z < 30: 1 shake -; 30 ≤ Z < 70: 2 shakes -; 70 ≤ Z: 3 shakes - ld a, [H_QUOTIENT + 3] - cp 10 - ld b, $20 - jr c, .setAnimData - cp 30 - ld b, $61 - jr c, .setAnimData - cp 70 - ld b, $62 - jr c, .setAnimData - ld b, $63 - -.setAnimData - ld a, b - ld [wPokeBallAnimData], a - -.skipShakeCalculations - ld c, 20 - call DelayFrames - -; Do the animation. - ld a, TOSS_ANIM - ld [wAnimationID], a - xor a - ld [H_WHOSETURN], a - ld [wAnimationType], a - ld [wDamageMultipliers], a - ld a, [wWhichPokemon] - push af - ld a, [wcf91] - push af - predef MoveAnimation - pop af - ld [wcf91], a - pop af - ld [wWhichPokemon], a - -; Determine the message to display from the animation. - ld a, [wPokeBallAnimData] - cp $10 - ld hl, ItemUseBallText00 - jp z, .printMessage - cp $20 - ld hl, ItemUseBallText01 - jp z, .printMessage - cp $61 - ld hl, ItemUseBallText02 - jp z, .printMessage - cp $62 - ld hl, ItemUseBallText03 - jp z, .printMessage - cp $63 - ld hl, ItemUseBallText04 - jp z, .printMessage - -; Save current HP. - ld hl, wEnemyMonHP - ld a, [hli] - push af - ld a, [hli] - push af - -; Save status ailment. - inc hl - ld a, [hl] - push af - - push hl - -; If the Pokémon is transformed, the Pokémon is assumed to be a Ditto. -; This is a bug because a wild Pokémon could have used Transform via -; Mirror Move even though the only wild Pokémon that knows Transform is Ditto. - ld hl, wEnemyBattleStatus3 - bit TRANSFORMED, [hl] - jr z, .notTransformed - ld a, DITTO - ld [wEnemyMonSpecies2], a - jr .skip6 - -.notTransformed -; If the Pokémon is not transformed, set the transformed bit and copy the -; DVs to wTransformedEnemyMonOriginalDVs so that LoadEnemyMonData won't generate -; new DVs. - set TRANSFORMED, [hl] - ld hl, wTransformedEnemyMonOriginalDVs - ld a, [wEnemyMonDVs] - ld [hli], a - ld a, [wEnemyMonDVs + 1] - ld [hl], a - -.skip6 - ld a, [wcf91] - push af - ld a, [wEnemyMonSpecies2] - ld [wcf91], a - ld a, [wEnemyMonLevel] - ld [wCurEnemyLVL], a - callab LoadEnemyMonData - pop af - ld [wcf91], a - pop hl - pop af - ld [hld], a - dec hl - pop af - ld [hld], a - pop af - ld [hl], a - ld a, [wEnemyMonSpecies] - ld [wCapturedMonSpecies], a - ld [wcf91], a - ld [wd11e], a - ld a, [wBattleType] - cp BATTLE_TYPE_OLD_MAN ; is this the old man battle? - jp z, .oldManCaughtMon ; if so, don't give the player the caught Pokémon - cp BATTLE_TYPE_PIKACHU - jr z, .oldManCaughtMon ; same with Pikachu battle - ld hl, ItemUseBallText05 - call PrintText - -; Add the caught Pokémon to the Pokédex. - predef IndexToPokedex - ld a, [wd11e] - dec a - ld c, a - ld b, FLAG_TEST - ld hl, wPokedexOwned - predef FlagActionPredef - ld a, c - push af - ld a, [wd11e] - dec a - ld c, a - ld b, FLAG_SET - predef FlagActionPredef - pop af - - and a ; was the Pokémon already in the Pokédex? - jr nz, .skipShowingPokedexData ; if so, don't show the Pokédex data - - ld hl, ItemUseBallText06 - call PrintText - call ClearSprites - ld a, [wEnemyMonSpecies] - ld [wd11e], a - predef ShowPokedexData - -.skipShowingPokedexData - ld a, $1 - ld [wd49c], a - ld a, $85 - ld [wPikachuMood], a - ld a, [wPartyCount] - cp PARTY_LENGTH ; is party full? - jr z, .sendToBox - xor a ; PLAYER_PARTY_DATA - ld [wMonDataLocation], a - call ClearSprites - ld hl, .emptyString - call PrintText - call AddPartyMon - jr .done - -.sendToBox - call ClearSprites - call SendNewMonToBox - ld hl, ItemUseBallText07 - CheckEvent EVENT_MET_BILL - jr nz, .printTransferredToPCText - ld hl, ItemUseBallText08 -.printTransferredToPCText - call PrintText - jr .done - -.oldManCaughtMon - ld hl, ItemUseBallText05 - -.printMessage - call PrintText - call ClearSprites - -.done - ld a, [wBattleType] - and a ; is this the old man battle? - ret nz ; if so, don't remove a ball from the bag - -; Remove a ball from the bag. - ld hl, wNumBagItems - inc a - ld [wItemQuantity], a - jp RemoveItemFromInventory - -.emptyString - db "@" - -ItemUseBallText00: -;"It dodged the thrown ball!" -;"This pokemon can't be caught" - TX_FAR _ItemUseBallText00 - db "@" -ItemUseBallText01: -;"You missed the pokemon!" - TX_FAR _ItemUseBallText01 - db "@" -ItemUseBallText02: -;"Darn! The pokemon broke free!" - TX_FAR _ItemUseBallText02 - db "@" -ItemUseBallText03: -;"Aww! It appeared to be caught!" - TX_FAR _ItemUseBallText03 - db "@" -ItemUseBallText04: -;"Shoot! It was so close too!" - TX_FAR _ItemUseBallText04 - db "@" -ItemUseBallText05: -;"All right! {MonName} was caught!" -;play sound - TX_FAR _ItemUseBallText05 - TX_SFX_CAUGHT_MON - TX_BLINK - db "@" -ItemUseBallText07: -;"X was transferred to Bill's PC" - TX_FAR _ItemUseBallText07 - db "@" -ItemUseBallText08: -;"X was transferred to someone's PC" - TX_FAR _ItemUseBallText08 - db "@" - -ItemUseBallText06: -;"New DEX data will be added..." -;play sound - TX_FAR _ItemUseBallText06 - TX_SFX_DEX_PAGE_ADDED - TX_BLINK - db "@" - -ItemUseTownMap: - ld a, [wIsInBattle] - and a - jp nz, ItemUseNotTime - jpba DisplayTownMap - -ItemUseBicycle: - ld a, [wIsInBattle] - and a - jp nz, ItemUseNotTime - ld a, [wWalkBikeSurfState] - ld [wWalkBikeSurfStateCopy], a - cp 2 ; is the player surfing? - jp z, ItemUseNotTime - dec a ; is player already bicycling? - jr nz, .tryToGetOnBike -.getOffBike - call ItemUseReloadOverworldData - xor a - ld [wWalkBikeSurfState], a ; change player state to walking - ld a, $00 - ld [wPikachuSpawnState], a - call PlayDefaultMusic ; play walking music - ld hl, GotOffBicycleText - jp PrintText - -.tryToGetOnBike - call IsBikeRidingAllowed - jp nc, NoCyclingAllowedHere - call ItemUseReloadOverworldData - xor a ; no keys pressed - ld [hJoyHeld], a ; current joypad state - ld a, $1 - ld [wWalkBikeSurfState], a ; change player state to bicycling - call PlayDefaultMusic ; play bike riding music - xor a - ld [wWalkBikeSurfState], a - ld hl, GotOnBicycleText - call PrintText - ld a, $1 - ld [wWalkBikeSurfState], a - ret - -; used for Surf out-of-battle effect -ItemUseSurfboard: - ld a, [wWalkBikeSurfState] - ld [wWalkBikeSurfStateCopy], a - cp 2 ; is the player already surfing? - jr z, .tryToStopSurfing -.tryToSurf - call IsNextTileShoreOrWater - jp nc, SurfingAttemptFailed - ld hl, TilePairCollisionsWater - call CheckForTilePairCollisions - jp c, SurfingAttemptFailed -.surf - call .makePlayerMoveForward - ld hl, wd730 - set 7, [hl] - ld a, 2 - ld [wWalkBikeSurfState], a ; change player state to surfing - call PlayDefaultMusic ; play surfing music - ld hl, SurfingGotOnText - jp PrintText - -.tryToStopSurfing - xor a - ld [hSpriteIndexOrTextID], a - ld d, 16 ; talking range in pixels (normal range) - call IsSpriteInFrontOfPlayer2 - res 7, [hl] - ld a, [hSpriteIndexOrTextID] - and a ; is there a sprite in the way? - jr nz, .cannotStopSurfing - ld hl, TilePairCollisionsWater - call CheckForTilePairCollisions - jr c, .cannotStopSurfing - ld a, [wTileInFrontOfPlayer] - ld c, a - call IsTilePassable - jr nc, .stopSurfing -.cannotStopSurfing - ld hl, SurfingNoPlaceToGetOffText - jp PrintText - -.stopSurfing - call .makePlayerMoveForward - ld a, $3 - ld [wPikachuSpawnState], a - ld hl, wPikachuOverworldStateFlags - set 5, [hl] - ld hl, wd730 - set 7, [hl] - xor a - ld [wWalkBikeSurfState], a ; change player state to walking - dec a - ld [wJoyIgnore], a - call PlayDefaultMusic ; play walking music - call GBPalWhiteOutWithDelay3 - jp LoadWalkingPlayerSpriteGraphics - -; uses a simulated button press to make the player move forward -.makePlayerMoveForward - ld a, [wPlayerDirection] ; direction the player is going - bit PLAYER_DIR_BIT_UP, a - ld b, D_UP - jr nz, .storeSimulatedButtonPress - bit PLAYER_DIR_BIT_DOWN, a - ld b, D_DOWN - jr nz, .storeSimulatedButtonPress - bit PLAYER_DIR_BIT_LEFT, a - ld b, D_LEFT - jr nz, .storeSimulatedButtonPress - ld b, D_RIGHT -.storeSimulatedButtonPress - ld a, b - ld [wSimulatedJoypadStatesEnd], a - xor a - ld [wWastedByteCD39], a - inc a - ld [wSimulatedJoypadStatesIndex], a - ret - -SurfingGotOnText: - TX_FAR _SurfingGotOnText - db "@" - -SurfingNoPlaceToGetOffText: - TX_FAR _SurfingNoPlaceToGetOffText - db "@" - -ItemUsePokedex: - predef_jump ShowPokedexMenu - -ItemUseEvoStone: - ld a, [wIsInBattle] - and a - jp nz, ItemUseNotTime - ld a, [wWhichPokemon] - push af - ld a, [wcf91] - ld [wEvoStoneItemID], a - push af - ld a, EVO_STONE_PARTY_MENU - ld [wPartyMenuTypeOrMessageID], a - ld a, $ff - ld [wUpdateSpritesEnabled], a - call DisplayPartyMenu - ld a, [wcf91] - ld [wLoadedMon], a - pop bc - jr c, .canceledItemUse - ld a, b - ld [wcf91], a - call Func_d85d - jr nc, .noEffect - callab IsThisPartymonStarterPikachu_Party - jr nc, .notPlayerPikachu - ld e, $1b - callab PlayPikachuSoundClip - ld a, [wWhichPokemon] - ld hl, wPartyMonNicks - call GetPartyMonName - ld hl, RefusingText - call PrintText - ld a, $4 - ld [wd49c], a - ld a, $82 - ld [wPikachuMood], a - jr .canceledItemUse - -.notPlayerPikachu - ld a, SFX_HEAL_AILMENT - call PlaySoundWaitForCurrent - call WaitForSoundToFinish - ld a, $01 - ld [wForceEvolution], a - callab TryEvolvingMon ; try to evolve pokemon - pop af - ld [wWhichPokemon], a - ld hl, wNumBagItems - ld a, 1 ; remove 1 stone - ld [wItemQuantity], a - jp RemoveItemFromInventory - -.noEffect - call ItemUseNoEffect -.canceledItemUse - xor a - ld [wActionResultOrTookBattleTurn], a ; item not used - pop af - ret - -Func_d85d: - ld hl, EvosMovesPointerTable - ld a, [wLoadedMon] - dec a - ld c, a - ld b, $0 - add hl, bc - add hl, bc - ld de, wcd6d - ld a, BANK(TryEvolvingMon) - ld bc, $2 - call FarCopyData - ld hl, wcd6d - ld a, [hli] - ld h, [hl] - ld l, a - ld de, wcd6d - ld a, BANK(TryEvolvingMon) - ld bc, 13 - call FarCopyData - ld hl, wcd6d -.loop - ld a, [hli] - and a - jr z, .cannotEvolveWithUsedStone - inc hl - inc hl - cp EV_ITEM - jr nz, .loop - dec hl - dec hl - ld b, [hl] - ld a, [wcf91] - inc hl - inc hl - inc hl - cp b - jr nz, .loop - scf - ret - -.cannotEvolveWithUsedStone - and a - ret - -RefusingText: - TX_FAR _RefusingText - db "@" - -ItemUseVitamin: - ld a, [wIsInBattle] - and a - jp nz, ItemUseNotTime - -ItemUseMedicine: - ld a, [wPartyCount] - and a - jp z, Func_e4bf - ld a, [wWhichPokemon] - push af - ld a, [wcf91] - push af - ld a, USE_ITEM_PARTY_MENU - ld [wPartyMenuTypeOrMessageID], a - ld a, $ff - ld [wUpdateSpritesEnabled], a - ld a, [wPseudoItemID] - and a ; using Softboiled? - jr z, .notUsingSoftboiled -; if using softboiled - call GoBackToPartyMenu - jr .getPartyMonDataAddress -.notUsingSoftboiled - call DisplayPartyMenu -.getPartyMonDataAddress - jp c, .canceledItemUse - ld hl, wPartyMons - ld bc, wPartyMon2 - wPartyMon1 - ld a, [wWhichPokemon] - call AddNTimes - ld a, [wWhichPokemon] - ld [wUsedItemOnWhichPokemon], a - ld d, a - ld a, [wcf91] - ld e, a - ld [wd0b5], a - pop af - push af - cp $28 - jr nc, .asm_d906 - push hl - push de - callabd_ModifyPikachuHappiness PIKAHAPPY_USEDITEM - pop de - pop hl -.asm_d906 - pop af - ld [wcf91], a - pop af - ld [wWhichPokemon], a - ld a, [wPseudoItemID] - and a ; using Softboiled? - jr z, .checkItemType -; if using softboiled - ld a, [wWhichPokemon] - cp d ; is the pokemon trying to use softboiled on itself? - jr z, ItemUseMedicine ; if so, force another choice -.checkItemType - ld a, [wcf91] - cp REVIVE - jr nc, .healHP ; if it's a Revive or Max Revive - cp FULL_HEAL - jr z, .cureStatusAilment ; if it's a Full Heal - cp HP_UP - jp nc, .useVitamin ; if it's a vitamin or Rare Candy - cp FULL_RESTORE - jr nc, .healHP ; if it's a Full Restore or one of the potions -; fall through if it's one of the status-specific healing items -.cureStatusAilment - ld bc, wPartyMon1Status - wPartyMon1 - add hl, bc ; hl now points to status - ld a, [wcf91] - lb bc, ANTIDOTE_MSG, 1 << PSN - cp ANTIDOTE - jr z, .checkMonStatus - lb bc, BURN_HEAL_MSG, 1 << BRN - cp BURN_HEAL - jr z, .checkMonStatus - lb bc, ICE_HEAL_MSG, 1 << FRZ - cp ICE_HEAL - jr z, .checkMonStatus - lb bc, AWAKENING_MSG, SLP - cp AWAKENING - jr z, .checkMonStatus - lb bc, PARALYZ_HEAL_MSG, 1 << PAR - cp PARLYZ_HEAL - jr z, .checkMonStatus - lb bc, FULL_HEAL_MSG, $ff ; Full Heal -.checkMonStatus - ld a, [hl] ; pokemon's status - and c ; does the pokemon have a status ailment the item can cure? - jp z, .healingItemNoEffect -; if the pokemon has a status the item can heal - xor a - ld [hl], a ; remove the status ailment in the party data - ld a, b - ld [wPartyMenuTypeOrMessageID], a ; the message to display for the item used - ld a, [wPlayerMonNumber] - cp d ; is pokemon the item was used on active in battle? - jp nz, .doneHealing -; if it is active in battle - xor a - ld [wBattleMonStatus], a ; remove the status ailment in the in-battle pokemon data - push hl - ld hl, wPlayerBattleStatus3 - res BADLY_POISONED, [hl] ; heal Toxic status - pop hl - ld bc, wPartyMon1Stats - wPartyMon1Status - add hl, bc ; hl now points to party stats - ld de, wBattleMonStats - ld bc, NUM_STATS * 2 - call CopyData ; copy party stats to in-battle stat data - predef DoubleOrHalveSelectedStats - jp .doneHealing - -.healHP - inc hl ; hl = address of current HP - ld a, [hli] - ld b, a - ld [wHPBarOldHP+1], a - ld a, [hl] - ld c, a - ld [wHPBarOldHP], a ; current HP stored at wHPBarOldHP (2 bytes, big-endian) - or b - jr nz, .notFainted -.fainted - ld a, [wcf91] - cp REVIVE - jr z, .updateInBattleFaintedData - cp MAX_REVIVE - jr z, .updateInBattleFaintedData - jp .healingItemNoEffect - -.updateInBattleFaintedData - ld a, [wWhichPokemon] - push af - ld a, [wUsedItemOnWhichPokemon] - ld [wWhichPokemon], a - push hl - push de - push bc - callab Func_2fd6a - pop bc - pop de - pop hl - pop af - ld [wWhichPokemon], a - - ld a, [wIsInBattle] - and a - jr z, .compareCurrentHPToMaxHP - push hl - push de - push bc - ld a, [wUsedItemOnWhichPokemon] - ld c, a - ld hl, wPartyFoughtCurrentEnemyFlags - ld b, FLAG_TEST - predef FlagActionPredef - ld a, c - and a - jr z, .next - ld a, [wUsedItemOnWhichPokemon] - ld c, a - ld hl, wPartyGainExpFlags - ld b, FLAG_SET - predef FlagActionPredef -.next - pop bc - pop de - pop hl - jr .compareCurrentHPToMaxHP - -.notFainted - ld a, [wcf91] - cp REVIVE - jp z, .healingItemNoEffect - cp MAX_REVIVE - jp z, .healingItemNoEffect -.compareCurrentHPToMaxHP - push hl - push bc - ld bc, wPartyMon1MaxHP - (wPartyMon1HP + 1) - add hl, bc ; hl now points to max HP - pop bc - ld a, [hli] - cp b - jr nz, .skipComparingLSB ; no need to compare the LSB's if the MSB's don't match - ld a, [hl] - cp c -.skipComparingLSB - pop hl - jr nz, .notFullHP -.fullHP ; if the pokemon's current HP equals its max HP - ld a, [wcf91] - cp FULL_RESTORE - jp nz, .healingItemNoEffect - inc hl - inc hl - ld a, [hld] ; status ailment - and a ; does the pokemon have a status ailment? - jp z, .healingItemNoEffect - ld a, FULL_HEAL - ld [wcf91], a - dec hl - dec hl - dec hl - jp .cureStatusAilment - -.notFullHP ; if the pokemon's current HP doesn't equal its max HP - xor a - ld [wLowHealthAlarm], a ;disable low health alarm - ld [wChannelSoundIDs + Ch5], a - push hl - push de - ld bc, wPartyMon1MaxHP - (wPartyMon1HP + 1) - add hl, bc ; hl now points to max HP - ld a, [hli] - ld [wHPBarMaxHP+1], a - ld a, [hl] - ld [wHPBarMaxHP], a ; max HP stored at wHPBarMaxHP (2 bytes, big-endian) - ld a, [wPseudoItemID] - and a ; using Softboiled? - jp z, .notUsingSoftboiled2 -; if using softboiled - ld hl, wHPBarMaxHP - ld a, [hli] - push af - ld a, [hli] - push af - ld a, [hli] - push af - ld a, [hl] - push af - ld hl, wPartyMon1MaxHP - ld a, [wWhichPokemon] - ld bc, wPartyMon2 - wPartyMon1 - call AddNTimes - ld a, [hli] - ld [wHPBarMaxHP + 1], a - ld [H_DIVIDEND], a - ld a, [hl] - ld [wHPBarMaxHP], a - ld [H_DIVIDEND + 1], a - ld a, 5 - ld [H_DIVISOR], a - ld b, 2 ; number of bytes - call Divide ; get 1/5 of max HP of pokemon that used Softboiled - ld bc, (wPartyMon1HP + 1) - (wPartyMon1MaxHP + 1) - add hl, bc ; hl now points to LSB of current HP of pokemon that used Softboiled -; subtract 1/5 of max HP from current HP of pokemon that used Softboiled - ld a, [H_QUOTIENT + 3] - push af - ld b, a - ld a, [hl] - ld [wHPBarOldHP], a - sub b - ld [hld], a - ld [wHPBarNewHP], a - ld a, [H_QUOTIENT + 2] - ld b, a - ld a, [hl] - ld [wHPBarOldHP+1], a - sbc b - ld [hl], a - ld [wHPBarNewHP+1], a - coord hl, 4, 1 - ld a, [wWhichPokemon] - ld bc, 2 * SCREEN_WIDTH - call AddNTimes ; calculate coordinates of HP bar of pokemon that used Softboiled - ld a, SFX_HEAL_HP - call PlaySoundWaitForCurrent - ld a, [hFlags_0xFFFA] - set 0, a - ld [hFlags_0xFFFA], a - ld a, $02 - ld [wHPBarType], a - predef UpdateHPBar2 ; animate HP bar decrease of pokemon that used Softboiled - ld a, [hFlags_0xFFFA] - res 0, a - ld [hFlags_0xFFFA], a - pop af - ld b, a ; store heal amount (1/5 of max HP) - ld hl, wHPBarOldHP + 1 - pop af - ld [hld], a - pop af - ld [hld], a - pop af - ld [hld], a - pop af - ld [hl], a - jr .addHealAmount - -.notUsingSoftboiled2 - ld a, [wcf91] - cp SODA_POP - ld b, 60 ; Soda Pop heal amount - jr z, .addHealAmount - ld b, 80 ; Lemonade heal amount - jr nc, .addHealAmount - cp FRESH_WATER - ld b, 50 ; Fresh Water heal amount - jr z, .addHealAmount - cp SUPER_POTION - ld b, 200 ; Hyper Potion heal amount - jr c, .addHealAmount - ld b, 50 ; Super Potion heal amount - jr z, .addHealAmount - ld b, 20 ; Potion heal amount -.addHealAmount - pop de - pop hl - ld a, [hl] - add b - ld [hld], a - ld [wHPBarNewHP], a - ld a, [hl] - ld [wHPBarNewHP+1], a - jr nc, .noCarry - inc [hl] - ld a, [hl] - ld [wHPBarNewHP + 1], a -.noCarry - push de - inc hl - ld d, h - ld e, l ; de now points to current HP - ld hl, (wPartyMon1MaxHP + 1) - (wPartyMon1HP + 1) - add hl, de ; hl now points to max HP - ld a, [wcf91] - cp REVIVE - jr z, .setCurrentHPToHalfMaxHP - ld a, [hld] - ld b, a - ld a, [de] - sub b - dec de - ld b, [hl] - ld a, [de] - sbc b - jr nc, .setCurrentHPToMaxHp ; if current HP exceeds max HP after healing - ld a, [wcf91] - cp HYPER_POTION - jr c, .setCurrentHPToMaxHp ; if using a Full Restore or Max Potion - cp MAX_REVIVE - jr z, .setCurrentHPToMaxHp ; if using a Max Revive - jr .updateInBattleData - -.setCurrentHPToHalfMaxHP - dec hl - dec de - ld a, [hli] - srl a - ld [de], a - ld [wHPBarNewHP+1], a - ld a, [hl] - rr a - inc de - ld [de], a - ld [wHPBarNewHP], a - dec de - jr .doneHealingPartyHP - -.setCurrentHPToMaxHp - ld a, [hli] - ld [de], a - ld [wHPBarNewHP+1], a - inc de - ld a, [hl] - ld [de], a - ld [wHPBarNewHP], a - dec de -.doneHealingPartyHP ; done updating the pokemon's current HP in the party data structure - ld a, [wcf91] - cp FULL_RESTORE - jr nz, .updateInBattleData - ld bc, wPartyMon1Status - (wPartyMon1MaxHP + 1) - add hl, bc - xor a - ld [hl], a ; remove the status ailment in the party data -.updateInBattleData - ld h, d - ld l, e - pop de - ld a, [wPlayerMonNumber] - cp d ; is pokemon the item was used on active in battle? - jr nz, .calculateHPBarCoords -; copy party HP to in-battle HP - ld a, [hli] - ld [wBattleMonHP], a - ld a, [hld] - ld [wBattleMonHP + 1], a - ld a, [wcf91] - cp FULL_RESTORE - jr nz, .calculateHPBarCoords - xor a - ld [wBattleMonStatus], a ; remove the status ailment in the in-battle pokemon data -.calculateHPBarCoords - ld hl, wOAMBuffer + $90 - ld bc, 2 * SCREEN_WIDTH - inc d -.calculateHPBarCoordsLoop - add hl, bc - dec d - jr nz, .calculateHPBarCoordsLoop - jr .doneHealing - -.healingItemNoEffect - call ItemUseNoEffect - jp .done - -.doneHealing - ld a, [wPseudoItemID] - and a ; using Softboiled? - jr nz, .skipRemovingItem ; no item to remove if using Softboiled - push hl - call RemoveUsedItem - pop hl -.skipRemovingItem - ld a, [wcf91] - cp FULL_RESTORE - jr c, .playStatusAilmentCuringSound - cp FULL_HEAL - jr z, .playStatusAilmentCuringSound - ld a, SFX_HEAL_HP - call PlaySoundWaitForCurrent - ld a, [hFlags_0xFFFA] - set 0, a - ld [hFlags_0xFFFA], a - ld a, $02 - ld [wHPBarType], a - predef UpdateHPBar2 ; animate the HP bar lengthening - ld a, [hFlags_0xFFFA] - res 0, a - ld [hFlags_0xFFFA], a - ld a, REVIVE_MSG - ld [wPartyMenuTypeOrMessageID], a - ld a, [wcf91] - cp REVIVE - jr z, .showHealingItemMessage - cp MAX_REVIVE - jr z, .showHealingItemMessage - ld a, POTION_MSG - ld [wPartyMenuTypeOrMessageID], a - jr .showHealingItemMessage - -.playStatusAilmentCuringSound - ld a, SFX_HEAL_AILMENT - call PlaySoundWaitForCurrent -.showHealingItemMessage - xor a - ld [H_AUTOBGTRANSFERENABLED], a - call ClearScreen - dec a - ld [wUpdateSpritesEnabled], a - call RedrawPartyMenu ; redraws the party menu and displays the message - ld a, 1 - ld [H_AUTOBGTRANSFERENABLED], a - ld c, 50 - call DelayFrames - call WaitForTextScrollButtonPress - jr .done - -.canceledItemUse - xor a - ld [wActionResultOrTookBattleTurn], a ; item use failed - pop af - pop af -.done - ld a, [wPseudoItemID] - and a ; using Softboiled? - ret nz ; if so, return - call GBPalWhiteOut - call z, RunDefaultPaletteCommand - ld a, [wIsInBattle] - and a - ret nz - jp ReloadMapData - -.useVitamin - push hl - ld a, [hl] - ld [wd0b5], a - ld [wd11e], a - ld bc, wPartyMon1Level - wPartyMon1 - add hl, bc ; hl now points to level - ld a, [hl] ; a = level - ld [wCurEnemyLVL], a ; store level - call GetMonHeader - push de - ld a, d - ld hl, wPartyMonNicks - call GetPartyMonName - pop de - pop hl - ld a, [wcf91] - cp RARE_CANDY - jp z, .useRareCandy - push hl - sub HP_UP - add a - ld bc, wPartyMon1HPExp - wPartyMon1 - add hl, bc - add l - ld l, a - jr nc, .noCarry2 - inc h -.noCarry2 - ld a, 10 - ld b, a - ld a, [hl] ; a = MSB of stat experience of the appropriate stat - cp 100 ; is there already at least 25600 (256 * 100) stat experience? - jr nc, .vitaminNoEffect ; if so, vitamins can't add any more - add b ; add 2560 (256 * 10) stat experience - jr nc, .noCarry3 ; a carry should be impossible here, so this will always jump - ld a, 255 -.noCarry3 - ld [hl], a - pop hl - call .recalculateStats - ld hl, VitaminText - ld a, [wcf91] - sub HP_UP - 1 - ld c, a -.statNameLoop ; loop to get the address of the name of the stat the vitamin increases - dec c - jr z, .gotStatName -.statNameInnerLoop - ld a, [hli] - ld b, a - ld a, $50 - cp b - jr nz, .statNameInnerLoop - jr .statNameLoop - -.gotStatName - ld de, wcf4b - ld bc, 10 - call CopyData ; copy the stat's name to wcf4b - ld a, SFX_HEAL_AILMENT - call PlaySound - ld hl, VitaminStatRoseText - call PrintText - jp RemoveUsedItem - -.vitaminNoEffect - pop hl - ld hl, VitaminNoEffectText - call PrintText - jp GBPalWhiteOut - -.recalculateStats - ld bc, wPartyMon1Stats - wPartyMon1 - add hl, bc - ld d, h - ld e, l ; de now points to stats - ld bc, (wPartyMon1Exp + 2) - wPartyMon1Stats - add hl, bc ; hl now points to LSB of experience - ld b, 1 - jp CalcStats ; recalculate stats -.useRareCandy - push hl - ld bc, wPartyMon1Level - wPartyMon1 - add hl, bc ; hl now points to level - ld a, [hl] ; a = level - cp MAX_LEVEL - jr z, .vitaminNoEffect ; can't raise level above 100 - inc a - ld [hl], a ; store incremented level - ld [wCurEnemyLVL], a - push hl - push de - ld d, a - callab CalcExperience ; calculate experience for next level and store it at $ff96 - pop de - pop hl - ld bc, wPartyMon1Exp - wPartyMon1Level - add hl, bc ; hl now points to MSB of experience -; update experience to minimum for new level - ld a, [hExperience] - ld [hli], a - ld a, [hExperience + 1] - ld [hli], a - ld a, [hExperience + 2] - ld [hl], a - pop hl - ld a, [wWhichPokemon] - push af - ld a, [wcf91] - push af - push de - push hl - ld bc, wPartyMon1MaxHP - wPartyMon1 - add hl, bc ; hl now points to MSB of max HP - ld a, [hli] - ld b, a - ld c, [hl] - pop hl - push bc - push hl - call .recalculateStats - pop hl - ld bc, (wPartyMon1MaxHP + 1) - wPartyMon1 - add hl, bc ; hl now points to LSB of max HP - pop bc - ld a, [hld] - sub c - ld c, a - ld a, [hl] - sbc b - ld b, a ; bc = the amount of max HP gained from leveling up -; add the amount gained to the current HP - ld de, (wPartyMon1HP + 1) - wPartyMon1MaxHP - add hl, de ; hl now points to LSB of current HP - ld a, [hl] - add c - ld [hld], a - ld a, [hl] - adc b - ld [hl], a - ld a, RARE_CANDY_MSG - ld [wPartyMenuTypeOrMessageID], a - call RedrawPartyMenu - pop de - ld a, d - ld [wWhichPokemon], a - ld a, e - ld [wd11e], a - xor a ; PLAYER_PARTY_DATA - ld [wMonDataLocation], a - call LoadMonData - ld d, $01 - callab PrintStatsBox ; display new stats text box - call WaitForTextScrollButtonPress ; wait for button press - xor a ; PLAYER_PARTY_DATA - ld [wMonDataLocation], a - predef LearnMoveFromLevelUp ; learn level up move, if any - - xor a - ld [wForceEvolution], a - callabd_ModifyPikachuHappiness PIKAHAPPY_LEVELUP - ld a, [wWhichPokemon] - push af - ld a, [wUsedItemOnWhichPokemon] - ld [wWhichPokemon], a - callab Func_2fd6a ; evolve pokemon, if appropriate - pop af - ld [wWhichPokemon], a - - callab TryEvolvingMon - ld a, $01 - ld [wUpdateSpritesEnabled], a - pop af - ld [wcf91], a - pop af - ld [wWhichPokemon], a - jp RemoveUsedItem - -VitaminStatRoseText: - TX_FAR _VitaminStatRoseText - db "@" - -VitaminNoEffectText: - TX_FAR _VitaminNoEffectText - db "@" - -VitaminText: - db "HEALTH@" - db "ATTACK@" - db "DEFENSE@" - db "SPEED@" - db "SPECIAL@" - -ItemUseBait: - ld hl, ThrewBaitText - call PrintText - ld hl, wEnemyMonActualCatchRate ; catch rate - srl [hl] ; halve catch rate - ld a, BAIT_ANIM - ld hl, wSafariBaitFactor ; bait factor - ld de, wSafariEscapeFactor ; escape factor - jr BaitRockCommon - -ItemUseRock: - ld hl, ThrewRockText - call PrintText - ld hl, wEnemyMonActualCatchRate ; catch rate - ld a, [hl] - add a ; double catch rate - jr nc, .noCarry - ld a, $ff -.noCarry - ld [hl], a - ld a, ROCK_ANIM - ld hl, wSafariEscapeFactor ; escape factor - ld de, wSafariBaitFactor ; bait factor - -BaitRockCommon: - ld [wAnimationID], a - xor a - ld [wAnimationType], a - ld [H_WHOSETURN], a - ld [de], a ; zero escape factor (for bait), zero bait factor (for rock) -.randomLoop ; loop until a random number less than 5 is generated - call Random - and 7 - cp 5 - jr nc, .randomLoop - inc a ; increment the random number, giving a range from 1 to 5 inclusive - ld b, a - ld a, [hl] - add b ; increase bait factor (for bait), increase escape factor (for rock) - jr nc, .noCarry - ld a, $ff -.noCarry - ld [hl], a - predef MoveAnimation ; do animation - ld c, 70 - jp DelayFrames - -ThrewBaitText: - TX_FAR _ThrewBaitText - db "@" - -ThrewRockText: - TX_FAR _ThrewRockText - db "@" - -; also used for Dig out-of-battle effect -ItemUseEscapeRope: - ld a, [wIsInBattle] - and a - jr nz, .notUsable - ld a, [wCurMap] - cp AGATHAS_ROOM - jr z, .notUsable - cp BILLS_HOUSE - jr z, .notUsable - cp POKEMON_FAN_CLUB - jr z, .notUsable - ld a, [wCurMapTileset] - ld b, a - ld hl, EscapeRopeTilesets -.loop - ld a, [hli] - cp $ff - jr z, .notUsable - cp b - jr nz, .loop - ld hl, wd732 - set 3, [hl] - set 6, [hl] - call Func_1510 - ld hl, wd72e - res 4, [hl] - ResetEvent EVENT_IN_SAFARI_ZONE - xor a - ld [wNumSafariBalls], a - ld [wSafariZoneGateCurScript], a - inc a - ld [wEscapedFromBattle], a - ld [wActionResultOrTookBattleTurn], a ; item used - ld a, [wPseudoItemID] - and a ; using Dig? - ret nz ; if so, return - call ItemUseReloadOverworldData - ld c, 30 - call DelayFrames - jp RemoveUsedItem - -.notUsable - jp ItemUseNotTime - -EscapeRopeTilesets: - db FOREST, CEMETERY, CAVERN, FACILITY, INTERIOR - db $ff ; terminator - -ItemUseRepel: - ld b, 100 - -ItemUseRepelCommon: - ld a, [wIsInBattle] - and a - jp nz, ItemUseNotTime - ld a, b - ld [wRepelRemainingSteps], a - jp PrintItemUseTextAndRemoveItem - -; handles X Accuracy item -ItemUseXAccuracy: - ld a, [wIsInBattle] - and a - jp z, ItemUseNotTime - ld hl, wPlayerBattleStatus2 - set USING_X_ACCURACY, [hl] ; X Accuracy bit - callabd_ModifyPikachuHappiness PIKAHAPPY_USEDXITEM - jp PrintItemUseTextAndRemoveItem - -; This function is bugged and never works. It always jumps to ItemUseNotTime. -; The Card Key is handled in a different way. -ItemUseCardKey: - xor a - ld [wUnusedD71F], a - call GetTileAndCoordsInFrontOfPlayer - ld a, [GetTileAndCoordsInFrontOfPlayer] - cp $18 - jr nz, .next0 - ld hl, CardKeyTable1 - jr .next1 - -.next0 - cp $24 - jr nz, .next2 - ld hl, CardKeyTable2 - jr .next1 - -.next2 - cp $5e - jp nz, ItemUseNotTime - ld hl, CardKeyTable3 -.next1 - ld a, [wCurMap] - ld b, a -.loop - ld a, [hli] - cp $ff - jp z, ItemUseNotTime - cp b - jr nz, .nextEntry1 - ld a, [hli] - cp d - jr nz, .nextEntry2 - ld a, [hli] - cp e - jr nz, .nextEntry3 - ld a, [hl] - ld [wUnusedD71F], a - jr .done - -.nextEntry1 - inc hl -.nextEntry2 - inc hl -.nextEntry3 - inc hl - jr .loop - -.done - ld hl, ItemUseText00 - call PrintText - ld hl, wd728 - set 7, [hl] - ret - -; These tables are probably supposed to be door locations in Silph Co., -; but they are unused. -; The reason there are 3 tables is unknown. - -; Format: -; 00: Map ID -; 01: Y -; 02: X -; 03: ID? - -CardKeyTable1: - db SILPH_CO_2F, $04, $04, $00 - db SILPH_CO_2F, $04, $05, $01 - db SILPH_CO_4F, $0C, $04, $02 - db SILPH_CO_4F, $0C, $05, $03 - db SILPH_CO_7F, $06, $0A, $04 - db SILPH_CO_7F, $06, $0B, $05 - db SILPH_CO_9F, $04, $12, $06 - db SILPH_CO_9F, $04, $13, $07 - db SILPH_CO_10F, $08, $0A, $08 - db SILPH_CO_10F, $08, $0B, $09 - db $ff - -CardKeyTable2: - db SILPH_CO_3F, $08, $09, $0A - db SILPH_CO_3F, $09, $09, $0B - db SILPH_CO_5F, $04, $07, $0C - db SILPH_CO_5F, $05, $07, $0D - db SILPH_CO_6F, $0C, $05, $0E - db SILPH_CO_6F, $0D, $05, $0F - db SILPH_CO_8F, $08, $07, $10 - db SILPH_CO_8F, $09, $07, $11 - db SILPH_CO_9F, $08, $03, $12 - db SILPH_CO_9F, $09, $03, $13 - db $ff - -CardKeyTable3: - db SILPH_CO_11F, $08, $09, $14 - db SILPH_CO_11F, $09, $09, $15 - db $ff - -ItemUsePokedoll: - ld a, [wIsInBattle] - dec a - jp nz, ItemUseNotTime - ld a, $01 - ld [wEscapedFromBattle], a - jp PrintItemUseTextAndRemoveItem - -ItemUseGuardSpec: - ld a, [wIsInBattle] - and a - jp z, ItemUseNotTime - - ld a, [wWhichPokemon] - push af - ld a, [wPlayerMonNumber] - ld [wWhichPokemon], a - callabd_ModifyPikachuHappiness PIKAHAPPY_USEDXITEM - pop af - ld [wWhichPokemon], a - - ld hl, wPlayerBattleStatus2 - set PROTECTED_BY_MIST, [hl] ; Mist bit - jp PrintItemUseTextAndRemoveItem - -ItemUseSuperRepel: - ld b, 200 - jp ItemUseRepelCommon - -ItemUseMaxRepel: - ld b, 250 - jp ItemUseRepelCommon - -ItemUseDireHit: - ld a, [wIsInBattle] - and a - jp z, ItemUseNotTime - - ld a, [wWhichPokemon] - push af - ld a, [wPlayerMonNumber] - ld [wWhichPokemon], a - callabd_ModifyPikachuHappiness PIKAHAPPY_USEDXITEM - pop af - ld [wWhichPokemon], a - - ld hl, wPlayerBattleStatus2 - set GETTING_PUMPED, [hl] ; Focus Energy bit - jp PrintItemUseTextAndRemoveItem - -ItemUseXStat: - ld a, [wIsInBattle] - and a - jr nz, .inBattle - call ItemUseNotTime - ld a, 2 - ld [wActionResultOrTookBattleTurn], a ; item not used - ret - -.inBattle - ld hl, wPlayerMoveNum - ld a, [hli] - push af ; save [wPlayerMoveNum] - ld a, [hl] - push af ; save [wPlayerMoveEffect] - push hl - ld a, [wcf91] - sub X_ATTACK - ATTACK_UP1_EFFECT - ld [hl], a ; store player move effect - call PrintItemUseTextAndRemoveItem - ld a, XSTATITEM_ANIM ; X stat item animation ID - ld [wPlayerMoveNum], a - call LoadScreenTilesFromBuffer1 ; restore saved screen - call Delay3 - xor a - ld [H_WHOSETURN], a ; set turn to player's turn - callba StatModifierUpEffect ; do stat increase move - - ld a, [wWhichPokemon] - push af - ld a, [wPlayerMonNumber] - ld [wWhichPokemon], a - callabd_ModifyPikachuHappiness PIKAHAPPY_USEDXITEM - pop af - ld [wWhichPokemon], a - - pop hl - pop af - ld [hld], a ; restore [wPlayerMoveEffect] - pop af - ld [hl], a ; restore [wPlayerMoveNum] - ret - -ItemUsePokeflute: - ld a, [wIsInBattle] - and a - jr nz, .inBattle -; if not in battle - call ItemUseReloadOverworldData - ld a, [wCurMap] - cp ROUTE_12 - jr nz, .notRoute12 - CheckEvent EVENT_BEAT_ROUTE12_SNORLAX - jr nz, .noSnorlaxOrPikachuToWakeUp -; if the player hasn't beaten Route 12 Snorlax - ld hl, Route12SnorlaxFluteCoords - call ArePlayerCoordsInArray - jr nc, .noSnorlaxOrPikachuToWakeUp - ld hl, PlayedFluteHadEffectText - call PrintText - SetEvent EVENT_FIGHT_ROUTE12_SNORLAX - ret - -.notRoute12 - cp ROUTE_16 - jr nz, .notRoute16 - CheckEvent EVENT_BEAT_ROUTE16_SNORLAX - jr nz, .noSnorlaxOrPikachuToWakeUp -; if the player hasn't beaten Route 16 Snorlax - ld hl, Route16SnorlaxFluteCoords - call ArePlayerCoordsInArray - jr nc, .noSnorlaxOrPikachuToWakeUp - ld hl, PlayedFluteHadEffectText - call PrintText - SetEvent EVENT_FIGHT_ROUTE16_SNORLAX - ret - -.notRoute16 - cp PEWTER_POKECENTER - jr nz, .noSnorlaxOrPikachuToWakeUp - call CheckPikachuFollowingPlayer - jr z, .noSnorlaxOrPikachuToWakeUp - callab IsPikachuRightNextToPlayer - jr nc, .noSnorlaxOrPikachuToWakeUp - ld hl, PlayedFluteHadEffectText - call PrintText - call ItemUseReloadOverworldData - ldpikaemotion e, PikachuEmotion26 - callab PlaySpecificPikachuEmotion - ret - -.noSnorlaxOrPikachuToWakeUp - ld hl, PlayedFluteNoEffectText - jp PrintText - -.inBattle - xor a - ld [wWereAnyMonsAsleep], a - ld b, ~SLP & $ff - ld hl, wPartyMon1Status - call WakeUpEntireParty - ld a, [wIsInBattle] - dec a ; is it a trainer battle? - jr z, .skipWakingUpEnemyParty -; if it's a trainer battle - ld hl, wEnemyMon1Status - call WakeUpEntireParty -.skipWakingUpEnemyParty - ld hl, wBattleMonStatus - ld a, [hl] - and b ; remove Sleep status - ld [hl], a - ld hl, wEnemyMonStatus - ld a, [hl] - ld c, a - and b ; remove Sleep status - ld [hl], a - ld a, c - and SLP - jr z, .asm_e063 - ld a, $1 - ld [wWereAnyMonsAsleep], a -.asm_e063 - call LoadScreenTilesFromBuffer2 ; restore saved screen - ld a, [wWereAnyMonsAsleep] - and a ; were any pokemon asleep before playing the flute? - ld hl, PlayedFluteNoEffectText - jp z, PrintText ; if no pokemon were asleep -; if some pokemon were asleep - ld hl, PlayedFluteHadEffectText - call PrintText - ld a, [wLowHealthAlarm] - and $80 - jr nz, .skipMusic - call WaitForSoundToFinish ; wait for sound to end - callba Music_PokeFluteInBattle ; play in-battle pokeflute music -.musicWaitLoop ; wait for music to finish playing - ld a, [wChannelSoundIDs + Ch7] - and a ; music off? - jr nz, .musicWaitLoop -.skipMusic - ld hl, FluteWokeUpText - jp PrintText - -; wakes up all party pokemon -; INPUT: -; hl must point to status of first pokemon in party (player's or enemy's) -; b must equal ~SLP -; [wWereAnyMonsAsleep] should be initialized to 0 -; OUTPUT: -; [wWereAnyMonsAsleep]: set to 1 if any pokemon were asleep -WakeUpEntireParty: - ld de, 44 - ld c, 6 -.loop - ld a, [hl] - push af - and SLP ; is pokemon asleep? - jr z, .notAsleep - ld a, 1 - ld [wWereAnyMonsAsleep], a ; indicate that a pokemon had to be woken up -.notAsleep - pop af - and b ; remove Sleep status - ld [hl], a - add hl, de - dec c - jr nz, .loop - ret - -; Format: -; 00: Y -; 01: X -Route12SnorlaxFluteCoords: - db 62, 9 ; one space West of Snorlax - db 61, 10 ; one space North of Snorlax - db 63, 10 ; one space South of Snorlax - db 62, 11 ; one space East of Snorlax - db $ff ; terminator - -; Format: -; 00: Y -; 01: X -Route16SnorlaxFluteCoords: - db 10, 27 ; one space East of Snorlax - db 10, 25 ; one space West of Snorlax - db $ff ; terminator - -PlayedFluteNoEffectText: - TX_FAR _PlayedFluteNoEffectText - db "@" - -FluteWokeUpText: - TX_FAR _FluteWokeUpText - db "@" - -PlayedFluteHadEffectText: - TX_FAR _PlayedFluteHadEffectText - TX_BLINK - TX_ASM - ld a, [wIsInBattle] - and a - jr nz, .done -; play out-of-battle pokeflute music - call StopAllMusic ; turn off music - ld a, SFX_POKEFLUTE - ld c, BANK(SFX_Pokeflute) - call PlayMusic -.musicWaitLoop ; wait for music to finish playing - ld a, [wChannelSoundIDs + Ch3] - cp SFX_POKEFLUTE - jr z, .musicWaitLoop - call PlayDefaultMusic ; start playing normal music again -.done - jp TextScriptEnd ; end text - -ItemUseCoinCase: - ld a, [wIsInBattle] - and a - jp nz, ItemUseNotTime - ld hl, CoinCaseNumCoinsText - jp PrintText - -CoinCaseNumCoinsText: - TX_FAR _CoinCaseNumCoinsText - db "@" - -ItemUseOldRod: - call FishingInit - jp c, ItemUseNotTime - lb bc, 5, MAGIKARP - ld a, $1 ; set bite - jr RodResponse - -ItemUseGoodRod: - call FishingInit - jp c, ItemUseNotTime -.RandomLoop - call Random - srl a - jr c, .SetBite - and %11 - cp 2 - jr nc, .RandomLoop - ; choose which monster appears - ld hl, GoodRodMons - add a - ld c, a - ld b, 0 - add hl, bc - ld b, [hl] - inc hl - ld c, [hl] - and a -.SetBite - ld a, 0 - rla - xor 1 - jr RodResponse - -INCLUDE "data/good_rod.asm" - -ItemUseSuperRod: - call FishingInit - jp c, ItemUseNotTime - callab ReadSuperRodData - ld c, e - ld b, d - ld a, $2 - ld [wRodResponse], a - ld a, c - and a ; are there fish in the map? - jr z, DoNotGenerateFishingEncounter ; if not, do not generate an encounter - ld a, $1 - ld [wRodResponse], a - call Random - and $1 - jr nz, RodResponse - xor a - ld [wRodResponse], a - jr DoNotGenerateFishingEncounter - -RodResponse: - ld [wRodResponse], a - - dec a ; is there a bite? - jr nz, DoNotGenerateFishingEncounter - ; if yes, store level and species data - ld a, 1 - ld [wMoveMissed], a - ld a, b ; level - ld [wCurEnemyLVL], a - ld a, c ; species - ld [wCurOpponent], a - -DoNotGenerateFishingEncounter: - ld hl, wWalkBikeSurfState - ld a, [hl] ; store the value in a - push af - push hl - ld [hl], 0 - callba FishingAnim - pop hl - pop af - ld [hl], a - ret - -; checks if fishing is possible and if so, runs initialization code common to all rods -; unsets carry if fishing is possible, sets carry if not -FishingInit: - ld a, [wIsInBattle] - and a - jr z, .notInBattle - scf ; can't fish during battle - ret - -.notInBattle - call IsNextTileShoreOrWater - jr nc, .cannotFish - ld a, [wWalkBikeSurfState] - cp 2 ; Surfing? - jr z, .cannotFish - call ItemUseReloadOverworldData - ld hl, ItemUseText00 - call PrintText - ld a, SFX_HEAL_AILMENT - call PlaySound - ld a, $2 - ld [wd49c], a - ld a, $81 - ld [wPikachuMood], a - ld c, 80 - call DelayFrames - and a - ret - -.cannotFish - scf ; can't fish when surfing - ret - -ItemUseOaksParcel: - jp ItemUseNotYoursToUse - -ItemUseItemfinder: - ld a, [wIsInBattle] - and a - jp nz, ItemUseNotTime - call ItemUseReloadOverworldData - callba HiddenItemNear ; check for hidden items - ld hl, ItemfinderFoundNothingText - jr nc, .printText ; if no hidden items - ld c, 4 -.loop - ld a, SFX_HEALING_MACHINE - call PlaySoundWaitForCurrent - ld a, SFX_PURCHASE - call PlaySoundWaitForCurrent - dec c - jr nz, .loop - ld hl, ItemfinderFoundItemText -.printText - jp PrintText - -ItemfinderFoundItemText: - TX_FAR _ItemfinderFoundItemText - db "@" - -ItemfinderFoundNothingText: - TX_FAR _ItemfinderFoundNothingText - db "@" - -ItemUsePPUp: - ld a, [wIsInBattle] - and a - jp nz, ItemUseNotTime - -ItemUsePPRestore: - ld a, [wWhichPokemon] - push af - ld a, [wcf91] - ld [wPPRestoreItem], a -.chooseMon - xor a - ld [wUpdateSpritesEnabled], a - ld a, USE_ITEM_PARTY_MENU - ld [wPartyMenuTypeOrMessageID], a - call DisplayPartyMenu - jr nc, .chooseMove - jp .itemNotUsed - -.chooseMove - ld a, [wIsInBattle] - and a - jr z, .usePPItem - ld a, [wWhichPokemon] - ld b, a - ld a, [wPlayerMonNumber] - cp b - jr nz, .usePPItem - ld a, [wPlayerBattleStatus3] - bit TRANSFORMED, a - jr z, .usePPItem - call ItemUseNotTime - jp .itemNotUsed - -.usePPItem - ld a, [wPPRestoreItem] - cp ELIXER - jp nc, .useElixir ; if Elixir or Max Elixir - ld a, $02 - ld [wMoveMenuType], a - ld hl, RaisePPWhichTechniqueText - ld a, [wPPRestoreItem] - cp ETHER ; is it a PP Up? - jr c, .printWhichTechniqueMessage ; if so, print the raise PP message - ld hl, RestorePPWhichTechniqueText ; otherwise, print the restore PP message -.printWhichTechniqueMessage - call PrintText - xor a - ld [wPlayerMoveListIndex], a - callab MoveSelectionMenu ; move selection menu - ld a, 0 - ld [wPlayerMoveListIndex], a - jr nz, .chooseMon - ld hl, wPartyMon1Moves - ld bc, wPartyMon2 - wPartyMon1 - call GetSelectedMoveOffset - push hl - ld a, [hl] - ld [wd11e], a - call GetMoveName - call CopyStringToCF4B ; copy name to wcf4b - pop hl - ld a, [wPPRestoreItem] - cp ETHER - jr nc, .useEther ; if Ether or Max Ether -.usePPUp - ld bc, wPartyMon1PP - wPartyMon1Moves - add hl, bc - ld a, [hl] ; move PP - cp 3 << 6 ; have 3 PP Ups already been used? - jr c, .PPNotMaxedOut - ld hl, PPMaxedOutText - call PrintText - jr .chooseMove - -.PPNotMaxedOut - ld a, [hl] - add 1 << 6 ; increase PP Up count by 1 - ld [hl], a - ld a, 1 ; 1 PP Up used - ld [wd11e], a - call RestoreBonusPP ; add the bonus PP to current PP - ld a, SFX_HEAL_AILMENT - call PlaySound - ld hl, PPIncreasedText - call PrintText -.done - pop af - ld [wWhichPokemon], a - call GBPalWhiteOut - call RunDefaultPaletteCommand - jp RemoveUsedItem - -.afterRestoringPP ; after using a (Max) Ether/Elixir - ld a, [wWhichPokemon] - ld b, a - ld a, [wPlayerMonNumber] - cp b ; is the pokemon whose PP was restored active in battle? - jr nz, .skipUpdatingInBattleData - ld hl, wPartyMon1PP - ld bc, wPartyMon2 - wPartyMon1 - call AddNTimes - ld de, wBattleMonPP - ld bc, 4 - call CopyData ; copy party data to in-battle data -.skipUpdatingInBattleData - ld a, SFX_HEAL_AILMENT - call PlaySound - ld hl, PPRestoredText - call PrintText - jr .done - -.useEther - call .restorePP - jr nz, .afterRestoringPP - jp .noEffect - -; unsets zero flag if PP was restored, sets zero flag if not -; however, this is bugged for Max Ethers and Max Elixirs (see below) -.restorePP - xor a ; PLAYER_PARTY_DATA - ld [wMonDataLocation], a - call GetMaxPP - ld hl, wPartyMon1Moves - ld bc, wPartyMon2 - wPartyMon1 - call GetSelectedMoveOffset - ld bc, wPartyMon1PP - wPartyMon1Moves - add hl, bc ; hl now points to move's PP - ld a, [wMaxPP] - ld b, a - ld a, [wPPRestoreItem] - cp MAX_ETHER - jr z, .fullyRestorePP - ld a, [hl] ; move PP - and %00111111 ; lower 6 bit bits store current PP - cp b ; does current PP equal max PP? - ret z ; if so, return - add 10 ; increase current PP by 10 -; b holds the max PP amount and b will hold the new PP amount. -; So, if the new amount meets or exceeds the max amount, -; cap the amount to the max amount by leaving b unchanged. -; Otherwise, store the new amount in b. - cp b ; does the new amount meet or exceed the maximum? - jr nc, .storeNewAmount - ld b, a -.storeNewAmount - ld a, [hl] ; move PP - and %11000000 ; PP Up counter bits - add b - ld [hl], a - ret - -.fullyRestorePP - ld a, [hl] ; move PP -; Note that this code has a bug. It doesn't mask out the upper two bits, which -; are used to count how many PP Ups have been used on the move. So, Max Ethers -; and Max Elixirs will not be detected as having no effect on a move with full -; PP if the move has had any PP Ups used on it. - cp b ; does current PP equal max PP? - ret z - jr .storeNewAmount - -.useElixir -; decrement the item ID so that ELIXER becomes ETHER and MAX_ELIXER becomes MAX_ETHER - ld hl, wPPRestoreItem - dec [hl] - dec [hl] - xor a - ld hl, wCurrentMenuItem - ld [hli], a - ld [hl], a ; zero the counter for number of moves that had their PP restored - ld b, 4 -; loop through each move and restore PP -.elixirLoop - push bc - ld hl, wPartyMon1Moves - ld bc, wPartyMon2 - wPartyMon1 - call GetSelectedMoveOffset - ld a, [hl] - and a ; does the current slot have a move? - jr z, .nextMove - call .restorePP - jr z, .nextMove -; if some PP was restored - ld hl, wTileBehindCursor ; counter for number of moves that had their PP restored - inc [hl] -.nextMove - ld hl, wCurrentMenuItem - inc [hl] - pop bc - dec b - jr nz, .elixirLoop - ld a, [wTileBehindCursor] - and a ; did any moves have their PP restored? - jp nz, .afterRestoringPP -.noEffect - call ItemUseNoEffect -.itemNotUsed - call GBPalWhiteOut - call RunDefaultPaletteCommand - pop af - xor a - ld [wActionResultOrTookBattleTurn], a ; item use failed - ret - -RaisePPWhichTechniqueText: - TX_FAR _RaisePPWhichTechniqueText - db "@" - -RestorePPWhichTechniqueText: - TX_FAR _RestorePPWhichTechniqueText - db "@" - -PPMaxedOutText: - TX_FAR _PPMaxedOutText - db "@" - -PPIncreasedText: - TX_FAR _PPIncreasedText - db "@" - -PPRestoredText: - TX_FAR _PPRestoredText - db "@" - -; for items that can't be used from the Item menu -UnusableItem: - jp ItemUseNotTime - -ItemUseTMHM: - ld a, [wIsInBattle] - and a - jp nz, ItemUseNotTime - ld a, [wcf91] - sub TM_01 - push af - jr nc, .skipAdding - add 55 ; if item is an HM, add 55 -.skipAdding - inc a - ld [wd11e], a - predef TMToMove ; get move ID from TM/HM ID - ld a, [wd11e] - ld [wMoveNum], a - call GetMoveName - call CopyStringToCF4B ; copy name to wcf4b - pop af - ld hl, BootedUpTMText - jr nc, .printBootedUpMachineText - ld hl, BootedUpHMText -.printBootedUpMachineText - call PrintText - ld hl, TeachMachineMoveText - call PrintText - coord hl, 14, 7 - lb bc, 8, 15 - ld a, TWO_OPTION_MENU - ld [wTextBoxID], a - call DisplayTextBoxID ; yes/no menu - ld a, [wCurrentMenuItem] - and a - jr z, .useMachine - ld a, 2 - ld [wActionResultOrTookBattleTurn], a ; item not used - ret - -.useMachine - ld a, [wWhichPokemon] - push af - ld a, [wcf91] - push af -.chooseMon - ld hl, wcf4b - ld de, wTempMoveNameBuffer - ld bc, 14 - call CopyData ; save the move name because DisplayPartyMenu will overwrite it - ld a, $ff - ld [wUpdateSpritesEnabled], a - ld a, TMHM_PARTY_MENU - ld [wPartyMenuTypeOrMessageID], a - call DisplayPartyMenu - push af - ld hl, wTempMoveNameBuffer - ld de, wcf4b - ld bc, 14 - call CopyData - pop af - jr nc, .checkIfAbleToLearnMove -; if the player canceled teaching the move - pop af - pop af - call GBPalWhiteOutWithDelay3 - call ClearSprites - call RunDefaultPaletteCommand - jp LoadScreenTilesFromBuffer1 ; restore saved screen -.checkIfAbleToLearnMove - predef CanLearnTM ; check if the pokemon can learn the move - push bc - ld a, [wWhichPokemon] - ld hl, wPartyMonNicks - call GetPartyMonName - pop bc - ld a, c - and a ; can the pokemon learn the move? - jr nz, .checkIfAlreadyLearnedMove -; if the pokemon can't learn the move - ld a, SFX_DENIED - call PlaySoundWaitForCurrent - ld hl, MonCannotLearnMachineMoveText - call PrintText - jr .chooseMon - -.checkIfAlreadyLearnedMove - callab CheckIfMoveIsKnown ; check if the pokemon already knows the move - jr c, .chooseMon - predef LearnMove ; teach move - ld a, [wWhichPokemon] - ld d, a - pop af - ld [wcf91], a - pop af - ld [wWhichPokemon], a - ld a, b - and a - ret z - - ld a, [wWhichPokemon] - push af - ld a, d - ld [wWhichPokemon], a - callabd_ModifyPikachuHappiness PIKAHAPPY_USEDTMHM - callab IsThisPartymonStarterPikachu_Party - jr nc, .notTeachingThunderboltOrThunderToPikachu - ld a, [wcf91] - cp TM_24 ; are we teaching thunderbolt to the player pikachu? - jr z, .teachingThunderboltOrThunderToPlayerPikachu - cp TM_25 ; are we teaching thunder then? - jr nz, .notTeachingThunderboltOrThunderToPikachu -.teachingThunderboltOrThunderToPlayerPikachu - ld a, $5 - ld [wd49c], a - ld a, $85 - ld [wPikachuMood], a -.notTeachingThunderboltOrThunderToPikachu - pop af - ld [wWhichPokemon], a - - ld a, [wcf91] - call IsItemHM - ret c - jp RemoveUsedItem - -BootedUpTMText: - TX_FAR _BootedUpTMText - db "@" - -BootedUpHMText: - TX_FAR _BootedUpHMText - db "@" - -TeachMachineMoveText: - TX_FAR _TeachMachineMoveText - db "@" - -MonCannotLearnMachineMoveText: - TX_FAR _MonCannotLearnMachineMoveText - db "@" - -PrintItemUseTextAndRemoveItem: - ld hl, ItemUseText00 - call PrintText - ld a, SFX_HEAL_AILMENT - call PlaySound - call WaitForTextScrollButtonPress ; wait for button press - -RemoveUsedItem: - ld hl, wNumBagItems - ld a, 1 ; one item - ld [wItemQuantity], a - jp RemoveItemFromInventory - -ItemUseNoEffect: - ld hl, ItemUseNoEffectText - jr ItemUseFailed - -ItemUseNotTime: - ld hl, ItemUseNotTimeText - jr ItemUseFailed - -ItemUseNotYoursToUse: - ld hl, ItemUseNotYoursToUseText - jr ItemUseFailed - -Func_e4bf: - ld a, $2 - ld [wActionResultOrTookBattleTurn], a - ld hl, DontHavePokemonText - jp PrintText - -ThrowBallAtTrainerMon: - call RunDefaultPaletteCommand - call LoadScreenTilesFromBuffer1 ; restore saved screen - call Delay3 - ld a, TOSS_ANIM - ld [wAnimationID], a - predef MoveAnimation ; do animation - ld hl, ThrowBallAtTrainerMonText1 - call PrintText - ld hl, ThrowBallAtTrainerMonText2 - call PrintText - jr RemoveUsedItem - -NoCyclingAllowedHere: - ld hl, NoCyclingAllowedHereText - jr ItemUseFailed - -BoxFullCannotThrowBall: - ld hl, BoxFullCannotThrowBallText - jr ItemUseFailed - -SurfingAttemptFailed: - ld hl, NoSurfingHereText - -ItemUseFailed: - xor a - ld [wActionResultOrTookBattleTurn], a ; item use failed - jp PrintText - -ItemUseNotTimeText: - TX_FAR _ItemUseNotTimeText - db "@" - -ItemUseNotYoursToUseText: - TX_FAR _ItemUseNotYoursToUseText - db "@" - -ItemUseNoEffectText: - TX_FAR _ItemUseNoEffectText - db "@" - -ThrowBallAtTrainerMonText1: - TX_FAR _ThrowBallAtTrainerMonText1 - db "@" - -ThrowBallAtTrainerMonText2: - TX_FAR _ThrowBallAtTrainerMonText2 - db "@" - -NoCyclingAllowedHereText: - TX_FAR _NoCyclingAllowedHereText - db "@" - -NoSurfingHereText: - TX_FAR _NoSurfingHereText - db "@" - -BoxFullCannotThrowBallText: - TX_FAR _BoxFullCannotThrowBallText - db "@" - -DontHavePokemonText: - TX_FAR _DontHavePokemonText - db "@" - -ItemUseText00: - TX_FAR _ItemUseText001 - TX_LINE - TX_FAR _ItemUseText002 - db "@" - -GotOnBicycleText: - TX_FAR _GotOnBicycleText1 - TX_LINE - TX_FAR _GotOnBicycleText2 - db "@" - -GotOffBicycleText: - TX_FAR _GotOffBicycleText1 - TX_LINE - TX_FAR _GotOffBicycleText2 - db "@" - -; restores bonus PP (from PP Ups) when healing at a pokemon center -; also, when a PP Up is used, it increases the current PP by one PP Up bonus -; INPUT: -; [wWhichPokemon] = index of pokemon in party -; [wCurrentMenuItem] = index of move (when using a PP Up) -RestoreBonusPP: - ld hl, wPartyMon1Moves - ld bc, wPartyMon2 - wPartyMon1 - ld a, [wWhichPokemon] - call AddNTimes - push hl - ld de, wNormalMaxPPList - 1 - predef LoadMovePPs ; loads the normal max PP of each of the pokemon's moves to wNormalMaxPPList - pop hl - ld c, wPartyMon1PP - wPartyMon1Moves - ld b, 0 - add hl, bc ; hl now points to move 1 PP - ld de, wNormalMaxPPList - ld b, 0 ; initialize move counter to zero -; loop through the pokemon's moves -.loop - inc b - ld a, b - cp 5 ; reached the end of the pokemon's moves? - ret z ; if so, return - ld a, [wUsingPPUp] - dec a ; using a PP Up? - jr nz, .skipMenuItemIDCheck -; if using a PP Up, check if this is the move it's being used on - ld a, [wCurrentMenuItem] - inc a - cp b - jr nz, .nextMove -.skipMenuItemIDCheck - ld a, [hl] - and %11000000 ; have any PP Ups been used? - call nz, AddBonusPP ; if so, add bonus PP -.nextMove - inc hl - inc de - jr .loop - -; adds bonus PP from PP Ups to current PP -; 1/5 of normal max PP (capped at 7) is added for each PP Up -; INPUT: -; [de] = normal max PP -; [hl] = move PP -AddBonusPP: - push bc - ld a, [de] ; normal max PP of move - ld [H_DIVIDEND + 3], a - xor a - ld [H_DIVIDEND], a - ld [H_DIVIDEND + 1], a - ld [H_DIVIDEND + 2], a - ld a, 5 - ld [H_DIVISOR], a - ld b, 4 - call Divide - ld a, [hl] ; move PP - ld b, a - swap a - and %00001111 - srl a - srl a - ld c, a ; c = number of PP Ups used -.loop - ld a, [H_QUOTIENT + 3] - cp 8 ; is the amount greater than or equal to 8? - jr c, .addAmount - ld a, 7 ; cap the amount at 7 -.addAmount - add b - ld b, a - ld a, [wUsingPPUp] - dec a ; is the player using a PP Up right now? - jr z, .done ; if so, only add the bonus once - dec c - jr nz, .loop -.done - ld [hl], b - pop bc - ret - -; gets max PP of a pokemon's move (including PP from PP Ups) -; INPUT: -; [wWhichPokemon] = index of pokemon within party/box -; [wMonDataLocation] = pokemon source -; 00: player's party -; 01: enemy's party -; 02: current box -; 03: daycare -; 04: player's in-battle pokemon -; [wCurrentMenuItem] = move index -; OUTPUT: -; [wMaxPP] = max PP -GetMaxPP: - ld a, [wMonDataLocation] - and a - ld hl, wPartyMon1Moves - ld bc, wPartyMon2 - wPartyMon1 - jr z, .sourceWithMultipleMon - ld hl, wEnemyMon1Moves - dec a - jr z, .sourceWithMultipleMon - ld hl, wBoxMon1Moves - ld bc, wBoxMon2 - wBoxMon1 - dec a - jr z, .sourceWithMultipleMon - ld hl, wDayCareMonMoves - dec a - jr z, .sourceWithOneMon - ld hl, wBattleMonMoves ; player's in-battle pokemon -.sourceWithOneMon - call GetSelectedMoveOffset2 - jr .next - -.sourceWithMultipleMon - call GetSelectedMoveOffset -.next - ld a, [hl] - dec a - push hl - ld hl, Moves - ld bc, MoveEnd - Moves - call AddNTimes - ld de, wcd6d - ld a, BANK(Moves) - call FarCopyData - ld de, wcd6d + 5 ; PP is byte 5 of move data - ld a, [de] - ld b, a ; b = normal max PP - pop hl - push bc - ld bc, wPartyMon1PP - wPartyMon1Moves ; PP offset if not player's in-battle pokemon data - ld a, [wMonDataLocation] - cp 4 ; player's in-battle pokemon? - jr nz, .addPPOffset - ld bc, wBattleMonPP - wBattleMonMoves ; PP offset if player's in-battle pokemon data -.addPPOffset - add hl, bc - ld a, [hl] ; a = current PP - and %11000000 ; get PP Up count - pop bc - or b ; place normal max PP in 6 lower bits of a - ld h, d - ld l, e - inc hl ; hl = wcd73 - ld [hl], a - xor a ; add the bonus for the existing PP Up count - ld [wUsingPPUp], a - call AddBonusPP ; add bonus PP from PP Ups - ld a, [hl] - and %00111111 ; mask out the PP Up count - ld [wMaxPP], a ; store max PP - ret - -GetSelectedMoveOffset: - ld a, [wWhichPokemon] - call AddNTimes - -GetSelectedMoveOffset2: - ld a, [wCurrentMenuItem] - ld c, a - ld b, 0 - add hl, bc - ret - -; confirms the item toss and then tosses the item -; INPUT: -; hl = address of inventory (either wNumBagItems or wNumBoxItems) -; [wcf91] = item ID -; [wWhichPokemon] = index of item within inventory -; [wItemQuantity] = quantity to toss -; OUTPUT: -; clears carry flag if the item is tossed, sets carry flag if not -TossItem_: - push hl - ld a, [wcf91] - call IsItemHM - pop hl - jr c, .tooImportantToToss - push hl - call IsKeyItem_ - ld a, [wIsKeyItem] - pop hl - and a - jr nz, .tooImportantToToss - push hl - ld a, [wcf91] - ld [wd11e], a - call GetItemName - call CopyStringToCF4B ; copy name to wcf4b - ld hl, IsItOKToTossItemText - call PrintText - coord hl, 14, 7 - lb bc, 8, 15 - ld a, TWO_OPTION_MENU - ld [wTextBoxID], a - call DisplayTextBoxID ; yes/no menu - ld a, [wMenuExitMethod] - cp CHOSE_SECOND_ITEM - pop hl - scf - ret z ; return if the player chose No -; if the player chose Yes - push hl - ld a, [wWhichPokemon] - call RemoveItemFromInventory - ld a, [wcf91] - ld [wd11e], a - call GetItemName - call CopyStringToCF4B ; copy name to wcf4b - ld hl, ThrewAwayItemText - call PrintText - pop hl - and a - ret - -.tooImportantToToss - push hl - ld hl, TooImportantToTossText - call PrintText - pop hl - scf - ret - -ThrewAwayItemText: - TX_FAR _ThrewAwayItemText - db "@" - -IsItOKToTossItemText: - TX_FAR _IsItOKToTossItemText - db "@" - -TooImportantToTossText: - TX_FAR _TooImportantToTossText - db "@" - -; checks if an item is a key item -; INPUT: -; [wcf91] = item ID -; OUTPUT: -; [wIsKeyItem] = result -; 00: item is not key item -; 01: item is key item -IsKeyItem_: - ld a, $01 - ld [wIsKeyItem], a - ld a, [wcf91] - cp HM_01 ; is the item an HM or TM? - jr nc, .checkIfItemIsHM -; if the item is not an HM or TM - push af - ld hl, KeyItemBitfield - ld de, wBuffer - ld bc, 15 ; only 11 bytes are actually used - call CopyData - pop af - dec a - ld c, a - ld hl, wBuffer - ld b, FLAG_TEST - predef FlagActionPredef - ld a, c - and a - ret nz -.checkIfItemIsHM - ld a, [wcf91] - call IsItemHM - ret c - xor a - ld [wIsKeyItem], a - ret - -INCLUDE "data/key_items.asm" - -SendNewMonToBox: - ld de, wNumInBox - ld a, [de] - inc a - ld [de], a - ld a, [wcf91] - ld [wd0b5], a - ld c, a -.asm_e6f5 - inc de - ld a, [de] - ld b, a - ld a, c - ld c, b - ld [de], a - cp $ff - jr nz, .asm_e6f5 - call GetMonHeader - ld hl, wBoxMonOT - ld bc, NAME_LENGTH - ld a, [wNumInBox] - dec a - jr z, .asm_e732 - dec a - call AddNTimes - push hl - ld bc, NAME_LENGTH - add hl, bc - ld d, h - ld e, l - pop hl - ld a, [wNumInBox] - dec a - ld b, a -.asm_e71f - push bc - push hl - ld bc, NAME_LENGTH - call CopyData - pop hl - ld d, h - ld e, l - ld bc, -NAME_LENGTH - add hl, bc - pop bc - dec b - jr nz, .asm_e71f -.asm_e732 - ld hl, wPlayerName - ld de, wBoxMonOT - ld bc, NAME_LENGTH - call CopyData - ld a, [wNumInBox] - dec a - jr z, .asm_e76e - ld hl, wBoxMonNicks - ld bc, NAME_LENGTH - dec a - call AddNTimes - push hl - ld bc, NAME_LENGTH - add hl, bc - ld d, h - ld e, l - pop hl - ld a, [wNumInBox] - dec a - ld b, a -.asm_e75b - push bc - push hl - ld bc, NAME_LENGTH - call CopyData - pop hl - ld d, h - ld e, l - ld bc, -NAME_LENGTH - add hl, bc - pop bc - dec b - jr nz, .asm_e75b -.asm_e76e - ld hl, wBoxMonNicks - ld a, NAME_MON_SCREEN - ld [wNamingScreenType], a - predef AskName - ld a, [wNumInBox] - dec a - jr z, .asm_e7ab - ld hl, wBoxMons - ld bc, wBoxMon2 - wBoxMon1 - dec a - call AddNTimes - push hl - ld bc, wBoxMon2 - wBoxMon1 - add hl, bc - ld d, h - ld e, l - pop hl - ld a, [wNumInBox] - dec a - ld b, a -.asm_e798 - push bc - push hl - ld bc, wBoxMon2 - wBoxMon1 - call CopyData - pop hl - ld d, h - ld e, l - ld bc, wBoxMon1 - wBoxMon2 - add hl, bc - pop bc - dec b - jr nz, .asm_e798 -.asm_e7ab - ld a, [wEnemyMonLevel] - ld [wEnemyMonBoxLevel], a - ld hl, wEnemyMon - ld de, wBoxMon1 - ld bc, wEnemyMonDVs - wEnemyMon - call CopyData - ld hl, wPlayerID - ld a, [hli] - ld [de], a - inc de - ld a, [hl] - ld [de], a - inc de - push de - ld a, [wCurEnemyLVL] - ld d, a - callab CalcExperience - pop de - ld a, [hExperience] - ld [de], a - inc de - ld a, [hExperience + 1] - ld [de], a - inc de - ld a, [hExperience + 2] - ld [de], a - inc de - xor a - ld b, NUM_STATS * 2 -.asm_e7e3 - ld [de], a - inc de - dec b - jr nz, .asm_e7e3 - ld hl, wEnemyMonDVs - ld a, [hli] - ld [de], a - inc de - ld a, [hli] - ld [de], a - ld hl, wEnemyMonPP - ld b, NUM_MOVES -.asm_e7f5 - ld a, [hli] - inc de - ld [de], a - dec b - jr nz, .asm_e7f5 - ld a, [wcf91] - cp KADABRA - jr nz, .notKadabra - ld a, $60 ; twistedspoon in gsc - ld [wBoxMon1CatchRate], a -.notKadabra - ret - -; checks if the tile in front of the player is a shore or water tile -; used for surfing and fishing -; unsets carry if it is, sets carry if not -IsNextTileShoreOrWater: - ld a, [wCurMapTileset] - ld hl, WaterTilesets - ld de, 1 - call IsInArray ; does the current map allow surfing? - ret nc ; if not, return - ld hl, WaterTile - ld a, [wCurMapTileset] - cp SHIP_PORT ; Vermilion Dock tileset - jr z, .skipShoreTiles ; if it's the Vermilion Dock tileset - cp GYM ; eastern shore tile in Safari Zone - jr z, .skipShoreTiles - cp DOJO ; usual eastern shore tile - jr z, .skipShoreTiles - ld hl, ShoreTiles -.skipShoreTiles - ld a, [wTileInFrontOfPlayer] - ld de, $1 - call IsInArray - ret - -; tilesets with water -WaterTilesets: - db OVERWORLD, FOREST, DOJO, GYM, SHIP, SHIP_PORT, CAVERN, FACILITY, PLATEAU - db $ff ; terminator - -; shore tiles -ShoreTiles: - db $48, $32 -WaterTile: - db $14 - db $ff ; terminator - -; reloads map view and processes sprite data -; for items that cause the overworld to be displayed -ItemUseReloadOverworldData: - call LoadCurrentMapView - jp UpdateSprites - -; creates a list at wBuffer of maps where the mon in [wd11e] can be found. -; this is used by the pokedex to display locations the mon can be found on the map. -FindWildLocationsOfMon: - ld hl, WildDataPointers - ld de, wBuffer - ld c, $0 -.loop - inc hl - ld a, [hld] - inc a - jr z, .done - push hl - ld a, [hli] - ld h, [hl] - ld l, a - ld a, [hli] - and a - call nz, CheckMapForMon ; land - ld a, [hli] - and a - call nz, CheckMapForMon ; water - pop hl - inc hl - inc hl - inc c - jr .loop -.done - ld a, $ff ; list terminator - ld [de], a - ret - -CheckMapForMon: - inc hl - ld b, $a -.loop - ld a, [wd11e] - cp [hl] - jr nz, .nextEntry - ld a, c - ld [de], a - inc de -.nextEntry - inc hl - inc hl - dec b - jr nz, .loop - dec hl - ret diff --git a/engine/items/subtract_paid_money.asm b/engine/items/subtract_paid_money.asm new file mode 100644 index 00000000..fdefe3d6 --- /dev/null +++ b/engine/items/subtract_paid_money.asm @@ -0,0 +1,17 @@ +; subtracts the amount the player paid from their money +; OUTPUT: carry = 0(success) or 1(fail because there is not enough money) +SubtractAmountPaidFromMoney_:: + ld de, wPlayerMoney + ld hl, hMoney ; total price of items + ld c, 3 ; length of money in bytes + call StringCmp + ret c + ld de, wPlayerMoney + 2 + ld hl, hMoney + 2 ; total price of items + ld c, 3 ; length of money in bytes + predef SubBCDPredef ; subtract total price from money + ld a, MONEY_BOX + ld [wTextBoxID], a + call DisplayTextBoxID ; redraw money text box + and a + ret diff --git a/engine/items/tm_prices.asm b/engine/items/tm_prices.asm index 80e6bf3c..df9761bd 100755 --- a/engine/items/tm_prices.asm +++ b/engine/items/tm_prices.asm @@ -1,9 +1,9 @@ -GetMachinePrice: +GetMachinePrice:: ; Input: [wcf91] = Item Id of a TM ; Output: Stores the TM price at hItemPrice ld a, [wcf91] ; a contains TM item id - sub TM_01 - ret c + sub TM01 ; underflows below 0 for HM items (before TM items) + ret c ; HMs are priceless ld d, a ld hl, TechnicalMachinePrices srl a @@ -16,10 +16,10 @@ GetMachinePrice: swap a .highNybbleIsPrice and $f0 - ld [hItemPrice + 1], a + ldh [hItemPrice + 1], a xor a - ld [hItemPrice], a - ld [hItemPrice + 2], a + ldh [hItemPrice], a + ldh [hItemPrice + 2], a ret -INCLUDE "data/tm_prices.asm" +INCLUDE "data/items/tm_prices.asm" diff --git a/engine/items/tmhm.asm b/engine/items/tmhm.asm index 7ccaa232..a11cd736 100755 --- a/engine/items/tmhm.asm +++ b/engine/items/tmhm.asm @@ -22,5 +22,5 @@ CheckIfMoveIsKnown: ret AlreadyKnowsText: - TX_FAR _AlreadyKnowsText - db "@" + text_far _AlreadyKnowsText + text_end diff --git a/engine/items/tms.asm b/engine/items/tms.asm index 84770747..dcf2665d 100755 --- a/engine/items/tms.asm +++ b/engine/items/tms.asm @@ -39,4 +39,4 @@ TMToMove: ld [wd11e], a ret -INCLUDE "data/tms.asm" +INCLUDE "data/moves/tmhm_moves.asm" diff --git a/engine/items/town_map.asm b/engine/items/town_map.asm new file mode 100755 index 00000000..c401d1c1 --- /dev/null +++ b/engine/items/town_map.asm @@ -0,0 +1,629 @@ +NOT_VISITED EQU $fe + +DisplayTownMap: + call LoadTownMap + ld hl, wUpdateSpritesEnabled + ld a, [hl] + push af + ld [hl], $ff + push hl + ld a, $1 + ldh [hJoy7], a + ld a, [wCurMap] + push af + ld b, $0 + call DrawPlayerOrBirdSprite ; player sprite + hlcoord 1, 0 + ld de, wcd6d + call PlaceString + ld hl, wOAMBuffer + ld de, wTileMapBackup + ld bc, $10 + call CopyData + ld hl, vSprites tile $04 + ld de, TownMapCursor + lb bc, BANK(TownMapCursor), (TownMapCursorEnd - TownMapCursor) / $8 + call CopyVideoDataDouble + xor a + ld [wWhichTownMapLocation], a + pop af + jr .enterLoop + +.townMapLoop + hlcoord 0, 0 + lb bc, 1, 20 + call ClearScreenArea + ld hl, TownMapOrder + ld a, [wWhichTownMapLocation] + ld c, a + ld b, 0 + add hl, bc + ld a, [hl] +.enterLoop + ld de, wTownMapCoords + call LoadTownMapEntry + ld a, [de] + push hl + call TownMapCoordsToOAMCoords + ld a, $4 + ld [wOAMBaseTile], a + ld hl, wOAMBuffer + $10 + call WriteTownMapSpriteOAM ; town map cursor sprite + pop hl + ld de, wcd6d +.copyMapName + ld a, [hli] + ld [de], a + inc de + cp $50 + jr nz, .copyMapName + hlcoord 1, 0 + ld de, wcd6d + call PlaceString + ld hl, wOAMBuffer + $10 + ld de, wTileMapBackup + 16 + ld bc, $10 + call CopyData +.inputLoop + call TownMapSpriteBlinkingAnimation + call JoypadLowSensitivity + ldh a, [hJoy5] + ld b, a + and A_BUTTON | B_BUTTON | D_UP | D_DOWN + jr z, .inputLoop + ld a, SFX_TINK + call PlaySound + bit 6, b + jr nz, .pressedUp + bit 7, b + jr nz, .pressedDown + xor a + ld [wTownMapSpriteBlinkingEnabled], a + ldh [hJoy7], a + ld [wAnimCounter], a + call ExitTownMap + pop hl + pop af + ld [hl], a + ret +.pressedUp + ld a, [wWhichTownMapLocation] + inc a + cp TownMapOrderEnd - TownMapOrder ; number of list items + 1 + jr nz, .noOverflow + xor a +.noOverflow + ld [wWhichTownMapLocation], a + jp .townMapLoop +.pressedDown + ld a, [wWhichTownMapLocation] + dec a + cp -1 + jr nz, .noUnderflow + ld a, TownMapOrderEnd - TownMapOrder - 1 ; number of list items +.noUnderflow + ld [wWhichTownMapLocation], a + jp .townMapLoop + +.asm_70f87 + ldh a, [hJoy5] + and D_DOWN | D_UP + ret z + callfar PlayPikachuSoundClip + ret + +INCLUDE "data/maps/town_map_order.asm" + +TownMapCursor: + INCBIN "gfx/town_map/town_map_cursor.1bpp" +TownMapCursorEnd: + +LoadTownMap_Nest: + call LoadTownMap + ld hl, wUpdateSpritesEnabled + ld a, [hl] + push af + ld [hl], $ff + push hl + call DisplayWildLocations + call GetMonName + hlcoord 1, 0 + call PlaceString + ld h, b + ld l, c + ld de, MonsNestText + call PlaceString + call WaitForTextScrollButtonPress + call ExitTownMap + pop hl + pop af + ld [hl], a + ret + +MonsNestText: + db "'s NEST@" + +LoadTownMap_Fly:: + call ClearSprites + call LoadTownMap + ld a, $1 + ldh [hJoy7], a + call LoadPlayerSpriteGraphics + call LoadFontTilePatterns + ld de, BirdSprite + ld b, BANK(BirdSprite) + ld c, $c + ld hl, vSprites tile $04 + call CopyVideoData + ld de, TownMapUpArrow + ld hl, vChars1 tile $6d + lb bc, BANK(TownMapUpArrow), (TownMapUpArrowEnd - TownMapUpArrow) / $8 + call CopyVideoDataDouble + call BuildFlyLocationsList + ld hl, wUpdateSpritesEnabled + ld a, [hl] + push af + ld [hl], $ff + push hl + hlcoord 0, 0 + ld de, ToText + call PlaceString + ld a, [wCurMap] + ld b, $0 + call DrawPlayerOrBirdSprite + ld hl, wFlyLocationsList + decoord 18, 0 +.townMapFlyLoop + ld a, " " + ld [de], a + push hl + push hl + hlcoord 3, 0 + lb bc, 1, 15 + call ClearScreenArea + pop hl + ld a, [hl] + ld b, $4 + call DrawPlayerOrBirdSprite ; draw bird sprite + hlcoord 3, 0 + ld de, wcd6d + call PlaceString + ld c, 15 + call DelayFrames + hlcoord 18, 0 + ld [hl], "▶" + hlcoord 19, 0 + ld [hl], "▼" + pop hl +.inputLoop + push hl + call DelayFrame + call JoypadLowSensitivity + ldh a, [hJoy5] + ld b, a + pop hl + and A_BUTTON | B_BUTTON | D_UP | D_DOWN + jr z, .inputLoop + bit 0, b + jr nz, .pressedA + ld a, SFX_TINK + call PlaySound + bit 6, b + jr nz, .pressedUp + bit 7, b + jr nz, .pressedDown + jr .pressedB +.pressedA + ld a, SFX_HEAL_AILMENT + call PlaySound + ld a, [hl] + ld [wDestinationMap], a + ld hl, wd732 + set 3, [hl] + inc hl + set 7, [hl] +.pressedB + xor a + ld [wTownMapSpriteBlinkingEnabled], a + ldh [hJoy7], a + call GBPalWhiteOutWithDelay3 + pop hl + pop af + ld [hl], a + ret +.pressedUp + decoord 18, 0 + inc hl + ld a, [hl] + cp $ff + jr z, .wrapToStartOfList + cp NOT_VISITED + jr z, .pressedUp ; skip past unvisited towns + jp .townMapFlyLoop +.wrapToStartOfList + ld hl, wFlyLocationsList + jp .townMapFlyLoop +.pressedDown + decoord 19, 0 + dec hl + ld a, [hl] + cp $ff + jr z, .wrapToEndOfList + cp NOT_VISITED + jr z, .pressedDown ; skip past unvisited towns + jp .townMapFlyLoop +.wrapToEndOfList + ld hl, wFlyLocationsList + NUM_CITY_MAPS + jr .pressedDown + +ToText: + db "To@" + +BuildFlyLocationsList: + ld hl, wFlyLocationsList - 1 + ld [hl], $ff + inc hl + ld a, [wTownVisitedFlag] + ld e, a + ld a, [wTownVisitedFlag + 1] + ld d, a + lb bc, 0, NUM_CITY_MAPS +.loop + srl d + rr e + ld a, NOT_VISITED + jr nc, .notVisited + ld a, b ; store the map number of the town if it has been visited +.notVisited + ld [hl], a + inc hl + inc b + dec c + jr nz, .loop + ld [hl], $ff + ret + +TownMapUpArrow: + INCBIN "gfx/town_map/up_arrow.1bpp" +TownMapUpArrowEnd: + +LoadTownMap: + call GBPalWhiteOutWithDelay3 + call ClearScreen + call UpdateSprites + hlcoord 0, 0 + lb bc, $12, $12 + call TextBoxBorder + call DisableLCD + ld hl, WorldMapTileGraphics + ld de, vChars2 tile $60 + ld bc, WorldMapTileGraphicsEnd - WorldMapTileGraphics + ld a, BANK(WorldMapTileGraphics) + call FarCopyData + ld hl, MonNestIcon + ld de, vSprites tile $04 + ld bc, MonNestIconEnd - MonNestIcon + ld a, BANK(MonNestIcon) + call FarCopyDataDouble + hlcoord 0, 0 + ld de, CompressedMap +.nextTile + ld a, [de] + and a + jr z, .done + ld b, a + and $f + ld c, a + ld a, b + swap a + and $f + add $60 +.writeRunLoop + ld [hli], a + dec c + jr nz, .writeRunLoop + inc de + jr .nextTile +.done + call EnableLCD + ld b, SET_PAL_TOWN_MAP + call RunPaletteCommand + call Delay3 + call GBPalNormal + xor a + ld [wAnimCounter], a + inc a + ld [wTownMapSpriteBlinkingEnabled], a + ret + +CompressedMap: + INCBIN "gfx/town_map/town_map.rle" + +ExitTownMap: +; clear town map graphics data and load usual graphics data + xor a + ld [wTownMapSpriteBlinkingEnabled], a + call GBPalWhiteOut + call ClearScreen + call ClearSprites + call LoadPlayerSpriteGraphics + call LoadFontTilePatterns + call UpdateSprites + jp RunDefaultPaletteCommand + +DrawPlayerOrBirdSprite: +; a = map number +; b = OAM base tile + push af + ld a, b + ld [wOAMBaseTile], a + pop af + ld de, wTownMapCoords + call LoadTownMapEntry + ld a, [de] + push hl + call TownMapCoordsToOAMCoords + call WritePlayerOrBirdSpriteOAM + pop hl + ld de, wcd6d +.loop + ld a, [hli] + ld [de], a + inc de + cp "@" + jr nz, .loop + ld hl, wOAMBuffer + ld de, wTileMapBackup + ld bc, $a0 + jp CopyData + +DisplayWildLocations: + farcall FindWildLocationsOfMon + call ZeroOutDuplicatesInList + ld hl, wOAMBuffer + ld de, wTownMapCoords +.loop + ld a, [de] + cp $ff + jr z, .exitLoop + and a + jr z, .nextEntry + push hl + call LoadTownMapEntry + pop hl + ld a, [de] + cp $19 ; Cerulean Cave's coordinates + jr z, .nextEntry ; skip Cerulean Cave + call TownMapCoordsToOAMCoords + ld a, $4 ; nest icon tile no. + ld [hli], a + xor a + ld [hli], a +.nextEntry + inc de + jr .loop +.exitLoop + ld a, l + and a ; were any OAM entries written? + jr nz, .drawPlayerSprite +; if no OAM entries were written, print area unknown text + hlcoord 1, 7 + lb bc, 2, 15 + call TextBoxBorder + hlcoord 2, 9 + ld de, AreaUnknownText + call PlaceString + jr .done +.drawPlayerSprite + ld a, [wCurMap] + ld b, $0 + call DrawPlayerOrBirdSprite +.done + ld hl, wOAMBuffer + ld de, wTileMapBackup + ld bc, $a0 + jp CopyData + +AreaUnknownText: + db " AREA UNKNOWN@" + +TownMapCoordsToOAMCoords: +; in: lower nybble of a = x, upper nybble of a = y +; out: b and [hl] = (y * 8) + 24, c and [hl+1] = (x * 8) + 24 + push af + and $f0 + srl a + add 24 + ld b, a + ld [hli], a + pop af + and $f + swap a + srl a + add 24 + ld c, a + ld [hli], a + ret + +WritePlayerOrBirdSpriteOAM: + ld a, [wOAMBaseTile] + and a + ld hl, wOAMBuffer + $90 ; for player sprite + jr z, WriteTownMapSpriteOAM + ld hl, wOAMBuffer + $80 ; for bird sprite + +WriteTownMapSpriteOAM: + push hl + +; Subtract 4 from c (X coord) and 4 from b (Y coord). However, the carry from c +; is added to b, so the net result is that only 3 is subtracted from b. + lb hl, -4, -4 + add hl, bc + + ld b, h + ld c, l + pop hl + +WriteAsymmetricMonPartySpriteOAM: +; Writes 4 OAM blocks for a helix mon party sprite, since it does not have +; a vertical line of symmetry. + lb de, 2, 2 +.loop + push de + push bc +.innerLoop + ld a, b + ld [hli], a + ld a, c + ld [hli], a + ld a, [wOAMBaseTile] + ld [hli], a + inc a + ld [wOAMBaseTile], a + xor a + ld [hli], a + inc d + ld a, 8 + add c + ld c, a + dec e + jr nz, .innerLoop + pop bc + pop de + ld a, 8 + add b + ld b, a + dec d + jr nz, .loop + ret + +WriteSymmetricMonPartySpriteOAM: +; Writes 4 OAM blocks for a mon party sprite other than a helix. All the +; sprites other than the helix one have a vertical line of symmetry which allows +; the X-flip OAM bit to be used so that only 2 rather than 4 tile patterns are +; needed. + xor a + ld [wSymmetricSpriteOAMAttributes], a + lb de, 2, 2 +.loop + push de + push bc +.innerLoop + ld a, b + ld [hli], a ; Y + ld a, c + ld [hli], a ; X + ld a, [wOAMBaseTile] + ld [hli], a ; tile + ld a, [wSymmetricSpriteOAMAttributes] + ld [hli], a ; attributes + xor (1 << OAM_X_FLIP) + ld [wSymmetricSpriteOAMAttributes], a + inc d + ld a, 8 + add c + ld c, a + dec e + jr nz, .innerLoop + pop bc + pop de + push hl + ld hl, wOAMBaseTile + inc [hl] + inc [hl] + pop hl + ld a, 8 + add b + ld b, a + dec d + jr nz, .loop + ret + +ZeroOutDuplicatesInList: +; replace duplicate bytes in the list of wild pokemon locations with 0 + ld de, wBuffer +.loop + ld a, [de] + inc de + cp $ff + ret z + ld c, a + ld l, e + ld h, d +.zeroDuplicatesLoop + ld a, [hl] + cp $ff + jr z, .loop + cp c + jr nz, .skipZeroing + xor a + ld [hl], a +.skipZeroing + inc hl + jr .zeroDuplicatesLoop + +LoadTownMapEntry: +; in: a = map number +; out: lower nybble of [de] = x, upper nybble of [de] = y, hl = address of name + cp FIRST_INDOOR_MAP + jr c, .external + ld bc, 4 + ld hl, InternalMapEntries +.loop + cp [hl] + jr c, .foundEntry + add hl, bc + jr .loop +.foundEntry + inc hl + jr .readEntry +.external + ld hl, ExternalMapEntries + ld c, a + ld b, 0 + add hl, bc + add hl, bc + add hl, bc +.readEntry + ld a, [hli] + ld [de], a + ld a, [hli] + ld h, [hl] + ld l, a + ret + +INCLUDE "data/maps/town_map_entries.asm" + +INCLUDE "data/maps/names.asm" + +MonNestIcon: + INCBIN "gfx/town_map/mon_nest_icon.1bpp" +MonNestIconEnd: + +TownMapSpriteBlinkingAnimation:: + ld a, [wAnimCounter] + inc a + cp 25 + jr z, .hideSprites + cp 50 + jr nz, .done +; show sprites when the counter reaches 50 + ld hl, wTileMapBackup + ld de, wOAMBuffer + ld bc, $90 + call CopyData + xor a + jr .done +.hideSprites + ld hl, wOAMBuffer + ld b, $24 + ld de, $4 +.hideSpritesLoop + ld [hl], $a0 + add hl, de + dec b + jr nz, .hideSpritesLoop + ld a, 25 +.done + ld [wAnimCounter], a + jp DelayFrame diff --git a/engine/joypad.asm b/engine/joypad.asm index 4126568c..06a15e4e 100644 --- a/engine/joypad.asm +++ b/engine/joypad.asm @@ -2,34 +2,34 @@ ReadJoypad_:: ; Poll joypad input. ; Unlike the hardware register, button ; presses are indicated by a set bit. - ld a, [hDisableJoypadPolling] + ldh a, [hDisableJoypadPolling] and a ret nz ld a, 1 << 5 ; select direction keys ;ld c, 0 - ld [rJOYP], a - ld a, [rJOYP] - ld a, [rJOYP] + ldh [rJOYP], a + ldh a, [rJOYP] + ldh a, [rJOYP] cpl and %1111 swap a ld b, a ld a, 1 << 4 ; select button keys - ld [rJOYP], a - rept 6 - ld a, [rJOYP] - endr + ldh [rJOYP], a + REPT 6 + ldh a, [rJOYP] + ENDR cpl and %1111 or b - ld [hJoyInput], a + ldh [hJoyInput], a ld a, 1 << 4 + 1 << 5 ; deselect keys - ld [rJOYP], a + ldh [rJOYP], a ret @@ -37,30 +37,30 @@ _Joypad:: ; hJoyReleased: (hJoyLast ^ hJoyInput) & hJoyLast ; hJoyPressed: (hJoyLast ^ hJoyInput) & hJoyInput - ld a, [hJoyInput] - ld b,a + ldh a, [hJoyInput] + ld b, a and $4F cp A_BUTTON + B_BUTTON + SELECT + START ; soft reset jp z, TrySoftReset - ld a, [hJoyLast] + ldh a, [hJoyLast] ld e, a xor b ld d, a and e - ld [hJoyReleased], a + ldh [hJoyReleased], a ld a, d and b - ld [hJoyPressed], a + ldh [hJoyPressed], a ld a, b - ld [hJoyLast], a + ldh [hJoyLast], a ld a, [wd730] bit 5, a jr nz, DiscardButtonPresses - ld a, [hJoyLast] - ld [hJoyHeld], a + ldh a, [hJoyLast] + ldh [hJoyHeld], a ld a, [wJoyIgnore] and a @@ -68,19 +68,19 @@ _Joypad:: cpl ld b, a - ld a, [hJoyHeld] + ldh a, [hJoyHeld] and b - ld [hJoyHeld], a - ld a, [hJoyPressed] + ldh [hJoyHeld], a + ldh a, [hJoyPressed] and b - ld [hJoyPressed], a + ldh [hJoyPressed], a ret DiscardButtonPresses: xor a - ld [hJoyHeld], a - ld [hJoyPressed], a - ld [hJoyReleased], a + ldh [hJoyHeld], a + ldh [hJoyPressed], a + ldh [hJoyReleased], a ret TrySoftReset: @@ -88,7 +88,7 @@ TrySoftReset: ; deselect (redundant) ld a, $30 - ld [rJOYP], a + ldh [rJOYP], a ld hl, hSoftReset dec [hl] diff --git a/engine/learn_move.asm b/engine/learn_move.asm deleted file mode 100755 index 021d0eeb..00000000 --- a/engine/learn_move.asm +++ /dev/null @@ -1,250 +0,0 @@ -LearnMove: - call SaveScreenTilesToBuffer1 - ld a, [wWhichPokemon] - ld hl, wPartyMonNicks - call GetPartyMonName - ld hl, wcd6d - ld de, wLearnMoveMonName - ld bc, NAME_LENGTH - call CopyData - -DontAbandonLearning: - ld hl, wPartyMon1Moves - ld bc, wPartyMon2Moves - wPartyMon1Moves - ld a, [wWhichPokemon] - call AddNTimes - ld d, h - ld e, l - ld b, NUM_MOVES -.findEmptyMoveSlotLoop - ld a, [hl] - and a - jr z, .next - inc hl - dec b - jr nz, .findEmptyMoveSlotLoop - push de - call TryingToLearn - pop de - jp c, AbandonLearning - push hl - push de - ld [wd11e], a - call GetMoveName - ld hl, OneTwoAndText - call PrintText - pop de - pop hl -.next - ld a, [wMoveNum] - ld [hl], a - ld bc, wPartyMon1PP - wPartyMon1Moves - add hl, bc - push hl - push de - dec a - ld hl, Moves - ld bc, MoveEnd - Moves - call AddNTimes - ld de, wBuffer - ld a, BANK(Moves) - call FarCopyData - ld a, [wBuffer + 5] ; a = move's max PP - pop de - pop hl - ld [hl], a - ld a, [wIsInBattle] - and a - jp z, PrintLearnedMove - ld a, [wWhichPokemon] - ld b, a - ld a, [wPlayerMonNumber] - cp b - jp nz, PrintLearnedMove - ld h, d - ld l, e - ld de, wBattleMonMoves - ld bc, NUM_MOVES - call CopyData - ld bc, wPartyMon1PP - wPartyMon1OTID - add hl, bc - ld de, wBattleMonPP - ld bc, NUM_MOVES - call CopyData - jp PrintLearnedMove - -AbandonLearning: - ld hl, AbandonLearningText - call PrintText - coord hl, 14, 7 - lb bc, 8, 15 - ld a, TWO_OPTION_MENU - ld [wTextBoxID], a - call DisplayTextBoxID ; yes/no menu - ld a, [wCurrentMenuItem] - and a - jp nz, DontAbandonLearning - ld hl, DidNotLearnText - call PrintText - ld b, 0 - ret - -PrintLearnedMove: - ld hl, LearnedMove1Text - call PrintText - ld b, 1 - ret - -TryingToLearn: - push hl - ld hl, TryingToLearnText - call PrintText - coord hl, 14, 7 - lb bc, 8, 15 - ld a, TWO_OPTION_MENU - ld [wTextBoxID], a - call DisplayTextBoxID ; yes/no menu - pop hl - ld a, [wCurrentMenuItem] - rra - ret c - ld bc, -NUM_MOVES - add hl, bc - push hl - ld de, wMoves - ld bc, NUM_MOVES - call CopyData - callab FormatMovesString - pop hl -.loop - push hl - ld hl, WhichMoveToForgetText - call PrintText - coord hl, 4, 7 - lb bc, 4, 14 - call TextBoxBorder - coord hl, 6, 8 - ld de, wMovesString - ld a, [hFlags_0xFFFA] - set 2, a - ld [hFlags_0xFFFA], a - call PlaceString - ld a, [hFlags_0xFFFA] - res 2, a - ld [hFlags_0xFFFA], a - ld hl, wTopMenuItemY - ld a, 8 - ld [hli], a ; wTopMenuItemY - ld a, 5 - ld [hli], a ; wTopMenuItemX - xor a - ld [hli], a ; wCurrentMenuItem - inc hl - ld a, [wNumMovesMinusOne] - ld [hli], a ; wMaxMenuItem - ld a, A_BUTTON | B_BUTTON - ld [hli], a ; wMenuWatchedKeys - ld [hl], 0 ; wLastMenuItem - ld hl, hFlags_0xFFFA - set 1, [hl] - call HandleMenuInput - ld hl, hFlags_0xFFFA - res 1, [hl] - push af - call LoadScreenTilesFromBuffer1 - pop af - pop hl - bit 1, a ; pressed b - jr nz, .cancel - push hl - ld a, [wCurrentMenuItem] - ld c, a - ld b, 0 - add hl, bc - ld a, [hl] - push af - push bc - call IsMoveHM - pop bc - pop de - ld a, d - jr c, .hm - pop hl - add hl, bc - and a - ret -.hm - ld hl, HMCantDeleteText - call PrintText - pop hl - jr .loop -.cancel - scf - ret - -LearnedMove1Text: - TX_FAR _LearnedMove1Text - TX_SFX_ITEM_1 ; plays SFX_GET_ITEM_1 in the party menu (rare candy) and plays SFX_LEVEL_UP in battle - TX_BLINK - db "@" - -WhichMoveToForgetText: - TX_FAR _WhichMoveToForgetText - db "@" - -AbandonLearningText: - TX_FAR _AbandonLearningText - db "@" - -DidNotLearnText: - TX_FAR _DidNotLearnText - db "@" - -TryingToLearnText: - TX_FAR _TryingToLearnText - db "@" - -OneTwoAndText: -; bugfix: In Red/Blue, the SFX_SWAP sound was played in the wrong bank, which played an incorrect sound -; Yellow has fixed this by swapping to the correct bank - TX_FAR _OneTwoAndText - TX_DELAY - TX_ASM - push af - push bc - push de - push hl - ld a, $1 - ld [wMuteAudioAndPauseMusic], a - call DelayFrame - ld a, [wAudioROMBank] - push af - ld a, BANK(SFX_Swap_1) - ld [wAudioROMBank], a - ld [wAudioSavedROMBank], a - call WaitForSoundToFinish - ld a, SFX_SWAP - call PlaySound - call WaitForSoundToFinish - pop af - ld [wAudioROMBank], a - ld [wAudioSavedROMBank], a - xor a - ld [wMuteAudioAndPauseMusic], a - pop hl - pop de - pop bc - pop af - ld hl, PoofText - ret - -PoofText: - TX_FAR _PoofText - TX_DELAY -ForgotAndText: - TX_FAR _ForgotAndText - db "@" - -HMCantDeleteText: - TX_FAR _HMCantDeleteText - db "@" diff --git a/engine/link/cable_club.asm b/engine/link/cable_club.asm new file mode 100755 index 00000000..c75ab200 --- /dev/null +++ b/engine/link/cable_club.asm @@ -0,0 +1,984 @@ +; performs the appropriate action when the player uses the gameboy on the table in the Colosseum or Trade Center +; In the Colosseum, it starts a battle. In the Trade Center, it displays the trade selection screen. +; Before doing either action, it swaps random numbers, trainer names and party data with the other gameboy. +CableClub_DoBattleOrTrade: + ld c, 80 + call DelayFrames + call ClearScreen + call UpdateSprites + call LoadFontTilePatterns + call LoadHpBarAndStatusTilePatterns + call LoadTrainerInfoTextBoxTiles + hlcoord 3, 8 + lb bc, 2, 12 + call CableClub_TextBoxBorder + hlcoord 4, 10 + ld de, PleaseWaitString + call PlaceString + ld hl, wPlayerNumHits + xor a + ld [hli], a + ld [hl], $50 + ; fall through + +; This is called after completing a trade. +CableClub_DoBattleOrTradeAgain: + ld hl, wSerialPlayerDataBlock + ld a, SERIAL_PREAMBLE_BYTE + ld b, 6 +.writePlayerDataBlockPreambleLoop + ld [hli], a + dec b + jr nz, .writePlayerDataBlockPreambleLoop + ld hl, wSerialRandomNumberListBlock + ld a, SERIAL_PREAMBLE_BYTE + ld b, 7 +.writeRandomNumberListPreambleLoop + ld [hli], a + dec b + jr nz, .writeRandomNumberListPreambleLoop + ld b, 10 +.generateRandomNumberListLoop + call Random + cp SERIAL_PREAMBLE_BYTE ; all the random numbers have to be less than the preamble byte + jr nc, .generateRandomNumberListLoop + ld [hli], a + dec b + jr nz, .generateRandomNumberListLoop + ld hl, wSerialPartyMonsPatchList + ld a, SERIAL_PREAMBLE_BYTE + ld [hli], a + ld [hli], a + ld [hli], a + ld b, $c8 + xor a +.zeroPlayerDataPatchListLoop + ld [hli], a + dec b + jr nz, .zeroPlayerDataPatchListLoop + ld hl, wGrassRate + ld bc, wTrainerHeaderPtr - wGrassRate +.zeroEnemyPartyLoop + xor a + ld [hli], a + dec bc + ld a, b + or c + jr nz, .zeroEnemyPartyLoop + ld hl, wPartyMons - 1 + ld de, wSerialPartyMonsPatchList + 10 + ld bc, 0 +.patchPartyMonsLoop + inc c + ld a, c + cp SERIAL_PREAMBLE_BYTE + jr z, .startPatchListPart2 + ld a, b + dec a ; are we in part 2 of the patch list? + jr nz, .checkPlayerDataByte ; jump if in part 1 +; if we're in part 2 + ld a, c + cp (wPartyMonOT - (wPartyMons - 1)) - (SERIAL_PREAMBLE_BYTE - 1) + jr z, .finishedPatchingPlayerData +.checkPlayerDataByte + inc hl + ld a, [hl] + cp SERIAL_NO_DATA_BYTE + jr nz, .patchPartyMonsLoop +; if the player data byte matches SERIAL_NO_DATA_BYTE, patch it with $FF and record the offset in the patch list + ld a, c + ld [de], a + inc de + ld [hl], $ff + jr .patchPartyMonsLoop +.startPatchListPart2 + ld a, SERIAL_PATCH_LIST_PART_TERMINATOR + ld [de], a ; end of part 1 + inc de + lb bc, 1, 0 + jr .patchPartyMonsLoop +.finishedPatchingPlayerData + ld a, SERIAL_PATCH_LIST_PART_TERMINATOR + ld [de], a ; end of part 2 + call Serial_SyncAndExchangeNybble + ldh a, [hSerialConnectionStatus] + cp USING_INTERNAL_CLOCK + jr nz, .skipSendingTwoZeroBytes +; if using internal clock +; send two zero bytes for syncing purposes? + call Delay3 + xor a + ldh [hSerialSendData], a + ld a, START_TRANSFER_INTERNAL_CLOCK + ldh [rSC], a + call DelayFrame + xor a + ldh [hSerialSendData], a + ld a, START_TRANSFER_INTERNAL_CLOCK + ldh [rSC], a +.skipSendingTwoZeroBytes + call Delay3 + call StopAllMusic + ld a, (1 << SERIAL) + ldh [rIE], a + ld hl, wSerialRandomNumberListBlock + ld de, wSerialOtherGameboyRandomNumberListBlock + ld bc, $11 + call Serial_ExchangeBytes + ld a, SERIAL_NO_DATA_BYTE + ld [de], a + ld hl, wSerialPlayerDataBlock + ld de, wSerialEnemyDataBlock + ld bc, $1a8 + call Serial_ExchangeBytes + ld a, SERIAL_NO_DATA_BYTE + ld [de], a + ld hl, wSerialPartyMonsPatchList + ld de, wSerialEnemyMonsPatchList + ld bc, $c8 + call Serial_ExchangeBytes + ld a, (1 << SERIAL) | (1 << TIMER) | (1 << VBLANK) + ldh [rIE], a + ldh a, [hSerialConnectionStatus] + cp USING_INTERNAL_CLOCK + jr z, .skipCopyingRandomNumberList ; the list generated by the gameboy clocking the connection is used by both gameboys + ld hl, wSerialOtherGameboyRandomNumberListBlock +.findStartOfRandomNumberListLoop + ld a, [hli] + and a + jr z, .findStartOfRandomNumberListLoop + cp SERIAL_PREAMBLE_BYTE + jr z, .findStartOfRandomNumberListLoop + cp SERIAL_NO_DATA_BYTE + jr z, .findStartOfRandomNumberListLoop + dec hl + ld de, wLinkBattleRandomNumberList + ld c, 10 +.copyRandomNumberListLoop + ld a, [hli] + cp SERIAL_NO_DATA_BYTE + jr z, .copyRandomNumberListLoop + ld [de], a + inc de + dec c + jr nz, .copyRandomNumberListLoop +.skipCopyingRandomNumberList + ld hl, wSerialEnemyDataBlock + 3 +.findStartOfEnemyNameLoop + ld a, [hli] + and a + jr z, .findStartOfEnemyNameLoop + cp SERIAL_PREAMBLE_BYTE + jr z, .findStartOfEnemyNameLoop + cp SERIAL_NO_DATA_BYTE + jr z, .findStartOfEnemyNameLoop + dec hl + ld de, wLinkEnemyTrainerName + ld c, NAME_LENGTH +.copyEnemyNameLoop + ld a, [hli] + cp SERIAL_NO_DATA_BYTE + jr z, .copyEnemyNameLoop + ld [de], a + inc de + dec c + jr nz, .copyEnemyNameLoop + ld de, wEnemyPartyCount + ld bc, wTrainerHeaderPtr - wEnemyPartyCount +.copyEnemyPartyLoop + ld a, [hli] + cp SERIAL_NO_DATA_BYTE + jr z, .copyEnemyPartyLoop + ld [de], a + inc de + dec bc + ld a, b + or c + jr nz, .copyEnemyPartyLoop + ld de, wSerialPartyMonsPatchList + ld hl, wPartyMons + ld c, 2 ; patch list has 2 parts +.unpatchPartyMonsLoop + ld a, [de] + inc de + and a + jr z, .unpatchPartyMonsLoop + cp SERIAL_PREAMBLE_BYTE + jr z, .unpatchPartyMonsLoop + cp SERIAL_NO_DATA_BYTE + jr z, .unpatchPartyMonsLoop + cp SERIAL_PATCH_LIST_PART_TERMINATOR + jr z, .finishedPartyMonsPatchListPart + push hl + push bc + ld b, 0 + dec a + ld c, a + add hl, bc + ld a, SERIAL_NO_DATA_BYTE + ld [hl], a + pop bc + pop hl + jr .unpatchPartyMonsLoop +.finishedPartyMonsPatchListPart + ld hl, wPartyMons + (SERIAL_PREAMBLE_BYTE - 1) + dec c ; is there another part? + jr nz, .unpatchPartyMonsLoop + ld de, wSerialEnemyMonsPatchList + ld hl, wEnemyMons + ld c, 2 ; patch list has 2 parts +.unpatchEnemyMonsLoop + ld a, [de] + inc de + and a + jr z, .unpatchEnemyMonsLoop + cp SERIAL_PREAMBLE_BYTE + jr z, .unpatchEnemyMonsLoop + cp SERIAL_NO_DATA_BYTE + jr z, .unpatchEnemyMonsLoop + cp SERIAL_PATCH_LIST_PART_TERMINATOR + jr z, .finishedEnemyMonsPatchListPart + push hl + push bc + ld b, 0 + dec a + ld c, a + add hl, bc + ld a, SERIAL_NO_DATA_BYTE + ld [hl], a + pop bc + pop hl + jr .unpatchEnemyMonsLoop +.finishedEnemyMonsPatchListPart + ld hl, wEnemyMons + (SERIAL_PREAMBLE_BYTE - 1) + dec c + jr nz, .unpatchEnemyMonsLoop + ld a, LOW(wEnemyMonOT) + ld [wUnusedCF8D], a + ld a, HIGH(wEnemyMonOT) + ld [wUnusedCF8D + 1], a + xor a + ld [wTradeCenterPointerTableIndex], a + call StopAllMusic + ldh a, [hSerialConnectionStatus] + cp USING_INTERNAL_CLOCK + ld c, 66 + call z, DelayFrames ; delay if using internal clock + ld a, [wLinkState] + cp LINK_STATE_START_BATTLE + ld a, LINK_STATE_TRADING + ld [wLinkState], a + jr nz, .trading + ld a, LINK_STATE_BATTLING + ld [wLinkState], a + ld a, OPP_RIVAL1 + ld [wCurOpponent], a + call ClearScreen + call Delay3 + ld b, $9 + call RunPaletteCommand + ld hl, wOptions + res 7, [hl] + ld a, [wLetterPrintingDelayFlags] + push af + xor a + ld [wLetterPrintingDelayFlags], a + predef InitOpponent + pop af + ld [wLetterPrintingDelayFlags], a + predef HealParty + jp ReturnToCableClubRoom +.trading + ld c, BANK(Music_GameCorner) + ld a, MUSIC_GAME_CORNER + call PlayMusic + jr CallCurrentTradeCenterFunction + +PleaseWaitString: + db "PLEASE WAIT!@" + +CallCurrentTradeCenterFunction: + ld hl, TradeCenterPointerTable + ld b, 0 + ld a, [wTradeCenterPointerTableIndex] + cp $ff + jp z, DisplayTitleScreen + add a + ld c, a + add hl, bc + ld a, [hli] + ld h, [hl] + ld l, a + jp hl + +TradeCenter_SelectMon: + call ClearScreen + call Delay3 + ld b, $9 + call RunPaletteCommand + call LoadTrainerInfoTextBoxTiles + call TradeCenter_DrawPartyLists + call TradeCenter_DrawCancelBox + xor a + ld hl, wSerialSyncAndExchangeNybbleReceiveData + ld [hli], a + ld [hli], a + ld [hli], a + ld [hl], a + ld [wMenuWatchMovingOutOfBounds], a + ld [wCurrentMenuItem], a + ld [wLastMenuItem], a + ld [wMenuJoypadPollCount], a + inc a + ld [wSerialExchangeNybbleSendData], a + jp .playerMonMenu +.enemyMonMenu + xor a + ld [wMenuWatchMovingOutOfBounds], a + inc a + ld [wWhichTradeMonSelectionMenu], a + ld a, D_DOWN | D_LEFT | A_BUTTON + ld [wMenuWatchedKeys], a + ld a, [wEnemyPartyCount] + ld [wMaxMenuItem], a + ld a, 9 + ld [wTopMenuItemY], a + ld a, 1 + ld [wTopMenuItemX], a +.enemyMonMenu_HandleInput + ld hl, hFlagsFFFA + set 1, [hl] + call HandleMenuInput + ld hl, hFlagsFFFA + res 1, [hl] + and a + jp z, .getNewInput + bit 0, a ; A button pressed? + jr z, .enemyMonMenu_ANotPressed +; if A button pressed + ld a, [wMaxMenuItem] + ld c, a + ld a, [wCurrentMenuItem] + cp c + jr c, .displayEnemyMonStats + ld a, [wMaxMenuItem] + dec a + ld [wCurrentMenuItem], a +.displayEnemyMonStats + ld a, INIT_ENEMYOT_LIST + ld [wInitListType], a + callfar InitList ; the list isn't used + ld hl, wEnemyMons + call TradeCenter_DisplayStats + jp .getNewInput +.enemyMonMenu_ANotPressed + bit 5, a ; Left pressed? + jr z, .enemyMonMenu_LeftNotPressed +; if Left pressed, switch back to the player mon menu + xor a ; player mon menu + ld [wWhichTradeMonSelectionMenu], a + ld a, [wMenuCursorLocation] + ld l, a + ld a, [wMenuCursorLocation + 1] + ld h, a + ld a, [wTileBehindCursor] + ld [hl], a + ld a, [wCurrentMenuItem] + ld b, a + ld a, [wPartyCount] + dec a + cp b + jr nc, .playerMonMenu + ld [wCurrentMenuItem], a + jr .playerMonMenu +.enemyMonMenu_LeftNotPressed + bit 7, a ; Down pressed? + jp z, .getNewInput + jp .selectedCancelMenuItem ; jump if Down pressed +.playerMonMenu + xor a ; player mon menu + ld [wWhichTradeMonSelectionMenu], a + ld [wMenuWatchMovingOutOfBounds], a + ld a, D_DOWN | D_RIGHT | A_BUTTON + ld [wMenuWatchedKeys], a + ld a, [wPartyCount] + ld [wMaxMenuItem], a + ld a, 1 + ld [wTopMenuItemY], a + ld a, 1 + ld [wTopMenuItemX], a + hlcoord 1, 1 + lb bc, 6, 1 + call ClearScreenArea +.playerMonMenu_HandleInput + ld hl, hFlagsFFFA + set 1, [hl] + call HandleMenuInput + ld hl, hFlagsFFFA + res 1, [hl] + and a ; was anything pressed? + jr nz, .playerMonMenu_SomethingPressed + jp .getNewInput +.playerMonMenu_SomethingPressed + bit 0, a ; A button pressed? + jr z, .playerMonMenu_ANotPressed + jp .chosePlayerMon ; jump if A button pressed +; unreachable code + ld a, INIT_PLAYEROT_LIST + ld [wInitListType], a + callfar InitList ; the list isn't used + call TradeCenter_DisplayStats + jp .getNewInput +.playerMonMenu_ANotPressed + bit 4, a ; Right pressed? + jr z, .playerMonMenu_RightNotPressed +; if Right pressed, switch to the enemy mon menu + ld a, $1 ; enemy mon menu + ld [wWhichTradeMonSelectionMenu], a + ld a, [wMenuCursorLocation] + ld l, a + ld a, [wMenuCursorLocation + 1] + ld h, a + ld a, [wTileBehindCursor] + ld [hl], a + ld a, [wCurrentMenuItem] + ld b, a + ld a, [wEnemyPartyCount] + dec a + cp b + jr nc, .notPastLastEnemyMon +; when switching to the enemy mon menu, if the menu selection would be past the last enemy mon, select the last enemy mon + ld [wCurrentMenuItem], a +.notPastLastEnemyMon + jp .enemyMonMenu +.playerMonMenu_RightNotPressed + bit 7, a ; Down pressed? + jr z, .getNewInput + jp .selectedCancelMenuItem ; jump if Down pressed +.getNewInput + ld a, [wWhichTradeMonSelectionMenu] + and a + jp z, .playerMonMenu_HandleInput + jp .enemyMonMenu_HandleInput +.chosePlayerMon + call SaveScreenTilesToBuffer1 + call PlaceUnfilledArrowMenuCursor + ld a, [wMaxMenuItem] + ld c, a + ld a, [wCurrentMenuItem] + cp c + jr c, .displayStatsTradeMenu + ld a, [wMaxMenuItem] + dec a +.displayStatsTradeMenu + push af + hlcoord 0, 14 + lb bc, 2, 18 + call CableClub_TextBoxBorder + hlcoord 2, 16 + ld de, .statsTrade + call PlaceString + xor a + ld [wCurrentMenuItem], a + ld [wLastMenuItem], a + ld [wMenuJoypadPollCount], a + ld [wMaxMenuItem], a + ld a, 16 + ld [wTopMenuItemY], a +.selectStatsMenuItem + ld a, " " + ldcoord_a 11, 16 + ld a, D_RIGHT | B_BUTTON | A_BUTTON + ld [wMenuWatchedKeys], a + ld a, 1 + ld [wTopMenuItemX], a + call HandleMenuInput + bit 4, a ; Right pressed? + jr nz, .selectTradeMenuItem + bit 1, a ; B button pressed? + jr z, .displayPlayerMonStats +.cancelPlayerMonChoice + pop af + ld [wCurrentMenuItem], a + call LoadScreenTilesFromBuffer1 + jp .playerMonMenu +.selectTradeMenuItem + ld a, " " + ldcoord_a 1, 16 + ld a, D_LEFT | B_BUTTON | A_BUTTON + ld [wMenuWatchedKeys], a + ld a, 11 + ld [wTopMenuItemX], a + call HandleMenuInput + bit 5, a ; Left pressed? + jr nz, .selectStatsMenuItem + bit 1, a ; B button pressed? + jr nz, .cancelPlayerMonChoice + jr .choseTrade +.displayPlayerMonStats + pop af + ld [wCurrentMenuItem], a + ld a, INIT_PLAYEROT_LIST + ld [wInitListType], a + callfar InitList ; the list isn't used + call TradeCenter_DisplayStats + call LoadScreenTilesFromBuffer1 + jp .playerMonMenu +.choseTrade + call PlaceUnfilledArrowMenuCursor + pop af + ld [wCurrentMenuItem], a + ld [wTradingWhichPlayerMon], a + ld [wSerialExchangeNybbleSendData], a + call Serial_PrintWaitingTextAndSyncAndExchangeNybble + ld a, [wSerialSyncAndExchangeNybbleReceiveData] + cp $f + jp z, CallCurrentTradeCenterFunction ; go back to the beginning of the trade selection menu if the other person cancelled + ld [wTradingWhichEnemyMon], a + call TradeCenter_PlaceSelectedEnemyMonMenuCursor + ld a, $1 ; TradeCenter_Trade + ld [wTradeCenterPointerTableIndex], a + jp CallCurrentTradeCenterFunction +.statsTrade + db "STATS TRADE@" +.selectedCancelMenuItem + ld a, [wCurrentMenuItem] + ld b, a + ld a, [wMaxMenuItem] + cp b + jp nz, .getNewInput + ld a, [wMenuCursorLocation] + ld l, a + ld a, [wMenuCursorLocation + 1] + ld h, a + ld a, " " + ld [hl], a +.cancelMenuItem_Loop + ld a, "▶" ; filled arrow cursor + ldcoord_a 1, 16 +.cancelMenuItem_JoypadLoop + call JoypadLowSensitivity + ldh a, [hJoy5] + and a ; pressed anything? + jr z, .cancelMenuItem_JoypadLoop + bit 0, a ; A button pressed? + jr nz, .cancelMenuItem_APressed + bit 6, a ; Up pressed? + jr z, .cancelMenuItem_JoypadLoop +; if Up pressed + ld a, " " + ldcoord_a 1, 16 + ld a, [wPartyCount] + dec a + ld [wCurrentMenuItem], a + jp .playerMonMenu +.cancelMenuItem_APressed + ld a, "▷" ; unfilled arrow cursor + ldcoord_a 1, 16 + ld a, $f + ld [wSerialExchangeNybbleSendData], a + call Serial_PrintWaitingTextAndSyncAndExchangeNybble + ld a, [wSerialSyncAndExchangeNybbleReceiveData] + cp $f ; did the other person choose Cancel too? + jr nz, .cancelMenuItem_Loop + ; fall through + +ReturnToCableClubRoom: + call GBPalWhiteOutWithDelay3 + ld hl, wFontLoaded + ld a, [hl] + push af + push hl + res 0, [hl] + xor a + ld [wd72d], a + dec a + ld [wDestinationWarpID], a + call LoadMapData + farcall ClearVariablesOnEnterMap + pop hl + pop af + ld [hl], a + call GBFadeInFromWhite + ret + +TradeCenter_DrawCancelBox: + hlcoord 11, 15 + ld a, $7e + ld bc, 2 * SCREEN_WIDTH + 9 + call FillMemory + hlcoord 0, 15 + lb bc, 1, 9 + call CableClub_TextBoxBorder + hlcoord 2, 16 + ld de, CancelTextString + jp PlaceString + +CancelTextString: + db "CANCEL@" + +TradeCenter_PlaceSelectedEnemyMonMenuCursor: + ld a, [wSerialSyncAndExchangeNybbleReceiveData] + hlcoord 1, 9 + ld bc, SCREEN_WIDTH + call AddNTimes + ld [hl], "▷" ; cursor + ret + +TradeCenter_DisplayStats: + ld a, [wCurrentMenuItem] + ld [wWhichPokemon], a + predef StatusScreen + predef StatusScreen2 + call Delay3 + ld b, $9 + call RunPaletteCommand + call GBPalNormal + call LoadTrainerInfoTextBoxTiles + call TradeCenter_DrawPartyLists + jp TradeCenter_DrawCancelBox + +TradeCenter_DrawPartyLists: + hlcoord 0, 0 + lb bc, 6, 18 + call CableClub_TextBoxBorder + hlcoord 0, 8 + lb bc, 6, 18 + call CableClub_TextBoxBorder + hlcoord 5, 0 + ld de, wPlayerName + call PlaceString + hlcoord 5, 8 + ld de, wLinkEnemyTrainerName + call PlaceString + hlcoord 2, 1 + ld de, wPartySpecies + call TradeCenter_PrintPartyListNames + hlcoord 2, 9 + ld de, wEnemyPartyMons + ; fall through + +TradeCenter_PrintPartyListNames: + ld c, $0 +.loop + ld a, [de] + cp $ff + ret z + ld [wd11e], a + push bc + push hl + push de + push hl + ld a, c + ldh [hPastLeadingZeros], a + call GetMonName + pop hl + call PlaceString + pop de + inc de + pop hl + ld bc, 20 + add hl, bc + pop bc + inc c + jr .loop + +TradeCenter_Trade: + ld c, 100 + call DelayFrames + xor a + ld [wSerialExchangeNybbleSendData + 1], a ; unnecessary + ld [wSerialExchangeNybbleReceiveData], a + ld [wMenuWatchMovingOutOfBounds], a + ld [wMenuJoypadPollCount], a + hlcoord 0, 12 + lb bc, 4, 18 + call CableClub_TextBoxBorder + ld a, [wTradingWhichPlayerMon] + ld hl, wPartySpecies + ld c, a + ld b, 0 + add hl, bc + ld a, [hl] + ld [wd11e], a + call GetMonName + ld hl, wcd6d + ld de, wNameOfPlayerMonToBeTraded + ld bc, NAME_LENGTH + call CopyData + ld a, [wTradingWhichEnemyMon] + ld hl, wEnemyPartyMons + ld c, a + ld b, 0 + add hl, bc + ld a, [hl] + ld [wd11e], a + call GetMonName + ld hl, WillBeTradedText + bccoord 1, 14 + call TextCommandProcessor + call SaveScreenTilesToBuffer1 + hlcoord 10, 7 + lb bc, 8, 11 + ld a, TRADE_CANCEL_MENU + ld [wTwoOptionMenuID], a + ld a, TWO_OPTION_MENU + ld [wTextBoxID], a + call DisplayTextBoxID + call LoadScreenTilesFromBuffer1 + ld a, [wCurrentMenuItem] + and a + jr z, .tradeConfirmed +; if trade cancelled + ld a, $1 + ld [wSerialExchangeNybbleSendData], a + hlcoord 0, 12 + lb bc, 4, 18 + call CableClub_TextBoxBorder + hlcoord 1, 14 + ld de, TradeCanceled + call PlaceString + call Serial_PrintWaitingTextAndSyncAndExchangeNybble + jp .tradeCancelled +.tradeConfirmed + ld a, $2 + ld [wSerialExchangeNybbleSendData], a + call Serial_PrintWaitingTextAndSyncAndExchangeNybble + ld a, [wSerialSyncAndExchangeNybbleReceiveData] + dec a ; did the other person cancel? + jr nz, .doTrade +; if the other person cancelled + hlcoord 0, 12 + lb bc, 4, 18 + call CableClub_TextBoxBorder + hlcoord 1, 14 + ld de, TradeCanceled + call PlaceString + jp .tradeCancelled +.doTrade + ld a, [wTradingWhichPlayerMon] + ld hl, wPartyMonOT + call SkipFixedLengthTextEntries + ld de, wTradedPlayerMonOT + ld bc, NAME_LENGTH + call CopyData + ld hl, wPartyMon1Species + ld a, [wTradingWhichPlayerMon] + ld bc, wPartyMon2 - wPartyMon1 + call AddNTimes + ld bc, wPartyMon1OTID - wPartyMon1 + add hl, bc + ld a, [hli] + ld [wTradedPlayerMonOTID], a + ld a, [hl] + ld [wTradedPlayerMonOTID + 1], a + ld a, [wTradingWhichEnemyMon] + ld hl, wEnemyMonOT + call SkipFixedLengthTextEntries + ld de, wTradedEnemyMonOT + ld bc, NAME_LENGTH + call CopyData + ld hl, wEnemyMons + ld a, [wTradingWhichEnemyMon] + ld bc, wEnemyMon2 - wEnemyMon1 + call AddNTimes + ld bc, wEnemyMon1OTID - wEnemyMon1 + add hl, bc + ld a, [hli] + ld [wTradedEnemyMonOTID], a + ld a, [hl] + ld [wTradedEnemyMonOTID + 1], a + ld a, [wTradingWhichPlayerMon] + ld [wWhichPokemon], a + ld hl, wPartySpecies + ld b, 0 + ld c, a + add hl, bc + ld a, [hl] + ld [wTradedPlayerMonSpecies], a + callabd_ModifyPikachuHappiness PIKAHAPPY_TRADE + xor a + ld [wRemoveMonFromBox], a + call RemovePokemon + ld a, [wTradingWhichEnemyMon] + ld c, a + ld [wWhichPokemon], a + ld hl, wEnemyPartyMons + ld d, 0 + ld e, a + add hl, de + ld a, [hl] + ld [wcf91], a + ld hl, wEnemyMons + ld a, c + ld bc, wEnemyMon2 - wEnemyMon1 + call AddNTimes + ld de, wLoadedMon + ld bc, wEnemyMon2 - wEnemyMon1 + call CopyData + call AddEnemyMonToPlayerParty + ld a, [wPartyCount] + dec a + ld [wWhichPokemon], a + ld a, $1 + ld [wForceEvolution], a + ld a, [wTradingWhichEnemyMon] + ld hl, wEnemyPartyMons + ld b, 0 + ld c, a + add hl, bc + ld a, [hl] + ld [wTradedEnemyMonSpecies], a + ld a, 10 + ld [wAudioFadeOutControl], a + ld a, BANK(Music_SafariZone) + ld [wAudioSavedROMBank], a + ld a, MUSIC_SAFARI_ZONE + ld [wNewSoundID], a + call PlaySound + ld c, 100 + call DelayFrames + call ClearScreen + call LoadHpBarAndStatusTilePatterns + xor a + ld [wUnusedCC5B], a + ldh a, [hSerialConnectionStatus] + cp USING_EXTERNAL_CLOCK + jr z, .usingExternalClock + predef InternalClockTradeAnim + jr .tradeCompleted +.usingExternalClock + predef ExternalClockTradeAnim +.tradeCompleted + callfar TryEvolvingMon + call ClearScreen + call LoadTrainerInfoTextBoxTiles + call Serial_PrintWaitingTextAndSyncAndExchangeNybble + ld c, 40 + call DelayFrames + call Delay3 + ld b, $9 + call RunPaletteCommand + hlcoord 0, 12 + lb bc, 4, 18 + call CableClub_TextBoxBorder + hlcoord 1, 14 + ld de, TradeCompleted + call PlaceString + predef SaveSAVtoSRAM2 + ld c, 50 + call DelayFrames + xor a + ld [wTradeCenterPointerTableIndex], a + jp CableClub_DoBattleOrTradeAgain +.tradeCancelled + ld c, 100 + call DelayFrames + xor a ; TradeCenter_SelectMon + ld [wTradeCenterPointerTableIndex], a + jp CallCurrentTradeCenterFunction + +WillBeTradedText: + text_far _WillBeTradedText + text_end + +TradeCompleted: + db "Trade completed!@" + +TradeCanceled: + db "Too bad! The trade" + next "was canceled!@" + +TradeCenterPointerTable: + dw TradeCenter_SelectMon + dw TradeCenter_Trade + +CableClub_Run: + ld a, [wLinkState] + cp LINK_STATE_START_TRADE + jr z, .doBattleOrTrade + cp LINK_STATE_START_BATTLE + jr z, .doBattleOrTrade + cp LINK_STATE_RESET ; this is never used + ret nz + predef EmptyFunc + jp Init +.doBattleOrTrade + call CableClub_DoBattleOrTrade + ld hl, Club_GFX + ld a, h + ld [wTilesetGfxPtr + 1], a + ld a, l + ld [wTilesetGfxPtr], a + ld a, BANK(Club_GFX) + ld [wTilesetBank], a + ld hl, Club_Coll + ld a, h + ld [wTilesetCollisionPtr + 1], a + ld a, l + ld [wTilesetCollisionPtr], a + xor a + ld [wGrassRate], a + inc a ; LINK_STATE_IN_CABLE_CLUB + ld [wLinkState], a + ldh [hJoy5], a + ld a, 10 + ld [wAudioFadeOutControl], a + ld a, BANK(Music_Celadon) + ld [wAudioSavedROMBank], a + ld a, MUSIC_CELADON + ld [wNewSoundID], a + jp PlaySound + +EmptyFunc: + ret + +Diploma_TextBoxBorder: + call GetPredefRegisters + +; b = height +; c = width +CableClub_TextBoxBorder: + push hl + ld a, $78 ; border upper left corner tile + ld [hli], a + inc a ; border top horizontal line tile + call CableClub_DrawHorizontalLine + inc a ; border upper right corner tile + ld [hl], a + pop hl + ld de, 20 + add hl, de +.loop + push hl + ld a, $7b ; border left vertical line tile + ld [hli], a + ld a, " " + call CableClub_DrawHorizontalLine + ld [hl], $77 ; border right vertical line tile + pop hl + ld de, 20 + add hl, de + dec b + jr nz, .loop + ld a, $7c ; border lower left corner tile + ld [hli], a + ld a, $76 ; border bottom horizontal line tile + call CableClub_DrawHorizontalLine + ld [hl], $7d ; border lower right corner tile + ret + +; c = width +CableClub_DrawHorizontalLine: + ld d, c +.loop + ld [hli], a + dec d + jr nz, .loop + ret + +LoadTrainerInfoTextBoxTiles: + ld de, TrainerInfoTextBoxTileGraphics + ld hl, vChars2 tile $76 + lb bc, BANK(TrainerInfoTextBoxTileGraphics), (TrainerInfoTextBoxTileGraphicsEnd - TrainerInfoTextBoxTileGraphics) / $10 + jp CopyVideoData diff --git a/engine/link/cable_club_npc.asm b/engine/link/cable_club_npc.asm new file mode 100755 index 00000000..4d0a0a8a --- /dev/null +++ b/engine/link/cable_club_npc.asm @@ -0,0 +1,208 @@ +CableClubNPC:: + ld hl, CableClubNPCWelcomeText + call PrintText + call CheckPikachuFollowingPlayer + jr nz, .asm_7048 + CheckEvent EVENT_GOT_POKEDEX + jp nz, .receivedPokedex +; if the player hasn't received the pokedex +.asm_7048 + ld c, 60 + call DelayFrames + ld hl, CableClubNPCMakingPreparationsText + call PrintText + jp .didNotConnect +.receivedPokedex + ld a, $1 + ld [wMenuJoypadPollCount], a + ld a, 90 + ld [wLinkTimeoutCounter], a +.establishConnectionLoop + ldh a, [hSerialConnectionStatus] + cp USING_INTERNAL_CLOCK + jr z, .establishedConnection + cp USING_EXTERNAL_CLOCK + jr z, .establishedConnection + ld a, CONNECTION_NOT_ESTABLISHED + ldh [hSerialConnectionStatus], a + ld a, ESTABLISH_CONNECTION_WITH_EXTERNAL_CLOCK + ldh [rSB], a + xor a + ldh [hSerialReceiveData], a + ld a, START_TRANSFER_EXTERNAL_CLOCK + ldh [rSC], a + ld a, [wLinkTimeoutCounter] + dec a + ld [wLinkTimeoutCounter], a + jr z, .failedToEstablishConnection + ld a, ESTABLISH_CONNECTION_WITH_INTERNAL_CLOCK + ldh [rSB], a + ld a, START_TRANSFER_INTERNAL_CLOCK + ldh [rSC], a + call DelayFrame + jr .establishConnectionLoop +.establishedConnection + call Serial_SendZeroByte + call DelayFrame + call Serial_SendZeroByte + ld c, 50 + call DelayFrames + ld hl, CableClubNPCPleaseApplyHereHaveToSaveText + call PrintText + xor a + ld [wMenuJoypadPollCount], a + call YesNoChoice + ld a, $1 + ld [wMenuJoypadPollCount], a + ld a, [wCurrentMenuItem] + and a + jr nz, .choseNo + callfar SaveSAVtoSRAM + call WaitForSoundToFinish + ld a, SFX_SAVE + call PlaySoundWaitForCurrent + ld hl, CableClubNPCPleaseWaitText + call PrintText + ld hl, wUnknownSerialCounter + ld a, $3 + ld [hli], a + xor a + ld [hl], a + ldh [hSerialReceivedNewData], a + ld [wSerialExchangeNybbleSendData], a + call Serial_SyncAndExchangeNybble + ld hl, wUnknownSerialCounter + ld a, [hli] + inc a + jr nz, .connected + ld a, [hl] + inc a + jr nz, .connected + ld b, 10 +.syncLoop + call DelayFrame + call Serial_SendZeroByte + dec b + jr nz, .syncLoop + call CloseLinkConnection + ld hl, CableClubNPCLinkClosedBecauseOfInactivityText + call PrintText + jr .didNotConnect +.failedToEstablishConnection + ld hl, CableClubNPCAreaReservedFor2FriendsLinkedByCableText + call PrintText + jr .didNotConnect +.choseNo + call CloseLinkConnection + ld hl, CableClubNPCPleaseComeAgainText + call PrintText +.didNotConnect + xor a + ld hl, wUnknownSerialCounter + ld [hli], a + ld [hl], a + ld hl, wd72e + res 6, [hl] + xor a + ld [wMenuJoypadPollCount], a + ret +.connected + xor a + ld [hld], a + ld [hl], a + ld a, [wLetterPrintingDelayFlags] + push af + callfar LinkMenu + pop af + ld [wLetterPrintingDelayFlags], a + ret + +; seems to be similar of Serial_SyncAndExchangeNybble +Serial_SyncAndExchangeNybbleDouble: + ld a, $ff + ld [wSerialExchangeNybbleReceiveData], a +.loop + call Serial_ExchangeNybble + call DelayFrame + push hl + ld hl, wUnknownSerialCounter + 1 + dec [hl] + jr nz, .next + dec hl + dec [hl] + jr nz, .next + pop hl + jr .setUnknownSerialCounterToFFFF +.next + pop hl + ld a, [wSerialExchangeNybbleReceiveData] + inc a + jr z, .loop + call DelayFrame + ld a, $ff + ld [wSerialExchangeNybbleReceiveData], a + call Serial_ExchangeNybble + ld a, [wSerialExchangeNybbleReceiveData] + inc a + jr z, .loop + ld b, 10 +.syncLoop1 + call DelayFrame + call Serial_ExchangeNybble + dec b + jr nz, .syncLoop1 + ld b, 10 +.syncLoop2 + call DelayFrame + call Serial_SendZeroByte + dec b + jr nz, .syncLoop2 + ld a, [wSerialExchangeNybbleReceiveData] + ld [wSerialSyncAndExchangeNybbleReceiveData], a + ret +.setUnknownSerialCounterToFFFF + ld a, $ff + ld [wUnknownSerialCounter], a + ld [wUnknownSerialCounter + 1], a + ret + +CableClubNPCAreaReservedFor2FriendsLinkedByCableText: + text_far _CableClubNPCAreaReservedFor2FriendsLinkedByCableText + text_end + +CableClubNPCWelcomeText: + text_far _CableClubNPCWelcomeText + text_end + +CableClubNPCPleaseApplyHereHaveToSaveText: + text_far _CableClubNPCPleaseApplyHereHaveToSaveText + text_end + +CableClubNPCPleaseWaitText: + text_far _CableClubNPCPleaseWaitText + text_pause + text_end + +CableClubNPCLinkClosedBecauseOfInactivityText: + text_far _CableClubNPCLinkClosedBecauseOfInactivityText + text_end + +CableClubNPCPleaseComeAgainText: + text_far _CableClubNPCPleaseComeAgainText + text_end + +CableClubNPCMakingPreparationsText: + text_far _CableClubNPCMakingPreparationsText + text_end + +CloseLinkConnection: + call Delay3 + ld a, CONNECTION_NOT_ESTABLISHED + ldh [hSerialConnectionStatus], a + ld a, ESTABLISH_CONNECTION_WITH_EXTERNAL_CLOCK + ldh [rSB], a + xor a + ldh [hSerialReceiveData], a + ld a, START_TRANSFER_EXTERNAL_CLOCK + ldh [rSC], a + ret diff --git a/engine/link/print_waiting_text.asm b/engine/link/print_waiting_text.asm new file mode 100644 index 00000000..98a44970 --- /dev/null +++ b/engine/link/print_waiting_text.asm @@ -0,0 +1,19 @@ +PrintWaitingText:: + hlcoord 3, 10 + lb bc, 1, 11 + ld a, [wIsInBattle] + and a + jr z, .asm_4b9a + call TextBoxBorder + jr .asm_4b9d +.asm_4b9a + call CableClub_TextBoxBorder +.asm_4b9d + hlcoord 4, 11 + ld de, WaitingText + call PlaceString + ld c, 50 + jp DelayFrames + +WaitingText: + db "Waiting...!@" diff --git a/engine/load_mon_data.asm b/engine/load_mon_data.asm deleted file mode 100644 index e708113f..00000000 --- a/engine/load_mon_data.asm +++ /dev/null @@ -1,68 +0,0 @@ -LoadMonData_: -; Load monster [wWhichPokemon] from list [wMonDataLocation]: -; 0: partymon -; 1: enemymon -; 2: boxmon -; 3: daycaremon -; Return monster id at wcf91 and its data at wLoadedMon. -; Also load base stats at wMonHeader for convenience. - - ld a, [wDayCareMonSpecies] - ld [wcf91], a - ld a, [wMonDataLocation] - cp DAYCARE_DATA - jr z, .GetMonHeader - - ld a, [wWhichPokemon] - ld e, a - call GetMonSpecies - -.GetMonHeader - ld a, [wcf91] - ld [wd0b5], a ; input for GetMonHeader - call GetMonHeader - - ld hl, wPartyMons - ld bc, wPartyMon2 - wPartyMon1 - ld a, [wMonDataLocation] - cp ENEMY_PARTY_DATA - jr c, .getMonEntry - - ld hl, wEnemyMons - jr z, .getMonEntry - - cp 2 - ld hl, wBoxMons - ld bc, wBoxMon2 - wBoxMon1 - jr z, .getMonEntry - - ld hl, wDayCareMon - jr .copyMonData - -.getMonEntry - ld a, [wWhichPokemon] - call AddNTimes - -.copyMonData - ld de, wLoadedMon - ld bc, wPartyMon2 - wPartyMon1 - jp CopyData - -; get species of mon e in list [wMonDataLocation] for LoadMonData -GetMonSpecies: - ld hl, wPartySpecies - ld a, [wMonDataLocation] - and a - jr z, .getSpecies - dec a - jr z, .enemyParty - ld hl, wBoxSpecies - jr .getSpecies -.enemyParty - ld hl, wEnemyPartyMons -.getSpecies - ld d, 0 - add hl, de - ld a, [hl] - ld [wcf91], a - ret diff --git a/engine/load_pokedex_tiles.asm b/engine/load_pokedex_tiles.asm deleted file mode 100755 index 70bcf04d..00000000 --- a/engine/load_pokedex_tiles.asm +++ /dev/null @@ -1,11 +0,0 @@ -; Loads tile patterns for tiles used in the pokedex. -LoadPokedexTilePatterns: - call LoadHpBarAndStatusTilePatterns - ld de, PokedexTileGraphics - ld hl, vChars2 + $600 - lb bc, BANK(PokedexTileGraphics), (PokedexTileGraphicsEnd - PokedexTileGraphics) / $10 - call CopyVideoData - ld de, PokeballTileGraphics - ld hl, vChars2 + $720 - lb bc, BANK(PokeballTileGraphics), $01 - jp CopyVideoData ; load pokeball tile for marking caught mons diff --git a/engine/math/bcd.asm b/engine/math/bcd.asm new file mode 100644 index 00000000..92bf6f17 --- /dev/null +++ b/engine/math/bcd.asm @@ -0,0 +1,218 @@ +; divide hMoney by hDivideBCDDivisor +; return output in hDivideBCDQuotient (same as hDivideBCDDivisor) +; used only to halve player money upon losing a fight +DivideBCDPredef:: +DivideBCDPredef2:: +DivideBCDPredef3:: ; only used function +DivideBCDPredef4:: + call GetPredefRegisters + +DivideBCD:: + xor a + ldh [hDivideBCDBuffer], a + ldh [hDivideBCDBuffer+1], a + ldh [hDivideBCDBuffer+2], a + ld d, $1 +.mulBy10Loop +; multiply the divisor by 10 until the leading digit is nonzero +; to set up the standard long division algorithm + ldh a, [hDivideBCDDivisor] + and $f0 + jr nz, .next + inc d + ldh a, [hDivideBCDDivisor] + swap a + and $f0 + ld b, a + ldh a, [hDivideBCDDivisor+1] + swap a + ldh [hDivideBCDDivisor+1], a + and $f + or b + ldh [hDivideBCDDivisor], a + ldh a, [hDivideBCDDivisor+1] + and $f0 + ld b, a + ldh a, [hDivideBCDDivisor+2] + swap a + ldh [hDivideBCDDivisor+2], a + and $f + or b + ldh [hDivideBCDDivisor+1], a + ldh a, [hDivideBCDDivisor+2] + and $f0 + ldh [hDivideBCDDivisor+2], a + jr .mulBy10Loop + +.next + push de + push de + call DivideBCD_getNextDigit + pop de + ld a, b + swap a + and $f0 + ldh [hDivideBCDBuffer], a + dec d + jr z, .next2 + push de + call DivideBCD_divDivisorBy10 + call DivideBCD_getNextDigit + pop de + ldh a, [hDivideBCDBuffer] + or b + ldh [hDivideBCDBuffer], a + dec d + jr z, .next2 + push de + call DivideBCD_divDivisorBy10 + call DivideBCD_getNextDigit + pop de + ld a, b + swap a + and $f0 + ldh [hDivideBCDBuffer+1], a + dec d + jr z, .next2 + push de + call DivideBCD_divDivisorBy10 + call DivideBCD_getNextDigit + pop de + ldh a, [hDivideBCDBuffer+1] + or b + ldh [hDivideBCDBuffer+1], a + dec d + jr z, .next2 + push de + call DivideBCD_divDivisorBy10 + call DivideBCD_getNextDigit + pop de + ld a, b + swap a + and $f0 + ldh [hDivideBCDBuffer+2], a + dec d + jr z, .next2 + push de + call DivideBCD_divDivisorBy10 + call DivideBCD_getNextDigit + pop de + ldh a, [hDivideBCDBuffer+2] + or b + ldh [hDivideBCDBuffer+2], a +.next2 + ldh a, [hDivideBCDBuffer] + ldh [hDivideBCDQuotient], a ; the same memory location as hDivideBCDDivisor + ldh a, [hDivideBCDBuffer+1] + ldh [hDivideBCDQuotient+1], a + ldh a, [hDivideBCDBuffer+2] + ldh [hDivideBCDQuotient+2], a + pop de + ld a, $6 + sub d + and a + ret z +.divResultBy10loop + push af + call DivideBCD_divDivisorBy10 + pop af + dec a + jr nz, .divResultBy10loop + ret + +DivideBCD_divDivisorBy10: + ldh a, [hDivideBCDDivisor+2] + swap a + and $f + ld b, a + ldh a, [hDivideBCDDivisor+1] + swap a + ldh [hDivideBCDDivisor+1], a + and $f0 + or b + ldh [hDivideBCDDivisor+2], a + ldh a, [hDivideBCDDivisor+1] + and $f + ld b, a + ldh a, [hDivideBCDDivisor] + swap a + ldh [hDivideBCDDivisor], a + and $f0 + or b + ldh [hDivideBCDDivisor+1], a + ldh a, [hDivideBCDDivisor] + and $f + ldh [hDivideBCDDivisor], a + ret + +DivideBCD_getNextDigit: + ld bc, $3 +.loop + ld de, hMoney ; the dividend + ld hl, hDivideBCDDivisor + push bc + call StringCmp + pop bc + ret c + inc b + ld de, hMoney + 2 ; since SubBCD works starting from the least significant digit + ld hl, hDivideBCDDivisor + 2 + push bc + call SubBCD + pop bc + jr .loop + + +AddBCDPredef:: + call GetPredefRegisters + +AddBCD:: + and a + ld b, c +.add + ld a, [de] + adc [hl] + daa + ld [de], a + dec de + dec hl + dec c + jr nz, .add + jr nc, .done + ld a, $99 + inc de +.fill + ld [de], a + inc de + dec b + jr nz, .fill +.done + ret + + +SubBCDPredef:: + call GetPredefRegisters + +SubBCD:: + and a + ld b, c +.sub + ld a, [de] + sbc [hl] + daa + ld [de], a + dec de + dec hl + dec c + jr nz, .sub + jr nc, .done + ld a, $00 + inc de +.fill + ld [de], a + inc de + dec b + jr nz, .fill + scf +.done + ret diff --git a/engine/math/multiply_divide.asm b/engine/math/multiply_divide.asm new file mode 100755 index 00000000..2fcda158 --- /dev/null +++ b/engine/math/multiply_divide.asm @@ -0,0 +1,143 @@ +_Multiply:: + ld a, $8 + ld b, a + xor a + ldh [hProduct], a + ldh [hMultiplyBuffer], a + ldh [hMultiplyBuffer+1], a + ldh [hMultiplyBuffer+2], a + ldh [hMultiplyBuffer+3], a +.loop + ldh a, [hMultiplier] + srl a + ldh [hMultiplier], a ; (aliases: hDivisor, hMultiplier, hPowerOf10) + jr nc, .smallMultiplier + ldh a, [hMultiplyBuffer+3] + ld c, a + ldh a, [hMultiplicand+2] + add c + ldh [hMultiplyBuffer+3], a + ldh a, [hMultiplyBuffer+2] + ld c, a + ldh a, [hMultiplicand+1] + adc c + ldh [hMultiplyBuffer+2], a + ldh a, [hMultiplyBuffer+1] + ld c, a + ldh a, [hMultiplicand] ; (aliases: hMultiplicand) + adc c + ldh [hMultiplyBuffer+1], a + ldh a, [hMultiplyBuffer] + ld c, a + ldh a, [hProduct] ; (aliases: hProduct, hPastLeadingZeros, hQuotient) + adc c + ldh [hMultiplyBuffer], a +.smallMultiplier + dec b + jr z, .done + ldh a, [hMultiplicand+2] + sla a + ldh [hMultiplicand+2], a + ldh a, [hMultiplicand+1] + rl a + ldh [hMultiplicand+1], a + ldh a, [hMultiplicand] + rl a + ldh [hMultiplicand], a + ldh a, [hProduct] + rl a + ldh [hProduct], a + jr .loop +.done + ldh a, [hMultiplyBuffer+3] + ldh [hProduct+3], a + ldh a, [hMultiplyBuffer+2] + ldh [hProduct+2], a + ldh a, [hMultiplyBuffer+1] + ldh [hProduct+1], a + ldh a, [hMultiplyBuffer] + ldh [hProduct], a + ret + +_Divide:: + xor a + ldh [hDivideBuffer], a + ldh [hDivideBuffer+1], a + ldh [hDivideBuffer+2], a + ldh [hDivideBuffer+3], a + ldh [hDivideBuffer+4], a + ld a, $9 + ld e, a +.asm_37db3 + ldh a, [hDivideBuffer] + ld c, a + ldh a, [hDividend+1] ; (aliases: hMultiplicand) + sub c + ld d, a + ldh a, [hDivisor] ; (aliases: hDivisor, hMultiplier, hPowerOf10) + ld c, a + ldh a, [hDividend] ; (aliases: hProduct, hPastLeadingZeros, hQuotient) + sbc c + jr c, .asm_37dce + ldh [hDividend], a ; (aliases: hProduct, hPastLeadingZeros, hQuotient) + ld a, d + ldh [hDividend+1], a ; (aliases: hMultiplicand) + ldh a, [hDivideBuffer+4] + inc a + ldh [hDivideBuffer+4], a + jr .asm_37db3 +.asm_37dce + ld a, b + cp $1 + jr z, .asm_37e18 + ldh a, [hDivideBuffer+4] + sla a + ldh [hDivideBuffer+4], a + ldh a, [hDivideBuffer+3] + rl a + ldh [hDivideBuffer+3], a + ldh a, [hDivideBuffer+2] + rl a + ldh [hDivideBuffer+2], a + ldh a, [hDivideBuffer+1] + rl a + ldh [hDivideBuffer+1], a + dec e + jr nz, .asm_37e04 + ld a, $8 + ld e, a + ldh a, [hDivideBuffer] + ldh [hDivisor], a ; (aliases: hDivisor, hMultiplier, hPowerOf10) + xor a + ldh [hDivideBuffer], a + ldh a, [hDividend+1] ; (aliases: hMultiplicand) + ldh [hDividend], a ; (aliases: hProduct, hPastLeadingZeros, hQuotient) + ldh a, [hDividend+2] + ldh [hDividend+1], a ; (aliases: hMultiplicand) + ldh a, [hDividend+3] + ldh [hDividend+2], a +.asm_37e04 + ld a, e + cp $1 + jr nz, .asm_37e0a + dec b +.asm_37e0a + ldh a, [hDivisor] ; (aliases: hDivisor, hMultiplier, hPowerOf10) + srl a + ldh [hDivisor], a ; (aliases: hDivisor, hMultiplier, hPowerOf10) + ldh a, [hDivideBuffer] + rr a + ldh [hDivideBuffer], a + jr .asm_37db3 +.asm_37e18 + ldh a, [hDividend+1] ; (aliases: hMultiplicand) + ldh [hRemainder], a ; (aliases: hDivisor, hMultiplier, hPowerOf10) + ldh a, [hDivideBuffer+4] + ldh [hQuotient+3], a + ldh a, [hDivideBuffer+3] + ldh [hQuotient+2], a + ldh a, [hDivideBuffer+2] + ldh [hQuotient+1], a ; (aliases: hMultiplicand) + ldh a, [hDivideBuffer+1] + ldh [hDividend], a ; (aliases: hProduct, hPastLeadingZeros, hQuotient) + ret diff --git a/engine/math/random.asm b/engine/math/random.asm new file mode 100755 index 00000000..c8760157 --- /dev/null +++ b/engine/math/random.asm @@ -0,0 +1,13 @@ +Random_:: +; Generate a random 16-bit value. + ldh a, [rDIV] + ld b, a + ldh a, [hRandomAdd] + adc b + ldh [hRandomAdd], a + ldh a, [rDIV] + ld b, a + ldh a, [hRandomSub] + sbc b + ldh [hRandomSub], a + ret diff --git a/engine/menu/bills_pc.asm b/engine/menu/bills_pc.asm deleted file mode 100644 index 41626310..00000000 --- a/engine/menu/bills_pc.asm +++ /dev/null @@ -1,598 +0,0 @@ -DisplayPCMainMenu:: - xor a - ld [H_AUTOBGTRANSFERENABLED], a - call SaveScreenTilesToBuffer2 - ld a, [wNumHoFTeams] - and a - jr nz, .leaguePCAvailable - CheckEvent EVENT_GOT_POKEDEX - jr z, .noOaksPC - ld a, [wNumHoFTeams] - and a - jr nz, .leaguePCAvailable - coord hl, 0, 0 - lb bc, 8, 14 - jr .next -.noOaksPC - coord hl, 0, 0 - lb bc, 6, 14 - jr .next -.leaguePCAvailable - coord hl, 0, 0 - lb bc, 10, 14 -.next - call TextBoxBorder - call UpdateSprites - ld a, 3 - ld [wMaxMenuItem], a - CheckEvent EVENT_MET_BILL - jr nz, .metBill - coord hl, 2, 2 - ld de, SomeonesPCText - jr .next2 -.metBill - coord hl, 2, 2 - ld de, BillsPCText -.next2 - call PlaceString - coord hl, 2, 4 - ld de, wPlayerName - call PlaceString - ld l, c - ld h, b - ld de, PlayersPCText - call PlaceString - CheckEvent EVENT_GOT_POKEDEX - jr z, .noOaksPC2 - coord hl, 2, 6 - ld de, OaksPCText - call PlaceString - ld a, [wNumHoFTeams] - and a - jr z, .noLeaguePC - ld a, 4 - ld [wMaxMenuItem], a - coord hl, 2, 8 - ld de, PKMNLeaguePCText - call PlaceString - coord hl, 2, 10 - ld de, LogOffPCText - jr .next3 -.noLeaguePC - coord hl, 2, 8 - ld de, LogOffPCText - jr .next3 -.noOaksPC2 - ld a, $2 - ld [wMaxMenuItem], a - coord hl, 2, 6 - ld de, LogOffPCText -.next3 - call PlaceString - ld a, A_BUTTON | B_BUTTON - ld [wMenuWatchedKeys], a - ld a, 2 - ld [wTopMenuItemY], a - ld a, 1 - ld [wTopMenuItemX], a - xor a - ld [wCurrentMenuItem], a - ld [wLastMenuItem], a - ld a, 1 - ld [H_AUTOBGTRANSFERENABLED], a - ret - -SomeonesPCText: db "SOMEONE's PC@" -BillsPCText: db "BILL's PC@" -PlayersPCText: db "'s PC@" -OaksPCText: db "PROF.OAK's PC@" -PKMNLeaguePCText: db $4a, "LEAGUE@" -LogOffPCText: db "LOG OFF@" - -BillsPC_:: - ld hl, wd730 - set 6, [hl] - xor a - ld [wParentMenuItem], a - inc a ; MONSTER_NAME - ld [wNameListType], a - call LoadHpBarAndStatusTilePatterns - ld a, [wListScrollOffset] - push af - ld a, [wFlags_0xcd60] - bit 3, a ; accessing Bill's PC through another PC? - jr nz, BillsPCMenu -; accessing it directly - ld a, SFX_TURN_ON_PC - call PlaySound - ld hl, SwitchOnText - call PrintText - -BillsPCMenu: - ld a, [wParentMenuItem] - ld [wCurrentMenuItem], a - ld hl, vChars2 + $780 - ld de, PokeballTileGraphics - lb bc, BANK(PokeballTileGraphics), $01 - call CopyVideoData - call LoadScreenTilesFromBuffer2DisableBGTransfer - coord hl, 0, 12 - lb bc, 4, 18 - call TextBoxBorder - coord hl, 0, 0 - lb bc, 12, 12 - call TextBoxBorder - call UpdateSprites - coord hl, 2, 2 - ld de, BillsPCMenuText - call PlaceString - ld hl, wTopMenuItemY - ld a, 2 - ld [hli], a ; wTopMenuItemY - dec a - ld [hli], a ; wTopMenuItemX - inc hl - inc hl - ld a, 5 - ld [hli], a ; wMaxMenuItem - ld a, A_BUTTON | B_BUTTON - ld [hli], a ; wMenuWatchedKeys - xor a - ld [hli], a ; wLastMenuItem - ld [hli], a ; wPartyAndBillsPCSavedMenuItem - ld hl, wListScrollOffset - ld [hli], a ; wListScrollOffset - ld [hl], a ; wMenuWatchMovingOutOfBounds - ld [wPlayerMonNumber], a - coord hl, 9, 14 - lb bc, 2, 9 - call TextBoxBorder - ld a, [wCurrentBoxNum] - and $7f - cp 9 - jr c, .singleDigitBoxNum -; two digit box num - sub 9 - coord hl, 17, 16 - ld [hl], "1" - add "0" - jr .next -.singleDigitBoxNum - add "1" -.next - Coorda 18, 16 - coord hl, 10, 16 - ld de, BoxNoPCText - call PlaceString - ld a, 1 - ld [H_AUTOBGTRANSFERENABLED], a - call Delay3 - call HandleMenuInput - bit 1, a - jp nz, ExitBillsPC ; b button - call PlaceUnfilledArrowMenuCursor - ld a, [wCurrentMenuItem] - ld [wParentMenuItem], a - and a - jp z, BillsPCWithdraw ; withdraw - cp $1 - jp z, BillsPCDeposit ; deposit - cp $2 - jp z, BillsPCRelease ; release - cp $3 - jp z, BillsPCChangeBox ; change box - cp $4 - jp z, BillsPCPrintBox - -ExitBillsPC: - ld a, [wFlags_0xcd60] - bit 3, a ; accessing Bill's PC through another PC? - jr nz, .next -; accessing it directly - call LoadTextBoxTilePatterns - ld a, SFX_TURN_OFF_PC - call PlaySound - call WaitForSoundToFinish -.next - ld hl, wFlags_0xcd60 - res 5, [hl] - call LoadScreenTilesFromBuffer2 - pop af - ld [wListScrollOffset], a - ld hl, wd730 - res 6, [hl] - ret - -BillsPCPrintBox: - callab PrintPCBox - jp BillsPCMenu - -BillsPCDeposit: - ld a, [wPartyCount] - dec a - jr nz, .partyLargeEnough - ld hl, CantDepositLastMonText - call PrintText - jp BillsPCMenu -.partyLargeEnough - ld a, [wNumInBox] - cp MONS_PER_BOX - jr nz, .boxNotFull - ld hl, BoxFullText - call PrintText - jp BillsPCMenu -.boxNotFull - ld hl, wPartyCount - call DisplayMonListMenu - jp c, BillsPCMenu - callab IsThisPartymonStarterPikachu_Party - jr nc, .asm_215ad - call CheckPikachuFollowingPlayer - jr z, .asm_215ad - ld hl, SleepingPikachuText2 - call PrintText - jp BillsPCMenu -.asm_215ad - call DisplayDepositWithdrawMenu - jp nc, BillsPCMenu - callab IsThisPartymonStarterPikachu_Party - jr nc, .asm_215c9 - ld e, $1b - callab PlayPikachuSoundClip - jr .asm_215cf -.asm_215c9 - ld a, [wcf91] - call PlayCry -.asm_215cf - callabd_ModifyPikachuHappiness PIKAHAPPY_DEPOSITED - ld a, PARTY_TO_BOX - ld [wMoveMonType], a - call MoveMon - xor a - ld [wRemoveMonFromBox], a - call RemovePokemon - call WaitForSoundToFinish - ld hl, wBoxNumString - ld a, [wCurrentBoxNum] - and $7f - cp 9 - jr c, .singleDigitBoxNum - sub 9 - ld [hl], "1" - inc hl - add "0" - jr .next -.singleDigitBoxNum - add "1" -.next - ld [hli], a - ld [hl], "@" - ld hl, MonWasStoredText - call PrintText - jp BillsPCMenu - -SleepingPikachuText2: - TX_FAR _SleepingPikachuText2 - db "@" - -BillsPCWithdraw: - ld a, [wNumInBox] - and a - jr nz, .boxNotEmpty - ld hl, NoMonText - call PrintText - jp BillsPCMenu -.boxNotEmpty - ld a, [wPartyCount] - cp PARTY_LENGTH - jr nz, .partyNotFull - ld hl, CantTakeMonText - call PrintText - jp BillsPCMenu -.partyNotFull - ld hl, wNumInBox - call DisplayMonListMenu - jp c, BillsPCMenu - call DisplayDepositWithdrawMenu - jp nc, BillsPCMenu - ld a, [wWhichPokemon] - ld hl, wBoxMonNicks - call GetPartyMonName - callab IsThisPartymonStarterPikachu_Box - jr nc, .asm_21660 - ld e, $22 - callab PlayPikachuSoundClip - jr .asm_21666 -.asm_21660 - ld a, [wcf91] - call PlayCry -.asm_21666 - xor a ; BOX_TO_PARTY - ld [wMoveMonType], a - call MoveMon - ld a, 1 - ld [wRemoveMonFromBox], a - call RemovePokemon - call WaitForSoundToFinish - ld hl, MonIsTakenOutText - call PrintText - jp BillsPCMenu - -BillsPCRelease: - ld a, [wNumInBox] - and a - jr nz, .loop - ld hl, NoMonText - call PrintText - jp BillsPCMenu -.loop - ld hl, wNumInBox - call DisplayMonListMenu - jp c, BillsPCMenu - callab IsThisPartymonStarterPikachu_Box - jr c, .asm_216cb - ld hl, OnceReleasedText - call PrintText - call YesNoChoice - ld a, [wCurrentMenuItem] - and a - jr nz, .loop - inc a - ld [wRemoveMonFromBox], a - call RemovePokemon - call WaitForSoundToFinish - ld a, [wcf91] - call PlayCry - ld hl, MonWasReleasedText - call PrintText - jp BillsPCMenu - -.asm_216cb - ld a, [wWhichPokemon] - ld hl, wBoxMonNicks - call GetPartyMonName - ld e, $27 - callab PlayPikachuSoundClip - ld hl, PikachuUnhappyText - call PrintText - jp BillsPCMenu - -BillsPCChangeBox: - callba ChangeBox - jp BillsPCMenu - -DisplayMonListMenu: - ld a, l - ld [wListPointer], a - ld a, h - ld [wListPointer + 1], a - xor a - ld [wPrintItemPrices], a - ld [wListMenuID], a - inc a ; MONSTER_NAME - ld [wNameListType], a - ld a, [wPartyAndBillsPCSavedMenuItem] - ld [wCurrentMenuItem], a - call DisplayListMenuID - ld a, [wCurrentMenuItem] - ld [wPartyAndBillsPCSavedMenuItem], a - ret - -BillsPCMenuText: - db "WITHDRAW ", $4a - next "DEPOSIT ", $4a - next "RELEASE ", $4a - next "CHANGE BOX" - next "PRINT BOX" - next "SEE YA!" - db "@" - -BoxNoPCText: - db "BOX No.@" - -KnowsHMMove:: -; returns whether mon with party index [wWhichPokemon] knows an HM move - ld hl, wPartyMon1Moves - ld bc, wPartyMon2 - wPartyMon1 - jr .next -; unreachable - ld hl, wBoxMon1Moves - ld bc, wBoxMon2 - wBoxMon1 -.next - ld a, [wWhichPokemon] - call AddNTimes - ld b, NUM_MOVES -.loop - ld a, [hli] - push hl - push bc - ld hl, HMMoveArray - ld de, 1 - call IsInArray - pop bc - pop hl - ret c - dec b - jr nz, .loop - and a - ret - -HMMoveArray: - db CUT - db FLY - db SURF - db STRENGTH - db FLASH - db -1 - -DisplayDepositWithdrawMenu: - coord hl, 9, 10 - lb bc, 6, 9 - call TextBoxBorder - ld a, [wParentMenuItem] - and a ; was the Deposit or Withdraw item selected in the parent menu? - ld de, DepositPCText - jr nz, .next - ld de, WithdrawPCText -.next - coord hl, 11, 12 - call PlaceString - coord hl, 11, 14 - ld de, StatsCancelPCText - call PlaceString - ld hl, wTopMenuItemY - ld a, 12 - ld [hli], a ; wTopMenuItemY - ld a, 10 - ld [hli], a ; wTopMenuItemX - xor a - ld [hli], a ; wCurrentMenuItem - inc hl - ld a, 2 - ld [hli], a ; wMaxMenuItem - ld a, A_BUTTON | B_BUTTON - ld [hli], a ; wMenuWatchedKeys - xor a - ld [hl], a ; wLastMenuItem - ld hl, wListScrollOffset - ld [hli], a ; wListScrollOffset - ld [hl], a ; wMenuWatchMovingOutOfBounds - ld [wPlayerMonNumber], a - ld [wPartyAndBillsPCSavedMenuItem], a -.loop - call HandleMenuInput - bit 1, a ; pressed B? - jr nz, .exit - ld a, [wCurrentMenuItem] - and a - jr z, .choseDepositWithdraw - dec a - jr z, .viewStats -.exit - and a - ret -.choseDepositWithdraw - scf - ret -.viewStats - call SaveScreenTilesToBuffer1 - ld a, [wParentMenuItem] - and a - ld a, PLAYER_PARTY_DATA - jr nz, .next2 - ld a, BOX_DATA -.next2 - ld [wMonDataLocation], a - predef StatusScreen - predef StatusScreen2 - call LoadScreenTilesFromBuffer1 - call ReloadTilesetTilePatterns - call RunDefaultPaletteCommand - call LoadGBPal - jr .loop - -DepositPCText: db "DEPOSIT@" -WithdrawPCText: db "WITHDRAW@" -StatsCancelPCText: - db "STATS" - next "CANCEL@" - -SwitchOnText: - TX_FAR _SwitchOnText - db "@" - -WhatText: - TX_FAR _WhatText - db "@" - -DepositWhichMonText: - TX_FAR _DepositWhichMonText - db "@" - -MonWasStoredText: - TX_FAR _MonWasStoredText - db "@" - -CantDepositLastMonText: - TX_FAR _CantDepositLastMonText - db "@" - -BoxFullText: - TX_FAR _BoxFullText - db "@" - -MonIsTakenOutText: - TX_FAR _MonIsTakenOutText - db "@" - -NoMonText: - TX_FAR _NoMonText - db "@" - -CantTakeMonText: - TX_FAR _CantTakeMonText - db "@" - -PikachuUnhappyText: - TX_FAR _PikachuUnhappyText - db "@" - -ReleaseWhichMonText: - TX_FAR _ReleaseWhichMonText - db "@" - -OnceReleasedText: - TX_FAR _OnceReleasedText - db "@" - -MonWasReleasedText: - TX_FAR _MonWasReleasedText - db "@" - -CableClubLeftGameboy:: - ld a, [hSerialConnectionStatus] - cp USING_EXTERNAL_CLOCK - ret z - ld a, [wSpritePlayerStateData1FacingDirection] ; player's sprite facing direction - cp SPRITE_FACING_RIGHT - ret nz - ld a, [wCurMap] - cp TRADE_CENTER - ld a, LINK_STATE_START_TRADE - jr z, .next - inc a ; LINK_STATE_START_BATTLE -.next - ld [wLinkState], a - call EnableAutoTextBoxDrawing - tx_pre_jump JustAMomentText - -CableClubRightGameboy:: - ld a, [hSerialConnectionStatus] - cp USING_INTERNAL_CLOCK - ret z - ld a, [wSpritePlayerStateData1FacingDirection] ; player's sprite facing direction - cp SPRITE_FACING_LEFT - ret nz - ld a, [wCurMap] - cp TRADE_CENTER - ld a, LINK_STATE_START_TRADE - jr z, .next - inc a ; LINK_STATE_START_BATTLE -.next - ld [wLinkState], a - call EnableAutoTextBoxDrawing - tx_pre_jump JustAMomentText - -JustAMomentText:: - TX_FAR _JustAMomentText - db "@" - - ld a, [wSpritePlayerStateData1FacingDirection] ; player's sprite facing direction - cp SPRITE_FACING_UP - ret nz - call EnableAutoTextBoxDrawing - tx_pre_jump OpenBillsPCText - -OpenBillsPCText:: - TX_BILLS_PC - diff --git a/engine/menu/diploma.asm b/engine/menu/diploma.asm deleted file mode 100644 index 3f309bd2..00000000 --- a/engine/menu/diploma.asm +++ /dev/null @@ -1,17 +0,0 @@ -DisplayDiploma: - call SaveScreenTilesToBuffer2 - call GBPalWhiteOutWithDelay3 - call ClearScreen - xor a - ld [wUpdateSpritesEnabled], a - ld hl, wd730 - set 6, [hl] - callab _DisplayDiploma - call WaitForTextScrollButtonPress - ld hl, wd730 - res 6, [hl] - call GBPalWhiteOutWithDelay3 - call ReloadTilesetTilePatterns - call RestoreScreenTilesAndReloadTilePatterns - call Delay3 - jp GBPalNormal diff --git a/engine/menu/draw_badges.asm b/engine/menu/draw_badges.asm deleted file mode 100644 index 9e6262a0..00000000 --- a/engine/menu/draw_badges.asm +++ /dev/null @@ -1,120 +0,0 @@ -DrawBadges: -; Draw 4x2 gym leader faces, with the faces replaced by -; badges if they are owned. Used in the player status screen. - -; In Japanese versions, names are displayed above faces. -; Instead of removing relevant code, the name graphics were erased. - -; Tile ids for face/badge graphics. - ld de, wBadgeOrFaceTiles - ld hl, .FaceBadgeTiles - ld bc, 8 - call CopyData - -; Booleans for each badge. - ld hl, wTempObtainedBadgesBooleans - ld bc, 8 - xor a - call FillMemory - -; Alter these based on owned badges. - ld de, wTempObtainedBadgesBooleans - ld hl, wBadgeOrFaceTiles - ld a, [wObtainedBadges] - ld b, a - ld c, 8 -.CheckBadge - srl b - jr nc, .NextBadge - ld a, [hl] - add 4 ; Badge graphics are after each face - ld [hl], a - ld a, 1 - ld [de], a -.NextBadge - inc hl - inc de - dec c - jr nz, .CheckBadge - -; Draw two rows of badges. - ld hl, wBadgeNumberTile - ld a, $d8 ; [1] - ld [hli], a - ld [hl], $60 ; First name - - coord hl, 2, 11 - ld de, wTempObtainedBadgesBooleans - call .DrawBadgeRow - - coord hl, 2, 14 - ld de, wTempObtainedBadgesBooleans + 4 -; call .DrawBadgeRow -; ret - -.DrawBadgeRow -; Draw 4 badges. - - ld c, 4 -.DrawBadge - push de - push hl - -; Badge no. - ld a, [wBadgeNumberTile] - ld [hli], a - inc a - ld [wBadgeNumberTile], a - -; Names aren't printed if the badge is owned. - ld a, [de] - and a - ld a, [wBadgeNameTile] - jr nz, .SkipName - call .PlaceTiles - jr .PlaceBadge - -.SkipName - inc a - inc a - inc hl - -.PlaceBadge - ld [wBadgeNameTile], a - ld de, SCREEN_WIDTH - 1 - add hl, de - ld a, [wBadgeOrFaceTiles] - call .PlaceTiles - add hl, de - call .PlaceTiles - -; Shift badge array back one byte. - push bc - ld hl, wBadgeOrFaceTiles + 1 - ld de, wBadgeOrFaceTiles - ld bc, 8 - call CopyData - pop bc - - pop hl - ld de, 4 - add hl, de - - pop de - inc de - dec c - jr nz, .DrawBadge - ret - -.PlaceTiles - ld [hli], a - inc a - ld [hl], a - inc a - ret - -.FaceBadgeTiles - db $20, $28, $30, $38, $40, $48, $50, $58 - -GymLeaderFaceAndBadgeTileGraphics: - INCBIN "gfx/badges.2bpp" diff --git a/engine/menu/draw_start_menu.asm b/engine/menu/draw_start_menu.asm deleted file mode 100644 index 632b8c3a..00000000 --- a/engine/menu/draw_start_menu.asm +++ /dev/null @@ -1,87 +0,0 @@ -; function that displays the start menu -DrawStartMenu: - CheckEvent EVENT_GOT_POKEDEX -; menu with pokedex - coord hl, 10, 0 - lb bc, 14, 8 - jr nz,.drawTextBoxBorder -; shorter menu if the player doesn't have the pokedex - coord hl, 10, 0 - lb bc, 12, 8 -.drawTextBoxBorder - call TextBoxBorder - ld a, D_DOWN | D_UP | START | B_BUTTON | A_BUTTON - ld [wMenuWatchedKeys], a - ld a, $02 - ld [wTopMenuItemY], a ; Y position of first menu choice - ld a, $0b - ld [wTopMenuItemX], a ; X position of first menu choice - ld a, [wBattleAndStartSavedMenuItem] ; remembered menu selection from last time - ld [wCurrentMenuItem], a - ld [wLastMenuItem], a - xor a - ld [wMenuWatchMovingOutOfBounds], a - ld hl, wd730 - set 6, [hl] ; no pauses between printing each letter - coord hl, 12, 2 - CheckEvent EVENT_GOT_POKEDEX -; case for not having pokedex - ld a, $06 - jr z, .storeMenuItemCount -; case for having pokedex - ld de, StartMenuPokedexText - call PrintStartMenuItem - ld a, $07 -.storeMenuItemCount - ld [wMaxMenuItem], a ; number of menu items - ld de, StartMenuPokemonText - call PrintStartMenuItem - ld de, StartMenuItemText - call PrintStartMenuItem - ld de, wPlayerName ; player's name - call PrintStartMenuItem - ld a, [wd72e] - bit 6, a ; is the player using the link feature? -; case for not using link feature - ld de, StartMenuSaveText - jr z, .printSaveOrResetText -; case for using link feature - ld de, StartMenuResetText -.printSaveOrResetText - call PrintStartMenuItem - ld de, StartMenuOptionText - call PrintStartMenuItem - ld de, StartMenuExitText - call PlaceString - ld hl, wd730 - res 6, [hl] ; turn pauses between printing letters back on - ret - -StartMenuPokedexText: - db "POKéDEX@" - -StartMenuPokemonText: - db "#MON@" - -StartMenuItemText: - db "ITEM@" - -StartMenuSaveText: - db "SAVE@" - -StartMenuResetText: - db "RESET@" - -StartMenuExitText: - db "EXIT@" - -StartMenuOptionText: - db "OPTION@" - -PrintStartMenuItem: - push hl - call PlaceString - pop hl - ld de, SCREEN_WIDTH * 2 - add hl, de - ret diff --git a/engine/menu/league_pc.asm b/engine/menu/league_pc.asm deleted file mode 100755 index 9946b90d..00000000 --- a/engine/menu/league_pc.asm +++ /dev/null @@ -1,119 +0,0 @@ -PKMNLeaguePC: - ld hl, AccessedHoFPCText - call PrintText - ld hl, wd730 - set 6, [hl] - push hl - ld a, [wUpdateSpritesEnabled] - push af - ld a, [hTilesetType] - push af - xor a - ld [hTilesetType], a - ld [wSpriteFlipped], a - ld [wUpdateSpritesEnabled], a - ld [wHoFTeamIndex2], a - ld [wHoFTeamNo], a - ld a, [wNumHoFTeams] - ld b, a - cp HOF_TEAM_CAPACITY + 1 - jr c, .loop -; If the total number of hall of fame teams is greater than the storage -; capacity, then calculate the number of the first team that is still recorded. - ld b, HOF_TEAM_CAPACITY - sub b - ld [wHoFTeamNo], a -.loop - ld hl, wHoFTeamNo - inc [hl] - push bc - ld a, [wHoFTeamIndex2] - ld [wHoFTeamIndex], a - callba LoadHallOfFameTeams - call LeaguePCShowTeam - pop bc - jr c, .doneShowingTeams - ld hl, wHoFTeamIndex2 - inc [hl] - ld a, [hl] - cp b - jr nz, .loop -.doneShowingTeams - pop af - ld [hTilesetType], a - pop af - ld [wUpdateSpritesEnabled], a - pop hl - res 6, [hl] - call GBPalWhiteOutWithDelay3 - call ClearScreen - call RunDefaultPaletteCommand - jp GBPalNormal - -LeaguePCShowTeam: - ld c, PARTY_LENGTH -.loop - push bc - call LeaguePCShowMon - call WaitForTextScrollButtonPress - ld a, [hJoyHeld] - bit 1, a - jr nz, .exit - ld hl, wHallOfFame + HOF_MON - ld de, wHallOfFame - ld bc, HOF_TEAM - HOF_MON - call CopyData - pop bc - ld a, [wHallOfFame + 0] - cp $ff - jr z, .done - dec c - jr nz, .loop -.done - and a - ret -.exit - pop bc - scf - ret - -LeaguePCShowMon: - call GBPalWhiteOutWithDelay3 - call ClearScreen - ld hl, wHallOfFame - ld a, [hli] - ld [wHoFMonSpecies], a - ld [wcf91], a - ld [wd0b5], a - ld [wBattleMonSpecies2], a - ld [wWholeScreenPaletteMonSpecies], a - ld a, [hli] - ld [wHoFMonLevel], a - ld de, wcd6d - ld bc, NAME_LENGTH - call CopyData - ld b, SET_PAL_POKEMON_WHOLE_SCREEN - ld c, 0 - call RunPaletteCommand - coord hl, 12, 5 - call GetMonHeader - call LoadFrontSpriteByMonIndex - call GBPalNormal - coord hl, 0, 13 - lb bc, 2, 18 - call TextBoxBorder - coord hl, 1, 15 - ld de, HallOfFameNoText - call PlaceString - coord hl, 16, 15 - ld de, wHoFTeamNo - lb bc, 1, 3 - call PrintNumber - jpba Func_7033f - -HallOfFameNoText: - db "HALL OF FAME No @" - -AccessedHoFPCText: - TX_FAR _AccessedHoFPCText - db "@" diff --git a/engine/menu/link_menu.asm b/engine/menu/link_menu.asm deleted file mode 100644 index 9bc28b31..00000000 --- a/engine/menu/link_menu.asm +++ /dev/null @@ -1,910 +0,0 @@ -Func_f531b:: - ld c,$14 - call DelayFrames - ld a,$1 - ld [wBuffer],a - xor a - ld [wUnknownSerialFlag_d499],a - coord hl, 0,0 - lb bc, 4, 5 - call TextBoxBorder - ld de,Text_f5791 - coord hl, 1,2 - call PlaceString - coord hl, 8,0 - lb bc, 8, 10 - call TextBoxBorder - coord hl, 10,2 - ld de,Text_f579c - call PlaceString - coord hl, 0,10 - lb bc, 6, 18 - call TextBoxBorder - call UpdateSprites - xor a - ld [wUnusedCD37],a - ld [wd72d],a - ld [wd11e],a - ld hl,wTopMenuItemY - ld a,$2 - ld [hli],a - ld a,$9 - ld [hli],a - xor a - ld [hli],a - inc hl - ld a,$3 - ld [hli],a - ld a,$3 - ld [hli],a - xor a - ld [hl],a -.asm_f5377 - call Func_f56bd - call HandleMenuInput - and $3 - add a - add a - ld b,a - ld a,[wCurrentMenuItem] - cp $3 - jr nz,.asm_f5390 - bit 2,b - jr z,.asm_f5390 - dec a - ld b,$8 -.asm_f5390 - add b - add $c0 - ld [wLinkMenuSelectionSendBuffer],a - ld [wLinkMenuSelectionSendBuffer+1],a -.asm_f5399 - ld hl,wLinkMenuSelectionSendBuffer - ld a,[hl] - ld [hSerialSendData],a - call Serial_ExchangeByte - push af - ld hl,wLinkMenuSelectionSendBuffer - ld a,[hl] - ld [hSerialSendData],a - call Serial_ExchangeByte - pop bc - cp b - jr nz,.asm_f5399 - and $f0 - cp $c0 - jr nz,.asm_f5399 - ld a,b - and $c - jr nz,.asm_f53c4 - ld a,[wLinkMenuSelectionSendBuffer] - and $c - jr z,.asm_f5377 - jr .asm_f53df -.asm_f53c4 - ld a,[wLinkMenuSelectionSendBuffer] - and $c - jr z,.asm_f53d1 - ld a,[hSerialConnectionStatus] - cp $2 - jr z,.asm_f53df -.asm_f53d1 - ld a,$1 - ld [wd11e],a - ld a,b - ld [wLinkMenuSelectionSendBuffer],a - and $3 - ld [wCurrentMenuItem],a -.asm_f53df - call DelayFrame - call DelayFrame - ld hl,wLinkMenuSelectionSendBuffer - ld a,[hl] - ld [hSerialSendData],a - call Serial_ExchangeByte - call Serial_ExchangeByte - ld b,$14 -.loop - call DelayFrame - call Serial_SendZeroByte - dec b - jr nz,.loop - ld b,$7f - ld c,$7f - ld d,$7f - ld e,$ec - ld a,[wLinkMenuSelectionSendBuffer] - bit 3,a - jr nz,.asm_f541a - ld b,e - ld e,c - ld a,[wCurrentMenuItem] - and a - jr z,.asm_f541a - ld c,b - ld b,d - dec a - jr z,.asm_f541a - ld d,c - ld c,b -.asm_f541a - ld a,b - Coorda 9,2 - ld a,c - Coorda 9,4 - ld a,d - Coorda 9,6 - ld a,e - Coorda 9,8 - ld c,40 - call DelayFrames - ld a,[wLinkMenuSelectionSendBuffer] - bit 3,a - jr nz,asm_f547f - ld a,[wCurrentMenuItem] - cp $3 - jr z,asm_f547f - inc a - ld [wUnknownSerialFlag_d499],a - ld a,[wCurrentMenuItem] - ld hl,PointerTable_f5488 - ld c,a - ld b,$0 - add hl,bc - add hl,bc - ld a,[hli] - ld h,[hl] - ld l,a - ld de,.returnaddress - push de - jp hl -.returnaddress - ld [wLinkMenuSelectionSendBuffer],a - xor a - ld [wUnknownSerialCounter],a - ld [wUnknownSerialCounter+1],a - call Serial_SyncAndExchangeNybble - ld a,[wLinkMenuSelectionSendBuffer] - and a - jr nz,asm_f547c - ld a, [wLinkMenuSelectionReceiveBuffer] - and a - jr nz, Func_f5476 - xor a - ld [wUnknownSerialCounter],a - ld [wUnknownSerialCounter+1],a - and a - ret - -Func_f5476:: - ld hl,ColosseumIneligibleText - call PrintText -asm_f547c:: - jp Func_f531b - -asm_f547f:: - xor a - ld [wUnknownSerialCounter],a - ld [wUnknownSerialCounter+1],a - scf - ret - -PointerTable_f5488:: - dw PokeCup - dw PikaCup - dw PetitCup - -PokeCup:: - ld hl,wPartyCount - ld a,[hli] - cp $3 - jp nz,NotThreeMonsInParty - ld b,$3 -.loop - ld a,[hli] - cp MEW - jp z,MewInParty - dec b - jr nz,.loop - dec hl - dec hl - cp [hl] ; is third mon second mon? - jp z,DuplicateSpecies - dec hl ; wPartySpecies - cp [hl] ; is third mon first mon? - jp z,DuplicateSpecies - ld a,[hli] - cp [hl] ; is first mon second mon? - jp z,DuplicateSpecies - ld a,[wPartyMon1Level] - cp 56 - jp nc,LevelAbove55 - cp 50 - jp c,LevelUnder50 - ld b,a - ld a,[wPartyMon2Level] - cp 56 - jp nc,LevelAbove55 - cp 50 - jp c,LevelUnder50 - ld c,a - ld a,[wPartyMon3Level] - cp 56 - jp nc,LevelAbove55 - cp 50 - jp c,LevelUnder50 - add b - add c - cp 156 - jp nc,CombinedLevelsGreaterThan155 - xor a - ret - -PikaCup:: - ld hl,wPartyCount - ld a,[hli] - cp $3 - jp nz,NotThreeMonsInParty - ld b,$3 -.loop - ld a,[hli] ; wPartySpecies - cp MEW - jp z,MewInParty - dec b - jr nz,.loop - dec hl - dec hl - cp [hl] ; is third mon second mon? - jp z,DuplicateSpecies - dec hl ; wPartySpecies - cp [hl] ; is third mon first mon? - jp z,DuplicateSpecies - ld a,[hli] - cp [hl] ; is first mon second mon? - jp z,DuplicateSpecies - ld a,[wPartyMon1Level] - cp 21 - jp nc,LevelAbove20 - cp 15 - jp c,LevelUnder15 - ld b,a - ld a,[wPartyMon2Level] - cp 21 - jp nc,LevelAbove20 - cp 15 - jp c,LevelUnder15 - ld c,a - ld a,[wPartyMon3Level] - cp 21 - jp nc,LevelAbove20 - cp 15 - jp c,LevelUnder15 - add b - add c - cp 51 - jp nc,CombinedLevelsAbove50 - xor a - ret - -PetitCup:: - ld hl,wPartyCount - ld a,[hli] - cp $3 - jp nz,NotThreeMonsInParty - ld b,$3 -.loop - ld a,[hli] - cp MEW - jp z,MewInParty - dec b - jr nz,.loop - dec hl - dec hl - cp [hl] ; is third mon second mon? - jp z,DuplicateSpecies - dec hl ; wPartySpecies - cp [hl] ; is third mon first mon? - jp z,DuplicateSpecies - ld a,[hli] - cp [hl] ; is first mon second mon? - jp z,DuplicateSpecies - dec hl - ld a,[hl] - ld [wcf91],a - push hl - callab Func_3b10f - pop hl - jp c,asm_f56ad - inc hl - ld a,[hl] - ld [wcf91],a - push hl - callab Func_3b10f - pop hl - jp c,asm_f56ad - inc hl - ld a,[hl] - ld [wcf91],a - push hl - callab Func_3b10f - pop hl - jp c,asm_f56ad - dec hl - dec hl - ld b,$3 -.bigloop - ld a,[hli] - push hl - push bc - push af - dec a - ld c,a - ld b,$0 - ld hl,PokedexEntryPointers - add hl,bc - add hl,bc - ld de,wcd6d - ld bc,$2 - ld a,BANK(PokedexEntryPointers) - call FarCopyData - ld hl,wcd6d - ld a,[hli] - ld h,[hl] - ld l,a - ld de,wcd6d - ld bc,$14 - ld a,BANK(PokedexEntryPointers) - call FarCopyData - ld hl,wcd6d -.loop2 - ld a,[hli] - cp "@" - jr nz,.loop2 - ld a,[hli] - cp $7 - jp nc,asm_f5689 - add a - add a - ld b,a - add a - add b - ld b,a - ld a,[hli] - add b - cp $51 - jp nc,asm_f5689 - ld a,[hli] - sub $b9 - ld a,[hl] - sbc $1 - jp nc,asm_f569b - pop af - pop bc - pop hl - dec b - jr nz,.bigloop - ld a,[wPartyMon1Level] - cp 31 - jp nc,LevelAbove30 - cp 25 - jp c,LevelUnder25 - ld b,a - ld a,[wPartyMon2Level] - cp 31 - jp nc,LevelAbove30 - cp 25 - jp c,LevelUnder25 - ld c,a - ld a,[wPartyMon3Level] - cp 31 - jp nc,LevelAbove30 - cp 25 - jp c,LevelUnder25 - add b - add c - cp 81 - jp nc,CombinedLevelsAbove80 - xor a - ret - -NotThreeMonsInParty:: - ld hl,Colosseum3MonsText - call PrintText - ld a,$1 - ret - -MewInParty:: - ld hl,ColosseumMewText - call PrintText - ld a,$2 - ret - -DuplicateSpecies:: - ld hl,ColosseumDifferentMonsText - call PrintText - ld a,$3 - ret - -LevelAbove55:: - ld hl,ColosseumMaxL55Text - call PrintText - ld a,$4 - ret - -LevelUnder50:: - ld hl,ColosseumMinL50Text - call PrintText - ld a,$5 - ret - -CombinedLevelsGreaterThan155:: - ld hl,ColosseumTotalL155Text - call PrintText - ld a,$6 - ret - -LevelAbove30:: - ld hl,ColosseumMaxL30Text - call PrintText - ld a,$7 - ret - -LevelUnder25:: - ld hl,ColosseumMinL25Text - call PrintText - ld a,$8 - ret - -CombinedLevelsAbove80:: - ld hl,ColosseumTotalL80Text - call PrintText - ld a,$9 - ret - -LevelAbove20:: - ld hl,ColosseumMaxL20Text - call PrintText - ld a,$a - ret - -LevelUnder15:: - ld hl,ColosseumMinL15Text - call PrintText - ld a,$b - ret - -CombinedLevelsAbove50:: - ld hl,ColosseumTotalL50Text - call PrintText - ld a,$c - ret - -asm_f5689:: - pop af - pop bc - pop hl - ld [wd11e],a - call GetMonName - ld hl,ColosseumHeightText - call PrintText - ld a,$d - ret - -asm_f569b:: - pop af - pop bc - pop hl - ld [wd11e],a - call GetMonName - ld hl,ColosseumWeightText - call PrintText - ld a,$e - ret - -asm_f56ad:: - ld a,[hl] - ld [wd11e],a - call GetMonName - ld hl,ColosseumEvolvedText - call PrintText - ld a,$f - ret - -Func_f56bd:: - xor a - ld [H_AUTOBGTRANSFERENABLED],a - coord hl, 1,11 - lb bc, 6, 18 - call ClearScreenArea - ld a,[wCurrentMenuItem] - cp $3 - jr nc,.asm_f56e6 - ld hl,PointerTable_f56ee - ld a,[wCurrentMenuItem] - ld c,a - ld b,$0 - add hl,bc - add hl,bc - ld a,[hli] - ld h,[hl] - ld l,a - ld d,h - ld e,l - coord hl, 1,12 - call PlaceString -.asm_f56e6 - call Delay3 - ld a,$1 - ld [H_AUTOBGTRANSFERENABLED],a - ret - -PointerTable_f56ee:: - dw Text_f56f4 - dw Text_f5728 - dw Text_f575b - -Text_f56f4:: - db "LVs of 3:50-55" - next "Sum of LVs:155 MAX" - next "MEW can't attend.@" - -Text_f5728:: - db "LVs of 3:15-20" - next "Sum of LVs:50 MAX" - next "MEW can't attend.@" - -Text_f575b:: - db "3 Basic .LV25-30" - next "Sum of LVs:80 MAX" - next "6′8″ and 44lb MAX@" - -Text_f5791:: - db "View" - next "Rules@" - -Text_f579c:: - db "# Cup" - next "Pika Cup" - next "Petit Cup" - next "CANCEL@" - -Colosseum3MonsText:: - TX_FAR _Colosseum3MonsText - db "@" - -ColosseumMewText:: - TX_FAR _ColosseumMewText - db "@" - -ColosseumDifferentMonsText:: - TX_FAR _ColosseumDifferentMonsText - db "@" - -ColosseumMaxL55Text:: - TX_FAR _ColosseumMaxL55Text - db "@" - -ColosseumMinL50Text:: - TX_FAR _ColosseumMinL50Text - db "@" - -ColosseumTotalL155Text:: - TX_FAR _ColosseumTotalL155Text - db "@" - -ColosseumMaxL30Text:: - TX_FAR _ColosseumMaxL30Text - db "@" - -ColosseumMinL25Text:: - TX_FAR _ColosseumMinL25Text - db "@" - -ColosseumTotalL80Text:: - TX_FAR _ColosseumTotalL80Text - db "@" - -ColosseumMaxL20Text:: - TX_FAR _ColosseumMaxL20Text - db "@" - -ColosseumMinL15Text:: - TX_FAR _ColosseumMinL15Text - db "@" - -ColosseumTotalL50Text:: - TX_FAR _ColosseumTotalL50Text - db "@" - -ColosseumHeightText:: - TX_FAR _ColosseumHeightText - db "@" - -ColosseumWeightText:: - TX_FAR _ColosseumWeightText - db "@" - -ColosseumEvolvedText:: - TX_FAR _ColosseumEvolvedText - db "@" - -ColosseumIneligibleText:: - TX_FAR _ColosseumIneligibleText - db "@" - -LinkMenu: - xor a - ld [wLetterPrintingDelayFlags], a - ld hl, wd72e - set 6, [hl] - ld hl, TextTerminator_f5a16 - call PrintText - call SaveScreenTilesToBuffer1 - ld hl, ColosseumWhereToText - call PrintText - coord hl, 5, 3 - lb bc, 8, 13 - call TextBoxBorder - call UpdateSprites - coord hl, 7, 5 - ld de, TradeCenterText - call PlaceString - xor a - ld [wUnusedCD37], a - ld [wd72d], a - ld [wd11e], a - ld hl, wTopMenuItemY - ld a, $5 - ld [hli], a - ld a, $6 - ld [hli], a - xor a - ld [hli], a - inc hl - ld a, $3 - ld [hli], a - ld [hli], a - xor a - ld [hl], a -.waitForInputLoop - call HandleMenuInput - and A_BUTTON | B_BUTTON - add a - add a - ld b, a - ld a, [wCurrentMenuItem] - cp $3 - jr nz,.asm_f586b - bit 2,b - jr z,.asm_f586b - dec a - ld b,$8 -.asm_f586b - add b - add $d0 - ld [wLinkMenuSelectionSendBuffer], a - ld [wLinkMenuSelectionSendBuffer + 1], a -.exchangeMenuSelectionLoop - call Serial_ExchangeLinkMenuSelection - ld a, [wLinkMenuSelectionReceiveBuffer] - ld b, a - and $f0 - cp $d0 - jr z, .asm_f5c7d - ld a, [wLinkMenuSelectionReceiveBuffer + 1] - ld b, a - and $f0 - cp $d0 - jr nz, .exchangeMenuSelectionLoop -.asm_f5c7d - ld a, b - and $c ; did the enemy press A or B? - jr nz, .enemyPressedAOrB -; the enemy didn't press A or B - ld a, [wLinkMenuSelectionSendBuffer] - and $c ; did the player press A or B? - jr z, .waitForInputLoop ; if neither the player nor the enemy pressed A or B, try again - jr .doneChoosingMenuSelection ; if the player pressed A or B but the enemy didn't, use the player's selection -.enemyPressedAOrB - ld a, [wLinkMenuSelectionSendBuffer] - and $c ; did the player press A or B? - jr z, .useEnemyMenuSelection ; if the enemy pressed A or B but the player didn't, use the enemy's selection -; the enemy and the player both pressed A or B -; The gameboy that is clocking the connection wins. - ld a, [hSerialConnectionStatus] - cp USING_INTERNAL_CLOCK - jr z, .doneChoosingMenuSelection -.useEnemyMenuSelection - ld a, $1 - ld [wd11e], a - ld a, b - ld [wLinkMenuSelectionSendBuffer], a - and $3 - ld [wCurrentMenuItem], a ; wCurrentMenuItem -.doneChoosingMenuSelection - ld a, [hSerialConnectionStatus] - cp USING_INTERNAL_CLOCK - jr nz, .skipStartingTransfer - call DelayFrame - call DelayFrame - ld a, START_TRANSFER_INTERNAL_CLOCK - ld [rSC], a -.skipStartingTransfer - ld b, " " - ld c, " " - ld d, " " - ld e, "▷" - ld a, [wLinkMenuSelectionSendBuffer] - and (B_BUTTON << 2) ; was B button pressed? - jr nz, .updateCursorPosition -; A button was pressed - ld a, [wCurrentMenuItem] - cp $2 - jp z, .asm_f5963 - ld b, e - ld e, c - ld a, [wCurrentMenuItem] - and a - jr z, .updateCursorPosition - ld c, b - ld b, d - dec a - jr z, .updateCursorPosition - ld d, c - ld c, b -.updateCursorPosition - call Func_f59ec - call LoadScreenTilesFromBuffer1 - ld a, [wLinkMenuSelectionSendBuffer] - and (B_BUTTON << 2) ; was B button pressed? - jr nz, .choseCancel ; cancel if B pressed - ld a, [wCurrentMenuItem] - cp $2 - jr z, .choseCancel - xor a - ld [wWalkBikeSurfState], a ; start walking - ld a, [wCurrentMenuItem] - and a - ld a, COLOSSEUM - jr nz, .next - ld a, TRADE_CENTER -.next - ld [wd72d], a - ld hl, ColosseumPleaseWaitText - call PrintText - ld c, 50 - call DelayFrames - ld hl, wd732 - res 1, [hl] - ld a, [wDefaultMap] - ld [wDestinationMap], a - callab SpecialWarpIn - ld c, 20 - call DelayFrames - xor a - ld [wMenuJoypadPollCount], a - ld [wSerialExchangeNybbleSendData], a - inc a ; LINK_STATE_IN_CABLE_CLUB - ld [wLinkState], a - ld [wEnteringCableClub], a - jpab SpecialEnterMap -.choseCancel - xor a - ld [wMenuJoypadPollCount], a - call Delay3 - callab CloseLinkConnection - ld hl, ColosseumCanceledText - call PrintText - ld hl, wd72e - res 6, [hl] - ret - -.asm_f5963 - ld a,[wd11e] - and a - jr nz,.asm_f5974 - ld b," " - ld c," " - ld d,"▷" - ld e," " - call Func_f59ec -.asm_f5974 - xor a - ld [wBuffer], a - ld a,$ff - ld [wSerialExchangeNybbleReceiveData],a - ld a, $b - ld [wLinkMenuSelectionSendBuffer], a - ld b,$78 -.loop - ld a,[hSerialConnectionStatus] - cp $2 - call z,DelayFrame - dec b - jr z,.asm_f59b2 - call Serial_ExchangeNybble - call DelayFrame - ld a,[wSerialExchangeNybbleReceiveData] - inc a - jr z,.loop - ld b,$f -.loop2 - call DelayFrame - call Serial_ExchangeNybble - dec b - jr nz,.loop2 - ld b,$f -.loop3 - call DelayFrame - call Serial_SendZeroByte - dec b - jr nz,.loop3 - jr .asm_f59d6 - -.asm_f59b2 - xor a - ld [wUnknownSerialCounter],a - ld [wUnknownSerialCounter+1],a - ld a,[wd11e] - and a - jr z,.asm_f59cd - ld b," " - ld c," " - ld d," " - ld e,"▷" - call Func_f59ec - jp .choseCancel - -.asm_f59cd - ld hl,ColosseumVersionText - call PrintText - jp .choseCancel - -.asm_f59d6 - ld b," " - ld c," " - ld d,"▷" - ld e," " - call Func_f59ec - call Func_f531b - jp c,.choseCancel - ld a,$f0 - jp .next - -Func_f59ec:: - ld a, b - Coorda 6, 5 - ld a, c - Coorda 6, 7 - ld a, d - Coorda 6, 9 - ld a, e - Coorda 6, 11 - ld c, 40 - call DelayFrames - ret - -ColosseumWhereToText: - TX_FAR _ColosseumWhereToText - db "@" - -ColosseumPleaseWaitText: - TX_FAR _ColosseumPleaseWaitText - db "@" - -ColosseumCanceledText: - TX_FAR _ColosseumCanceledText - db "@" - -ColosseumVersionText: - TX_FAR _ColosseumVersionText - db "@" - -TextTerminator_f5a16: - db "@" - -TradeCenterText: - db "TRADE CENTER" - next "COLOSSEUM" - next "COLOSSEUM2" - next "CANCEL@" diff --git a/engine/menu/main_menu.asm b/engine/menu/main_menu.asm deleted file mode 100755 index ce27ebba..00000000 --- a/engine/menu/main_menu.asm +++ /dev/null @@ -1,297 +0,0 @@ -MainMenu: -; Check save file - call InitOptions - xor a - ld [wOptionsInitialized], a - inc a - ld [wSaveFileStatus], a - call CheckForPlayerNameInSRAM - jr nc, .mainMenuLoop - - predef LoadSAV - -.mainMenuLoop - ld c, 20 - call DelayFrames - xor a ; LINK_STATE_NONE - ld [wLinkState], a - ld hl, wPartyAndBillsPCSavedMenuItem - ld [hli], a - ld [hli], a - ld [hli], a - ld [hl], a - ld [wDefaultMap], a - ld hl, wd72e - res 6, [hl] - call ClearScreen - call RunDefaultPaletteCommand - call LoadTextBoxTilePatterns - call LoadFontTilePatterns - ld hl, wd730 - set 6, [hl] - ld a, [wSaveFileStatus] - cp 1 - jr z, .noSaveFile -; there's a save file - coord hl, 0, 0 - lb bc, 6, 13 - call TextBoxBorder - coord hl, 2, 2 - ld de, ContinueText - call PlaceString - jr .next2 -.noSaveFile - coord hl, 0, 0 - lb bc, 4, 13 - call TextBoxBorder - coord hl, 2, 2 - ld de, NewGameText - call PlaceString -.next2 - ld hl, wd730 - res 6, [hl] - call UpdateSprites - xor a - ld [wCurrentMenuItem], a - ld [wLastMenuItem], a - ld [wMenuJoypadPollCount], a - inc a - ld [wTopMenuItemX], a - inc a - ld [wTopMenuItemY], a - ld a, A_BUTTON | B_BUTTON | START - ld [wMenuWatchedKeys], a - ld a, [wSaveFileStatus] - ld [wMaxMenuItem], a - call HandleMenuInput - bit 1, a ; pressed B? - jp nz, DisplayTitleScreen ; if so, go back to the title screen - ld c, 20 - call DelayFrames - ld a, [wCurrentMenuItem] - ld b, a - ld a, [wSaveFileStatus] - cp 2 - jp z, .skipInc -; If there's no save file, increment the current menu item so that the numbers -; are the same whether or not there's a save file. - inc b -.skipInc - ld a, b - and a - jr z, .choseContinue - cp 1 - jp z, StartNewGame - call DisplayOptionMenu - ld a, 1 - ld [wOptionsInitialized], a - jp .mainMenuLoop -.choseContinue - call DisplayContinueGameInfo - ld hl, wCurrentMapScriptFlags - set 5, [hl] -.inputLoop - xor a - ld [hJoyPressed], a - ld [hJoyReleased], a - ld [hJoyHeld], a - call Joypad - ld a, [hJoyHeld] - bit 0, a - jr nz, .pressedA - bit 1, a - jp nz, .mainMenuLoop ; pressed B - jr .inputLoop -.pressedA - call GBPalWhiteOutWithDelay3 - call ClearScreen - ld a, PLAYER_DIR_DOWN - ld [wPlayerDirection], a - ld c, 10 - call DelayFrames - ld a, [wNumHoFTeams] - and a - jp z, SpecialEnterMap - ld a, [wCurMap] ; map ID - cp HALL_OF_FAME - jp nz, SpecialEnterMap - xor a - ld [wDestinationMap], a - ld hl, wd732 - set 2, [hl] ; fly warp or dungeon warp - call SpecialWarpIn - jp SpecialEnterMap - -InitOptions: - ld a, 1 ; no delay - ld [wLetterPrintingDelayFlags], a - ld a, 3 ; medium speed - ld [wOptions], a - ld a, 64 ; audio? - ld [wPrinterSettings], a - ret - -Func_5cc1: -; unused? - ld a, $6d - cp $80 - ret c ; will always be executed - ld hl, NotEnoughMemoryText - call PrintText - ret - -NotEnoughMemoryText: - TX_FAR _NotEnoughMemoryText - db "@" - -StartNewGame: - ld hl, wd732 - res 1, [hl] - call OakSpeech - ld a, $8 - ld [wPlayerMovingDirection], a - ld c, 20 - call DelayFrames - -; enter map after using a special warp or loading the game from the main menu -SpecialEnterMap: - xor a - ld [hJoyPressed], a - ld [hJoyHeld], a - ld [hJoy5], a - ld [wd72d], a - ld hl, wd732 - set 0, [hl] ; count play time - call ResetPlayerSpriteData - ld c, 20 - call DelayFrames - call Func_5cc1 - ld a, [wEnteringCableClub] - and a - ret nz - jp EnterMap - -ContinueText: - db "CONTINUE", $4e - -NewGameText: - db "NEW GAME" - next "OPTION@" - -DisplayContinueGameInfo: - xor a - ld [H_AUTOBGTRANSFERENABLED], a - coord hl, 4, 7 - lb bc, 8, 14 - call TextBoxBorder - coord hl, 5, 9 - ld de, SaveScreenInfoText - call PlaceString - coord hl, 12, 9 - ld de, wPlayerName - call PlaceString - coord hl, 17, 11 - call PrintNumBadges - coord hl, 16, 13 - call PrintNumOwnedMons - coord hl, 13, 15 - call PrintPlayTime - ld a, 1 - ld [H_AUTOBGTRANSFERENABLED], a - ld c, 30 - jp DelayFrames - -PrintSaveScreenText: - xor a - ld [H_AUTOBGTRANSFERENABLED], a - coord hl, 4, 0 - lb bc, 8, 14 - call TextBoxBorder - call LoadTextBoxTilePatterns - call UpdateSprites - coord hl, 5, 2 - ld de, SaveScreenInfoText - call PlaceString - coord hl, 12, 2 - ld de, wPlayerName - call PlaceString - coord hl, 17, 4 - call PrintNumBadges - coord hl, 16, 6 - call PrintNumOwnedMons - coord hl, 13, 8 - call PrintPlayTime - ld a, $1 - ld [H_AUTOBGTRANSFERENABLED], a - ld c, 30 - jp DelayFrames - -PrintNumBadges: - push hl - ld hl, wObtainedBadges - ld b, $1 - call CountSetBits - pop hl - ld de, wNumSetBits - lb bc, 1, 2 - jp PrintNumber - -PrintNumOwnedMons: - push hl - ld hl, wPokedexOwned - ld b, wPokedexOwnedEnd - wPokedexOwned - call CountSetBits - pop hl - ld de, wNumSetBits - lb bc, 1, 3 - jp PrintNumber - -PrintPlayTime: - ld de, wPlayTimeHours - lb bc, 1, 3 - call PrintNumber - ld [hl], $6d - inc hl - ld de, wPlayTimeMinutes - lb bc, LEADING_ZEROES | 1, 2 - jp PrintNumber - -SaveScreenInfoText: - db "PLAYER" - next "BADGES " - next "#DEX " - next "TIME@" - -DisplayOptionMenu: - callab DisplayOptionMenu_ - ret - -CheckForPlayerNameInSRAM: -; Check if the player name data in SRAM has a string terminator character -; (indicating that a name may have been saved there) and return whether it does -; in carry. - ld a, SRAM_ENABLE - ld [MBC1SRamEnable], a - ld a, $1 - ld [MBC1SRamBankingMode], a - ld [MBC1SRamBank], a - ld b, NAME_LENGTH - ld hl, sPlayerName -.loop - ld a, [hli] - cp "@" - jr z, .found - dec b - jr nz, .loop -; not found - xor a - ld [MBC1SRamEnable], a - ld [MBC1SRamBankingMode], a - and a - ret -.found - xor a - ld [MBC1SRamEnable], a - ld [MBC1SRamBankingMode], a - scf - ret diff --git a/engine/menu/naming_screen.asm b/engine/menu/naming_screen.asm deleted file mode 100755 index 2560677a..00000000 --- a/engine/menu/naming_screen.asm +++ /dev/null @@ -1,526 +0,0 @@ -AskName: - call SaveScreenTilesToBuffer1 - call GetPredefRegisters - push hl - ld a, [wIsInBattle] - dec a - coord hl, 0, 0 - lb bc, 4, 11 - call z, ClearScreenArea ; only if in wild battle - ld a, [wcf91] - ld [wd11e], a - call GetMonName - ld hl, DoYouWantToNicknameText - call PrintText - coord hl, 14, 7 - lb bc, 8, 15 - ld a, TWO_OPTION_MENU - ld [wTextBoxID], a - call DisplayTextBoxID - pop hl - ld a, [wCurrentMenuItem] - and a - jr nz, .declinedNickname - ld a, [wUpdateSpritesEnabled] - push af - xor a - ld [wUpdateSpritesEnabled], a - push hl - ld a, NAME_MON_SCREEN - ld [wNamingScreenType], a - call DisplayNamingScreen - ld a, [wIsInBattle] - and a - jr nz, .inBattle - call ReloadMapSpriteTilePatterns -.inBattle - call LoadScreenTilesFromBuffer1 - pop hl - pop af - ld [wUpdateSpritesEnabled], a - ld a, [wcf4b] - cp "@" - ret nz -.declinedNickname - ld d, h - ld e, l - ld hl, wcd6d - ld bc, NAME_LENGTH - jp CopyData - -DoYouWantToNicknameText: - TX_FAR _DoYouWantToNicknameText - db "@" - -DisplayNameRaterScreen: - ld hl, wBuffer - xor a - ld [wUpdateSpritesEnabled], a - ld a, NAME_MON_SCREEN - ld [wNamingScreenType], a - call DisplayNamingScreen - call GBPalWhiteOutWithDelay3 - call RestoreScreenTilesAndReloadTilePatterns - call LoadGBPal - ld a, [wcf4b] - cp "@" - jr z, .playerCancelled - ld hl, wPartyMonNicks - ld bc, NAME_LENGTH - ld a, [wWhichPokemon] - call AddNTimes - ld e, l - ld d, h - ld hl, wBuffer - ld bc, NAME_LENGTH - call CopyData - and a - ret -.playerCancelled - scf - ret - -DisplayNamingScreen: - push hl - ld hl, wd730 - set 6, [hl] - call GBPalWhiteOutWithDelay3 - call ClearScreen - call UpdateSprites - ld b, SET_PAL_GENERIC - call RunPaletteCommand - call LoadHpBarAndStatusTilePatterns - call LoadEDTile - callba LoadMonPartySpriteGfx - coord hl, 0, 4 - lb bc, 9, 18 - call TextBoxBorder - call PrintNamingText - ld a, 3 - ld [wTopMenuItemY], a - ld a, 1 - ld [wTopMenuItemX], a - ld [wLastMenuItem], a - ld [wCurrentMenuItem], a - ld a, $ff - ld [wMenuWatchedKeys], a - ld a, 7 - ld [wMaxMenuItem], a - ld a, "@" - ld [wcf4b], a - xor a - ld hl, wNamingScreenSubmitName - ld [hli], a - ld [hli], a - ld [wAnimCounter], a -.selectReturnPoint - call PrintAlphabet - call GBPalNormal -.ABStartReturnPoint - ld a, [wNamingScreenSubmitName] - and a - jr nz, .submitNickname - call PrintNicknameAndUnderscores -.dPadReturnPoint - call PlaceMenuCursor -.inputLoop - ld a, [wCurrentMenuItem] - push af - callba AnimatePartyMon_ForceSpeed1 - pop af - ld [wCurrentMenuItem], a - call JoypadLowSensitivity - ld a, [hJoyPressed] - and a - jr z, .inputLoop - ld hl, .namingScreenButtonFunctions -.checkForPressedButton - sla a - jr c, .foundPressedButton - inc hl - inc hl - inc hl - inc hl - jr .checkForPressedButton -.foundPressedButton - ld a, [hli] - ld e, a - ld a, [hli] - ld d, a - ld a, [hli] - ld h, [hl] - ld l, a - push de - jp hl - -.submitNickname - pop de - ld hl, wcf4b - ld bc, NAME_LENGTH - call CopyData - call GBPalWhiteOutWithDelay3 - call ClearScreen - call ClearSprites - call RunDefaultPaletteCommand - call GBPalNormal - xor a - ld [wAnimCounter], a - ld hl, wd730 - res 6, [hl] - ld a, [wIsInBattle] - and a - jp z, LoadTextBoxTilePatterns - jpab LoadHudTilePatterns - -.namingScreenButtonFunctions - dw .dPadReturnPoint - dw .pressedDown - dw .dPadReturnPoint - dw .pressedUp - dw .dPadReturnPoint - dw .pressedLeft - dw .dPadReturnPoint - dw .pressedRight - dw .ABStartReturnPoint - dw .pressedStart - dw .selectReturnPoint - dw .pressedSelect - dw .ABStartReturnPoint - dw .pressedB - dw .ABStartReturnPoint - dw .pressedA - -.pressedA_changedCase - pop de - ld de, .selectReturnPoint - push de -.pressedSelect - ld a, [wAlphabetCase] - xor $1 - ld [wAlphabetCase], a - ret - -.pressedStart - ld a, 1 - ld [wNamingScreenSubmitName], a - ret - -.pressedA - ld a, [wCurrentMenuItem] - cp $5 ; "ED" row - jr nz, .didNotPressED - ld a, [wTopMenuItemX] - cp $11 ; "ED" column - jr z, .pressedStart -.didNotPressED - ld a, [wCurrentMenuItem] - cp $6 ; case switch row - jr nz, .didNotPressCaseSwtich - ld a, [wTopMenuItemX] - cp $1 ; case switch column - jr z, .pressedA_changedCase -.didNotPressCaseSwtich - ld hl, wMenuCursorLocation - ld a, [hli] - ld h, [hl] - ld l, a - inc hl - ld a, [hl] - ld [wNamingScreenLetter], a - call CalcStringLength - ld a, [wNamingScreenLetter] - cp $e5 - ld de, Dakutens - jr z, .dakutensAndHandakutens - cp $e4 - ld de, Handakutens - jr z, .dakutensAndHandakutens - ld a, [wNamingScreenType] - cp NAME_MON_SCREEN - jr nc, .checkMonNameLength - ld a, [wNamingScreenNameLength] - cp $7 ; max length of player/rival names - jr .checkNameLength -.checkMonNameLength - ld a, [wNamingScreenNameLength] - cp $a ; max length of pokemon nicknames -.checkNameLength - jr c, .addLetter - ret - -.dakutensAndHandakutens - push hl - call DakutensAndHandakutens - pop hl - ret nc - dec hl -.addLetter - ld a, [wNamingScreenLetter] - ld [hli], a - ld [hl], "@" - ld a, SFX_PRESS_AB - call PlaySound - ret -.pressedB - ld a, [wNamingScreenNameLength] - and a - ret z - call CalcStringLength - dec hl - ld [hl], "@" - ret -.pressedRight - ld a, [wCurrentMenuItem] - cp $6 - ret z ; can't scroll right on bottom row - ld a, [wTopMenuItemX] - cp $11 ; max - jp z, .wrapToFirstColumn - inc a - inc a - jr .done -.wrapToFirstColumn - ld a, $1 - jr .done -.pressedLeft - ld a, [wCurrentMenuItem] - cp $6 - ret z ; can't scroll right on bottom row - ld a, [wTopMenuItemX] - dec a - jp z, .wrapToLastColumn - dec a - jr .done -.wrapToLastColumn - ld a, $11 ; max - jr .done -.pressedUp - ld a, [wCurrentMenuItem] - dec a - ld [wCurrentMenuItem], a - and a - ret nz - ld a, $6 ; wrap to bottom row - ld [wCurrentMenuItem], a - ld a, $1 ; force left column - jr .done -.pressedDown - ld a, [wCurrentMenuItem] - inc a - ld [wCurrentMenuItem], a - cp $7 - jr nz, .wrapToTopRow - ld a, $1 - ld [wCurrentMenuItem], a - jr .done -.wrapToTopRow - cp $6 - ret nz - ld a, $1 -.done - ld [wTopMenuItemX], a - jp EraseMenuCursor - -LoadEDTile: -; In Red/Blue, the bank for the ED_tile was defined incorrectly as bank0 -; Luckily, the MBC3 treats loading $0 into $2000-$2fff range as loading bank1 into $4000-$7fff range -; Because Yellow uses the MBC5, loading $0 into $2000 - $2fff range will load bank0 instead of bank1 and thus incorrectly load the tile -; Instead of defining the correct bank, GameFreak decided to simply copy the ED_Tile in the function during HBlank - ld de, ED_Tile - ld hl, vFont + $700 - ld c, $4 ; number of copies needed -.waitForHBlankLoop - ld a, [rSTAT] - and %10 ; in HBlank? - jr nz, .waitForHBlankLoop - ld a, [de] - ld [hli], a - ld [hli], a - inc de - ld a, [de] - ld [hli], a - ld [hli], a - inc de - dec c - jr nz, .waitForHBlankLoop - ret - -ED_Tile: - INCBIN "gfx/ED_tile.1bpp" -ED_TileEnd: - -PrintAlphabet: - xor a - ld [H_AUTOBGTRANSFERENABLED], a - ld a, [wAlphabetCase] - and a - ld de, LowerCaseAlphabet - jr nz, .lowercase - ld de, UpperCaseAlphabet -.lowercase - coord hl, 2, 5 - lb bc, 5, 9 ; 5 rows, 9 columns -.outerLoop - push bc -.innerLoop - ld a, [de] - ld [hli], a - inc hl - inc de - dec c - jr nz, .innerLoop - ld bc, SCREEN_WIDTH + 2 - add hl, bc - pop bc - dec b - jr nz, .outerLoop - call PlaceString - ld a, $1 - ld [H_AUTOBGTRANSFERENABLED], a - jp Delay3 - -LowerCaseAlphabet: - db "abcdefghijklmnopqrstuvwxyz ×():;[]",$e1,$e2,"-?!♂♀/⠄,¥UPPER CASE@" - -UpperCaseAlphabet: - db "ABCDEFGHIJKLMNOPQRSTUVWXYZ ×():;[]",$e1,$e2,"-?!♂♀/⠄,¥lower case@" - -PrintNicknameAndUnderscores: - call CalcStringLength - ld a, c - ld [wNamingScreenNameLength], a - coord hl, 10, 2 - lb bc, 1, 10 - call ClearScreenArea - coord hl, 10, 2 - ld de, wcf4b - call PlaceString - coord hl, 10, 3 - ld a, [wNamingScreenType] - cp NAME_MON_SCREEN - jr nc, .pokemon1 - ld b, 7 ; player or rival max name length - jr .playerOrRival1 -.pokemon1 - ld b, 10 ; pokemon max name length -.playerOrRival1 - ld a, $76 ; underscore tile id -.placeUnderscoreLoop - ld [hli], a - dec b - jr nz, .placeUnderscoreLoop - ld a, [wNamingScreenType] - cp NAME_MON_SCREEN - ld a, [wNamingScreenNameLength] - jr nc, .pokemon2 - cp 7 ; player or rival max name length - jr .playerOrRival2 -.pokemon2 - cp 10 ; pokemon max name length -.playerOrRival2 - jr nz, .emptySpacesRemaining - ; when all spaces are filled, force the cursor onto the ED tile - call EraseMenuCursor - ld a, $11 ; "ED" x coord - ld [wTopMenuItemX], a - ld a, $5 ; "ED" y coord - ld [wCurrentMenuItem], a - ld a, [wNamingScreenType] - cp NAME_MON_SCREEN - ld a, 9 ; keep the last underscore raised - jr nc, .pokemon3 - ld a, 6 ; keep the last underscore raised -.pokemon3 -.emptySpacesRemaining - ld c, a - ld b, $0 - coord hl, 10, 3 - add hl, bc - ld [hl], $77 ; raised underscore tile id - ret - -DakutensAndHandakutens: - push de - call CalcStringLength - dec hl - ld a, [hl] - pop hl - ld de, $2 - call IsInArray - ret nc - inc hl - ld a, [hl] - ld [wNamingScreenLetter], a - ret - -Dakutens: - db "かが", "きぎ", "くぐ", "けげ", "こご" - db "さざ", "しじ", "すず", "せぜ", "そぞ" - db "ただ", "ちぢ", "つづ", "てで", "とど" - db "はば", "ひび", "ふぶ", "へべ", "ほぼ" - db "カガ", "キギ", "クグ", "ケゲ", "コゴ" - db "サザ", "シジ", "スズ", "セゼ", "ソゾ" - db "タダ", "チヂ", "ツヅ", "テデ", "トド" - db "ハバ", "ヒビ", "フブ", "へべ", "ホボ" - db $ff - -Handakutens: - db "はぱ", "ひぴ", "ふぷ", "へぺ", "ほぽ" - db "ハパ", "ヒピ", "フプ", "へぺ", "ホポ" - db $ff - -; calculates the length of the string at wcf4b and stores it in c -CalcStringLength: - ld hl, wcf4b - ld c, $0 -.loop - ld a, [hl] - cp "@" - ret z - inc hl - inc c - jr .loop - -PrintNamingText: - coord hl, 0, 1 - ld a, [wNamingScreenType] - ld de, YourTextString - and a - jr z, .notNickname - ld de, RivalsTextString - dec a - jr z, .notNickname - ld a, [wcf91] - ld [wMonPartySpriteSpecies], a - push af - callba WriteMonPartySpriteOAMBySpecies - pop af - ld [wd11e], a - call GetMonName - coord hl, 4, 1 - call PlaceString - ld hl, $1 - add hl, bc - ld [hl], $c9 - coord hl, 1, 3 - ld de, NicknameTextString - jr .placeString -.notNickname - call PlaceString - ld l, c - ld h, b - ld de, NameTextString -.placeString - jp PlaceString - -YourTextString: - db "YOUR @" - -RivalsTextString: - db "RIVAL's @" - -NameTextString: - db "NAME?@" - -NicknameTextString: - db "NICKNAME?@" diff --git a/engine/menu/oaks_pc.asm b/engine/menu/oaks_pc.asm deleted file mode 100755 index 03c9b8f1..00000000 --- a/engine/menu/oaks_pc.asm +++ /dev/null @@ -1,28 +0,0 @@ -OpenOaksPC: - call SaveScreenTilesToBuffer2 - ld hl, AccessedOaksPCText - call PrintText - ld hl, GetDexRatedText - call PrintText - call YesNoChoice - ld a, [wCurrentMenuItem] - and a - jr nz, .closePC - predef DisplayDexRating -.closePC - ld hl, ClosedOaksPCText - call PrintText - jp LoadScreenTilesFromBuffer2 - -GetDexRatedText: - TX_FAR _GetDexRatedText - db "@" - -ClosedOaksPCText: - TX_FAR _ClosedOaksPCText - TX_WAIT - db "@" - -AccessedOaksPCText: - TX_FAR _AccessedOaksPCText - db "@" diff --git a/engine/menu/options.asm b/engine/menu/options.asm deleted file mode 100644 index da89ad82..00000000 --- a/engine/menu/options.asm +++ /dev/null @@ -1,443 +0,0 @@ -DisplayOptionMenu_: - call InitOptionsMenu -.optionMenuLoop - call JoypadLowSensitivity - ld a, [hJoy5] - and START | B_BUTTON - jr nz, .exitOptionMenu - call OptionsControl - jr c, .dpadDelay - call GetOptionPointer - jr c, .exitOptionMenu -.dpadDelay - call OptionsMenu_UpdateCursorPosition - call DelayFrame - call DelayFrame - call DelayFrame - jr .optionMenuLoop -.exitOptionMenu - ret - -GetOptionPointer: - ld a, [wOptionsCursorLocation] - ld e, a - ld d, $0 - ld hl, OptionMenuJumpTable - add hl, de - add hl, de - ld a, [hli] - ld h, [hl] - ld l, a - jp hl ; jump to the function for the current highlighted option - -OptionMenuJumpTable: - dw OptionsMenu_TextSpeed - dw OptionsMenu_BattleAnimations - dw OptionsMenu_BattleStyle - dw OptionsMenu_SpeakerSettings - dw OptionsMenu_GBPrinterBrightness - dw OptionsMenu_Dummy - dw OptionsMenu_Dummy - dw OptionsMenu_Cancel - -OptionsMenu_TextSpeed: - call GetTextSpeed - ld a, [hJoy5] - bit 4, a ; right - jr nz, .pressedRight - bit 5, a - jr nz, .pressedLeft - jr .asm_41ce0 -.pressedRight - ld a, c - cp $2 - jr c, .asm_41cca - ld c, $ff -.asm_41cca - inc c - ld a, e - jr .asm_41cd6 -.pressedLeft - ld a, c - and a - jr nz, .asm_41cd4 - ld c, $3 -.asm_41cd4 - dec c - ld a, d -.asm_41cd6 - ld b, a - ld a, [wOptions] - and $f0 - or b - ld [wOptions], a -.asm_41ce0 - ld b, $0 - ld hl, TextSpeedStringsPointerTable - add hl, bc - add hl, bc - ld e, [hl] - inc hl - ld d, [hl] - coord hl, 14, 2 - call PlaceString - and a - ret - -TextSpeedStringsPointerTable: - dw FastText - dw MidText - dw SlowText - -FastText: - db "FAST@" -MidText: - db "MID @" -SlowText: - db "SLOW@" - -GetTextSpeed: - ld a, [wOptions] - and $f - cp $5 - jr z, .slowTextOption - cp $1 - jr z, .fastTextOption -; mid text option - ld c, $1 - lb de, 1, 5 - ret -.slowTextOption - ld c, $2 - lb de, 3, 1 - ret -.fastTextOption - ld c, $0 - lb de, 5, 3 - ret - -OptionsMenu_BattleAnimations: - ld a, [hJoy5] - and D_RIGHT | D_LEFT - jr nz, .asm_41d33 - ld a, [wOptions] - and $80 ; mask other bits - jr .asm_41d3b -.asm_41d33 - ld a, [wOptions] - xor $80 - ld [wOptions], a -.asm_41d3b - ld bc, $0 - sla a - rl c - ld hl, AnimationOptionStringsPointerTable - add hl, bc - add hl, bc - ld e, [hl] - inc hl - ld d, [hl] - coord hl, 14, 4 - call PlaceString - and a - ret - -AnimationOptionStringsPointerTable: - dw AnimationOnText - dw AnimationOffText - -AnimationOnText: - db "ON @" -AnimationOffText: - db "OFF@" - -OptionsMenu_BattleStyle: - ld a, [hJoy5] - and D_LEFT | D_RIGHT - jr nz, .asm_41d6b - ld a, [wOptions] - and $40 ; mask other bits - jr .asm_41d73 -.asm_41d6b - ld a, [wOptions] - xor $40 - ld [wOptions], a -.asm_41d73 - ld bc, $0 - sla a - sla a - rl c - ld hl, BattleStyleOptionStringsPointerTable - add hl, bc - add hl, bc - ld e, [hl] - inc hl - ld d, [hl] - coord hl, 14, 6 - call PlaceString - and a - ret - -BattleStyleOptionStringsPointerTable: - dw BattleStyleShiftText - dw BattleStyleSetText - -BattleStyleShiftText: - db "SHIFT@" -BattleStyleSetText: - db "SET @" - -OptionsMenu_SpeakerSettings: - ld a, [wOptions] - and $30 - swap a - ld c, a - ld a, [hJoy5] - bit 4, a - jr nz, .pressedRight - bit 5, a - jr nz, .pressedLeft - jr .asm_41dca -.pressedRight - ld a, c - inc a - and $3 - jr .asm_41dba -.pressedLeft - ld a, c - dec a - and $3 -.asm_41dba - ld c, a - swap a - ld b, a - xor a - ld [rNR51], a - ld a, [wOptions] - and $cf - or b - ld [wOptions], a -.asm_41dca - ld b, $0 - ld hl, SpeakerOptionStringsPointerTable - add hl, bc - add hl, bc - ld e, [hl] - inc hl - ld d, [hl] - coord hl, 8, 8 - call PlaceString - and a - ret - -SpeakerOptionStringsPointerTable: - dw MonoSoundText - dw Earphone1SoundText - dw Earphone2SoundText - dw Earphone3SoundText - -MonoSoundText: - db "MONO @" -Earphone1SoundText: - db "EARPHONE1@" -Earphone2SoundText: - db "EARPHONE2@" -Earphone3SoundText: - db "EARPHONE3@" - -OptionsMenu_GBPrinterBrightness: - call Func_41e7b - ld a, [hJoy5] - bit 4, a - jr nz, .pressedRight - bit 5, a - jr nz, .pressedLeft - jr .asm_41e32 -.pressedRight - ld a, c - cp $4 - jr c, .asm_41e22 - ld c, $ff -.asm_41e22 - inc c - ld a, e - jr .asm_41e2e -.pressedLeft - ld a, c - and a - jr nz, .asm_41e2c - ld c, $5 -.asm_41e2c - dec c - ld a, d -.asm_41e2e - ld b, a - ld [wPrinterSettings], a -.asm_41e32 - ld b, $0 - ld hl, GBPrinterOptionStringsPointerTable - add hl, bc - add hl, bc - ld e, [hl] - inc hl - ld d, [hl] - coord hl, 8, 10 - call PlaceString - and a - ret - -GBPrinterOptionStringsPointerTable: - dw LightestPrintText - dw LighterPrintText - dw NormalPrintText - dw DarkerPrintText - dw DarkestPrintText - -LightestPrintText: - db "LIGHTEST@" -LighterPrintText: - db "LIGHTER @" -NormalPrintText: - db "NORMAL @" -DarkerPrintText: - db "DARKER @" -DarkestPrintText: - db "DARKEST @" - -Func_41e7b: - ld a, [wPrinterSettings] - and a - jr z, .asm_41e93 - cp $20 - jr z, .asm_41e99 - cp $60 - jr z, .asm_41e9f - cp $7f - jr z, .asm_41ea5 - ld c, $2 - lb de, $20, $60 - ret -.asm_41e93 - ld c, $0 - lb de, $7f, $20 - ret -.asm_41e99 - ld c, $1 - lb de, $0, $40 - ret -.asm_41e9f - ld c, $3 - lb de, $40, $7f - ret -.asm_41ea5 - ld c, $4 - lb de, $60, $0 - ret - -OptionsMenu_Dummy: - and a - ret - -OptionsMenu_Cancel: - ld a, [hJoy5] - and A_BUTTON - jr nz, .pressedCancel - and a - ret -.pressedCancel - scf - ret - -OptionsControl: - ld hl, wOptionsCursorLocation - ld a, [hJoy5] - cp D_DOWN - jr z, .pressedDown - cp D_UP - jr z, .pressedUp - and a - ret -.pressedDown - ld a, [hl] - cp $7 - jr nz, .doNotWrapAround - ld [hl], $0 - scf - ret -.doNotWrapAround - cp $4 - jr c, .regularIncrement - ld [hl], $6 -.regularIncrement - inc [hl] - scf - ret -.pressedUp - ld a, [hl] - cp $7 - jr nz, .doNotMoveCursorToPrintOption - ld [hl], $4 - scf - ret -.doNotMoveCursorToPrintOption - and a - jr nz, .regularDecrement - ld [hl], $8 -.regularDecrement - dec [hl] - scf - ret - -OptionsMenu_UpdateCursorPosition: - coord hl, 1, 1 - ld de, SCREEN_WIDTH - ld c, 16 -.loop - ld [hl], " " - add hl, de - dec c - jr nz, .loop - coord hl, 1, 2 - ld bc, SCREEN_WIDTH * 2 - ld a, [wOptionsCursorLocation] - call AddNTimes - ld [hl], "▶" - ret - -InitOptionsMenu: - coord hl, 0, 0 - lb bc, SCREEN_HEIGHT - 2, SCREEN_WIDTH - 2 - call TextBoxBorder - coord hl, 2, 2 - ld de, AllOptionsText - call PlaceString - coord hl, 2, 16 - ld de, OptionMenuCancelText - call PlaceString - xor a - ld [wOptionsCursorLocation], a - ld c, 5 ; the number of options to loop through -.loop - push bc - call GetOptionPointer ; updates the next option - pop bc - ld hl, wOptionsCursorLocation - inc [hl] ; moves the cursor for the highlighted option - dec c - jr nz, .loop - xor a - ld [wOptionsCursorLocation], a - inc a - ld [H_AUTOBGTRANSFERENABLED], a - call Delay3 - ret - -AllOptionsText: - db "TEXT SPEED :" - next "ANIMATION :" - next "BATTLESTYLE:" - next "SOUND:" - next "PRINT:@" - -OptionMenuCancelText: - db "CANCEL@" diff --git a/engine/menu/party_menu.asm b/engine/menu/party_menu.asm deleted file mode 100755 index 00c757be..00000000 --- a/engine/menu/party_menu.asm +++ /dev/null @@ -1,333 +0,0 @@ -; [wPartyMenuTypeOrMessageID] = menu type / message ID -; if less than $F0, it is a menu type -; menu types: -; 00: normal pokemon menu (e.g. Start menu) -; 01: use healing item on pokemon menu -; 02: in-battle switch pokemon menu -; 03: learn TM/HM menu -; 04: swap pokemon positions menu -; 05: use evolution stone on pokemon menu -; otherwise, it is a message ID -; f0: poison healed -; f1: burn healed -; f2: freeze healed -; f3: sleep healed -; f4: paralysis healed -; f5: HP healed -; f6: health returned -; f7: revitalized -; f8: leveled up -DrawPartyMenu_: - xor a - ld [H_AUTOBGTRANSFERENABLED], a - call ClearScreen - call UpdateSprites - callba LoadMonPartySpriteGfxWithLCDDisabled ; load pokemon icon graphics - -RedrawPartyMenu_: - ld a, [wPartyMenuTypeOrMessageID] - cp SWAP_MONS_PARTY_MENU - jp z, .printMessage - call ErasePartyMenuCursors - callba InitPartyMenuBlkPacket - coord hl, 3, 0 - ld de, wPartySpecies - xor a - ld c, a - ld [hPartyMonIndex], a - ld [wWhichPartyMenuHPBar], a -.loop - ld a, [de] - cp $FF ; reached the terminator? - jp z, .afterDrawingMonEntries - push bc - push de - push hl - ld a, c - push hl - ld hl, wPartyMonNicks - call GetPartyMonName - pop hl - call PlaceString ; print the pokemon's name - ld a, [hPartyMonIndex] - ld [wWhichPokemon], a - callab IsThisPartymonStarterPikachu_Party - jr nc, .regularMon - call CheckPikachuFollowingPlayer - jr z, .regularMon - ld a, $ff - ld [hPartyMonIndex], a -.regularMon - callba WriteMonPartySpriteOAMByPartyIndex ; place the appropriate pokemon icon - ld a, [wWhichPokemon] - inc a - ld [hPartyMonIndex], a - call LoadMonData - pop hl - push hl - ld a, [wMenuItemToSwap] - and a ; is the player swapping pokemon positions? - jr z, .skipUnfilledRightArrow -; if the player is swapping pokemon positions - dec a - ld b, a - ld a, [wWhichPokemon] - cp b ; is the player swapping the current pokemon in the list? - jr nz, .skipUnfilledRightArrow -; the player is swapping the current pokemon in the list - dec hl - dec hl - dec hl - ld a, "▷" ; unfilled right arrow menu cursor - ld [hli], a ; place the cursor - inc hl - inc hl -.skipUnfilledRightArrow - ld a, [wPartyMenuTypeOrMessageID] ; menu type - cp TMHM_PARTY_MENU - jr z, .teachMoveMenu - cp EVO_STONE_PARTY_MENU - jr z, .evolutionStoneMenu - push hl - ld bc, 14 ; 14 columns to the right - add hl, bc - ld de, wLoadedMonStatus - call PrintStatusCondition - pop hl - push hl - ld bc, SCREEN_WIDTH + 1 ; down 1 row and right 1 column - ld a, [hFlags_0xFFFA] - set 0, a - ld [hFlags_0xFFFA], a - add hl, bc - predef DrawHP2 ; draw HP bar and prints current / max HP - ld a, [hFlags_0xFFFA] - res 0, a - ld [hFlags_0xFFFA], a - call SetPartyMenuHPBarColor ; color the HP bar (on SGB) - pop hl - jr .printLevel -.teachMoveMenu - push hl - predef CanLearnTM ; check if the pokemon can learn the move - pop hl - ld de, .ableToLearnMoveText - ld a, c - and a - jr nz, .placeMoveLearnabilityString - ld de, .notAbleToLearnMoveText -.placeMoveLearnabilityString - push hl - ld bc, 20 + 9 ; down 1 row and right 9 columns - add hl, bc - call PlaceString - pop hl -.printLevel - ld bc, 10 ; move 10 columns to the right - add hl, bc - call PrintLevel - pop hl - pop de - inc de - ld bc, 2 * 20 - add hl, bc - pop bc - inc c - jp .loop -.ableToLearnMoveText - db "ABLE@" -.notAbleToLearnMoveText - db "NOT ABLE@" -.evolutionStoneMenu - push hl - ld hl, EvosMovesPointerTable - ld b, 0 - ld a, [wLoadedMonSpecies] - dec a - add a - rl b - ld c, a - add hl, bc - ld de, wEvosMoves - ld a, BANK(EvosMovesPointerTable) - ld bc, 2 - call FarCopyData - ld hl, wEvosMoves - ld a, [hli] - ld h, [hl] - ld l, a - ld de, wEvosMoves - ld a, BANK(EvosMovesPointerTable) - ld bc, wEvosMoves.end - wEvosMoves - call FarCopyData - ld hl, wEvosMoves - ld de, .notAbleToEvolveText -; loop through the pokemon's evolution entries -.checkEvolutionsLoop - ld a, [hli] - and a ; reached terminator? - jr z, .placeEvolutionStoneString ; if so, place the "NOT ABLE" string - inc hl - inc hl - cp EV_ITEM - jr nz, .checkEvolutionsLoop -; if it's a stone evolution entry - dec hl - dec hl - ld b, [hl] - ld a, [wEvoStoneItemID] ; the stone the player used - inc hl - inc hl - inc hl - cp b ; does the player's stone match this evolution entry's stone? - jr nz, .checkEvolutionsLoop -; if it does match - ld de, .ableToEvolveText -.placeEvolutionStoneString - pop hl - push hl - ld bc, 20 + 9 ; down 1 row and right 9 columns - add hl, bc - call PlaceString - pop hl - jr .printLevel -.ableToEvolveText - db "ABLE@" -.notAbleToEvolveText - db "NOT ABLE@" -.afterDrawingMonEntries - ld b, SET_PAL_PARTY_MENU - call RunPaletteCommand -.printMessage - ld hl, wd730 - ld a, [hl] - push af - push hl - set 6, [hl] ; turn off letter printing delay - ld a, [wPartyMenuTypeOrMessageID] ; message ID - cp $F0 - jr nc, .printItemUseMessage - add a - ld hl, PartyMenuMessagePointers - ld b, 0 - ld c, a - add hl, bc - ld a, [hli] - ld h, [hl] - ld l, a - call PrintText -.done - pop hl - pop af - ld [hl], a - ld a, 1 - ld [H_AUTOBGTRANSFERENABLED], a - call Delay3 - jp GBPalNormal -.printItemUseMessage - and $0F - ld hl, PartyMenuItemUseMessagePointers - add a - ld c, a - ld b, 0 - add hl, bc - ld a, [hli] - ld h, [hl] - ld l, a - push hl - ld a, [wUsedItemOnWhichPokemon] - ld hl, wPartyMonNicks - call GetPartyMonName - pop hl - call PrintText - jr .done - -PartyMenuItemUseMessagePointers: - dw AntidoteText - dw BurnHealText - dw IceHealText - dw AwakeningText - dw ParlyzHealText - dw PotionText - dw FullHealText - dw ReviveText - dw RareCandyText - -PartyMenuMessagePointers: - dw PartyMenuNormalText - dw PartyMenuItemUseText - dw PartyMenuBattleText - dw PartyMenuUseTMText - dw PartyMenuSwapMonText - dw PartyMenuItemUseText - -PartyMenuNormalText: - TX_FAR _PartyMenuNormalText - db "@" - -PartyMenuItemUseText: - TX_FAR _PartyMenuItemUseText - db "@" - -PartyMenuBattleText: - TX_FAR _PartyMenuBattleText - db "@" - -PartyMenuUseTMText: - TX_FAR _PartyMenuUseTMText - db "@" - -PartyMenuSwapMonText: - TX_FAR _PartyMenuSwapMonText - db "@" - -PotionText: - TX_FAR _PotionText - db "@" - -AntidoteText: - TX_FAR _AntidoteText - db "@" - -ParlyzHealText: - TX_FAR _ParlyzHealText - db "@" - -BurnHealText: - TX_FAR _BurnHealText - db "@" - -IceHealText: - TX_FAR _IceHealText - db "@" - -AwakeningText: - TX_FAR _AwakeningText - db "@" - -FullHealText: - TX_FAR _FullHealText - db "@" - -ReviveText: - TX_FAR _ReviveText - db "@" - -RareCandyText: - TX_FAR _RareCandyText - TX_SFX_ITEM_1 ; probably supposed to play SFX_LEVEL_UP but the wrong music bank is loaded - TX_BLINK - db "@" - -SetPartyMenuHPBarColor: - ld hl, wPartyMenuHPBarColors - ld a, [wWhichPartyMenuHPBar] - ld c, a - ld b, 0 - add hl, bc - call GetHealthBarColor - ld b, UPDATE_PARTY_MENU_BLK_PACKET - call RunPaletteCommand - ld hl, wWhichPartyMenuHPBar - inc [hl] - ret diff --git a/engine/menu/pc.asm b/engine/menu/pc.asm deleted file mode 100755 index 5639bd99..00000000 --- a/engine/menu/pc.asm +++ /dev/null @@ -1,141 +0,0 @@ -ActivatePC: - call SaveScreenTilesToBuffer2 - ld a, SFX_TURN_ON_PC - call PlaySound - ld hl, TurnedOnPC1Text - call PrintText - call WaitForSoundToFinish - ld hl, wFlags_0xcd60 - set 3, [hl] - call LoadScreenTilesFromBuffer2 - call Delay3 -PCMainMenu: - callba DisplayPCMainMenu - ld hl, wFlags_0xcd60 - set 5, [hl] - call HandleMenuInput - bit 1, a ;if player pressed B - jp nz, LogOff - ld a, [wMaxMenuItem] - cp 2 - jr nz, .next ;if not 2 menu items (not counting log off) (2 occurs before you get the pokedex) - ld a, [wCurrentMenuItem] - and a - jp z, BillsPC ;if current menu item id is 0, it's bills pc - cp 1 - jr z, .playersPC ;if current menu item id is 1, it's players pc - jp LogOff ;otherwise, it's 2, and you're logging off -.next - cp 3 - jr nz, .next2 ;if not 3 menu items (not counting log off) (3 occurs after you get the pokedex, before you beat the pokemon league) - ld a, [wCurrentMenuItem] - and a - jp z, BillsPC ;if current menu item id is 0, it's bills pc - cp 1 - jr z, .playersPC ;if current menu item id is 1, it's players pc - cp 2 - jp z, OaksPC ;if current menu item id is 2, it's oaks pc - jp LogOff ;otherwise, it's 3, and you're logging off -.next2 - ld a, [wCurrentMenuItem] - and a - jp z, BillsPC ;if current menu item id is 0, it's bills pc - cp 1 - jr z, .playersPC ;if current menu item id is 1, it's players pc - cp 2 - jp z, OaksPC ;if current menu item id is 2, it's oaks pc - cp 3 - jp z, PKMNLeague ;if current menu item id is 3, it's pkmnleague - jp LogOff ;otherwise, it's 4, and you're logging off -.playersPC - ld hl, wFlags_0xcd60 - res 5, [hl] - set 3, [hl] - ld a, SFX_ENTER_PC - call PlaySound - call WaitForSoundToFinish - ld hl, AccessedMyPCText - call PrintText - callba PlayerPC - jr ReloadMainMenu -OaksPC: - ld a, SFX_ENTER_PC - call PlaySound - call WaitForSoundToFinish - callba OpenOaksPC - jr ReloadMainMenu -PKMNLeague: - ld a, SFX_ENTER_PC - call PlaySound - call WaitForSoundToFinish - callba PKMNLeaguePC - jr ReloadMainMenu -BillsPC: - ld a, SFX_ENTER_PC - call PlaySound - call WaitForSoundToFinish - CheckEvent EVENT_MET_BILL - jr nz, .billsPC ;if you've met bill, use that bill's instead of someone's - ld hl, AccessedSomeonesPCText - jr .printText -.billsPC - ld hl, AccessedBillsPCText -.printText - call PrintText - callba BillsPC_ -ReloadMainMenu: - xor a - ld [wDoNotWaitForButtonPressAfterDisplayingText], a - call ReloadMapData - call UpdateSprites - jp PCMainMenu -LogOff: - ld a, SFX_TURN_OFF_PC - call PlaySound - call WaitForSoundToFinish - ld hl, wFlags_0xcd60 - res 3, [hl] - res 5, [hl] - ret - -TurnedOnPC1Text: - TX_FAR _TurnedOnPC1Text - db "@" - -AccessedBillsPCText: - TX_FAR _AccessedBillsPCText - db "@" - -AccessedSomeonesPCText: - TX_FAR _AccessedSomeonesPCText - db "@" - -AccessedMyPCText: - TX_FAR _AccessedMyPCText - db "@" - -; removes one of the specified item ID [hItemToRemoveID] from bag (if existent) -RemoveItemByID: - ld hl, wBagItems - ld a, [hItemToRemoveID] - ld b, a - xor a - ld [hItemToRemoveIndex], a -.loop - ld a, [hli] - cp -1 ; reached terminator? - ret z - cp b - jr z, .foundItem - inc hl - ld a, [hItemToRemoveIndex] - inc a - ld [hItemToRemoveIndex], a - jr .loop -.foundItem - ld a, $1 - ld [wItemQuantity], a - ld a, [hItemToRemoveIndex] - ld [wWhichPokemon], a - ld hl, wNumBagItems - jp RemoveItemFromInventory diff --git a/engine/menu/players_pc.asm b/engine/menu/players_pc.asm deleted file mode 100755 index 1cc02cbf..00000000 --- a/engine/menu/players_pc.asm +++ /dev/null @@ -1,302 +0,0 @@ -PlayerPC: - ld a, ITEM_NAME - ld [wNameListType], a - call SaveScreenTilesToBuffer1 - xor a - ld [wBagSavedMenuItem], a - ld [wParentMenuItem], a - ld a, [wFlags_0xcd60] - bit 3, a ; accessing player's PC through another PC? - jr nz, PlayerPCMenu -; accessing it directly - ld a, SFX_TURN_ON_PC - call PlaySound - ld hl, TurnedOnPC2Text - call PrintText - -PlayerPCMenu: - ld hl, wd730 - set 6, [hl] - ld a, [wParentMenuItem] - ld [wCurrentMenuItem], a - ld hl, wFlags_0xcd60 - set 5, [hl] - call LoadScreenTilesFromBuffer2 - coord hl, 0, 0 - lb bc, 8, 14 - call TextBoxBorder - call UpdateSprites - coord hl, 2, 2 - ld de, PlayersPCMenuEntries - call PlaceString - ld hl, wTopMenuItemY - ld a, 2 - ld [hli], a ; wTopMenuItemY - dec a - ld [hli], a ; wTopMenuItemX - inc hl - inc hl - ld a, 3 - ld [hli], a ; wMaxMenuItem - ld a, A_BUTTON | B_BUTTON - ld [hli], a ; wMenuWatchedKeys - xor a - ld [hl], a - ld hl, wListScrollOffset - ld [hli], a ; wListScrollOffset - ld [hl], a ; wMenuWatchMovingOutOfBounds - ld [wPlayerMonNumber], a - ld hl, WhatDoYouWantText - call PrintText - call HandleMenuInput - bit 1, a - jp nz, ExitPlayerPC - call PlaceUnfilledArrowMenuCursor - ld a, [wCurrentMenuItem] - ld [wParentMenuItem], a - and a - jp z, PlayerPCWithdraw - dec a - jp z, PlayerPCDeposit - dec a - jp z, PlayerPCToss - -ExitPlayerPC: - ld a, [wFlags_0xcd60] - bit 3, a ; accessing player's PC through another PC? - jr nz, .next -; accessing it directly - ld a, SFX_TURN_OFF_PC - call PlaySound - call WaitForSoundToFinish -.next - ld hl, wFlags_0xcd60 - res 5, [hl] - call LoadScreenTilesFromBuffer2 - xor a - ld [wListScrollOffset], a - ld [wBagSavedMenuItem], a - ld hl, wd730 - res 6, [hl] - xor a - ld [wDoNotWaitForButtonPressAfterDisplayingText], a - ret - -PlayerPCDeposit: - xor a - ld [wCurrentMenuItem], a - ld [wListScrollOffset], a - ld a, [wNumBagItems] - and a - jr nz, .loop - ld hl, NothingToDepositText - call PrintText - jp PlayerPCMenu -.loop - ld hl, WhatToDepositText - call PrintText - ld hl, wNumBagItems - ld a, l - ld [wListPointer], a - ld a, h - ld [wListPointer + 1], a - xor a - ld [wPrintItemPrices], a - ld a, ITEMLISTMENU - ld [wListMenuID], a - call DisplayListMenuID - jp c, PlayerPCMenu - call IsKeyItem - ld a, 1 - ld [wItemQuantity], a - ld a, [wIsKeyItem] - and a - jr nz, .next -; if it's not a key item, there can be more than one of the item - ld hl, DepositHowManyText - call PrintText - call DisplayChooseQuantityMenu - cp $ff - jp z, .loop -.next - ld hl, wNumBoxItems - call AddItemToInventory - jr c, .roomAvailable - ld hl, NoRoomToStoreText - call PrintText - jp .loop -.roomAvailable - ld hl, wNumBagItems - call RemoveItemFromInventory - call WaitForSoundToFinish - ld a, SFX_WITHDRAW_DEPOSIT - call PlaySound - call WaitForSoundToFinish - ld hl, ItemWasStoredText - call PrintText - jp .loop - -PlayerPCWithdraw: - xor a - ld [wCurrentMenuItem], a - ld [wListScrollOffset], a - ld a, [wNumBoxItems] - and a - jr nz, .loop - ld hl, NothingStoredText - call PrintText - jp PlayerPCMenu -.loop - ld hl, WhatToWithdrawText - call PrintText - ld hl, wNumBoxItems - ld a, l - ld [wListPointer], a - ld a, h - ld [wListPointer + 1], a - xor a - ld [wPrintItemPrices], a - ld a, ITEMLISTMENU - ld [wListMenuID], a - call DisplayListMenuID - jp c, PlayerPCMenu - call IsKeyItem - ld a, 1 - ld [wItemQuantity], a - ld a, [wIsKeyItem] - and a - jr nz, .next -; if it's not a key item, there can be more than one of the item - ld hl, WithdrawHowManyText - call PrintText - call DisplayChooseQuantityMenu - cp $ff - jp z, .loop -.next - ld hl, wNumBagItems - call AddItemToInventory - jr c, .roomAvailable - ld hl, CantCarryMoreText - call PrintText - jp .loop -.roomAvailable - ld hl, wNumBoxItems - call RemoveItemFromInventory - call WaitForSoundToFinish - ld a, SFX_WITHDRAW_DEPOSIT - call PlaySound - call WaitForSoundToFinish - ld hl, WithdrewItemText - call PrintText - jp .loop - -PlayerPCToss: - xor a - ld [wCurrentMenuItem], a - ld [wListScrollOffset], a - ld a, [wNumBoxItems] - and a - jr nz, .loop - ld hl, NothingStoredText - call PrintText - jp PlayerPCMenu -.loop - ld hl, WhatToTossText - call PrintText - ld hl, wNumBoxItems - ld a, l - ld [wListPointer], a - ld a, h - ld [wListPointer + 1], a - xor a - ld [wPrintItemPrices], a - ld a, ITEMLISTMENU - ld [wListMenuID], a - push hl - call DisplayListMenuID - pop hl - jp c, PlayerPCMenu - push hl - call IsKeyItem - pop hl - ld a, 1 - ld [wItemQuantity], a - ld a, [wIsKeyItem] - and a - jr nz, .next - ld a, [wcf91] - call IsItemHM - jr c, .next -; if it's not a key item, there can be more than one of the item - push hl - ld hl, TossHowManyText - call PrintText - call DisplayChooseQuantityMenu - pop hl - cp $ff - jp z, .loop -.next - call TossItem ; disallows tossing key items - jp .loop - -PlayersPCMenuEntries: - db "WITHDRAW ITEM" - next "DEPOSIT ITEM" - next "TOSS ITEM" - next "LOG OFF@" - -TurnedOnPC2Text: - TX_FAR _TurnedOnPC2Text - db "@" - -WhatDoYouWantText: - TX_FAR _WhatDoYouWantText - db "@" - -WhatToDepositText: - TX_FAR _WhatToDepositText - db "@" - -DepositHowManyText: - TX_FAR _DepositHowManyText - db "@" - -ItemWasStoredText: - TX_FAR _ItemWasStoredText - db "@" - -NothingToDepositText: - TX_FAR _NothingToDepositText - db "@" - -NoRoomToStoreText: - TX_FAR _NoRoomToStoreText - db "@" - -WhatToWithdrawText: - TX_FAR _WhatToWithdrawText - db "@" - -WithdrawHowManyText: - TX_FAR _WithdrawHowManyText - db "@" - -WithdrewItemText: - TX_FAR _WithdrewItemText - db "@" - -NothingStoredText: - TX_FAR _NothingStoredText - db "@" - -CantCarryMoreText: - TX_FAR _CantCarryMoreText - db "@" - -WhatToTossText: - TX_FAR _WhatToTossText - db "@" - -TossHowManyText: - TX_FAR _TossHowManyText - db "@" diff --git a/engine/menu/pokedex.asm b/engine/menu/pokedex.asm deleted file mode 100755 index bc2a7e9b..00000000 --- a/engine/menu/pokedex.asm +++ /dev/null @@ -1,747 +0,0 @@ -ShowPokedexMenu: - call GBPalWhiteOut - call ClearScreen - call UpdateSprites - ld a, [wListScrollOffset] - push af - xor a - ld [wCurrentMenuItem], a - ld [wListScrollOffset], a - ld [wLastMenuItem], a - inc a - ld [wd11e], a - ld [hJoy7], a -.setUpGraphics - callab LoadPokedexTilePatterns -.loop - ld b, SET_PAL_GENERIC - call RunPaletteCommand -.doPokemonListMenu - ld hl, wTopMenuItemY - ld a, 3 - ld [hli], a ; top menu item Y - xor a - ld [hli], a ; top menu item X - inc a - ld [wMenuWatchMovingOutOfBounds], a - inc hl - inc hl - ld a, 6 - ld [hli], a ; max menu item ID - ld [hl], D_LEFT | D_RIGHT | B_BUTTON | A_BUTTON - call HandlePokedexListMenu - jr c, .goToSideMenu ; if the player chose a pokemon from the list -.exitPokedex - xor a - ld [wMenuWatchMovingOutOfBounds], a - ld [wCurrentMenuItem], a - ld [wLastMenuItem], a - ld [hJoy7], a - ld [wWastedByteCD3A], a - ld [wOverrideSimulatedJoypadStatesMask], a - pop af - ld [wListScrollOffset], a - call GBPalWhiteOutWithDelay3 - call RunDefaultPaletteCommand - jp ReloadMapData - -.goToSideMenu - call HandlePokedexSideMenu - dec b - jr z, .exitPokedex ; if the player chose Quit - dec b - jr z, .doPokemonListMenu ; if pokemon not seen or player pressed B button - dec b - jr z, .loop - jp .setUpGraphics ; if pokemon data or area was shown - -; handles the menu on the lower right in the pokedex screen -; OUTPUT: -; b = reason for exiting menu -; 00: showed pokemon data or area -; 01: the player chose Quit -; 02: the pokemon has not been seen yet or the player pressed the B button -HandlePokedexSideMenu: - call PlaceUnfilledArrowMenuCursor - ld a, [wCurrentMenuItem] - push af - ld b, a - ld a, [wLastMenuItem] - push af - ld a, [wListScrollOffset] - push af - add b - inc a - ld [wd11e], a - ld a, [wd11e] - push af - ld a, [wDexMaxSeenMon] - push af ; this doesn't need to be preserved - ld hl, wPokedexSeen - call IsPokemonBitSet - ld b, 2 - jr z, .exitSideMenu - call PokedexToIndex - ld hl, wTopMenuItemY - ld a, 8 - ld [hli], a ; top menu item Y - ld a, 15 - ld [hli], a ; top menu item X - xor a - ld [hli], a ; current menu item ID - inc hl - ld a, 4 - ld [hli], a ; max menu item ID - ld a, A_BUTTON | B_BUTTON - ld [hli], a ; menu watched keys (A button and B button) - xor a - ld [hli], a ; old menu item ID - ld [wMenuWatchMovingOutOfBounds], a - ld [hJoy7], a -.handleMenuInput - call HandleMenuInput - bit 1, a ; was the B button pressed? - ld b, 2 - jr nz, .buttonBPressed - ld a, [wCurrentMenuItem] - and a - jr z, .choseData - dec a - jr z, .choseCry - dec a - jr z, .choseArea - dec a - jr z, .chosePrint -.choseQuit - ld b, 1 -.exitSideMenu - pop af - ld [wDexMaxSeenMon], a - pop af - ld [wd11e], a - pop af - ld [wListScrollOffset], a - pop af - ld [wLastMenuItem], a - pop af - ld [wCurrentMenuItem], a - ld a, $1 - ld [hJoy7], a - push bc - coord hl, 0, 3 - ld de, 20 - lb bc, " ", 13 - call DrawTileLine ; cover up the menu cursor in the pokemon list - pop bc - ret - -.buttonBPressed - push bc - coord hl, 15, 8 - ld de, 20 - lb bc, " ", 9 - call DrawTileLine ; cover up the menu cursor in the side menu - pop bc - jr .exitSideMenu - -.choseData - call ShowPokedexDataInternal - ld b, 0 - jr .exitSideMenu - -; play pokemon cry -.choseCry - ld a, [wd11e] - call GetCryData - call PlaySound - jr .handleMenuInput - -.choseArea - predef LoadTownMap_Nest ; display pokemon areas - ld b, 0 - jr .exitSideMenu - -.chosePrint - ld a, [hTilesetType] - push af - xor a - ld [hTilesetType], a - ld a, [wd11e] - ld [wcf91], a - callab PrintPokedexEntry - xor a - ld [H_AUTOBGTRANSFERENABLED], a - call ClearScreen - pop af - ld [hTilesetType], a - ld b, $3 - jr .exitSideMenu - -; handles the list of pokemon on the left of the pokedex screen -; sets carry flag if player presses A, unsets carry flag if player presses B -HandlePokedexListMenu: - call Pokedex_DrawInterface -.loop - call Pokedex_PlacePokemonList - call GBPalNormal - call HandleMenuInput - bit BIT_B_BUTTON, a ; was the B button pressed? - jp nz, .buttonBPressed - bit BIT_A_BUTTON, a ; was the A button pressed? - jp nz, .buttonAPressed -.checkIfUpPressed - bit BIT_D_UP, a ; was Up pressed? - jr z, .checkIfDownPressed -.upPressed ; scroll up one row - ld a, [wListScrollOffset] - and a - jp z, .loop - dec a - ld [wListScrollOffset], a - jp .loop - -.checkIfDownPressed - bit BIT_D_DOWN, a ; was Down pressed? - jr z, .checkIfRightPressed -.downPressed ; scroll down one row - ld a, [wDexMaxSeenMon] - cp a, 7 - jp c, .loop ; can't if the list is shorter than 7 - sub a, 7 - ld b, a - ld a, [wListScrollOffset] - cp b - jp z, .loop - inc a - ld [wListScrollOffset], a - jp .loop - -.checkIfRightPressed - bit BIT_D_RIGHT, a ; was Right pressed? - jr z, .checkIfLeftPressed -.rightPressed ; scroll down 7 rows - ld a, [wDexMaxSeenMon] - cp a, 7 - jp c, .loop ; can't if the list is shorter than 7 - sub a, 6 - ld b, a - ld a, [wListScrollOffset] - add a, 7 - ld [wListScrollOffset], a - cp b - jp c, .loop - dec b - ld a, b - ld [wListScrollOffset], a - jp .loop - -.checkIfLeftPressed ; scroll up 7 rows - bit BIT_D_LEFT, a ; was Left pressed? - jr z, .buttonAPressed -.leftPressed - ld a, [wListScrollOffset] - sub a, 7 - ld [wListScrollOffset], a - jp nc, .loop - xor a - ld [wListScrollOffset], a - jp .loop - -.buttonAPressed - scf - ret - -.buttonBPressed - and a - ret - -Pokedex_DrawInterface: - xor a - ld [H_AUTOBGTRANSFERENABLED], a -; draw the horizontal line separating the seen and owned amounts from the menu - coord hl, 15, 6 - ld a, "─" - ld [hli], a - ld [hli], a - ld [hli], a - ld [hli], a - ld [hli], a - coord hl, 14, 0 - ld [hl], $71 ; vertical line tile - coord hl, 14, 1 - call DrawPokedexVerticalLine - coord hl, 14, 9 - call DrawPokedexVerticalLine - ld hl, wPokedexSeen - ld b, wPokedexSeenEnd - wPokedexSeen - call CountSetBits - ld de, wNumSetBits - coord hl, 16, 2 - lb bc, 1, 3 - call PrintNumber ; print number of seen pokemon - ld hl, wPokedexOwned - ld b, wPokedexOwnedEnd - wPokedexOwned - call CountSetBits - ld de, wNumSetBits - coord hl, 16, 5 - lb bc, 1, 3 - call PrintNumber ; print number of owned pokemon - coord hl, 16, 1 - ld de, PokedexSeenText - call PlaceString - coord hl, 16, 4 - ld de, PokedexOwnText - call PlaceString - coord hl, 1, 1 - ld de, PokedexContentsText - call PlaceString - coord hl, 16, 8 - ld de, PokedexMenuItemsText - call PlaceString -; find the highest pokedex number among the pokemon the player has seen - ld hl, wPokedexSeenEnd - 1 - ld b, (wPokedexSeenEnd - wPokedexSeen) * 8 + 1 -.maxSeenPokemonLoop - ld a, [hld] - ld c, 8 -.maxSeenPokemonInnerLoop - dec b - sla a - jr c, .storeMaxSeenPokemon - dec c - jr nz, .maxSeenPokemonInnerLoop - jr .maxSeenPokemonLoop - -.storeMaxSeenPokemon - ld a, b - ld [wDexMaxSeenMon], a - ret - -DrawPokedexVerticalLine: - ld c, 9 ; height of line - ld de, SCREEN_WIDTH ; width of screen - ld a, $71 ; vertical line tile -.loop - ld [hl], a - add hl, de - xor a, 1 ; toggle between vertical line tile and box tile - dec c - jr nz, .loop - ret - -PokedexSeenText: - db "SEEN@" - -PokedexOwnText: - db "OWN@" - -PokedexContentsText: - db "CONTENTS@" - -PokedexMenuItemsText: - db "DATA" - next "CRY" - next "AREA" - next "PRNT" - next "QUIT@" - -Pokedex_PlacePokemonList: - xor a - ld [H_AUTOBGTRANSFERENABLED], a - coord hl, 4, 2 - lb bc, 14, 10 - call ClearScreenArea - coord hl, 1, 3 - ld a, [wListScrollOffset] - ld [wd11e], a - ld d, 7 - ld a, [wDexMaxSeenMon] - cp 7 - jr nc, .printPokemonLoop - ld d, a - dec a - ld [wMaxMenuItem], a -; loop to print pokemon pokedex numbers and names -; if the player has owned the pokemon, it puts a pokeball beside the name -.printPokemonLoop - ld a, [wd11e] - inc a - ld [wd11e], a - push af - push de - push hl - ld de, -SCREEN_WIDTH - add hl, de - ld de, wd11e - lb bc, LEADING_ZEROES | 1, 3 - call PrintNumber ; print the pokedex number - ld de, SCREEN_WIDTH - add hl, de - dec hl - push hl - ld hl, wPokedexOwned - call IsPokemonBitSet - pop hl - ld a, " " - jr z, .writeTile - ld a, $72 ; pokeball tile -.writeTile - ld [hl], a ; put a pokeball next to pokemon that the player has owned - push hl - ld hl, wPokedexSeen - call IsPokemonBitSet - jr nz, .getPokemonName ; if the player has seen the pokemon - ld de, .dashedLine ; print a dashed line in place of the name if the player hasn't seen the pokemon - jr .skipGettingName -.dashedLine ; for unseen pokemon in the list - db "----------@" -.getPokemonName - call PokedexToIndex - call GetMonName -.skipGettingName - pop hl - inc hl - call PlaceString - pop hl - ld bc, 2 * SCREEN_WIDTH - add hl, bc - pop de - pop af - ld [wd11e], a - dec d - jr nz, .printPokemonLoop - ld a, 01 - ld [H_AUTOBGTRANSFERENABLED], a - call Delay3 - ret - -; tests if a pokemon's bit is set in the seen or owned pokemon bit fields -; INPUT: -; [wd11e] = pokedex number -; hl = address of bit field -IsPokemonBitSet: - ld a, [wd11e] - dec a - ld c, a - ld b, FLAG_TEST - predef FlagActionPredef - ld a, c - and a - ret - -; function to display pokedex data from outside the pokedex -ShowPokedexData: - call GBPalWhiteOutWithDelay3 - call ClearScreen - call UpdateSprites - callab LoadPokedexTilePatterns ; load pokedex tiles - -; function to display pokedex data from inside the pokedex -ShowPokedexDataInternal: - ld hl, wd72c - set 1, [hl] - ld a, $33 ; 3/7 volume - ld [rNR50], a - ld a, [hTilesetType] - push af - xor a - ld [hTilesetType], a - call GBPalWhiteOut ; zero all palettes - ld a, [wd11e] ; pokemon ID - ld [wcf91], a - push af - ld b, SET_PAL_POKEDEX - call RunPaletteCommand - pop af - ld [wd11e], a - call DrawDexEntryOnScreen - call c, Pokedex_PrintFlavorTextAtRow11 -.waitForButtonPress - call JoypadLowSensitivity - ld a, [hJoy5] - and a, A_BUTTON | B_BUTTON - jr z, .waitForButtonPress - pop af - ld [hTilesetType], a - call GBPalWhiteOut - call ClearScreen - call RunDefaultPaletteCommand - call LoadTextBoxTilePatterns - call GBPalNormal - ld hl, wd72c - res 1, [hl] - ld a, $77 ; max volume - ld [rNR50], a - ret - -HeightWeightText: - db "HT ?", $60, "??", $61 - next "WT ???lb@" - -; XXX does anything point to this? -PokeText: - db "#@" - -; horizontal line that divides the pokedex text description from the rest of the data -PokedexDataDividerLine: - db $68, $69, $6B, $69, $6B - db $69, $6B, $69, $6B, $6B - db $6B, $6B, $69, $6B, $69 - db $6B, $69, $6B, $69, $6A - db "@" - -DrawDexEntryOnScreen: - call ClearScreen - - coord hl, 0, 0 - ld de, 1 - lb bc, $64, SCREEN_WIDTH - call DrawTileLine ; draw top border - - coord hl, 0, 17 - ld b, $6f - call DrawTileLine ; draw bottom border - - coord hl, 0, 1 - ld de, 20 - lb bc, $66, $10 - call DrawTileLine ; draw left border - - coord hl, 19, 1 - ld b, $67 - call DrawTileLine ; draw right border - - ld a, $63 ; upper left corner tile - Coorda 0, 0 - ld a, $65 ; upper right corner tile - Coorda 19, 0 - ld a, $6c ; lower left corner tile - Coorda 0, 17 - ld a, $6e ; lower right corner tile - Coorda 19, 17 - - coord hl, 0, 9 - ld de, PokedexDataDividerLine - call PlaceString ; draw horizontal divider line - - coord hl, 9, 6 - ld de, HeightWeightText - call PlaceString - - call GetMonName - coord hl, 9, 2 - call PlaceString - - ld hl, PokedexEntryPointers - ld a, [wd11e] - dec a - ld e, a - ld d, 0 - add hl, de - add hl, de - ld a, [hli] - ld e, a - ld d, [hl] ; de = address of pokedex entry - - coord hl, 9, 4 - call PlaceString ; print species name - - ld h, b - ld l, c - push de - ld a, [wd11e] - push af - call IndexToPokedex - - coord hl, 2, 8 - ld a, "№" - ld [hli], a - ld a, "⠄" - ld [hli], a - ld de, wd11e - lb bc, LEADING_ZEROES | 1, 3 - call PrintNumber ; print pokedex number - - ld hl, wPokedexOwned - call IsPokemonBitSet - pop af - ld [wd11e], a - ld a, [wcf91] - ld [wd0b5], a - pop de - - push af - push bc - push de - push hl - - call Delay3 - call GBPalNormal - call GetMonHeader ; load pokemon picture location - coord hl, 1, 1 - call LoadFlippedFrontSpriteByMonIndex ; draw pokemon picture - ld a, [wcf91] - call PlayCry ; play pokemon cry - - pop hl - pop de - pop bc - pop af - - ld a, c - and a - ret z ; if the pokemon has not been owned, don't print the height, weight, or description - - inc de ; de = address of feet (height) - ld a, [de] ; reads feet, but a is overwritten without being used - coord hl, 12, 6 - lb bc, 1, 2 - call PrintNumber ; print feet (height) - ld a, $60 ; feet symbol tile (one tick) - ld [hl], a - inc de - inc de ; de = address of inches (height) - coord hl, 15, 6 - lb bc, LEADING_ZEROES | 1, 2 - call PrintNumber ; print inches (height) - ld a, $61 ; inches symbol tile (two ticks) - ld [hl], a -; now print the weight (note that weight is stored in tenths of pounds internally) - inc de - inc de - inc de ; de = address of upper byte of weight - push de -; put weight in big-endian order at hDexWeight - ld hl, hDexWeight - ld a, [hl] ; save existing value of [hDexWeight] - push af - ld a, [de] ; a = upper byte of weight - ld [hli], a ; store upper byte of weight in [hDexWeight] - ld a, [hl] ; save existing value of [hDexWeight + 1] - push af - dec de - ld a, [de] ; a = lower byte of weight - ld [hl], a ; store lower byte of weight in [hDexWeight + 1] - ld de, hDexWeight - coord hl, 11, 8 - lb bc, 2, 5 ; 2 bytes, 5 digits - call PrintNumber ; print weight - coord hl, 14, 8 - ld a, [hDexWeight + 1] - sub 10 - ld a, [hDexWeight] - sbc 0 - jr nc, .next - ld [hl], "0" ; if the weight is less than 10, put a 0 before the decimal point -.next - inc hl - ld a, [hli] - ld [hld], a ; make space for the decimal point by moving the last digit forward one tile - ld [hl], "⠄" ; decimal point tile - pop af - ld [hDexWeight + 1], a ; restore original value of [hDexWeight + 1] - pop af - ld [hDexWeight], a ; restore original value of [hDexWeight] - pop hl - inc hl ; hl = address of pokedex description text - scf - ret - -Pokedex_PrintFlavorTextAtRow11: - coord bc, 1, 11 -Pokedex_PrintFlavorTextAtBC: - ld a, 2 - ld [$fff9], a - call TextCommandProcessor ; print pokedex description text - xor a - ld [$fff9], a - ret - -Pokedex_PrepareDexEntryForPrinting: - coord hl, 0, 0 - ld de, SCREEN_WIDTH - lb bc, $66, $d - call DrawTileLine - coord hl, 19, 0 - ld b, $67 - call DrawTileLine - coord hl, 0, 13 - ld de, $1 - lb bc, $6f, SCREEN_WIDTH - call DrawTileLine - ld a, $6c - Coorda 0, 13 - ld a, $6e - Coorda 19, 13 - ld a, [wPrinterPokedexEntryTextPointer] - ld l, a - ld a, [wPrinterPokedexEntryTextPointer + 1] - ld h, a - coord bc, 1, 1 - ld a, [hFlags_0xFFFA] - set 3, a - ld [hFlags_0xFFFA], a - call Pokedex_PrintFlavorTextAtBC - ld a, [hFlags_0xFFFA] - res 3, a - ld [hFlags_0xFFFA], a - ret - -; draws a line of tiles -; INPUT: -; b = tile ID -; c = number of tile ID's to write -; de = amount to destination address after each tile (1 for horizontal, 20 for vertical) -; hl = destination address -DrawTileLine: - push bc - push de -.loop - ld [hl], b - add hl, de - dec c - jr nz, .loop - pop de - pop bc - ret - -INCLUDE "data/pokedex_entries.asm" - -PokedexToIndex: - ; converts the Pokédex number at wd11e to an index - push bc - push hl - ld a, [wd11e] - ld b, a - ld c, 0 - ld hl, PokedexOrder - -.loop ; go through the list until we find an entry with a matching dex number - inc c - ld a, [hli] - cp b - jr nz, .loop - - ld a, c - ld [wd11e], a - pop hl - pop bc - ret - -IndexToPokedex: - ; converts the index number at wd11e to a Pokédex number - push bc - push hl - ld a, [wd11e] - dec a - ld hl, PokedexOrder - ld b, 0 - ld c, a - add hl, bc - ld a, [hl] - ld [wd11e], a - pop hl - pop bc - ret - -INCLUDE "data/pokedex_order.asm" diff --git a/engine/menu/prize_menu.asm b/engine/menu/prize_menu.asm deleted file mode 100755 index 405441c8..00000000 --- a/engine/menu/prize_menu.asm +++ /dev/null @@ -1,307 +0,0 @@ -CeladonPrizeMenu: - ld b, COIN_CASE - call IsItemInBag - jr nz, .havingCoinCase - ld hl, RequireCoinCaseTextPtr - jp PrintText -.havingCoinCase - ld hl, wd730 - set 6, [hl] ; disable letter-printing delay - ld hl, ExchangeCoinsForPrizesTextPtr - call PrintText -; the following are the menu settings - xor a - ld [wCurrentMenuItem], a - ld [wLastMenuItem], a - ld a, A_BUTTON | B_BUTTON - ld [wMenuWatchedKeys], a - ld a, $03 - ld [wMaxMenuItem], a - ld a, $04 - ld [wTopMenuItemY], a - ld a, $01 - ld [wTopMenuItemX], a - call PrintPrizePrice - coord hl, 0, 2 - lb bc, 8, 16 - call TextBoxBorder - call GetPrizeMenuId - call UpdateSprites - ld hl, WhichPrizeTextPtr - call PrintText - call HandleMenuInput ; menu choice handler - bit 1, a ; keypress = B (Cancel) - jr nz, .noChoice - ld a, [wCurrentMenuItem] - cp 3 ; "NO,THANKS" choice - jr z, .noChoice - call HandlePrizeChoice -.noChoice - ld hl, wd730 - res 6, [hl] - ret - -RequireCoinCaseTextPtr: - TX_FAR _RequireCoinCaseText - TX_WAIT - db "@" - -ExchangeCoinsForPrizesTextPtr: - TX_FAR _ExchangeCoinsForPrizesText - db "@" - -WhichPrizeTextPtr: - TX_FAR _WhichPrizeText - db "@" - -GetPrizeMenuId: -; determine which one among the three -; prize-texts has been selected -; using the text ID (stored in [hSpriteIndexOrTextID]) -; load the three prizes at wd13d-wd13f -; load the three prices at wd141-wd146 -; display the three prizes' names -; (distinguishing between Pokemon names -; and Items (specifically TMs) names) - ld a, [hSpriteIndexOrTextID] - sub 3 ; prize-texts' id are 3, 4 and 5 - ld [wWhichPrizeWindow], a ; prize-texts' id (relative, i.e. 0, 1 or 2) - add a - add a - ld d, 0 - ld e, a - ld hl, PrizeDifferentMenuPtrs - add hl, de - ld a, [hli] - ld d, [hl] - ld e, a - inc hl - push hl - ld hl, wPrize1 - call CopyString - pop hl - ld a, [hli] - ld h, [hl] - ld l, a - ld de, wPrize1Price - ld bc, 6 - call CopyData - ld a, [wWhichPrizeWindow] - cp 2 ;is TM_menu? - jr nz, .putMonName - ld a, [wPrize1] - ld [wd11e], a - call GetItemName - coord hl, 2, 4 - call PlaceString - ld a, [wPrize2] - ld [wd11e], a - call GetItemName - coord hl, 2, 6 - call PlaceString - ld a, [wPrize3] - ld [wd11e], a - call GetItemName - coord hl, 2, 8 - call PlaceString - jr .putNoThanksText -.putMonName - ld a, [wPrize1] - ld [wd11e], a - call GetMonName - coord hl, 2, 4 - call PlaceString - ld a, [wPrize2] - ld [wd11e], a - call GetMonName - coord hl, 2, 6 - call PlaceString - ld a, [wPrize3] - ld [wd11e], a - call GetMonName - coord hl, 2, 8 - call PlaceString -.putNoThanksText - coord hl, 2, 10 - ld de, NoThanksText - call PlaceString -; put prices on the right side of the textbox - ld de, wPrize1Price - coord hl, 13, 5 -; reg. c: -; [low nybble] number of bytes -; [bit 765 = %100] space-padding (not zero-padding) - ld c, (1 << 7 | 2) -; Function $15CD displays BCD value (same routine -; used by text-command $02) - call PrintBCDNumber - ld de, wPrize2Price - coord hl, 13, 7 - ld c, (1 << 7 | 2) - call PrintBCDNumber - ld de, wPrize3Price - coord hl, 13, 9 - ld c, (1 << 7 | 2) - jp PrintBCDNumber - -NoThanksText: - db "NO THANKS@" - -INCLUDE "data/prizes.asm" - -PrintPrizePrice: - coord hl, 11, 0 - lb bc, 1, 7 - call TextBoxBorder - call UpdateSprites - coord hl, 12, 0 - ld de, .CoinString - call PlaceString - coord hl, 13, 1 - ld de, .SixSpacesString - call PlaceString - coord hl, 13, 1 - ld de, wPlayerCoins - ld c, %10000010 - call PrintBCDNumber - ret - -.CoinString: - db "COIN@" - -.SixSpacesString: - db " @" - -LoadCoinsToSubtract: - ld a, [wWhichPrize] - add a - ld d, 0 - ld e, a - ld hl, wPrize1Price - add hl, de ; get selected prize's price - xor a - ld [hUnusedCoinsByte], a - ld a, [hli] - ld [hCoins], a - ld a, [hl] - ld [hCoins + 1], a - ret - -HandlePrizeChoice: - ld a, [wCurrentMenuItem] - ld [wWhichPrize], a - ld d, 0 - ld e, a - ld hl, wPrize1 - add hl, de - ld a, [hl] - ld [wd11e], a - ld a, [wWhichPrizeWindow] - cp 2 ; is prize a TM? - jr nz, .getMonName - call GetItemName - jr .givePrize -.getMonName - call GetMonName -.givePrize - ld hl, SoYouWantPrizeTextPtr - call PrintText - call YesNoChoice - ld a, [wCurrentMenuItem] ; yes/no answer (Y=0, N=1) - and a - jr nz, .printOhFineThen - call LoadCoinsToSubtract - call HasEnoughCoins - jr c, .notEnoughCoins - ld a, [wWhichPrizeWindow] - cp $02 - jr nz, .giveMon - ld a, [wd11e] - ld b, a - ld a, 1 - ld c, a - call GiveItem - jr nc, .bagFull - jr .subtractCoins -.giveMon - ld a, [wd11e] - ld [wcf91], a - push af - call GetPrizeMonLevel - ld c, a - pop af - ld b, a - call GivePokemon - -; If either the party or box was full, wait after displaying message. - push af - ld a, [wAddedToParty] - and a - call z, WaitForTextScrollButtonPress - pop af - -; If the mon couldn't be given to the player (because both the party and box -; were full), return without subtracting coins. - ret nc - -.subtractCoins - call LoadCoinsToSubtract - ld hl, hCoins + 1 - ld de, wPlayerCoins + 1 - ld c, $02 ; how many bytes - predef SubBCDPredef - jp PrintPrizePrice -.bagFull - ld hl, PrizeRoomBagIsFullTextPtr - jp PrintText -.notEnoughCoins - ld hl, SorryNeedMoreCoinsText - jp PrintText -.printOhFineThen - ld hl, OhFineThenTextPtr - jp PrintText - -UnknownPrizeData: -; XXX what's this? - db $00,$01,$00,$01,$00,$01,$00,$00,$01 - -HereYouGoTextPtr: - TX_FAR _HereYouGoText - TX_WAIT - db "@" - -SoYouWantPrizeTextPtr: - TX_FAR _SoYouWantPrizeText - db "@" - -SorryNeedMoreCoinsText: - TX_FAR _SorryNeedMoreCoinsText - TX_WAIT - db "@" - -PrizeRoomBagIsFullTextPtr: - TX_FAR _OopsYouDontHaveEnoughRoomText - TX_WAIT - db "@" - -OhFineThenTextPtr: - TX_FAR _OhFineThenText - TX_WAIT - db "@" - -GetPrizeMonLevel: - ld a, [wcf91] - ld b, a - ld hl, PrizeMonLevelDictionary -.loop - ld a, [hli] - cp b - jr z, .matchFound - inc hl - jr .loop -.matchFound - ld a, [hl] - ld [wCurEnemyLVL], a - ret - -INCLUDE "data/prize_mon_levels.asm" diff --git a/engine/menu/start_menu.asm b/engine/menu/start_menu.asm deleted file mode 100755 index 498d1467..00000000 --- a/engine/menu/start_menu.asm +++ /dev/null @@ -1,84 +0,0 @@ -DisplayStartMenu:: - switchbank StartMenu_Pokedex ; also bank for other functions - ld a, [wWalkBikeSurfState] ; walking/biking/surfing - ld [wWalkBikeSurfStateCopy], a - ld a, SFX_START_MENU - call PlaySound - -RedisplayStartMenu:: - callba DrawStartMenu -RedisplayStartMenu_DoNotDrawStartMenu: - callba PrintSafariZoneSteps ; print Safari Zone info, if in Safari Zone - call UpdateSprites -.loop - call HandleMenuInput - ld b, a -.checkIfUpPressed - bit 6, a ; was Up pressed? - jr z, .checkIfDownPressed - ld a, [wCurrentMenuItem] ; menu selection - and a - jr nz, .loop - ld a, [wLastMenuItem] - and a - jr nz, .loop -; if the player pressed tried to go past the top item, wrap around to the bottom - CheckEvent EVENT_GOT_POKEDEX - ld a, 6 ; there are 7 menu items with the pokedex, so the max index is 6 - jr nz, .wrapMenuItemId - dec a ; there are only 6 menu items without the pokedex -.wrapMenuItemId - ld [wCurrentMenuItem], a - call EraseMenuCursor - jr .loop -.checkIfDownPressed - bit 7, a - jr z, .buttonPressed -; if the player pressed tried to go past the bottom item, wrap around to the top - CheckEvent EVENT_GOT_POKEDEX - ld a, [wCurrentMenuItem] - ld c, 7 ; there are 7 menu items with the pokedex - jr nz, .checkIfPastBottom - dec c ; there are only 6 menu items without the pokedex -.checkIfPastBottom - cp c - jr nz, .loop -; the player went past the bottom, so wrap to the top - xor a - ld [wCurrentMenuItem], a - call EraseMenuCursor - jr .loop -.buttonPressed ; A, B, or Start button pressed - call PlaceUnfilledArrowMenuCursor - ld a, [wCurrentMenuItem] - ld [wBattleAndStartSavedMenuItem], a ; save current menu selection - ld a, b - and %00001010 ; was the Start button or B button pressed? - jp nz, CloseStartMenu - call SaveScreenTilesToBuffer2 ; copy background from wTileMap to wTileMapBackup2 - CheckEvent EVENT_GOT_POKEDEX - ld a, [wCurrentMenuItem] - jr nz, .displayMenuItem - inc a ; adjust position to account for missing pokedex menu item -.displayMenuItem - cp 0 - jp z, StartMenu_Pokedex - cp 1 - jp z, StartMenu_Pokemon - cp 2 - jp z, StartMenu_Item - cp 3 - jp z, StartMenu_TrainerInfo - cp 4 - jp z, StartMenu_SaveReset - cp 5 - jp z, StartMenu_Option - -; EXIT falls through to here -CloseStartMenu:: - call Joypad - ld a, [hJoyPressed] - bit 0, a ; was A button newly pressed? - jr nz, CloseStartMenu - call LoadTextBoxTilePatterns - jp CloseTextDisplay diff --git a/engine/menu/start_sub_menus.asm b/engine/menu/start_sub_menus.asm deleted file mode 100755 index abc8f000..00000000 --- a/engine/menu/start_sub_menus.asm +++ /dev/null @@ -1,871 +0,0 @@ -StartMenu_Pokedex: - predef ShowPokedexMenu - call LoadScreenTilesFromBuffer2 ; restore saved screen - call Delay3 - call LoadGBPal - call UpdateSprites - jp RedisplayStartMenu - -StartMenu_Pokemon: - ld a, [wPartyCount] - and a - jp z, RedisplayStartMenu - xor a - ld [wMenuItemToSwap], a - ld [wPartyMenuTypeOrMessageID], a - ld [wUpdateSpritesEnabled], a - call DisplayPartyMenu - jr .checkIfPokemonChosen -.loop - xor a - ld [wMenuItemToSwap], a - ld [wPartyMenuTypeOrMessageID], a - call GoBackToPartyMenu -.checkIfPokemonChosen - jr nc, .chosePokemon -.exitMenu - call GBPalWhiteOutWithDelay3 - call RestoreScreenTilesAndReloadTilePatterns - call LoadGBPal - jp RedisplayStartMenu -.chosePokemon - call SaveScreenTilesToBuffer1 - ld a, FIELD_MOVE_MON_MENU - ld [wTextBoxID], a - call DisplayTextBoxID ; display pokemon menu options - ld hl, wFieldMoves - lb bc, 2, 12 ; max menu item ID, top menu item Y - ld e, 5 -.adjustMenuVariablesLoop - dec e - jr z, .storeMenuVariables - ld a, [hli] - and a ; end of field moves? - jr z, .storeMenuVariables - inc b - dec c - dec c - jr .adjustMenuVariablesLoop -.storeMenuVariables - ld hl, wTopMenuItemY - ld a, c - ld [hli], a ; top menu item Y - ld a, [hFieldMoveMonMenuTopMenuItemX] - ld [hli], a ; top menu item X - xor a - ld [hli], a ; current menu item ID - inc hl - ld a, b - ld [hli], a ; max menu item ID - ld a, A_BUTTON | B_BUTTON - ld [hli], a ; menu watched keys - xor a - ld [hl], a - call HandleMenuInput - push af - call LoadScreenTilesFromBuffer1 ; restore saved screen - pop af - bit 1, a ; was the B button pressed? - jp nz, .loop -; if the B button wasn't pressed - ld a, [wMaxMenuItem] - ld b, a - ld a, [wCurrentMenuItem] ; menu selection - cp b - jp z, .exitMenu ; if the player chose Cancel - dec b - cp b - jr z, .choseSwitch - dec b - cp b - jp z, .choseStats - ld c, a - ld b, 0 - ld hl, wFieldMoves - add hl, bc - jp .choseOutOfBattleMove -.choseSwitch - ld a, [wPartyCount] - cp 2 ; is there more than one pokemon in the party? - jp c, StartMenu_Pokemon ; if not, no switching - call SwitchPartyMon_InitVarOrSwapData ; init [wMenuItemToSwap] - ld a, SWAP_MONS_PARTY_MENU - ld [wPartyMenuTypeOrMessageID], a - call GoBackToPartyMenu - jp .checkIfPokemonChosen -.choseStats - call ClearSprites - xor a ; PLAYER_PARTY_DATA - ld [wMonDataLocation], a - predef StatusScreen - predef StatusScreen2 - call ReloadMapData - jp StartMenu_Pokemon -.choseOutOfBattleMove - push hl - ld a, [wWhichPokemon] - ld hl, wPartyMonNicks - call GetPartyMonName - pop hl - ld a, [hl] - dec a - add a - ld b, 0 - ld c, a - ld hl, .outOfBattleMovePointers - add hl, bc - ld a, [hli] - ld h, [hl] - ld l, a - ld a, [wObtainedBadges] ; badges obtained - jp hl -.outOfBattleMovePointers - dw .cut - dw .fly - dw .surf - dw .surf - dw .strength - dw .flash - dw .dig - dw .teleport - dw .softboiled -.fly - bit 2, a ; does the player have the Thunder Badge? - jp z, .newBadgeRequired - call CheckIfInOutsideMap - jr z, .canFly - ld a, [wWhichPokemon] - ld hl, wPartyMonNicks - call GetPartyMonName - ld hl, .cannotFlyHereText - call PrintText - jp .loop -.canFly - call ChooseFlyDestination - ld a, [wd732] - bit 3, a ; did the player decide to fly? - jr nz, .asm_5d4c - call LoadFontTilePatterns - ld hl, wd72e - set 1, [hl] - jp StartMenu_Pokemon -.asm_5d4c - call Func_1510 - jp .goBackToMap -.cut - bit 1, a ; does the player have the Cascade Badge? - jp z, .newBadgeRequired - predef UsedCut - ld a, [wActionResultOrTookBattleTurn] - and a - jp z, .loop - jp CloseTextDisplay -.surf - bit 4, a ; does the player have the Soul Badge? - jp z, .newBadgeRequired - callba IsSurfingAllowed - ld hl, wd728 - bit 1, [hl] - res 1, [hl] - jp z, .loop - ld a, [wcf91] - cp PIKACHU ; is this surfing pikachu? - jr z, .surfingPikachu - ld a, $1 - jr .continue -.surfingPikachu - ld a, $2 -.continue - ld [wd473], a - ld a,SURFBOARD - ld [wcf91], a - ld [wPseudoItemID], a - call UseItem - ld a, [wActionResultOrTookBattleTurn] - and a - jr z, .reloadNormalSprite - call GBPalWhiteOutWithDelay3 - jp .goBackToMap -.reloadNormalSprite - xor a - ld [wd473], a - jp .loop -.strength - bit 3, a ; does the player have the Rainbow Badge? - jp z, .newBadgeRequired - predef PrintStrengthTxt - call GBPalWhiteOutWithDelay3 - jp .goBackToMap -.flash - bit 0, a ; does the player have the Boulder Badge? - jp z, .newBadgeRequired - xor a - ld [wMapPalOffset], a - ld hl, .flashLightsAreaText - call PrintText - call GBPalWhiteOutWithDelay3 - jp .goBackToMap -.flashLightsAreaText - TX_FAR _FlashLightsAreaText - db "@" -.dig - ld a, ESCAPE_ROPE - ld [wcf91], a - ld [wPseudoItemID], a - call UseItem - ld a, [wActionResultOrTookBattleTurn] - and a - jp z, .loop - call GBPalWhiteOutWithDelay3 - jp .goBackToMap -.teleport - call CheckIfInOutsideMap - jr z, .canTeleport - ld a, [wWhichPokemon] - ld hl, wPartyMonNicks - call GetPartyMonName - ld hl, .cannotUseTeleportNowText - call PrintText - jp .loop -.canTeleport - ld hl, .warpToLastPokemonCenterText - call PrintText - ld hl, wd732 - set 3, [hl] - set 6, [hl] - call Func_1510 - ld hl, wd72e - set 1, [hl] - res 4, [hl] - ld c, 60 - call DelayFrames - call GBPalWhiteOutWithDelay3 - jp .goBackToMap -.warpToLastPokemonCenterText - TX_FAR _WarpToLastPokemonCenterText - db "@" -.cannotUseTeleportNowText - TX_FAR _CannotUseTeleportNowText - db "@" -.cannotFlyHereText - TX_FAR _CannotFlyHereText - db "@" -.softboiled - ld hl, wPartyMon1MaxHP - ld a, [wWhichPokemon] - ld bc, wPartyMon2 - wPartyMon1 - call AddNTimes - ld a, [hli] - ld [H_DIVIDEND], a - ld a, [hl] - ld [H_DIVIDEND + 1], a - ld a, 5 - ld [H_DIVISOR], a - ld b, 2 ; number of bytes - call Divide - ld bc, wPartyMon1HP - wPartyMon1MaxHP - add hl, bc - ld a, [hld] - ld b, a - ld a, [H_QUOTIENT + 3] - sub b - ld b, [hl] - ld a, [H_QUOTIENT + 2] - sbc b - jp nc, .notHealthyEnough - ld a, [wPartyAndBillsPCSavedMenuItem] - push af - ld a, POTION - ld [wcf91], a - ld [wPseudoItemID], a - call UseItem - pop af - ld [wPartyAndBillsPCSavedMenuItem], a - jp .loop -.notHealthyEnough ; if current HP is less than 1/5 of max HP - ld hl, .notHealthyEnoughText - call PrintText - jp .loop -.notHealthyEnoughText - TX_FAR _NotHealthyEnoughText - db "@" -.goBackToMap - call RestoreScreenTilesAndReloadTilePatterns - jp CloseTextDisplay -.newBadgeRequired - ld hl, .newBadgeRequiredText - call PrintText - jp .loop -.newBadgeRequiredText - TX_FAR _NewBadgeRequiredText - db "@" - -; writes a blank tile to all possible menu cursor positions on the party menu -ErasePartyMenuCursors: - coord hl, 0, 1 - ld bc, 2 * 20 ; menu cursor positions are 2 rows apart - ld a, 6 ; 6 menu cursor positions -.loop - ld [hl], " " - add hl, bc - dec a - jr nz, .loop - ret - -ItemMenuLoop: - call LoadScreenTilesFromBuffer2DisableBGTransfer ; restore saved screen - call RunDefaultPaletteCommand - -StartMenu_Item: - ld a, [wLinkState] - dec a ; is the player in the Colosseum or Trade Centre? - jr nz, .notInCableClubRoom - ld hl, CannotUseItemsHereText - call PrintText - jr .exitMenu -.notInCableClubRoom - ld hl, wListPointer - ld [hl], wNumBagItems & $ff - inc hl - ld [hl], wNumBagItems / $100 ; store item bag pointer in wListPointer (for DisplayListMenuID) - xor a - ld [wPrintItemPrices], a - ld a, ITEMLISTMENU - ld [wListMenuID], a - ld a, [wBagSavedMenuItem] - ld [wCurrentMenuItem], a - call DisplayListMenuID - ld a, [wCurrentMenuItem] - ld [wBagSavedMenuItem], a - jr nc, .choseItem -.exitMenu - call LoadScreenTilesFromBuffer2 ; restore saved screen - call LoadTextBoxTilePatterns - call UpdateSprites - jp RedisplayStartMenu -.choseItem -; erase menu cursor (blank each tile in front of an item name) - ld a, " " - Coorda 5, 4 - Coorda 5, 6 - Coorda 5, 8 - Coorda 5, 10 - call PlaceUnfilledArrowMenuCursor - xor a - ld [wMenuItemToSwap], a - ld a, [wcf91] - cp BICYCLE - jp z, .useOrTossItem -.notBicycle1 - ld a, USE_TOSS_MENU_TEMPLATE - ld [wTextBoxID], a - call DisplayTextBoxID - ld hl, wTopMenuItemY - ld a, 11 - ld [hli], a ; top menu item Y - ld a, 14 - ld [hli], a ; top menu item X - xor a - ld [hli], a ; current menu item ID - inc hl - inc a ; a = 1 - ld [hli], a ; max menu item ID - ld a, A_BUTTON | B_BUTTON - ld [hli], a ; menu watched keys - xor a - ld [hl], a ; old menu item id - call HandleMenuInput - call PlaceUnfilledArrowMenuCursor - bit 1, a ; was the B button pressed? - jr z, .useOrTossItem - jp ItemMenuLoop -.useOrTossItem ; if the player made the choice to use or toss the item - ld a, [wcf91] - ld [wd11e], a - call GetItemName - call CopyStringToCF4B ; copy name to wcf4b - ld a, [wcf91] - cp BICYCLE - jr nz, .notBicycle2 - ld a, [wd732] - bit 5, a - jr z, .useItem_closeMenu - ld hl, CannotGetOffHereText - call PrintText - jp ItemMenuLoop -.notBicycle2 - ld a, [wCurrentMenuItem] - and a - jr nz, .tossItem -; use item - ld [wPseudoItemID], a ; a must be 0 due to above conditional jump - ld a, [wcf91] - cp HM_01 - jr nc, .useItem_partyMenu - ld hl, UsableItems_CloseMenu - ld de, 1 - call IsInArray - jr c, .useItem_closeMenu - ld a, [wcf91] - ld hl, UsableItems_PartyMenu - ld de, 1 - call IsInArray - jr c, .useItem_partyMenu - call UseItem - jp ItemMenuLoop -.useItem_closeMenu - xor a - ld [wPseudoItemID], a - call UseItem - ld a, [wActionResultOrTookBattleTurn] - and a - jp z, ItemMenuLoop - jp CloseStartMenu -.useItem_partyMenu - ld a, [wUpdateSpritesEnabled] - push af - call UseItem - ld a, [wActionResultOrTookBattleTurn] - cp $02 - jp z, .partyMenuNotDisplayed - call GBPalWhiteOutWithDelay3 - call RestoreScreenTilesAndReloadTilePatterns - pop af - ld [wUpdateSpritesEnabled], a - jp StartMenu_Item -.partyMenuNotDisplayed - pop af - ld [wUpdateSpritesEnabled], a - jp ItemMenuLoop -.tossItem - call IsKeyItem - ld a, [wIsKeyItem] - and a - jr nz, .skipAskingQuantity - ld a, [wcf91] - call IsItemHM - jr c, .skipAskingQuantity - call DisplayChooseQuantityMenu - inc a - jr z, .tossZeroItems -.skipAskingQuantity - ld hl, wNumBagItems - call TossItem -.tossZeroItems - jp ItemMenuLoop - -CannotUseItemsHereText: - TX_FAR _CannotUseItemsHereText - db "@" - -CannotGetOffHereText: - TX_FAR _CannotGetOffHereText - db "@" - -; items which bring up the party menu when used -UsableItems_PartyMenu: - db MOON_STONE - db ANTIDOTE - db BURN_HEAL - db ICE_HEAL - db AWAKENING - db PARLYZ_HEAL - db FULL_RESTORE - db MAX_POTION - db HYPER_POTION - db SUPER_POTION - db POTION - db FIRE_STONE - db THUNDER_STONE - db WATER_STONE - db HP_UP - db PROTEIN - db IRON - db CARBOS - db CALCIUM - db RARE_CANDY - db LEAF_STONE - db FULL_HEAL - db REVIVE - db MAX_REVIVE - db FRESH_WATER - db SODA_POP - db LEMONADE - db X_ATTACK - db X_DEFEND - db X_SPEED - db X_SPECIAL - db PP_UP - db ETHER - db MAX_ETHER - db ELIXER - db MAX_ELIXER - db $ff - -; items which close the item menu when used -UsableItems_CloseMenu: - db ESCAPE_ROPE - db ITEMFINDER - db POKE_FLUTE - db OLD_ROD - db GOOD_ROD - db SUPER_ROD - db $ff - -StartMenu_TrainerInfo: - call GBPalWhiteOut - call ClearScreen - call UpdateSprites - ld a, [hTilesetType] - push af - xor a - ld [hTilesetType], a - call DrawTrainerInfo - predef DrawBadges ; draw badges - ld b, SET_PAL_TRAINER_CARD - call RunPaletteCommand - call GBPalNormal - call WaitForTextScrollButtonPress ; wait for button press - call GBPalWhiteOut - call LoadFontTilePatterns - call LoadScreenTilesFromBuffer2 ; restore saved screen - call RunDefaultPaletteCommand - call ReloadMapData - callba DrawStartMenu ; XXX what difference does this make? - call LoadGBPal - pop af - ld [hTilesetType], a - jp RedisplayStartMenu_DoNotDrawStartMenu - -; loads tile patterns and draws everything except for gym leader faces / badges -DrawTrainerInfo: - ld de, RedPicFront - lb bc, BANK(RedPicFront), $01 - predef DisplayPicCenteredOrUpperRight - call DisableLCD - coord hl, 0, 2 - ld a, " " - call TrainerInfo_DrawVerticalLine - coord hl, 1, 2 - call TrainerInfo_DrawVerticalLine - ld hl, vChars2 + $70 - ld de, vChars2 - ld bc, $70 * 4 - call CopyData - ld hl, TrainerInfoTextBoxTileGraphics ; trainer info text box tile patterns - ld de, vChars2 + $770 - ld bc, $0080 - push bc - call TrainerInfo_FarCopyData - ld hl, BlankLeaderNames - ld de, vChars2 + $600 - ld bc, $0170 - call TrainerInfo_FarCopyData - pop bc - ld hl, BadgeNumbersTileGraphics ; badge number tile patterns - ld de, vChars1 + $580 - call TrainerInfo_FarCopyData - ld hl, GymLeaderFaceAndBadgeTileGraphics ; gym leader face and badge tile patterns - ld de, vChars2 + $200 - ld bc, $0400 - ld a, $03 - call FarCopyData - ld hl, TextBoxGraphics - ld de, $00d0 - add hl, de ; hl = colon tile pattern - ld de, vChars1 + $560 - ld bc, $0010 - ld a, $04 - push bc - call FarCopyData - pop bc - ld hl, TrainerInfoTextBoxTileGraphics + $80 ; background tile pattern - ld de, vChars1 + $570 - call TrainerInfo_FarCopyData - call EnableLCD - ld hl, wTrainerInfoTextBoxWidthPlus1 - ld a, 18 + 1 - ld [hli], a - dec a - ld [hli], a - ld [hl], 1 - coord hl, 0, 0 - call TrainerInfo_DrawTextBox - ld hl, wTrainerInfoTextBoxWidthPlus1 - ld a, 16 + 1 - ld [hli], a - dec a - ld [hli], a - ld [hl], 3 - coord hl, 1, 10 - call TrainerInfo_DrawTextBox - coord hl, 0, 10 - ld a, $d7 - call TrainerInfo_DrawVerticalLine - coord hl, 19, 10 - call TrainerInfo_DrawVerticalLine - coord hl, 6, 9 - ld de, TrainerInfo_BadgesText - call PlaceString - coord hl, 2, 2 - ld de, TrainerInfo_NameMoneyTimeText - call PlaceString - coord hl, 7, 2 - ld de, wPlayerName - call PlaceString - coord hl, 8, 4 - ld de, wPlayerMoney - ld c, $e3 - call PrintBCDNumber - coord hl, 9, 6 - ld de, wPlayTimeHours ; hours - lb bc, LEFT_ALIGN | 1, 3 - call PrintNumber - ld [hl], $d6 ; colon tile ID - inc hl - ld de, wPlayTimeMinutes ; minutes - lb bc, LEADING_ZEROES | 1, 2 - jp PrintNumber - -TrainerInfo_FarCopyData: - ld a, BANK(TrainerInfoTextBoxTileGraphics) - jp FarCopyData - -TrainerInfo_NameMoneyTimeText: - db "NAME/" - next "MONEY/" - next "TIME/@" - -; $76 is a circle tile -TrainerInfo_BadgesText: - db $76,"BADGES",$76,"@" - -; draws a text box on the trainer info screen -; height is always 6 -; INPUT: -; hl = destination address -; [wTrainerInfoTextBoxWidthPlus1] = width -; [wTrainerInfoTextBoxWidth] = width - 1 -; [wTrainerInfoTextBoxNextRowOffset] = distance from the end of a text box row to the start of the next -TrainerInfo_DrawTextBox: - ld a, $79 ; upper left corner tile ID - lb de, $7a, $7b ; top edge and upper right corner tile ID's - call TrainerInfo_DrawHorizontalEdge ; draw top edge - call TrainerInfo_NextTextBoxRow - ld a, [wTrainerInfoTextBoxWidthPlus1] - ld e, a - ld d, 0 - ld c, 6 ; height of the text box -.loop - ld [hl], $7c ; left edge tile ID - add hl, de - ld [hl], $78 ; right edge tile ID - call TrainerInfo_NextTextBoxRow - dec c - jr nz, .loop - ld a, $7d ; lower left corner tile ID - lb de, $77, $7e ; bottom edge and lower right corner tile ID's - -TrainerInfo_DrawHorizontalEdge: - ld [hli], a ; place left corner tile - ld a, [wTrainerInfoTextBoxWidth] - ld c, a - ld a, d -.loop - ld [hli], a ; place edge tile - dec c - jr nz, .loop - ld a, e - ld [hl], a ; place right corner tile - ret - -TrainerInfo_NextTextBoxRow: - ld a, [wTrainerInfoTextBoxNextRowOffset] ; distance to the start of the next row -.loop - inc hl - dec a - jr nz, .loop - ret - -; draws a vertical line -; INPUT: -; hl = address of top tile in the line -; a = tile ID -TrainerInfo_DrawVerticalLine: - ld de, SCREEN_WIDTH - ld c, 8 -.loop - ld [hl], a - add hl, de - dec c - jr nz, .loop - ret - -StartMenu_SaveReset: - ld a, [wd72e] - bit 6, a ; is the player using the link feature? - jp nz, Init - predef SaveSAV ; save the game - call LoadScreenTilesFromBuffer2 ; restore saved screen - jp HoldTextDisplayOpen - -StartMenu_Option: - xor a - ld [H_AUTOBGTRANSFERENABLED], a - call ClearScreen - call UpdateSprites - callab DisplayOptionMenu - call LoadScreenTilesFromBuffer2 ; restore saved screen - call LoadTextBoxTilePatterns - call UpdateSprites - jp RedisplayStartMenu - -SwitchPartyMon: - call SwitchPartyMon_InitVarOrSwapData ; swap data - ld a, [wSwappedMenuItem] - call SwitchPartyMon_ClearGfx - ld a, [wCurrentMenuItem] - call SwitchPartyMon_ClearGfx - jp RedrawPartyMenu_ - -SwitchPartyMon_ClearGfx: - push af - coord hl, 0, 0 - ld bc, SCREEN_WIDTH * 2 - call AddNTimes - ld c, SCREEN_WIDTH * 2 - ld a, " " -.clearMonBGLoop ; clear the mon's row in the party menu - ld [hli], a - dec c - jr nz, .clearMonBGLoop - pop af - ld hl, wOAMBuffer - ld bc, $10 - call AddNTimes - ld de, $4 - ld c, e -.clearMonOAMLoop - ld [hl], $a0 - add hl, de - dec c - jr nz, .clearMonOAMLoop - call WaitForSoundToFinish - ld a, SFX_SWAP - jp PlaySound - -SwitchPartyMon_InitVarOrSwapData: -; This is used to initialise [wMenuItemToSwap] and to actually swap the data. - ld a, [wMenuItemToSwap] - and a ; has [wMenuItemToSwap] been initialised yet? - jr nz, .pickedMonsToSwap -; If not, initialise [wMenuItemToSwap] so that it matches the current mon. - ld a, [wWhichPokemon] - inc a ; [wMenuItemToSwap] counts from 1 - ld [wMenuItemToSwap], a - ret -.pickedMonsToSwap - xor a - ld [wPartyMenuTypeOrMessageID], a - ld a, [wMenuItemToSwap] - dec a - ld b, a - ld a, [wCurrentMenuItem] - ld [wSwappedMenuItem], a - cp b ; swapping a mon with itself? - jr nz, .swappingDifferentMons -; can't swap a mon with itself - xor a - ld [wMenuItemToSwap], a - ld [wPartyMenuTypeOrMessageID], a - ret -.swappingDifferentMons - ld a, b - ld [wMenuItemToSwap], a - push hl - push de - ld hl, wPartySpecies - ld d, h - ld e, l - ld a, [wCurrentMenuItem] - add l - ld l, a - jr nc, .noCarry - inc h -.noCarry - ld a, [wMenuItemToSwap] - add e - ld e, a - jr nc, .noCarry2 - inc d -.noCarry2 - ld a, [hl] - ld [hSwapTemp], a - ld a, [de] - ld [hl], a - ld a, [hSwapTemp] - ld [de], a - ld hl, wPartyMons - ld bc, wPartyMon2 - wPartyMon1 - ld a, [wCurrentMenuItem] - call AddNTimes - push hl - ld de, wSwitchPartyMonTempBuffer - ld bc, wPartyMon2 - wPartyMon1 - call CopyData - ld hl, wPartyMons - ld bc, wPartyMon2 - wPartyMon1 - ld a, [wMenuItemToSwap] - call AddNTimes - pop de - push hl - ld bc, wPartyMon2 - wPartyMon1 - call CopyData - pop de - ld hl, wSwitchPartyMonTempBuffer - ld bc, wPartyMon2 - wPartyMon1 - call CopyData - ld hl, wPartyMonOT - ld a, [wCurrentMenuItem] - call SkipFixedLengthTextEntries - push hl - ld de, wSwitchPartyMonTempBuffer - ld bc, NAME_LENGTH - call CopyData - ld hl, wPartyMonOT - ld a, [wMenuItemToSwap] - call SkipFixedLengthTextEntries - pop de - push hl - ld bc, NAME_LENGTH - call CopyData - pop de - ld hl, wSwitchPartyMonTempBuffer - ld bc, NAME_LENGTH - call CopyData - ld hl, wPartyMonNicks - ld a, [wCurrentMenuItem] - call SkipFixedLengthTextEntries - push hl - ld de, wSwitchPartyMonTempBuffer - ld bc, NAME_LENGTH - call CopyData - ld hl, wPartyMonNicks - ld a, [wMenuItemToSwap] - call SkipFixedLengthTextEntries - pop de - push hl - ld bc, NAME_LENGTH - call CopyData - pop de - ld hl, wSwitchPartyMonTempBuffer - ld bc, NAME_LENGTH - call CopyData - ld a, [wMenuItemToSwap] - ld [wSwappedMenuItem], a - xor a - ld [wMenuItemToSwap], a - ld [wPartyMenuTypeOrMessageID], a - pop de - pop hl - ret diff --git a/engine/menu/status_screen.asm b/engine/menu/status_screen.asm deleted file mode 100755 index 1e2ba889..00000000 --- a/engine/menu/status_screen.asm +++ /dev/null @@ -1,495 +0,0 @@ -DrawHP: -; Draws the HP bar in the stats screen - call GetPredefRegisters - ld a, $1 - jr DrawHP_ - -DrawHP2: -; Draws the HP bar in the party screen - call GetPredefRegisters - ld a, $2 - -DrawHP_: - ld [wHPBarType], a - push hl - ld a, [wLoadedMonHP] - ld b, a - ld a, [wLoadedMonHP + 1] - ld c, a - or b - jr nz, .nonzeroHP - xor a - ld c, a - ld e, a - ld a, $6 - ld d, a - jp .drawHPBarAndPrintFraction -.nonzeroHP - ld a, [wLoadedMonMaxHP] - ld d, a - ld a, [wLoadedMonMaxHP + 1] - ld e, a - predef HPBarLength - ld a, $6 - ld d, a - ld c, a -.drawHPBarAndPrintFraction - pop hl - push de - push hl - push hl - call DrawHPBar - pop hl - ld a, [hFlags_0xFFFA] - bit 0, a - jr z, .printFractionBelowBar - ld bc, $9 ; right of bar - jr .printFraction -.printFractionBelowBar - ld bc, SCREEN_WIDTH + 1 ; below bar -.printFraction - add hl, bc - ld de, wLoadedMonHP - lb bc, 2, 3 - call PrintNumber - ld a, "/" - ld [hli], a - ld de, wLoadedMonMaxHP - lb bc, 2, 3 - call PrintNumber - pop hl - pop de - ret - - -; Predef 0x37 -StatusScreen: - call LoadMonData - ld a, [wMonDataLocation] - cp BOX_DATA - jr c, .DontRecalculate -; mon is in a box or daycare - ld a, [wLoadedMonBoxLevel] - ld [wLoadedMonLevel], a - ld [wCurEnemyLVL], a - ld hl, wLoadedMonHPExp - 1 - ld de, wLoadedMonStats - ld b, $1 - call CalcStats ; Recalculate stats -.DontRecalculate - ld hl, wd72c - set 1, [hl] - ld a, $33 - ld [rNR50], a ; Reduce the volume - call GBPalWhiteOutWithDelay3 - call ClearScreen - call UpdateSprites - call LoadHpBarAndStatusTilePatterns - ld de, BattleHudTiles1 ; source - ld hl, vChars2 + $6d0 ; dest - lb bc, BANK(BattleHudTiles1), $03 - call CopyVideoDataDouble ; ·│ :L and halfarrow line end - ld de, BattleHudTiles2 - ld hl, vChars2 + $780 - lb bc, BANK(BattleHudTiles2), $01 - call CopyVideoDataDouble ; │ - ld de, BattleHudTiles3 - ld hl, vChars2 + $760 - lb bc, BANK(BattleHudTiles3), $02 - call CopyVideoDataDouble ; ─┘ - ld de, PTile - ld hl, vChars2 + $720 - lb bc, BANK(PTile), (PTileEnd - PTile) / $8 - call CopyVideoDataDouble ; P (for PP), inline - ld a, [hTilesetType] - push af - xor a - ld [hTilesetType], a - coord hl, 19, 1 - lb bc, 6, 10 - call DrawLineBox ; Draws the box around name, HP and status - ld de, -6 - add hl, de - ld [hl], "⠄" ; . after No ("." is a different one) - dec hl - ld [hl], "№" - coord hl, 19, 9 - lb bc, 8, 6 - call DrawLineBox ; Draws the box around types, ID No. and OT - coord hl, 10, 9 - ld de, Type1Text - call PlaceString ; "TYPE1/" - coord hl, 11, 3 - predef DrawHP - ld hl, wStatusScreenHPBarColor - call GetHealthBarColor - ld b, SET_PAL_STATUS_SCREEN - call RunPaletteCommand - coord hl, 16, 6 - ld de, wLoadedMonStatus - call PrintStatusCondition - jr nz, .StatusWritten - coord hl, 16, 6 - ld de, OKText - call PlaceString ; "OK" -.StatusWritten - coord hl, 9, 6 - ld de, StatusText - call PlaceString ; "STATUS/" - coord hl, 14, 2 - call PrintLevel ; Pokémon level - ld a, [wMonHIndex] - ld [wd11e], a - ld [wd0b5], a - predef IndexToPokedex - coord hl, 3, 7 - ld de, wd11e - lb bc, LEADING_ZEROES | 1, 3 - call PrintNumber ; Pokémon no. - coord hl, 11, 10 - predef PrintMonType - ld hl, NamePointers2 - call .GetStringPointer - ld d, h - ld e, l - coord hl, 9, 1 - call PlaceString ; Pokémon name - ld hl, OTPointers - call .GetStringPointer - ld d, h - ld e, l - coord hl, 12, 16 - call PlaceString ; OT - coord hl, 12, 14 - ld de, wLoadedMonOTID - lb bc, LEADING_ZEROES | 2, 5 - call PrintNumber ; ID Number - ld d, $0 - call PrintStatsBox - call Delay3 - call GBPalNormal - coord hl, 1, 0 - call LoadFlippedFrontSpriteByMonIndex ; draw Pokémon picture - ld a, [wMonDataLocation] - cp ENEMY_PARTY_DATA - jr z, .playRegularCry - cp BOX_DATA - jr z, .checkBoxData - callab IsThisPartymonStarterPikachu_Party - jr nc, .playRegularCry - jr .playPikachuSoundClip -.checkBoxData - callab IsThisPartymonStarterPikachu_Box - jr nc, .playRegularCry -.playPikachuSoundClip - ld e, 16 - callab PlayPikachuSoundClip - jr .continue -.playRegularCry - ld a, [wcf91] - call PlayCry ; play Pokémon cry -.continue - call WaitForTextScrollButtonPress ; wait for button - pop af - ld [hTilesetType], a - ret - -.GetStringPointer - ld a, [wMonDataLocation] - add a - ld c, a - ld b, 0 - add hl, bc - ld a, [hli] - ld h, [hl] - ld l, a - ld a, [wMonDataLocation] - cp DAYCARE_DATA - ret z - ld a, [wWhichPokemon] - jp SkipFixedLengthTextEntries - -OTPointers: - dw wPartyMonOT - dw wEnemyMonOT - dw wBoxMonOT - dw wDayCareMonOT - -NamePointers2: - dw wPartyMonNicks - dw wEnemyMonNicks - dw wBoxMonNicks - dw wDayCareMonName - -Type1Text: - db "TYPE1/", $4e - -Type2Text: - db "TYPE2/", $4e - -IDNoText: - db $73, "№/", $4e - -OTText: - db "OT/" - next "@" - -StatusText: - db "STATUS/@" - -OKText: - db "OK@" - -; Draws a line starting from hl high b and wide c -DrawLineBox: - ld de, SCREEN_WIDTH ; New line -.PrintVerticalLine - ld [hl], $78 ; │ - add hl, de - dec b - jr nz, .PrintVerticalLine - ld [hl], $77 ; ┘ - dec hl -.PrintHorizLine - ld [hl], $76 ; ─ - dec hl - dec c - jr nz, .PrintHorizLine - ld [hl], $6f ; ← (halfarrow ending) - ret - -PTile: ; This is a single 1bpp "P" tile - INCBIN "gfx/p_tile.1bpp" -PTileEnd: - -PrintStatsBox: - ld a, d - and a ; a is 0 from the status screen - jr nz, .DifferentBox - coord hl, 0, 8 - lb bc, 8, 8 - call TextBoxBorder ; Draws the box - coord hl, 1, 9 ; Start printing stats from here - ld bc, $0019 ; Number offset - jr .PrintStats -.DifferentBox - coord hl, 9, 2 - lb bc, 8, 9 - call TextBoxBorder - coord hl, 11, 3 - ld bc, $0018 -.PrintStats - push bc - push hl - ld de, StatsText - call PlaceString - pop hl - pop bc - add hl, bc - ld de, wLoadedMonAttack - lb bc, 2, 3 - call PrintStat - ld de, wLoadedMonDefense - call PrintStat - ld de, wLoadedMonSpeed - call PrintStat - ld de, wLoadedMonSpecial - jp PrintNumber -PrintStat: - push hl - call PrintNumber - pop hl - ld de, SCREEN_WIDTH * 2 - add hl, de - ret - -StatsText: - db "ATTACK" - next "DEFENSE" - next "SPEED" - next "SPECIAL@" - -StatusScreen2: - ld a, [hTilesetType] - push af - xor a - ld [hTilesetType], a - ld [H_AUTOBGTRANSFERENABLED], a - ld bc, NUM_MOVES + 1 - ld hl, wMoves - call FillMemory - ld hl, wLoadedMonMoves - ld de, wMoves - ld bc, NUM_MOVES - call CopyData - callab FormatMovesString - coord hl, 9, 2 - lb bc, 5, 10 - call ClearScreenArea ; Clear under name - coord hl, 19, 3 - ld [hl], $78 - coord hl, 0, 8 - lb bc, 8, 18 - call TextBoxBorder ; Draw move container - coord hl, 2, 9 - ld de, wMovesString - call PlaceString ; Print moves - ld a, [wNumMovesMinusOne] - inc a - ld c, a - ld a, $4 - sub c - ld b, a ; Number of moves ? - coord hl, 11, 10 - ld de, SCREEN_WIDTH * 2 - ld a, $72 ; special P tile id - call StatusScreen_PrintPP ; Print "PP" - ld a, b - and a - jr z, .InitPP - ld c, a - ld a, "-" - call StatusScreen_PrintPP ; Fill the rest with -- -.InitPP - ld hl, wLoadedMonMoves - coord de, 14, 10 - ld b, 0 -.PrintPP - ld a, [hli] - and a - jr z, .PPDone - push bc - push hl - push de - ld hl, wCurrentMenuItem - ld a, [hl] - push af - ld a, b - ld [hl], a - push hl - callab GetMaxPP - pop hl - pop af - ld [hl], a - pop de - pop hl - push hl - ld bc, wPartyMon1PP - wPartyMon1Moves - 1 - add hl, bc - ld a, [hl] - and $3f - ld [wStatusScreenCurrentPP], a - ld h, d - ld l, e - push hl - ld de, wStatusScreenCurrentPP - lb bc, 1, 2 - call PrintNumber - ld a, "/" - ld [hli], a - ld de, wMaxPP - lb bc, 1, 2 - call PrintNumber - pop hl - ld de, SCREEN_WIDTH * 2 - add hl, de - ld d, h - ld e, l - pop hl - pop bc - inc b - ld a, b - cp $4 - jr nz, .PrintPP -.PPDone - coord hl, 9, 3 - ld de, StatusScreenExpText - call PlaceString - ld a, [wLoadedMonLevel] - push af - cp MAX_LEVEL - jr z, .Level100 - inc a - ld [wLoadedMonLevel], a ; Increase temporarily if not 100 -.Level100 - coord hl, 14, 6 - ld [hl], $70 ; 1-tile "to" - inc hl - inc hl - call PrintLevel - pop af - ld [wLoadedMonLevel], a - ld de, wLoadedMonExp - coord hl, 12, 4 - lb bc, 3, 7 - call PrintNumber ; exp - call CalcExpToLevelUp - ld de, wLoadedMonExp - coord hl, 7, 6 - lb bc, 3, 7 - call PrintNumber ; exp needed to level up - coord hl, 9, 0 - call StatusScreen_ClearName - coord hl, 9, 1 - call StatusScreen_ClearName - ld a, [wMonHIndex] - ld [wd11e], a - call GetMonName - coord hl, 9, 1 - call PlaceString - ld a, $1 - ld [H_AUTOBGTRANSFERENABLED], a - call Delay3 - call WaitForTextScrollButtonPress ; wait for button - pop af - ld [hTilesetType], a - ld hl, wd72c - res 1, [hl] - ld a, $77 - ld [rNR50], a - call GBPalWhiteOut - jp ClearScreen - -CalcExpToLevelUp: - ld a, [wLoadedMonLevel] - cp MAX_LEVEL - jr z, .atMaxLevel - inc a - ld d, a - callab CalcExperience - ld hl, wLoadedMonExp + 2 - ld a, [hExperience + 2] - sub [hl] - ld [hld], a - ld a, [hExperience + 1] - sbc [hl] - ld [hld], a - ld a, [hExperience] - sbc [hl] - ld [hld], a - ret -.atMaxLevel - ld hl, wLoadedMonExp - xor a - ld [hli], a - ld [hli], a - ld [hl], a - ret - -StatusScreenExpText: - db "EXP POINTS" - next "LEVEL UP@" - -StatusScreen_ClearName: - ld bc, 10 - ld a, " " - jp FillMemory - -StatusScreen_PrintPP: -; print PP or -- c times, going down two rows each time - ld [hli], a - ld [hld], a - add hl, de - dec c - jr nz, StatusScreen_PrintPP - ret diff --git a/engine/menu/swap_items.asm b/engine/menu/swap_items.asm deleted file mode 100644 index 563fc7d5..00000000 --- a/engine/menu/swap_items.asm +++ /dev/null @@ -1,149 +0,0 @@ -HandleItemListSwapping: - ld a, [wListMenuID] - cp ITEMLISTMENU - jp nz, DisplayListMenuIDLoop ; only rearrange item list menus - push hl - ld hl, wListPointer - ld a, [hli] - ld h, [hl] - ld l, a - inc hl ; hl = beginning of list entries - ld a, [wCurrentMenuItem] - ld b, a - ld a, [wListScrollOffset] - add b - add a - ld c, a - ld b, 0 - add hl, bc ; hl = address of currently selected item entry - ld a, [hl] - pop hl - inc a - jp z, DisplayListMenuIDLoop ; ignore attempts to swap the Cancel menu item - ld a, [wMenuItemToSwap] ; ID of item chosen for swapping (counts from 1) - and a ; has the first item to swap already been chosen? - jr nz, .swapItems -; if not, set the currently selected item as the first item - ld a, [wCurrentMenuItem] - inc a - ld b, a - ld a, [wListScrollOffset] ; index of top (visible) menu item within the list - add b - ld [wMenuItemToSwap], a ; ID of item chosen for swapping (counts from 1) - ld c, 20 - call DelayFrames - jp DisplayListMenuIDLoop -.swapItems - ld a, [wCurrentMenuItem] - inc a - ld b, a - ld a, [wListScrollOffset] - add b - ld b, a - ld a, [wMenuItemToSwap] ; ID of item chosen for swapping (counts from 1) - cp b ; is the currently selected item the same as the first item to swap? - jp z, DisplayListMenuIDLoop ; ignore attempts to swap an item with itself - dec a - ld [wMenuItemToSwap], a ; ID of item chosen for swapping (counts from 1) - ld c, 20 - call DelayFrames - push hl - push de - ld hl, wListPointer - ld a, [hli] - ld h, [hl] - ld l, a - inc hl ; hl = beginning of list entries - ld d, h - ld e, l ; de = beginning of list entries - ld a, [wCurrentMenuItem] - ld b, a - ld a, [wListScrollOffset] - add b - add a - ld c, a - ld b, 0 - add hl, bc ; hl = address of currently selected item entry - ld a, [wMenuItemToSwap] ; ID of item chosen for swapping (counts from 1) - add a - add e - ld e, a - jr nc, .noCarry - inc d -.noCarry ; de = address of first item to swap - ld a, [de] - ld b, a - ld a, [hli] - cp b - jr z, .swapSameItemType -.swapDifferentItems - ld [$ff95], a ; [$ff95] = second item ID - ld a, [hld] - ld [$ff96], a ; [$ff96] = second item quantity - ld a, [de] - ld [hli], a ; put first item ID in second item slot - inc de - ld a, [de] - ld [hl], a ; put first item quantity in second item slot - ld a, [$ff96] - ld [de], a ; put second item quantity in first item slot - dec de - ld a, [$ff95] - ld [de], a ; put second item ID in first item slot - xor a - ld [wMenuItemToSwap], a ; 0 means no item is currently being swapped - pop de - pop hl - jp DisplayListMenuIDLoop -.swapSameItemType - inc de - ld a, [hl] - ld b, a - ld a, [de] - add b ; a = sum of both item quantities - cp 100 ; is the sum too big for one item slot? - jr c, .combineItemSlots -; swap enough items from the first slot to max out the second slot if they can't be combined - sub 99 - ld [de], a - ld a, 99 - ld [hl], a - jr .done -.combineItemSlots - ld [hl], a ; put the sum in the second item slot - ld hl, wListPointer - ld a, [hli] - ld h, [hl] - ld l, a - dec [hl] ; decrease the number of items - ld a, [hl] - ld [wListCount], a ; update number of items variable - cp 1 - jr nz, .skipSettingMaxMenuItemID - ld [wMaxMenuItem], a ; if the number of items is only one now, update the max menu item ID -.skipSettingMaxMenuItemID - dec de - ld h, d - ld l, e - inc hl - inc hl ; hl = address of item after first item to swap -.moveItemsUpLoop ; erase the first item slot and move up all the following item slots to fill the gap - ld a, [hli] - ld [de], a - inc de - inc a ; reached the $ff terminator? - jr z, .afterMovingItemsUp - ld a, [hli] - ld [de], a - inc de - jr .moveItemsUpLoop -.afterMovingItemsUp - xor a - ld [wListScrollOffset], a - ld [wCurrentMenuItem], a -.done - xor a - ld [wMenuItemToSwap], a ; 0 means no item is currently being swapped - pop de - pop hl - jp DisplayListMenuIDLoop diff --git a/engine/menu/text_box.asm b/engine/menu/text_box.asm deleted file mode 100644 index a109bff2..00000000 --- a/engine/menu/text_box.asm +++ /dev/null @@ -1,739 +0,0 @@ -; function to draw various text boxes -DisplayTextBoxID_: - ld a, [wTextBoxID] - cp TWO_OPTION_MENU - jp z, DisplayTwoOptionMenu - ld c, a - ld hl, TextBoxFunctionTable - ld de, 3 - call SearchTextBoxTable - jr c, .functionTableMatch - ld hl, TextBoxCoordTable - ld de, 5 - call SearchTextBoxTable - jr c, .coordTableMatch - ld hl, TextBoxTextAndCoordTable - ld de, 9 - call SearchTextBoxTable - jr c, .textAndCoordTableMatch -.done - ret -.functionTableMatch - ld a, [hli] - ld h, [hl] - ld l, a ; hl = address of function - ld de, .done - push de - jp hl ; jump to the function -.coordTableMatch - call GetTextBoxIDCoords - call GetAddressOfScreenCoords - call TextBoxBorder - ret -.textAndCoordTableMatch - call GetTextBoxIDCoords - push hl - call GetAddressOfScreenCoords - call TextBoxBorder - pop hl - call GetTextBoxIDText - ld a, [wd730] - push af - ld a, [wd730] - set 6, a ; no pauses between printing each letter - ld [wd730], a - call PlaceString - pop af - ld [wd730], a - call UpdateSprites - ret - -; function to search a table terminated with $ff for a byte matching c in increments of de -; sets carry flag if a match is found and clears carry flag if not -SearchTextBoxTable: - dec de -.loop - ld a, [hli] - cp $ff - jr z, .notFound - cp c - jr z, .found - add hl, de - jr .loop -.found - scf -.notFound - ret - -; function to load coordinates from the TextBoxCoordTable or the TextBoxTextAndCoordTable -; INPUT: -; hl = address of coordinates -; OUTPUT: -; b = height -; c = width -; d = row of upper left corner -; e = column of upper left corner -GetTextBoxIDCoords: - ld a, [hli] ; column of upper left corner - ld e, a - ld a, [hli] ; row of upper left corner - ld d, a - ld a, [hli] ; column of lower right corner - sub e - dec a - ld c, a ; c = width - ld a, [hli] ; row of lower right corner - sub d - dec a - ld b, a ; b = height - ret - -; function to load a text address and text coordinates from the TextBoxTextAndCoordTable -GetTextBoxIDText: - ld a, [hli] - ld e, a - ld a, [hli] - ld d, a ; de = address of text - push de ; save text address - ld a, [hli] - ld e, a ; column of upper left corner of text - ld a, [hl] - ld d, a ; row of upper left corner of text - call GetAddressOfScreenCoords - pop de ; restore text address - ret - -; function to point hl to the screen coordinates -; INPUT: -; d = row -; e = column -; OUTPUT: -; hl = address of upper left corner of text box -GetAddressOfScreenCoords: - push bc - coord hl, 0, 0 - ld bc, 20 -.loop ; loop to add d rows to the base address - ld a, d - and a - jr z, .addedRows - add hl, bc - dec d - jr .loop -.addedRows - pop bc - add hl, de - ret - -; Format: -; 00: text box ID -; 01-02: function address -TextBoxFunctionTable: - dbw MONEY_BOX, DisplayMoneyBox - dbw BUY_SELL_QUIT_MENU, DoBuySellQuitMenu - dbw FIELD_MOVE_MON_MENU, DisplayFieldMoveMonMenu - db $ff ; terminator - -; Format: -; 00: text box ID -; 01: column of upper left corner -; 02: row of upper left corner -; 03: column of lower right corner -; 04: row of lower right corner -TextBoxCoordTable: - db MESSAGE_BOX, 0, 12, 19, 17 - db $03, 0, 0, 19, 14 - db $07, 0, 0, 11, 6 - db LIST_MENU_BOX, 4, 2, 19, 12 - db $10, 7, 0, 19, 17 - db MON_SPRITE_POPUP, 6, 4, 14, 13 - db $ff ; terminator - -; Format: -; 00: text box ID -; 01: column of upper left corner -; 02: row of upper left corner -; 03: column of lower right corner -; 04: row of lower right corner -; 05-06: address of text -; 07: column of beginning of text -; 08: row of beginning of text -; table of window positions and corresponding text [key, start column, start row, end column, end row, text pointer [2 bytes], text column, text row] -TextBoxTextAndCoordTable: - db JP_MOCHIMONO_MENU_TEMPLATE - db 0,0,14,17 ; text box coordinates - dw JapaneseMochimonoText - db 3,0 ; text coordinates - - db USE_TOSS_MENU_TEMPLATE - db 13,10,19,14 ; text box coordinates - dw UseTossText - db 15,11 ; text coordinates - - db JP_SAVE_MESSAGE_MENU_TEMPLATE - db 0,0,7,5 ; text box coordinates - dw JapaneseSaveMessageText - db 2,2 ; text coordinates - - db JP_SPEED_OPTIONS_MENU_TEMPLATE - db 0,6,5,10 ; text box coordinates - dw JapaneseSpeedOptionsText - db 2,7 ; text coordinates - - db BATTLE_MENU_TEMPLATE - db 8,12,19,17 ; text box coordinates - dw BattleMenuText - db 10,14 ; text coordinates - - db SAFARI_BATTLE_MENU_TEMPLATE - db 0,12,19,17 ; text box coordinates - dw SafariZoneBattleMenuText - db 2,14 ; text coordinates - - db SWITCH_STATS_CANCEL_MENU_TEMPLATE - db 11,11,19,17 ; text box coordinates - dw SwitchStatsCancelText - db 13,12 ; text coordinates - - db BUY_SELL_QUIT_MENU_TEMPLATE - db 0,0,10,6 ; text box coordinates - dw BuySellQuitText - db 2,1 ; text coordinates - - db MONEY_BOX_TEMPLATE - db 11,0,19,2 ; text box coordinates - dw MoneyText - db 13,0 ; text coordinates - - db JP_AH_MENU_TEMPLATE - db 7,6,11,10 ; text box coordinates - dw JapaneseAhText - db 8,8 ; text coordinates - - db JP_POKEDEX_MENU_TEMPLATE - db 11,8,19,17 ; text box coordinates - dw JapanesePokedexMenu - db 12,10 ; text coordinates - -; note that there is no terminator - -BuySellQuitText: - db "BUY" - next "SELL" - next "QUIT@@" - -UseTossText: - db "USE" - next "TOSS@" - -JapaneseSaveMessageText: - db "きろく" - next "メッセージ@" - -JapaneseSpeedOptionsText: - db "はやい" - next "おそい@" - -MoneyText: - db "MONEY@" - -JapaneseMochimonoText: - db "もちもの@" - -JapaneseMainMenuText: - db "つづきから" - next "さいしょから@" - -BattleMenuText: - db "FIGHT ",$E1,$E2 - next "ITEM RUN@" - -SafariZoneBattleMenuText: - db "BALL× BAIT" - next "THROW ROCK RUN@" - -SwitchStatsCancelText: - db "SWITCH" - next "STATS" - next "CANCEL@" - -JapaneseAhText: - db "アッ!@" - -JapanesePokedexMenu: - db "データをみる" - next "なきごえ" - next "ぶんぷをみる" - next "キャンセル@" - -DisplayMoneyBox: - ld hl, wd730 - set 6, [hl] - ld a, MONEY_BOX_TEMPLATE - ld [wTextBoxID], a - call DisplayTextBoxID - coord hl, 13, 1 - lb bc, 1, 6 - call ClearScreenArea - coord hl, 12, 1 - ld de, wPlayerMoney - ld c, $a3 - call PrintBCDNumber - ld hl, wd730 - res 6, [hl] - ret - -CurrencyString: - db " ¥@" - -DoBuySellQuitMenu: - ld a, [wd730] - set 6, a ; no printing delay - ld [wd730], a - xor a - ld [wChosenMenuItem], a - ld a, BUY_SELL_QUIT_MENU_TEMPLATE - ld [wTextBoxID], a - call DisplayTextBoxID - ld a, A_BUTTON | B_BUTTON - ld [wMenuWatchedKeys], a - ld a, $2 - ld [wMaxMenuItem], a - ld a, $1 - ld [wTopMenuItemY], a - ld a, $1 - ld [wTopMenuItemX], a - xor a - ld [wCurrentMenuItem], a - ld [wLastMenuItem], a - ld [wMenuWatchMovingOutOfBounds], a - ld a, [wd730] - res 6, a ; turn on the printing delay - ld [wd730], a - call HandleMenuInput - call PlaceUnfilledArrowMenuCursor - bit 0, a ; was A pressed? - jr nz, .pressedA - bit 1, a ; was B pressed? (always true since only A/B are watched) - jr z, .pressedA - ld a, CANCELLED_MENU - ld [wMenuExitMethod], a - jr .quit -.pressedA - ld a, CHOSE_MENU_ITEM - ld [wMenuExitMethod], a - ld a, [wCurrentMenuItem] - ld [wChosenMenuItem], a - ld b, a - ld a, [wMaxMenuItem] - cp b - jr z, .quit - ret -.quit - ld a, CANCELLED_MENU - ld [wMenuExitMethod], a - ld a, [wCurrentMenuItem] - ld [wChosenMenuItem], a - scf - ret - -; displays a menu with two options to choose from -; b = Y of upper left corner of text region -; c = X of upper left corner of text region -; hl = address where the text box border should be drawn -DisplayTwoOptionMenu: - push hl - ld a, [wd730] - set 6, a ; no printing delay - ld [wd730], a - -; pointless because both values are overwritten before they are read - xor a - ld [wChosenMenuItem], a - ld [wMenuExitMethod], a - - ld a, A_BUTTON | B_BUTTON - ld [wMenuWatchedKeys], a - ld a, $1 - ld [wMaxMenuItem], a - ld a, b - ld [wTopMenuItemY], a - ld a, c - ld [wTopMenuItemX], a - xor a - ld [wLastMenuItem], a - ld [wMenuWatchMovingOutOfBounds], a - push hl - ld hl, wTwoOptionMenuID - bit 7, [hl] ; select second menu item by default? - res 7, [hl] - jr z, .storeCurrentMenuItem - inc a -.storeCurrentMenuItem - ld [wCurrentMenuItem], a - pop hl - push hl - push hl - call TwoOptionMenu_SaveScreenTiles - ld a, [wTwoOptionMenuID] - ld hl, TwoOptionMenuStrings - ld e, a - ld d, $0 - ld a, $5 -.menuStringLoop - add hl, de - dec a - jr nz, .menuStringLoop - ld a, [hli] - ld c, a - ld a, [hli] - ld b, a - ld e, l - ld d, h - pop hl - push de - ld a, [wTwoOptionMenuID] - cp TRADE_CANCEL_MENU - jr nz, .notTradeCancelMenu - call CableClub_TextBoxBorder - jr .afterTextBoxBorder -.notTradeCancelMenu - call TextBoxBorder -.afterTextBoxBorder - call UpdateSprites - pop hl - ld a, [hli] - and a ; put blank line before first menu item? - ld bc, 20 + 2 - jr z, .noBlankLine - ld bc, 2 * 20 + 2 -.noBlankLine - ld a, [hli] - ld e, a - ld a, [hli] - ld d, a - pop hl - add hl, bc - call PlaceString - xor a - ld [wTwoOptionMenuID], a - ld hl, wd730 - res 6, [hl] ; turn on the printing delay - call HandleMenuInput - pop hl - bit 1, a ; A button pressed? - jr nz, .choseSecondMenuItem ; automatically choose the second option if B is pressed -.pressedAButton - ld a, [wCurrentMenuItem] - ld [wChosenMenuItem], a - and a - jr nz, .choseSecondMenuItem -; chose first menu item - ld a, CHOSE_FIRST_ITEM - ld [wMenuExitMethod], a - ld c, 15 - call DelayFrames - call TwoOptionMenu_RestoreScreenTiles - and a - ret -.choseSecondMenuItem - ld a, 1 - ld [wCurrentMenuItem], a - ld [wChosenMenuItem], a - ld a, CHOSE_SECOND_ITEM - ld [wMenuExitMethod], a - ld c, 15 - call DelayFrames - call TwoOptionMenu_RestoreScreenTiles - scf - ret - -; Some of the wider/taller two option menus will not have the screen areas -; they cover be fully saved/restored by the two functions below. -; The bottom and right edges of the menu may remain after the function returns. - -TwoOptionMenu_SaveScreenTiles: - ld de, wBuffer - lb bc, 5, 6 -.loop - ld a, [hli] - ld [de], a - inc de - dec c - jr nz, .loop - push bc - ld bc, SCREEN_WIDTH - 6 - add hl, bc - pop bc - ld c, $6 - dec b - jr nz, .loop - ret - -TwoOptionMenu_RestoreScreenTiles: - ld de, wBuffer - lb bc, 5, 6 -.loop - ld a, [de] - inc de - ld [hli], a - dec c - jr nz, .loop - push bc - ld bc, SCREEN_WIDTH - 6 - add hl, bc - pop bc - ld c, 6 - dec b - jr nz, .loop - call UpdateSprites - ret - -; Format: -; 00: byte width -; 01: byte height -; 02: byte put blank line before first menu item -; 03: word text pointer -TwoOptionMenuStrings: - db 4,3,0 - dw .YesNoMenu - db 6,3,0 - dw .NorthWestMenu - db 6,3,0 - dw .SouthEastMenu - db 6,3,0 - dw .YesNoMenu - db 6,3,0 - dw .NorthEastMenu - db 7,3,0 - dw .TradeCancelMenu - db 7,4,1 - dw .HealCancelMenu - db 4,3,0 - dw .NoYesMenu - -.NoYesMenu - db "NO" - next "YES@" -.YesNoMenu - db "YES" - next "NO@" -.NorthWestMenu - db "NORTH" - next "WEST@" -.SouthEastMenu - db "SOUTH" - next "EAST@" -.NorthEastMenu - db "NORTH" - next "EAST@" -.TradeCancelMenu - db "TRADE" - next "CANCEL@" -.HealCancelMenu - db "HEAL" - next "CANCEL@" - -DisplayFieldMoveMonMenu: - xor a - ld hl, wFieldMoves - ld [hli], a ; wFieldMoves - ld [hli], a ; wFieldMoves + 1 - ld [hli], a ; wFieldMoves + 2 - ld [hli], a ; wFieldMoves + 3 - ld [hli], a ; wNumFieldMoves - ld [hl], 12 ; wFieldMovesLeftmostXCoord - call GetMonFieldMoves - ld a, [wNumFieldMoves] - and a - jr nz, .fieldMovesExist - -; no field moves - coord hl, 11, 11 - lb bc, 5, 7 - call TextBoxBorder - call UpdateSprites - ld a, 12 - ld [hFieldMoveMonMenuTopMenuItemX], a - coord hl, 13, 12 - ld de, PokemonMenuEntries - jp PlaceString - -.fieldMovesExist - push af - -; Calculate the text box position and dimensions based on the leftmost X coord -; of the field move names before adjusting for the number of field moves. - coord hl, 0, 11 - ld a, [wFieldMovesLeftmostXCoord] - dec a - ld e, a - ld d, 0 - add hl, de - ld b, 5 - ld a, 18 - sub e - ld c, a - pop af - -; For each field move, move the top of the text box up 2 rows while the leaving -; the bottom of the text box at the bottom of the screen. - ld de, -SCREEN_WIDTH * 2 -.textBoxHeightLoop - add hl, de - inc b - inc b - dec a - jr nz, .textBoxHeightLoop - -; Make space for an extra blank row above the top field move. - ld de, -SCREEN_WIDTH - add hl, de - inc b - - call TextBoxBorder - call UpdateSprites - -; Calculate the position of the first field move name to print. - coord hl, 0, 12 - ld a, [wFieldMovesLeftmostXCoord] - inc a - ld e, a - ld d, 0 - add hl, de - ld de, -SCREEN_WIDTH * 2 - ld a, [wNumFieldMoves] -.calcFirstFieldMoveYLoop - add hl, de - dec a - jr nz, .calcFirstFieldMoveYLoop - - xor a - ld [wNumFieldMoves], a - ld de, wFieldMoves -.printNamesLoop - push hl - ld hl, FieldMoveNames - ld a, [de] - and a - jr z, .donePrintingNames - inc de - ld b, a ; index of name -.skipNamesLoop ; skip past names before the name we want - dec b - jr z, .reachedName -.skipNameLoop ; skip past current name - ld a, [hli] - cp "@" - jr nz, .skipNameLoop - jr .skipNamesLoop -.reachedName - ld b, h - ld c, l - pop hl - push de - ld d, b - ld e, c - call PlaceString - ld bc, SCREEN_WIDTH * 2 - add hl, bc - pop de - jr .printNamesLoop - -.donePrintingNames - pop hl - ld a, [wFieldMovesLeftmostXCoord] - ld [hFieldMoveMonMenuTopMenuItemX], a - coord hl, 0, 12 - ld a, [wFieldMovesLeftmostXCoord] - inc a - ld e, a - ld d, 0 - add hl, de - ld de, PokemonMenuEntries - jp PlaceString - -FieldMoveNames: - db "CUT@" - db "FLY@" - db "@" - db "SURF@" - db "STRENGTH@" - db "FLASH@" - db "DIG@" - db "TELEPORT@" - db "SOFTBOILED@" - -PokemonMenuEntries: - db "STATS" - next "SWITCH" - next "CANCEL@" - -GetMonFieldMoves: - ld a, [wWhichPokemon] - ld hl, wPartyMon1Moves - ld bc, wPartyMon2 - wPartyMon1 - call AddNTimes - ld d, h - ld e, l - ld c, NUM_MOVES + 1 - ld hl, wFieldMoves -.loop - push hl -.nextMove - dec c - jr z, .done - ld a, [de] ; move ID - and a - jr z, .done - ld b, a - inc de - ld hl, FieldMoveDisplayData -.fieldMoveLoop - ld a, [hli] - cp $ff - jr z, .nextMove ; if the move is not a field move - cp b - jr z, .foundFieldMove - inc hl - inc hl - jr .fieldMoveLoop -.foundFieldMove - ld a, b - ld [wLastFieldMoveID], a - ld a, [hli] ; field move name index - ld b, [hl] ; field move leftmost X coordinate - pop hl - ld [hli], a ; store name index in wFieldMoves - ld a, [wNumFieldMoves] - inc a - ld [wNumFieldMoves], a - ld a, [wFieldMovesLeftmostXCoord] - cp b - jr c, .skipUpdatingLeftmostXCoord - ld a, b - ld [wFieldMovesLeftmostXCoord], a -.skipUpdatingLeftmostXCoord - ld a, [wLastFieldMoveID] - ld b, a - jr .loop -.done - pop hl - ret - -; Format: [Move id], [name index], [leftmost tile] -; Move id = id of move -; Name index = index of name in FieldMoveNames -; Leftmost tile = -1 + tile column in which the first letter of the move's name should be displayed -; "SOFTBOILED" is $08 because it has 4 more letters than "SURF", for example, whose value is $0C -FieldMoveDisplayData: - db CUT, $01, $0C - db FLY, $02, $0C - db $B4, $03, $0C ; unused field move - db SURF, $04, $0C - db STRENGTH, $05, $0A - db FLASH, $06, $0C - db DIG, $07, $0C - db TELEPORT, $08, $0A - db SOFTBOILED, $09, $08 - db $ff ; list terminator diff --git a/engine/menu/vending_machine.asm b/engine/menu/vending_machine.asm deleted file mode 100755 index 37d9b9e7..00000000 --- a/engine/menu/vending_machine.asm +++ /dev/null @@ -1,138 +0,0 @@ -VendingMachineMenu: - ld hl, VendingMachineText1 - call PrintText - ld a, MONEY_BOX - ld [wTextBoxID], a - call DisplayTextBoxID - xor a - ld [wCurrentMenuItem], a - ld [wLastMenuItem], a - ld a, A_BUTTON | B_BUTTON - ld [wMenuWatchedKeys], a - ld a, 3 - ld [wMaxMenuItem], a - ld a, 5 - ld [wTopMenuItemY], a - ld a, 1 - ld [wTopMenuItemX], a - ld hl, wd730 - set 6, [hl] - coord hl, 0, 3 - lb bc, 8, 12 - call TextBoxBorder - call UpdateSprites - coord hl, 2, 5 - ld de, DrinkText - call PlaceString - coord hl, 9, 6 - ld de, DrinkPriceText - call PlaceString - ld hl, wd730 - res 6, [hl] - call HandleMenuInput - bit 1, a ; pressed B? - jr nz, .notThirsty - ld a, [wCurrentMenuItem] - cp 3 ; chose Cancel? - jr z, .notThirsty - xor a - ld [hMoney], a - ld [hMoney + 2], a - ld a, $2 - ld [hMoney + 1], a - call HasEnoughMoney - jr nc, .enoughMoney - ld hl, VendingMachineText4 - jp PrintText -.enoughMoney - call LoadVendingMachineItem - ld a, [hVendingMachineItem] - ld b, a - ld c, 1 - call GiveItem - jr nc, .BagFull - - ld b, 60 ; number of times to play the "brrrrr" sound -.playDeliverySound - ld c, 2 - call DelayFrames - push bc - ld a, SFX_PUSH_BOULDER - call PlaySound - pop bc - dec b - jr nz, .playDeliverySound - - ld hl, VendingMachineText5 - call PrintText - ld hl, hVendingMachinePrice + 2 - ld de, wPlayerMoney + 2 - ld c, $3 - predef SubBCDPredef - ld a, MONEY_BOX - ld [wTextBoxID], a - jp DisplayTextBoxID -.BagFull - ld hl, VendingMachineText6 - jp PrintText -.notThirsty - ld hl, VendingMachineText7 - jp PrintText - -VendingMachineText1: - TX_FAR _VendingMachineText1 - db "@" - -DrinkText: - db "FRESH WATER" - next "SODA POP" - next "LEMONADE" - next "CANCEL@" - -DrinkPriceText: - db "¥200" - next "¥300" - next "¥350" - next "@" - -VendingMachineText4: - TX_FAR _VendingMachineText4 - db "@" - -VendingMachineText5: - TX_FAR _VendingMachineText5 - db "@" - -VendingMachineText6: - TX_FAR _VendingMachineText6 - db "@" - -VendingMachineText7: - TX_FAR _VendingMachineText7 - db "@" - -LoadVendingMachineItem: - ld hl, VendingPrices - ld a, [wCurrentMenuItem] - add a - add a - ld d, 0 - ld e, a - add hl, de - ld a, [hli] - ld [hVendingMachineItem], a - ld a, [hli] - ld [hVendingMachinePrice], a - ld a, [hli] - ld [hVendingMachinePrice + 1], a - ld a, [hl] - ld [hVendingMachinePrice + 2], a - ret - -VendingPrices: - db FRESH_WATER - money 200 - db SODA_POP - money 300 - db LEMONADE - money 350 diff --git a/engine/menus/display_text_id_init.asm b/engine/menus/display_text_id_init.asm new file mode 100644 index 00000000..17f290b4 --- /dev/null +++ b/engine/menus/display_text_id_init.asm @@ -0,0 +1,76 @@ +; function that performs initialization for DisplayTextID +DisplayTextIDInit:: + xor a + ld [wListMenuID], a + ld a, [wAutoTextBoxDrawingControl] + bit 0, a + jr nz, .skipDrawingTextBoxBorder + ldh a, [hSpriteIndexOrTextID] ; text ID (or sprite ID) + and a + jr nz, .notStartMenu +; if text ID is 0 (i.e. the start menu) +; Note that the start menu text border is also drawn in the function directly +; below this, so this seems unnecessary. + CheckEvent EVENT_GOT_POKEDEX +; start menu with pokedex + hlcoord 10, 0 + lb bc, 14, 8 + jr nz, .drawTextBoxBorder +; start menu without pokedex + hlcoord 10, 0 + lb bc, 12, 8 + jr .drawTextBoxBorder +; if text ID is not 0 (i.e. not the start menu) then do a standard dialogue text box +.notStartMenu + hlcoord 0, 12 + lb bc, 4, 18 +.drawTextBoxBorder + call TextBoxBorder +.skipDrawingTextBoxBorder + ld hl, wFontLoaded + set 0, [hl] + ld hl, wFlags_0xcd60 + bit 4, [hl] + res 4, [hl] + jr nz, .skipMovingSprites + call UpdateSprites +.skipMovingSprites +; loop to copy [x#SPRITESTATEDATA1_FACINGDIRECTION] to +; [x#SPRITESTATEDATA2_ORIGFACINGDIRECTION] for each non-player sprite +; this is done because when you talk to an NPC, they turn to look your way +; the original direction they were facing must be restored after the dialogue is over + ld hl, wSprite01StateData1FacingDirection + ld c, $0f + ld de, $10 +.spriteFacingDirectionCopyLoop + ld a, [hl] ; x#SPRITESTATEDATA1_FACINGDIRECTION + inc h + ld [hl], a ; [x#SPRITESTATEDATA2_ORIGFACINGDIRECTION] + dec h + add hl, de + dec c + jr nz, .spriteFacingDirectionCopyLoop +; loop to force all the sprites in the middle of animation to stand still +; (so that they don't like they're frozen mid-step during the dialogue) + ld hl, wSpritePlayerStateData1ImageIndex + ld de, $10 + ld c, e +.spriteStandStillLoop + ld a, [hl] + cp $ff ; is the sprite visible? + jr z, .nextSprite +; if it is visible + and $fc + ld [hl], a +.nextSprite + add hl, de + dec c + jr nz, .spriteStandStillLoop + ld b, $9c ; window background address + call CopyScreenTileBufferToVRAM ; transfer background in WRAM to VRAM + xor a + ldh [hWY], a ; put the window on the screen + call LoadFontTilePatterns + ld a, $01 + ldh [hAutoBGTransferEnabled], a ; enable continuous WRAM to VRAM transfer each V-blank + ret diff --git a/engine/menus/draw_badges.asm b/engine/menus/draw_badges.asm new file mode 100644 index 00000000..0bb433cc --- /dev/null +++ b/engine/menus/draw_badges.asm @@ -0,0 +1,120 @@ +DrawBadges: +; Draw 4x2 gym leader faces, with the faces replaced by +; badges if they are owned. Used in the player status screen. + +; In Japanese versions, names are displayed above faces. +; Instead of removing relevant code, the name graphics were erased. + +; Tile ids for face/badge graphics. + ld de, wBadgeOrFaceTiles + ld hl, .FaceBadgeTiles + ld bc, NUM_BADGES + call CopyData + +; Booleans for each badge. + ld hl, wTempObtainedBadgesBooleans + ld bc, NUM_BADGES + xor a + call FillMemory + +; Alter these based on owned badges. + ld de, wTempObtainedBadgesBooleans + ld hl, wBadgeOrFaceTiles + ld a, [wObtainedBadges] + ld b, a + ld c, NUM_BADGES +.CheckBadge + srl b + jr nc, .NextBadge + ld a, [hl] + add 4 ; Badge graphics are after each face + ld [hl], a + ld a, 1 + ld [de], a +.NextBadge + inc hl + inc de + dec c + jr nz, .CheckBadge + +; Draw two rows of badges. + ld hl, wBadgeNumberTile + ld a, $d8 ; [1] + ld [hli], a + ld [hl], $60 ; First name + + hlcoord 2, 11 + ld de, wTempObtainedBadgesBooleans + call .DrawBadgeRow + + hlcoord 2, 14 + ld de, wTempObtainedBadgesBooleans + 4 +; call .DrawBadgeRow +; ret + +.DrawBadgeRow +; Draw 4 badges. + + ld c, 4 +.DrawBadge + push de + push hl + +; Badge no. + ld a, [wBadgeNumberTile] + ld [hli], a + inc a + ld [wBadgeNumberTile], a + +; Names aren't printed if the badge is owned. + ld a, [de] + and a + ld a, [wBadgeNameTile] + jr nz, .SkipName + call .PlaceTiles + jr .PlaceBadge + +.SkipName + inc a + inc a + inc hl + +.PlaceBadge + ld [wBadgeNameTile], a + ld de, SCREEN_WIDTH - 1 + add hl, de + ld a, [wBadgeOrFaceTiles] + call .PlaceTiles + add hl, de + call .PlaceTiles + +; Shift badge array back one byte. + push bc + ld hl, wBadgeOrFaceTiles + 1 + ld de, wBadgeOrFaceTiles + ld bc, NUM_BADGES + call CopyData + pop bc + + pop hl + ld de, 4 + add hl, de + + pop de + inc de + dec c + jr nz, .DrawBadge + ret + +.PlaceTiles + ld [hli], a + inc a + ld [hl], a + inc a + ret + +.FaceBadgeTiles + db $20, $28, $30, $38, $40, $48, $50, $58 + +GymLeaderFaceAndBadgeTileGraphics: + INCBIN "gfx/trainer_card/badges.2bpp" diff --git a/engine/menus/draw_start_menu.asm b/engine/menus/draw_start_menu.asm new file mode 100644 index 00000000..7ca75ecb --- /dev/null +++ b/engine/menus/draw_start_menu.asm @@ -0,0 +1,87 @@ +; function that displays the start menu +DrawStartMenu:: + CheckEvent EVENT_GOT_POKEDEX +; menu with pokedex + hlcoord 10, 0 + lb bc, 14, 8 + jr nz, .drawTextBoxBorder +; shorter menu if the player doesn't have the pokedex + hlcoord 10, 0 + lb bc, 12, 8 +.drawTextBoxBorder + call TextBoxBorder + ld a, D_DOWN | D_UP | START | B_BUTTON | A_BUTTON + ld [wMenuWatchedKeys], a + ld a, $02 + ld [wTopMenuItemY], a ; Y position of first menu choice + ld a, $0b + ld [wTopMenuItemX], a ; X position of first menu choice + ld a, [wBattleAndStartSavedMenuItem] ; remembered menu selection from last time + ld [wCurrentMenuItem], a + ld [wLastMenuItem], a + xor a + ld [wMenuWatchMovingOutOfBounds], a + ld hl, wd730 + set 6, [hl] ; no pauses between printing each letter + hlcoord 12, 2 + CheckEvent EVENT_GOT_POKEDEX +; case for not having pokedex + ld a, $06 + jr z, .storeMenuItemCount +; case for having pokedex + ld de, StartMenuPokedexText + call PrintStartMenuItem + ld a, $07 +.storeMenuItemCount + ld [wMaxMenuItem], a ; number of menu items + ld de, StartMenuPokemonText + call PrintStartMenuItem + ld de, StartMenuItemText + call PrintStartMenuItem + ld de, wPlayerName ; player's name + call PrintStartMenuItem + ld a, [wd72e] + bit 6, a ; is the player using the link feature? +; case for not using link feature + ld de, StartMenuSaveText + jr z, .printSaveOrResetText +; case for using link feature + ld de, StartMenuResetText +.printSaveOrResetText + call PrintStartMenuItem + ld de, StartMenuOptionText + call PrintStartMenuItem + ld de, StartMenuExitText + call PlaceString + ld hl, wd730 + res 6, [hl] ; turn pauses between printing letters back on + ret + +StartMenuPokedexText: + db "POKéDEX@" + +StartMenuPokemonText: + db "#MON@" + +StartMenuItemText: + db "ITEM@" + +StartMenuSaveText: + db "SAVE@" + +StartMenuResetText: + db "RESET@" + +StartMenuExitText: + db "EXIT@" + +StartMenuOptionText: + db "OPTION@" + +PrintStartMenuItem: + push hl + call PlaceString + pop hl + ld de, SCREEN_WIDTH * 2 + add hl, de + ret diff --git a/engine/menus/league_pc.asm b/engine/menus/league_pc.asm new file mode 100755 index 00000000..5551fd0b --- /dev/null +++ b/engine/menus/league_pc.asm @@ -0,0 +1,119 @@ +PKMNLeaguePC: + ld hl, AccessedHoFPCText + call PrintText + ld hl, wd730 + set 6, [hl] + push hl + ld a, [wUpdateSpritesEnabled] + push af + ldh a, [hTilesetType] + push af + xor a + ldh [hTilesetType], a + ld [wSpriteFlipped], a + ld [wUpdateSpritesEnabled], a + ld [wHoFTeamIndex2], a + ld [wHoFTeamNo], a + ld a, [wNumHoFTeams] + ld b, a + cp HOF_TEAM_CAPACITY + 1 + jr c, .loop +; If the total number of hall of fame teams is greater than the storage +; capacity, then calculate the number of the first team that is still recorded. + ld b, HOF_TEAM_CAPACITY + sub b + ld [wHoFTeamNo], a +.loop + ld hl, wHoFTeamNo + inc [hl] + push bc + ld a, [wHoFTeamIndex2] + ld [wHoFTeamIndex], a + farcall LoadHallOfFameTeams + call LeaguePCShowTeam + pop bc + jr c, .doneShowingTeams + ld hl, wHoFTeamIndex2 + inc [hl] + ld a, [hl] + cp b + jr nz, .loop +.doneShowingTeams + pop af + ldh [hTilesetType], a + pop af + ld [wUpdateSpritesEnabled], a + pop hl + res 6, [hl] + call GBPalWhiteOutWithDelay3 + call ClearScreen + call RunDefaultPaletteCommand + jp GBPalNormal + +LeaguePCShowTeam: + ld c, PARTY_LENGTH +.loop + push bc + call LeaguePCShowMon + call WaitForTextScrollButtonPress + ldh a, [hJoyHeld] + bit 1, a + jr nz, .exit + ld hl, wHallOfFame + HOF_MON + ld de, wHallOfFame + ld bc, HOF_TEAM - HOF_MON + call CopyData + pop bc + ld a, [wHallOfFame + 0] + cp $ff + jr z, .done + dec c + jr nz, .loop +.done + and a + ret +.exit + pop bc + scf + ret + +LeaguePCShowMon: + call GBPalWhiteOutWithDelay3 + call ClearScreen + ld hl, wHallOfFame + ld a, [hli] + ld [wHoFMonSpecies], a + ld [wcf91], a + ld [wd0b5], a + ld [wBattleMonSpecies2], a + ld [wWholeScreenPaletteMonSpecies], a + ld a, [hli] + ld [wHoFMonLevel], a + ld de, wcd6d + ld bc, NAME_LENGTH + call CopyData + ld b, SET_PAL_POKEMON_WHOLE_SCREEN + ld c, 0 + call RunPaletteCommand + hlcoord 12, 5 + call GetMonHeader + call LoadFrontSpriteByMonIndex + call GBPalNormal + hlcoord 0, 13 + lb bc, 2, 18 + call TextBoxBorder + hlcoord 1, 15 + ld de, HallOfFameNoText + call PlaceString + hlcoord 16, 15 + ld de, wHoFTeamNo + lb bc, 1, 3 + call PrintNumber + farjp Func_7033f + +HallOfFameNoText: + db "HALL OF FAME No @" + +AccessedHoFPCText: + text_far _AccessedHoFPCText + text_end diff --git a/engine/menus/link_menu.asm b/engine/menus/link_menu.asm new file mode 100644 index 00000000..2f2db573 --- /dev/null +++ b/engine/menus/link_menu.asm @@ -0,0 +1,910 @@ +Func_f531b:: + ld c, $14 + call DelayFrames + ld a, $1 + ld [wBuffer], a + xor a + ld [wUnknownSerialFlag_d499], a + coord hl, 0, 0 + lb bc, 4, 5 + call TextBoxBorder + ld de, Text_f5791 + coord hl, 1, 2 + call PlaceString + coord hl, 8, 0 + lb bc, 8, 10 + call TextBoxBorder + coord hl, 10, 2 + ld de, Text_f579c + call PlaceString + coord hl, 0, 10 + lb bc, 6, 18 + call TextBoxBorder + call UpdateSprites + xor a + ld [wUnusedCD37], a + ld [wd72d], a + ld [wd11e], a + ld hl, wTopMenuItemY + ld a, $2 + ld [hli], a + ld a, $9 + ld [hli], a + xor a + ld [hli], a + inc hl + ld a, $3 + ld [hli], a + ld a, $3 + ld [hli], a + xor a + ld [hl], a +.asm_f5377 + call Func_f56bd + call HandleMenuInput + and $3 + add a + add a + ld b, a + ld a, [wCurrentMenuItem] + cp $3 + jr nz, .asm_f5390 + bit 2, b + jr z, .asm_f5390 + dec a + ld b, $8 +.asm_f5390 + add b + add $c0 + ld [wLinkMenuSelectionSendBuffer], a + ld [wLinkMenuSelectionSendBuffer+1], a +.asm_f5399 + ld hl, wLinkMenuSelectionSendBuffer + ld a, [hl] + ldh [hSerialSendData], a + call Serial_ExchangeByte + push af + ld hl, wLinkMenuSelectionSendBuffer + ld a, [hl] + ldh [hSerialSendData], a + call Serial_ExchangeByte + pop bc + cp b + jr nz, .asm_f5399 + and $f0 + cp $c0 + jr nz, .asm_f5399 + ld a, b + and $c + jr nz, .asm_f53c4 + ld a, [wLinkMenuSelectionSendBuffer] + and $c + jr z, .asm_f5377 + jr .asm_f53df +.asm_f53c4 + ld a, [wLinkMenuSelectionSendBuffer] + and $c + jr z, .asm_f53d1 + ldh a, [hSerialConnectionStatus] + cp $2 + jr z, .asm_f53df +.asm_f53d1 + ld a, $1 + ld [wd11e], a + ld a, b + ld [wLinkMenuSelectionSendBuffer], a + and $3 + ld [wCurrentMenuItem], a +.asm_f53df + call DelayFrame + call DelayFrame + ld hl, wLinkMenuSelectionSendBuffer + ld a, [hl] + ldh [hSerialSendData], a + call Serial_ExchangeByte + call Serial_ExchangeByte + ld b, $14 +.loop + call DelayFrame + call Serial_SendZeroByte + dec b + jr nz, .loop + ld b, " " + ld c, " " + ld d, " " + ld e, "▷" + ld a, [wLinkMenuSelectionSendBuffer] + bit 3, a + jr nz, .asm_f541a + ld b, e + ld e, c + ld a, [wCurrentMenuItem] + and a + jr z, .asm_f541a + ld c, b + ld b, d + dec a + jr z, .asm_f541a + ld d, c + ld c, b +.asm_f541a + ld a, b + ldcoord_a 9, 2 + ld a, c + ldcoord_a 9, 4 + ld a, d + ldcoord_a 9, 6 + ld a, e + ldcoord_a 9, 8 + ld c, 40 + call DelayFrames + ld a, [wLinkMenuSelectionSendBuffer] + bit 3, a + jr nz, asm_f547f + ld a, [wCurrentMenuItem] + cp $3 + jr z, asm_f547f + inc a + ld [wUnknownSerialFlag_d499], a + ld a, [wCurrentMenuItem] + ld hl, PointerTable_f5488 + ld c, a + ld b, $0 + add hl, bc + add hl, bc + ld a, [hli] + ld h, [hl] + ld l, a + ld de, .returnaddress + push de + jp hl +.returnaddress + ld [wLinkMenuSelectionSendBuffer], a + xor a + ld [wUnknownSerialCounter], a + ld [wUnknownSerialCounter+1], a + call Serial_SyncAndExchangeNybble + ld a, [wLinkMenuSelectionSendBuffer] + and a + jr nz, asm_f547c + ld a, [wLinkMenuSelectionReceiveBuffer] + and a + jr nz, Func_f5476 + xor a + ld [wUnknownSerialCounter], a + ld [wUnknownSerialCounter+1], a + and a + ret + +Func_f5476:: + ld hl, ColosseumIneligibleText + call PrintText +asm_f547c:: + jp Func_f531b + +asm_f547f:: + xor a + ld [wUnknownSerialCounter], a + ld [wUnknownSerialCounter+1], a + scf + ret + +PointerTable_f5488:: + dw PokeCup + dw PikaCup + dw PetitCup + +PokeCup:: + ld hl, wPartyCount + ld a, [hli] + cp $3 + jp nz, NotThreeMonsInParty + ld b, $3 +.loop + ld a, [hli] + cp MEW + jp z, MewInParty + dec b + jr nz, .loop + dec hl + dec hl + cp [hl] ; is third mon second mon? + jp z, DuplicateSpecies + dec hl ; wPartySpecies + cp [hl] ; is third mon first mon? + jp z, DuplicateSpecies + ld a, [hli] + cp [hl] ; is first mon second mon? + jp z, DuplicateSpecies + ld a, [wPartyMon1Level] + cp 56 + jp nc, LevelAbove55 + cp 50 + jp c, LevelUnder50 + ld b, a + ld a, [wPartyMon2Level] + cp 56 + jp nc, LevelAbove55 + cp 50 + jp c, LevelUnder50 + ld c, a + ld a, [wPartyMon3Level] + cp 56 + jp nc, LevelAbove55 + cp 50 + jp c, LevelUnder50 + add b + add c + cp 156 + jp nc, CombinedLevelsGreaterThan155 + xor a + ret + +PikaCup:: + ld hl, wPartyCount + ld a, [hli] + cp $3 + jp nz, NotThreeMonsInParty + ld b, $3 +.loop + ld a, [hli] ; wPartySpecies + cp MEW + jp z, MewInParty + dec b + jr nz, .loop + dec hl + dec hl + cp [hl] ; is third mon second mon? + jp z, DuplicateSpecies + dec hl ; wPartySpecies + cp [hl] ; is third mon first mon? + jp z, DuplicateSpecies + ld a, [hli] + cp [hl] ; is first mon second mon? + jp z, DuplicateSpecies + ld a, [wPartyMon1Level] + cp 21 + jp nc, LevelAbove20 + cp 15 + jp c, LevelUnder15 + ld b, a + ld a, [wPartyMon2Level] + cp 21 + jp nc, LevelAbove20 + cp 15 + jp c, LevelUnder15 + ld c, a + ld a, [wPartyMon3Level] + cp 21 + jp nc, LevelAbove20 + cp 15 + jp c, LevelUnder15 + add b + add c + cp 51 + jp nc, CombinedLevelsAbove50 + xor a + ret + +PetitCup:: + ld hl, wPartyCount + ld a, [hli] + cp $3 + jp nz, NotThreeMonsInParty + ld b, $3 +.loop + ld a, [hli] + cp MEW + jp z, MewInParty + dec b + jr nz, .loop + dec hl + dec hl + cp [hl] ; is third mon second mon? + jp z, DuplicateSpecies + dec hl ; wPartySpecies + cp [hl] ; is third mon first mon? + jp z, DuplicateSpecies + ld a, [hli] + cp [hl] ; is first mon second mon? + jp z, DuplicateSpecies + dec hl + ld a, [hl] + ld [wcf91], a + push hl + callfar Func_3b10f + pop hl + jp c, asm_f56ad + inc hl + ld a, [hl] + ld [wcf91], a + push hl + callfar Func_3b10f + pop hl + jp c, asm_f56ad + inc hl + ld a, [hl] + ld [wcf91], a + push hl + callfar Func_3b10f + pop hl + jp c, asm_f56ad + dec hl + dec hl + ld b, $3 +.bigloop + ld a, [hli] + push hl + push bc + push af + dec a + ld c, a + ld b, $0 + ld hl, PokedexEntryPointers + add hl, bc + add hl, bc + ld de, wcd6d + ld bc, $2 + ld a, BANK(PokedexEntryPointers) + call FarCopyData + ld hl, wcd6d + ld a, [hli] + ld h, [hl] + ld l, a + ld de, wcd6d + ld bc, $14 + ld a, BANK(PokedexEntryPointers) + call FarCopyData + ld hl, wcd6d +.loop2 + ld a, [hli] + cp "@" + jr nz, .loop2 + ld a, [hli] + cp $7 + jp nc, asm_f5689 + add a + add a + ld b, a + add a + add b + ld b, a + ld a, [hli] + add b + cp $51 + jp nc, asm_f5689 + ld a, [hli] + sub $b9 + ld a, [hl] + sbc $1 + jp nc, asm_f569b + pop af + pop bc + pop hl + dec b + jr nz, .bigloop + ld a, [wPartyMon1Level] + cp 31 + jp nc, LevelAbove30 + cp 25 + jp c, LevelUnder25 + ld b, a + ld a, [wPartyMon2Level] + cp 31 + jp nc, LevelAbove30 + cp 25 + jp c, LevelUnder25 + ld c, a + ld a, [wPartyMon3Level] + cp 31 + jp nc, LevelAbove30 + cp 25 + jp c, LevelUnder25 + add b + add c + cp 81 + jp nc, CombinedLevelsAbove80 + xor a + ret + +NotThreeMonsInParty:: + ld hl, Colosseum3MonsText + call PrintText + ld a, $1 + ret + +MewInParty:: + ld hl, ColosseumMewText + call PrintText + ld a, $2 + ret + +DuplicateSpecies:: + ld hl, ColosseumDifferentMonsText + call PrintText + ld a, $3 + ret + +LevelAbove55:: + ld hl, ColosseumMaxL55Text + call PrintText + ld a, $4 + ret + +LevelUnder50:: + ld hl, ColosseumMinL50Text + call PrintText + ld a, $5 + ret + +CombinedLevelsGreaterThan155:: + ld hl, ColosseumTotalL155Text + call PrintText + ld a, $6 + ret + +LevelAbove30:: + ld hl, ColosseumMaxL30Text + call PrintText + ld a, $7 + ret + +LevelUnder25:: + ld hl, ColosseumMinL25Text + call PrintText + ld a, $8 + ret + +CombinedLevelsAbove80:: + ld hl, ColosseumTotalL80Text + call PrintText + ld a, $9 + ret + +LevelAbove20:: + ld hl, ColosseumMaxL20Text + call PrintText + ld a, $a + ret + +LevelUnder15:: + ld hl, ColosseumMinL15Text + call PrintText + ld a, $b + ret + +CombinedLevelsAbove50:: + ld hl, ColosseumTotalL50Text + call PrintText + ld a, $c + ret + +asm_f5689:: + pop af + pop bc + pop hl + ld [wd11e], a + call GetMonName + ld hl, ColosseumHeightText + call PrintText + ld a, $d + ret + +asm_f569b:: + pop af + pop bc + pop hl + ld [wd11e], a + call GetMonName + ld hl, ColosseumWeightText + call PrintText + ld a, $e + ret + +asm_f56ad:: + ld a, [hl] + ld [wd11e], a + call GetMonName + ld hl, ColosseumEvolvedText + call PrintText + ld a, $f + ret + +Func_f56bd:: + xor a + ldh [hAutoBGTransferEnabled], a + coord hl, 1, 11 + lb bc, 6, 18 + call ClearScreenArea + ld a, [wCurrentMenuItem] + cp $3 + jr nc, .asm_f56e6 + ld hl, PointerTable_f56ee + ld a, [wCurrentMenuItem] + ld c, a + ld b, $0 + add hl, bc + add hl, bc + ld a, [hli] + ld h, [hl] + ld l, a + ld d, h + ld e, l + coord hl, 1, 12 + call PlaceString +.asm_f56e6 + call Delay3 + ld a, $1 + ldh [hAutoBGTransferEnabled], a + ret + +PointerTable_f56ee:: + dw Text_f56f4 + dw Text_f5728 + dw Text_f575b + +Text_f56f4:: + db "LVs of 3:50-55" + next "Sum of LVs:155 MAX" + next "MEW can't attend.@" + +Text_f5728:: + db "LVs of 3:15-20" + next "Sum of LVs:50 MAX" + next "MEW can't attend.@" + +Text_f575b:: + db "3 Basic .LV25-30" + next "Sum of LVs:80 MAX" + next "6’8” and 44lb MAX@" + +Text_f5791:: + db "View" + next "Rules@" + +Text_f579c:: + db "# Cup" + next "Pika Cup" + next "Petit Cup" + next "CANCEL@" + +Colosseum3MonsText:: + text_far _Colosseum3MonsText + text_end + +ColosseumMewText:: + text_far _ColosseumMewText + text_end + +ColosseumDifferentMonsText:: + text_far _ColosseumDifferentMonsText + text_end + +ColosseumMaxL55Text:: + text_far _ColosseumMaxL55Text + text_end + +ColosseumMinL50Text:: + text_far _ColosseumMinL50Text + text_end + +ColosseumTotalL155Text:: + text_far _ColosseumTotalL155Text + text_end + +ColosseumMaxL30Text:: + text_far _ColosseumMaxL30Text + text_end + +ColosseumMinL25Text:: + text_far _ColosseumMinL25Text + text_end + +ColosseumTotalL80Text:: + text_far _ColosseumTotalL80Text + text_end + +ColosseumMaxL20Text:: + text_far _ColosseumMaxL20Text + text_end + +ColosseumMinL15Text:: + text_far _ColosseumMinL15Text + text_end + +ColosseumTotalL50Text:: + text_far _ColosseumTotalL50Text + text_end + +ColosseumHeightText:: + text_far _ColosseumHeightText + text_end + +ColosseumWeightText:: + text_far _ColosseumWeightText + text_end + +ColosseumEvolvedText:: + text_far _ColosseumEvolvedText + text_end + +ColosseumIneligibleText:: + text_far _ColosseumIneligibleText + text_end + +LinkMenu: + xor a + ld [wLetterPrintingDelayFlags], a + ld hl, wd72e + set 6, [hl] + ld hl, TextTerminator_f5a16 + call PrintText + call SaveScreenTilesToBuffer1 + ld hl, ColosseumWhereToText + call PrintText + hlcoord 5, 3 + lb bc, 8, 13 + call TextBoxBorder + call UpdateSprites + hlcoord 7, 5 + ld de, TradeCenterText + call PlaceString + xor a + ld [wUnusedCD37], a + ld [wd72d], a + ld [wd11e], a + ld hl, wTopMenuItemY + ld a, $5 + ld [hli], a + ld a, $6 + ld [hli], a + xor a + ld [hli], a + inc hl + ld a, $3 + ld [hli], a + ld [hli], a + xor a + ld [hl], a +.waitForInputLoop + call HandleMenuInput + and A_BUTTON | B_BUTTON + add a + add a + ld b, a + ld a, [wCurrentMenuItem] + cp $3 + jr nz, .asm_f586b + bit 2, b + jr z, .asm_f586b + dec a + ld b, $8 +.asm_f586b + add b + add $d0 + ld [wLinkMenuSelectionSendBuffer], a + ld [wLinkMenuSelectionSendBuffer + 1], a +.exchangeMenuSelectionLoop + call Serial_ExchangeLinkMenuSelection + ld a, [wLinkMenuSelectionReceiveBuffer] + ld b, a + and $f0 + cp $d0 + jr z, .asm_f5c7d + ld a, [wLinkMenuSelectionReceiveBuffer + 1] + ld b, a + and $f0 + cp $d0 + jr nz, .exchangeMenuSelectionLoop +.asm_f5c7d + ld a, b + and $c ; did the enemy press A or B? + jr nz, .enemyPressedAOrB +; the enemy didn't press A or B + ld a, [wLinkMenuSelectionSendBuffer] + and $c ; did the player press A or B? + jr z, .waitForInputLoop ; if neither the player nor the enemy pressed A or B, try again + jr .doneChoosingMenuSelection ; if the player pressed A or B but the enemy didn't, use the player's selection +.enemyPressedAOrB + ld a, [wLinkMenuSelectionSendBuffer] + and $c ; did the player press A or B? + jr z, .useEnemyMenuSelection ; if the enemy pressed A or B but the player didn't, use the enemy's selection +; the enemy and the player both pressed A or B +; The gameboy that is clocking the connection wins. + ldh a, [hSerialConnectionStatus] + cp USING_INTERNAL_CLOCK + jr z, .doneChoosingMenuSelection +.useEnemyMenuSelection + ld a, $1 + ld [wd11e], a + ld a, b + ld [wLinkMenuSelectionSendBuffer], a + and $3 + ld [wCurrentMenuItem], a ; wCurrentMenuItem +.doneChoosingMenuSelection + ldh a, [hSerialConnectionStatus] + cp USING_INTERNAL_CLOCK + jr nz, .skipStartingTransfer + call DelayFrame + call DelayFrame + ld a, START_TRANSFER_INTERNAL_CLOCK + ldh [rSC], a +.skipStartingTransfer + ld b, " " + ld c, " " + ld d, " " + ld e, "▷" + ld a, [wLinkMenuSelectionSendBuffer] + and (B_BUTTON << 2) ; was B button pressed? + jr nz, .updateCursorPosition +; A button was pressed + ld a, [wCurrentMenuItem] + cp $2 + jp z, .asm_f5963 + ld b, e + ld e, c + ld a, [wCurrentMenuItem] + and a + jr z, .updateCursorPosition + ld c, b + ld b, d + dec a + jr z, .updateCursorPosition + ld d, c + ld c, b +.updateCursorPosition + call Func_f59ec + call LoadScreenTilesFromBuffer1 + ld a, [wLinkMenuSelectionSendBuffer] + and (B_BUTTON << 2) ; was B button pressed? + jr nz, .choseCancel ; cancel if B pressed + ld a, [wCurrentMenuItem] + cp $2 + jr z, .choseCancel + xor a + ld [wWalkBikeSurfState], a ; start walking + ld a, [wCurrentMenuItem] + and a + ld a, COLOSSEUM + jr nz, .next + ld a, TRADE_CENTER +.next + ld [wd72d], a + ld hl, ColosseumPleaseWaitText + call PrintText + ld c, 50 + call DelayFrames + ld hl, wd732 + res 1, [hl] + ld a, [wDefaultMap] + ld [wDestinationMap], a + callfar SpecialWarpIn + ld c, 20 + call DelayFrames + xor a + ld [wMenuJoypadPollCount], a + ld [wSerialExchangeNybbleSendData], a + inc a ; LINK_STATE_IN_CABLE_CLUB + ld [wLinkState], a + ld [wEnteringCableClub], a + jpfar SpecialEnterMap +.choseCancel + xor a + ld [wMenuJoypadPollCount], a + call Delay3 + callfar CloseLinkConnection + ld hl, ColosseumCanceledText + call PrintText + ld hl, wd72e + res 6, [hl] + ret + +.asm_f5963 + ld a, [wd11e] + and a + jr nz, .asm_f5974 + ld b, " " + ld c, " " + ld d, "▷" + ld e, " " + call Func_f59ec +.asm_f5974 + xor a + ld [wBuffer], a + ld a, $ff + ld [wSerialExchangeNybbleReceiveData], a + ld a, $b + ld [wLinkMenuSelectionSendBuffer], a + ld b, $78 +.loop + ldh a, [hSerialConnectionStatus] + cp $2 + call z, DelayFrame + dec b + jr z, .asm_f59b2 + call Serial_ExchangeNybble + call DelayFrame + ld a, [wSerialExchangeNybbleReceiveData] + inc a + jr z, .loop + ld b, $f +.loop2 + call DelayFrame + call Serial_ExchangeNybble + dec b + jr nz, .loop2 + ld b, $f +.loop3 + call DelayFrame + call Serial_SendZeroByte + dec b + jr nz, .loop3 + jr .asm_f59d6 + +.asm_f59b2 + xor a + ld [wUnknownSerialCounter], a + ld [wUnknownSerialCounter+1], a + ld a, [wd11e] + and a + jr z, .asm_f59cd + ld b, " " + ld c, " " + ld d, " " + ld e, "▷" + call Func_f59ec + jp .choseCancel + +.asm_f59cd + ld hl, ColosseumVersionText + call PrintText + jp .choseCancel + +.asm_f59d6 + ld b, " " + ld c, " " + ld d, "▷" + ld e, " " + call Func_f59ec + call Func_f531b + jp c, .choseCancel + ld a, $f0 + jp .next + +Func_f59ec:: + ld a, b + ldcoord_a 6, 5 + ld a, c + ldcoord_a 6, 7 + ld a, d + ldcoord_a 6, 9 + ld a, e + ldcoord_a 6, 11 + ld c, 40 + call DelayFrames + ret + +ColosseumWhereToText: + text_far _ColosseumWhereToText + text_end + +ColosseumPleaseWaitText: + text_far _ColosseumPleaseWaitText + text_end + +ColosseumCanceledText: + text_far _ColosseumCanceledText + text_end + +ColosseumVersionText: + text_far _ColosseumVersionText + text_end + +TextTerminator_f5a16: + text_end + +TradeCenterText: + db "TRADE CENTER" + next "COLOSSEUM" + next "COLOSSEUM2" + next "CANCEL@" diff --git a/engine/menus/main_menu.asm b/engine/menus/main_menu.asm new file mode 100755 index 00000000..7d81d2f6 --- /dev/null +++ b/engine/menus/main_menu.asm @@ -0,0 +1,300 @@ +MainMenu: +; Check save file + call InitOptions + xor a + ld [wOptionsInitialized], a + inc a + ld [wSaveFileStatus], a + call CheckForPlayerNameInSRAM + jr nc, .mainMenuLoop + + predef LoadSAV + +.mainMenuLoop + ld c, 20 + call DelayFrames + xor a ; LINK_STATE_NONE + ld [wLinkState], a + ld hl, wPartyAndBillsPCSavedMenuItem + ld [hli], a + ld [hli], a + ld [hli], a + ld [hl], a + ld [wDefaultMap], a + ld hl, wd72e + res 6, [hl] + call ClearScreen + call RunDefaultPaletteCommand + call LoadTextBoxTilePatterns + call LoadFontTilePatterns + ld hl, wd730 + set 6, [hl] + ld a, [wSaveFileStatus] + cp 1 + jr z, .noSaveFile +; there's a save file + hlcoord 0, 0 + lb bc, 6, 13 + call TextBoxBorder + hlcoord 2, 2 + ld de, ContinueText + call PlaceString + jr .next2 +.noSaveFile + hlcoord 0, 0 + lb bc, 4, 13 + call TextBoxBorder + hlcoord 2, 2 + ld de, NewGameText + call PlaceString +.next2 + ld hl, wd730 + res 6, [hl] + call UpdateSprites + xor a + ld [wCurrentMenuItem], a + ld [wLastMenuItem], a + ld [wMenuJoypadPollCount], a + inc a + ld [wTopMenuItemX], a + inc a + ld [wTopMenuItemY], a + ld a, A_BUTTON | B_BUTTON | START + ld [wMenuWatchedKeys], a + ld a, [wSaveFileStatus] + ld [wMaxMenuItem], a + call HandleMenuInput + bit 1, a ; pressed B? + jp nz, DisplayTitleScreen ; if so, go back to the title screen + ld c, 20 + call DelayFrames + ld a, [wCurrentMenuItem] + ld b, a + ld a, [wSaveFileStatus] + cp 2 + jp z, .skipInc +; If there's no save file, increment the current menu item so that the numbers +; are the same whether or not there's a save file. + inc b +.skipInc + ld a, b + and a + jr z, .choseContinue + cp 1 + jp z, StartNewGame + call DisplayOptionMenu + ld a, 1 + ld [wOptionsInitialized], a + jp .mainMenuLoop +.choseContinue + call DisplayContinueGameInfo + ld hl, wCurrentMapScriptFlags + set 5, [hl] +.inputLoop + xor a + ldh [hJoyPressed], a + ldh [hJoyReleased], a + ldh [hJoyHeld], a + call Joypad + ldh a, [hJoyHeld] + bit 0, a + jr nz, .pressedA + bit 1, a + jp nz, .mainMenuLoop ; pressed B + jr .inputLoop +.pressedA + call GBPalWhiteOutWithDelay3 + call ClearScreen + ld a, PLAYER_DIR_DOWN + ld [wPlayerDirection], a + ld c, 10 + call DelayFrames + ld a, [wNumHoFTeams] + and a + jp z, SpecialEnterMap + ld a, [wCurMap] ; map ID + cp HALL_OF_FAME + jp nz, SpecialEnterMap + xor a + ld [wDestinationMap], a + ld hl, wd732 + set 2, [hl] ; fly warp or dungeon warp + call SpecialWarpIn + jp SpecialEnterMap + +InitOptions: + ld a, 1 ; no delay + ld [wLetterPrintingDelayFlags], a + ld a, 3 ; medium speed + ld [wOptions], a + ld a, 64 ; audio? + ld [wPrinterSettings], a + ret + +Func_5cc1: +; unused? + ld a, $6d + cp $80 + ret c ; will always be executed + ld hl, NotEnoughMemoryText + call PrintText + ret + +NotEnoughMemoryText: + text_far _NotEnoughMemoryText + text_end + +StartNewGame: + ld hl, wd732 + res 1, [hl] +StartNewGameDebug: + call OakSpeech + ld a, $8 + ld [wPlayerMovingDirection], a + ld c, 20 + call DelayFrames + +; enter map after using a special warp or loading the game from the main menu +SpecialEnterMap:: + xor a + ldh [hJoyPressed], a + ldh [hJoyHeld], a + ldh [hJoy5], a + ld [wd72d], a + ld hl, wd732 + set 0, [hl] ; count play time + call ResetPlayerSpriteData + ld c, 20 + call DelayFrames + call Func_5cc1 + ld a, [wEnteringCableClub] + and a + ret nz + jp EnterMap + +ContinueText: + db "CONTINUE" + next "" + ; fallthrough + +NewGameText: + db "NEW GAME" + next "OPTION@" + +DisplayContinueGameInfo: + xor a + ldh [hAutoBGTransferEnabled], a + hlcoord 4, 7 + lb bc, 8, 14 + call TextBoxBorder + hlcoord 5, 9 + ld de, SaveScreenInfoText + call PlaceString + hlcoord 12, 9 + ld de, wPlayerName + call PlaceString + hlcoord 17, 11 + call PrintNumBadges + hlcoord 16, 13 + call PrintNumOwnedMons + hlcoord 13, 15 + call PrintPlayTime + ld a, 1 + ldh [hAutoBGTransferEnabled], a + ld c, 30 + jp DelayFrames + +PrintSaveScreenText: + xor a + ldh [hAutoBGTransferEnabled], a + hlcoord 4, 0 + lb bc, 8, 14 + call TextBoxBorder + call LoadTextBoxTilePatterns + call UpdateSprites + hlcoord 5, 2 + ld de, SaveScreenInfoText + call PlaceString + hlcoord 12, 2 + ld de, wPlayerName + call PlaceString + hlcoord 17, 4 + call PrintNumBadges + hlcoord 16, 6 + call PrintNumOwnedMons + hlcoord 13, 8 + call PrintPlayTime + ld a, $1 + ldh [hAutoBGTransferEnabled], a + ld c, 30 + jp DelayFrames + +PrintNumBadges: + push hl + ld hl, wObtainedBadges + ld b, $1 + call CountSetBits + pop hl + ld de, wNumSetBits + lb bc, 1, 2 + jp PrintNumber + +PrintNumOwnedMons: + push hl + ld hl, wPokedexOwned + ld b, wPokedexOwnedEnd - wPokedexOwned + call CountSetBits + pop hl + ld de, wNumSetBits + lb bc, 1, 3 + jp PrintNumber + +PrintPlayTime: + ld de, wPlayTimeHours + lb bc, 1, 3 + call PrintNumber + ld [hl], $6d + inc hl + ld de, wPlayTimeMinutes + lb bc, LEADING_ZEROES | 1, 2 + jp PrintNumber + +SaveScreenInfoText: + db "PLAYER" + next "BADGES " + next "#DEX " + next "TIME@" + +DisplayOptionMenu: + callfar DisplayOptionMenu_ + ret + +CheckForPlayerNameInSRAM: +; Check if the player name data in SRAM has a string terminator character +; (indicating that a name may have been saved there) and return whether it does +; in carry. + ld a, SRAM_ENABLE + ld [MBC1SRamEnable], a + ld a, $1 + ld [MBC1SRamBankingMode], a + ld [MBC1SRamBank], a + ld b, NAME_LENGTH + ld hl, sPlayerName +.loop + ld a, [hli] + cp "@" + jr z, .found + dec b + jr nz, .loop +; not found + xor a + ld [MBC1SRamEnable], a + ld [MBC1SRamBankingMode], a + and a + ret +.found + xor a + ld [MBC1SRamEnable], a + ld [MBC1SRamBankingMode], a + scf + ret diff --git a/engine/menus/naming_screen.asm b/engine/menus/naming_screen.asm new file mode 100755 index 00000000..553c47d0 --- /dev/null +++ b/engine/menus/naming_screen.asm @@ -0,0 +1,508 @@ +AskName: + call SaveScreenTilesToBuffer1 + call GetPredefRegisters + push hl + ld a, [wIsInBattle] + dec a + hlcoord 0, 0 + lb bc, 4, 11 + call z, ClearScreenArea ; only if in wild battle + ld a, [wcf91] + ld [wd11e], a + call GetMonName + ld hl, DoYouWantToNicknameText + call PrintText + hlcoord 14, 7 + lb bc, 8, 15 + ld a, TWO_OPTION_MENU + ld [wTextBoxID], a + call DisplayTextBoxID + pop hl + ld a, [wCurrentMenuItem] + and a + jr nz, .declinedNickname + ld a, [wUpdateSpritesEnabled] + push af + xor a + ld [wUpdateSpritesEnabled], a + push hl + ld a, NAME_MON_SCREEN + ld [wNamingScreenType], a + call DisplayNamingScreen + ld a, [wIsInBattle] + and a + jr nz, .inBattle + call ReloadMapSpriteTilePatterns +.inBattle + call LoadScreenTilesFromBuffer1 + pop hl + pop af + ld [wUpdateSpritesEnabled], a + ld a, [wcf4b] + cp "@" + ret nz +.declinedNickname + ld d, h + ld e, l + ld hl, wcd6d + ld bc, NAME_LENGTH + jp CopyData + +DoYouWantToNicknameText: + text_far _DoYouWantToNicknameText + text_end + +DisplayNameRaterScreen:: + ld hl, wBuffer + xor a + ld [wUpdateSpritesEnabled], a + ld a, NAME_MON_SCREEN + ld [wNamingScreenType], a + call DisplayNamingScreen + call GBPalWhiteOutWithDelay3 + call RestoreScreenTilesAndReloadTilePatterns + call LoadGBPal + ld a, [wcf4b] + cp "@" + jr z, .playerCancelled + ld hl, wPartyMonNicks + ld bc, NAME_LENGTH + ld a, [wWhichPokemon] + call AddNTimes + ld e, l + ld d, h + ld hl, wBuffer + ld bc, NAME_LENGTH + call CopyData + and a + ret +.playerCancelled + scf + ret + +DisplayNamingScreen: + push hl + ld hl, wd730 + set 6, [hl] + call GBPalWhiteOutWithDelay3 + call ClearScreen + call UpdateSprites + ld b, SET_PAL_GENERIC + call RunPaletteCommand + call LoadHpBarAndStatusTilePatterns + call LoadEDTile + farcall LoadMonPartySpriteGfx + hlcoord 0, 4 + lb bc, 9, 18 + call TextBoxBorder + call PrintNamingText + ld a, 3 + ld [wTopMenuItemY], a + ld a, 1 + ld [wTopMenuItemX], a + ld [wLastMenuItem], a + ld [wCurrentMenuItem], a + ld a, $ff + ld [wMenuWatchedKeys], a + ld a, 7 + ld [wMaxMenuItem], a + ld a, "@" + ld [wcf4b], a + xor a + ld hl, wNamingScreenSubmitName + ld [hli], a + ld [hli], a + ld [wAnimCounter], a +.selectReturnPoint + call PrintAlphabet + call GBPalNormal +.ABStartReturnPoint + ld a, [wNamingScreenSubmitName] + and a + jr nz, .submitNickname + call PrintNicknameAndUnderscores +.dPadReturnPoint + call PlaceMenuCursor +.inputLoop + ld a, [wCurrentMenuItem] + push af + farcall AnimatePartyMon_ForceSpeed1 + pop af + ld [wCurrentMenuItem], a + call JoypadLowSensitivity + ldh a, [hJoyPressed] + and a + jr z, .inputLoop + ld hl, .namingScreenButtonFunctions +.checkForPressedButton + sla a + jr c, .foundPressedButton + inc hl + inc hl + inc hl + inc hl + jr .checkForPressedButton +.foundPressedButton + ld a, [hli] + ld e, a + ld a, [hli] + ld d, a + ld a, [hli] + ld h, [hl] + ld l, a + push de + jp hl + +.submitNickname + pop de + ld hl, wcf4b + ld bc, NAME_LENGTH + call CopyData + call GBPalWhiteOutWithDelay3 + call ClearScreen + call ClearSprites + call RunDefaultPaletteCommand + call GBPalNormal + xor a + ld [wAnimCounter], a + ld hl, wd730 + res 6, [hl] + ld a, [wIsInBattle] + and a + jp z, LoadTextBoxTilePatterns + jpfar LoadHudTilePatterns + +.namingScreenButtonFunctions + dw .dPadReturnPoint + dw .pressedDown + dw .dPadReturnPoint + dw .pressedUp + dw .dPadReturnPoint + dw .pressedLeft + dw .dPadReturnPoint + dw .pressedRight + dw .ABStartReturnPoint + dw .pressedStart + dw .selectReturnPoint + dw .pressedSelect + dw .ABStartReturnPoint + dw .pressedB + dw .ABStartReturnPoint + dw .pressedA + +.pressedA_changedCase + pop de + ld de, .selectReturnPoint + push de +.pressedSelect + ld a, [wAlphabetCase] + xor $1 + ld [wAlphabetCase], a + ret + +.pressedStart + ld a, 1 + ld [wNamingScreenSubmitName], a + ret + +.pressedA + ld a, [wCurrentMenuItem] + cp $5 ; "ED" row + jr nz, .didNotPressED + ld a, [wTopMenuItemX] + cp $11 ; "ED" column + jr z, .pressedStart +.didNotPressED + ld a, [wCurrentMenuItem] + cp $6 ; case switch row + jr nz, .didNotPressCaseSwtich + ld a, [wTopMenuItemX] + cp $1 ; case switch column + jr z, .pressedA_changedCase +.didNotPressCaseSwtich + ld hl, wMenuCursorLocation + ld a, [hli] + ld h, [hl] + ld l, a + inc hl + ld a, [hl] + ld [wNamingScreenLetter], a + call CalcStringLength + ld a, [wNamingScreenLetter] + cp "゙" + ld de, Dakutens + jr z, .dakutensAndHandakutens + cp "゚" + ld de, Handakutens + jr z, .dakutensAndHandakutens + ld a, [wNamingScreenType] + cp NAME_MON_SCREEN + jr nc, .checkMonNameLength + ld a, [wNamingScreenNameLength] + cp $7 ; max length of player/rival names + jr .checkNameLength +.checkMonNameLength + ld a, [wNamingScreenNameLength] + cp $a ; max length of pokemon nicknames +.checkNameLength + jr c, .addLetter + ret + +.dakutensAndHandakutens + push hl + call DakutensAndHandakutens + pop hl + ret nc + dec hl +.addLetter + ld a, [wNamingScreenLetter] + ld [hli], a + ld [hl], "@" + ld a, SFX_PRESS_AB + call PlaySound + ret +.pressedB + ld a, [wNamingScreenNameLength] + and a + ret z + call CalcStringLength + dec hl + ld [hl], "@" + ret +.pressedRight + ld a, [wCurrentMenuItem] + cp $6 + ret z ; can't scroll right on bottom row + ld a, [wTopMenuItemX] + cp $11 ; max + jp z, .wrapToFirstColumn + inc a + inc a + jr .done +.wrapToFirstColumn + ld a, $1 + jr .done +.pressedLeft + ld a, [wCurrentMenuItem] + cp $6 + ret z ; can't scroll right on bottom row + ld a, [wTopMenuItemX] + dec a + jp z, .wrapToLastColumn + dec a + jr .done +.wrapToLastColumn + ld a, $11 ; max + jr .done +.pressedUp + ld a, [wCurrentMenuItem] + dec a + ld [wCurrentMenuItem], a + and a + ret nz + ld a, $6 ; wrap to bottom row + ld [wCurrentMenuItem], a + ld a, $1 ; force left column + jr .done +.pressedDown + ld a, [wCurrentMenuItem] + inc a + ld [wCurrentMenuItem], a + cp $7 + jr nz, .wrapToTopRow + ld a, $1 + ld [wCurrentMenuItem], a + jr .done +.wrapToTopRow + cp $6 + ret nz + ld a, $1 +.done + ld [wTopMenuItemX], a + jp EraseMenuCursor + +LoadEDTile: +; In Red/Blue, the bank for the ED_tile was defined incorrectly as bank0 +; Luckily, the MBC3 treats loading $0 into $2000-$2fff range as loading bank1 into $4000-$7fff range +; Because Yellow uses the MBC5, loading $0 into $2000 - $2fff range will load bank0 instead of bank1 and thus incorrectly load the tile +; Instead of defining the correct bank, GameFreak decided to simply copy the ED_Tile in the function during HBlank + ld de, ED_Tile + ld hl, vFont tile $70 + ld c, $4 ; number of copies needed +.waitForHBlankLoop + ldh a, [rSTAT] + and %10 ; in HBlank? + jr nz, .waitForHBlankLoop + ld a, [de] + ld [hli], a + ld [hli], a + inc de + ld a, [de] + ld [hli], a + ld [hli], a + inc de + dec c + jr nz, .waitForHBlankLoop + ret + +ED_Tile: + INCBIN "gfx/font/ED.1bpp" +ED_TileEnd: + +PrintAlphabet: + xor a + ldh [hAutoBGTransferEnabled], a + ld a, [wAlphabetCase] + and a + ld de, LowerCaseAlphabet + jr nz, .lowercase + ld de, UpperCaseAlphabet +.lowercase + hlcoord 2, 5 + lb bc, 5, 9 ; 5 rows, 9 columns +.outerLoop + push bc +.innerLoop + ld a, [de] + ld [hli], a + inc hl + inc de + dec c + jr nz, .innerLoop + ld bc, SCREEN_WIDTH + 2 + add hl, bc + pop bc + dec b + jr nz, .outerLoop + call PlaceString + ld a, $1 + ldh [hAutoBGTransferEnabled], a + jp Delay3 + +INCLUDE "data/text/alphabets.asm" + +PrintNicknameAndUnderscores: + call CalcStringLength + ld a, c + ld [wNamingScreenNameLength], a + hlcoord 10, 2 + lb bc, 1, 10 + call ClearScreenArea + hlcoord 10, 2 + ld de, wcf4b + call PlaceString + hlcoord 10, 3 + ld a, [wNamingScreenType] + cp NAME_MON_SCREEN + jr nc, .pokemon1 + ld b, 7 ; player or rival max name length + jr .playerOrRival1 +.pokemon1 + ld b, 10 ; pokemon max name length +.playerOrRival1 + ld a, $76 ; underscore tile id +.placeUnderscoreLoop + ld [hli], a + dec b + jr nz, .placeUnderscoreLoop + ld a, [wNamingScreenType] + cp NAME_MON_SCREEN + ld a, [wNamingScreenNameLength] + jr nc, .pokemon2 + cp 7 ; player or rival max name length + jr .playerOrRival2 +.pokemon2 + cp 10 ; pokemon max name length +.playerOrRival2 + jr nz, .emptySpacesRemaining + ; when all spaces are filled, force the cursor onto the ED tile + call EraseMenuCursor + ld a, $11 ; "ED" x coord + ld [wTopMenuItemX], a + ld a, $5 ; "ED" y coord + ld [wCurrentMenuItem], a + ld a, [wNamingScreenType] + cp NAME_MON_SCREEN + ld a, 9 ; keep the last underscore raised + jr nc, .pokemon3 + ld a, 6 ; keep the last underscore raised +.pokemon3 +.emptySpacesRemaining + ld c, a + ld b, $0 + hlcoord 10, 3 + add hl, bc + ld [hl], $77 ; raised underscore tile id + ret + +DakutensAndHandakutens: + push de + call CalcStringLength + dec hl + ld a, [hl] + pop hl + ld de, $2 + call IsInArray + ret nc + inc hl + ld a, [hl] + ld [wNamingScreenLetter], a + ret + +INCLUDE "data/text/dakutens.asm" + +; calculates the length of the string at wcf4b and stores it in c +CalcStringLength: + ld hl, wcf4b + ld c, $0 +.loop + ld a, [hl] + cp "@" + ret z + inc hl + inc c + jr .loop + +PrintNamingText: + hlcoord 0, 1 + ld a, [wNamingScreenType] + ld de, YourTextString + and a + jr z, .notNickname + ld de, RivalsTextString + dec a + jr z, .notNickname + ld a, [wcf91] + ld [wMonPartySpriteSpecies], a + push af + farcall WriteMonPartySpriteOAMBySpecies + pop af + ld [wd11e], a + call GetMonName + hlcoord 4, 1 + call PlaceString + ld hl, $1 + add hl, bc + ld [hl], "の" ; leftover from Japanese version; blank tile $c9 in English + hlcoord 1, 3 + ld de, NicknameTextString + jr .placeString +.notNickname + call PlaceString + ld l, c + ld h, b + ld de, NameTextString +.placeString + jp PlaceString + +YourTextString: + db "YOUR @" + +RivalsTextString: + db "RIVAL's @" + +NameTextString: + db "NAME?@" + +NicknameTextString: + db "NICKNAME?@" diff --git a/engine/menus/oaks_pc.asm b/engine/menus/oaks_pc.asm new file mode 100755 index 00000000..7743e5df --- /dev/null +++ b/engine/menus/oaks_pc.asm @@ -0,0 +1,28 @@ +OpenOaksPC: + call SaveScreenTilesToBuffer2 + ld hl, AccessedOaksPCText + call PrintText + ld hl, GetDexRatedText + call PrintText + call YesNoChoice + ld a, [wCurrentMenuItem] + and a + jr nz, .closePC + predef DisplayDexRating +.closePC + ld hl, ClosedOaksPCText + call PrintText + jp LoadScreenTilesFromBuffer2 + +GetDexRatedText: + text_far _GetDexRatedText + text_end + +ClosedOaksPCText: + text_far _ClosedOaksPCText + text_waitbutton + text_end + +AccessedOaksPCText: + text_far _AccessedOaksPCText + text_end diff --git a/engine/menus/options.asm b/engine/menus/options.asm new file mode 100644 index 00000000..110bef2a --- /dev/null +++ b/engine/menus/options.asm @@ -0,0 +1,443 @@ +DisplayOptionMenu_: + call InitOptionsMenu +.optionMenuLoop + call JoypadLowSensitivity + ldh a, [hJoy5] + and START | B_BUTTON + jr nz, .exitOptionMenu + call OptionsControl + jr c, .dpadDelay + call GetOptionPointer + jr c, .exitOptionMenu +.dpadDelay + call OptionsMenu_UpdateCursorPosition + call DelayFrame + call DelayFrame + call DelayFrame + jr .optionMenuLoop +.exitOptionMenu + ret + +GetOptionPointer: + ld a, [wOptionsCursorLocation] + ld e, a + ld d, $0 + ld hl, OptionMenuJumpTable + add hl, de + add hl, de + ld a, [hli] + ld h, [hl] + ld l, a + jp hl ; jump to the function for the current highlighted option + +OptionMenuJumpTable: + dw OptionsMenu_TextSpeed + dw OptionsMenu_BattleAnimations + dw OptionsMenu_BattleStyle + dw OptionsMenu_SpeakerSettings + dw OptionsMenu_GBPrinterBrightness + dw OptionsMenu_Dummy + dw OptionsMenu_Dummy + dw OptionsMenu_Cancel + +OptionsMenu_TextSpeed: + call GetTextSpeed + ldh a, [hJoy5] + bit 4, a ; right + jr nz, .pressedRight + bit 5, a + jr nz, .pressedLeft + jr .asm_41ce0 +.pressedRight + ld a, c + cp $2 + jr c, .asm_41cca + ld c, $ff +.asm_41cca + inc c + ld a, e + jr .asm_41cd6 +.pressedLeft + ld a, c + and a + jr nz, .asm_41cd4 + ld c, $3 +.asm_41cd4 + dec c + ld a, d +.asm_41cd6 + ld b, a + ld a, [wOptions] + and $f0 + or b + ld [wOptions], a +.asm_41ce0 + ld b, $0 + ld hl, TextSpeedStringsPointerTable + add hl, bc + add hl, bc + ld e, [hl] + inc hl + ld d, [hl] + hlcoord 14, 2 + call PlaceString + and a + ret + +TextSpeedStringsPointerTable: + dw FastText + dw MidText + dw SlowText + +FastText: + db "FAST@" +MidText: + db "MID @" +SlowText: + db "SLOW@" + +GetTextSpeed: + ld a, [wOptions] + and $f + cp $5 + jr z, .slowTextOption + cp $1 + jr z, .fastTextOption +; mid text option + ld c, $1 + lb de, 1, 5 + ret +.slowTextOption + ld c, $2 + lb de, 3, 1 + ret +.fastTextOption + ld c, $0 + lb de, 5, 3 + ret + +OptionsMenu_BattleAnimations: + ldh a, [hJoy5] + and D_RIGHT | D_LEFT + jr nz, .asm_41d33 + ld a, [wOptions] + and $80 ; mask other bits + jr .asm_41d3b +.asm_41d33 + ld a, [wOptions] + xor $80 + ld [wOptions], a +.asm_41d3b + ld bc, $0 + sla a + rl c + ld hl, AnimationOptionStringsPointerTable + add hl, bc + add hl, bc + ld e, [hl] + inc hl + ld d, [hl] + hlcoord 14, 4 + call PlaceString + and a + ret + +AnimationOptionStringsPointerTable: + dw AnimationOnText + dw AnimationOffText + +AnimationOnText: + db "ON @" +AnimationOffText: + db "OFF@" + +OptionsMenu_BattleStyle: + ldh a, [hJoy5] + and D_LEFT | D_RIGHT + jr nz, .asm_41d6b + ld a, [wOptions] + and $40 ; mask other bits + jr .asm_41d73 +.asm_41d6b + ld a, [wOptions] + xor $40 + ld [wOptions], a +.asm_41d73 + ld bc, $0 + sla a + sla a + rl c + ld hl, BattleStyleOptionStringsPointerTable + add hl, bc + add hl, bc + ld e, [hl] + inc hl + ld d, [hl] + hlcoord 14, 6 + call PlaceString + and a + ret + +BattleStyleOptionStringsPointerTable: + dw BattleStyleShiftText + dw BattleStyleSetText + +BattleStyleShiftText: + db "SHIFT@" +BattleStyleSetText: + db "SET @" + +OptionsMenu_SpeakerSettings: + ld a, [wOptions] + and $30 + swap a + ld c, a + ldh a, [hJoy5] + bit 4, a + jr nz, .pressedRight + bit 5, a + jr nz, .pressedLeft + jr .asm_41dca +.pressedRight + ld a, c + inc a + and $3 + jr .asm_41dba +.pressedLeft + ld a, c + dec a + and $3 +.asm_41dba + ld c, a + swap a + ld b, a + xor a + ldh [rNR51], a + ld a, [wOptions] + and $cf + or b + ld [wOptions], a +.asm_41dca + ld b, $0 + ld hl, SpeakerOptionStringsPointerTable + add hl, bc + add hl, bc + ld e, [hl] + inc hl + ld d, [hl] + hlcoord 8, 8 + call PlaceString + and a + ret + +SpeakerOptionStringsPointerTable: + dw MonoSoundText + dw Earphone1SoundText + dw Earphone2SoundText + dw Earphone3SoundText + +MonoSoundText: + db "MONO @" +Earphone1SoundText: + db "EARPHONE1@" +Earphone2SoundText: + db "EARPHONE2@" +Earphone3SoundText: + db "EARPHONE3@" + +OptionsMenu_GBPrinterBrightness: + call Func_41e7b + ldh a, [hJoy5] + bit 4, a + jr nz, .pressedRight + bit 5, a + jr nz, .pressedLeft + jr .asm_41e32 +.pressedRight + ld a, c + cp $4 + jr c, .asm_41e22 + ld c, $ff +.asm_41e22 + inc c + ld a, e + jr .asm_41e2e +.pressedLeft + ld a, c + and a + jr nz, .asm_41e2c + ld c, $5 +.asm_41e2c + dec c + ld a, d +.asm_41e2e + ld b, a + ld [wPrinterSettings], a +.asm_41e32 + ld b, $0 + ld hl, GBPrinterOptionStringsPointerTable + add hl, bc + add hl, bc + ld e, [hl] + inc hl + ld d, [hl] + hlcoord 8, 10 + call PlaceString + and a + ret + +GBPrinterOptionStringsPointerTable: + dw LightestPrintText + dw LighterPrintText + dw NormalPrintText + dw DarkerPrintText + dw DarkestPrintText + +LightestPrintText: + db "LIGHTEST@" +LighterPrintText: + db "LIGHTER @" +NormalPrintText: + db "NORMAL @" +DarkerPrintText: + db "DARKER @" +DarkestPrintText: + db "DARKEST @" + +Func_41e7b: + ld a, [wPrinterSettings] + and a + jr z, .asm_41e93 + cp $20 + jr z, .asm_41e99 + cp $60 + jr z, .asm_41e9f + cp $7f + jr z, .asm_41ea5 + ld c, $2 + lb de, $20, $60 + ret +.asm_41e93 + ld c, $0 + lb de, $7f, $20 + ret +.asm_41e99 + ld c, $1 + lb de, $0, $40 + ret +.asm_41e9f + ld c, $3 + lb de, $40, $7f + ret +.asm_41ea5 + ld c, $4 + lb de, $60, $0 + ret + +OptionsMenu_Dummy: + and a + ret + +OptionsMenu_Cancel: + ldh a, [hJoy5] + and A_BUTTON + jr nz, .pressedCancel + and a + ret +.pressedCancel + scf + ret + +OptionsControl: + ld hl, wOptionsCursorLocation + ldh a, [hJoy5] + cp D_DOWN + jr z, .pressedDown + cp D_UP + jr z, .pressedUp + and a + ret +.pressedDown + ld a, [hl] + cp $7 + jr nz, .doNotWrapAround + ld [hl], $0 + scf + ret +.doNotWrapAround + cp $4 + jr c, .regularIncrement + ld [hl], $6 +.regularIncrement + inc [hl] + scf + ret +.pressedUp + ld a, [hl] + cp $7 + jr nz, .doNotMoveCursorToPrintOption + ld [hl], $4 + scf + ret +.doNotMoveCursorToPrintOption + and a + jr nz, .regularDecrement + ld [hl], $8 +.regularDecrement + dec [hl] + scf + ret + +OptionsMenu_UpdateCursorPosition: + hlcoord 1, 1 + ld de, SCREEN_WIDTH + ld c, 16 +.loop + ld [hl], " " + add hl, de + dec c + jr nz, .loop + hlcoord 1, 2 + ld bc, SCREEN_WIDTH * 2 + ld a, [wOptionsCursorLocation] + call AddNTimes + ld [hl], "▶" + ret + +InitOptionsMenu: + hlcoord 0, 0 + lb bc, SCREEN_HEIGHT - 2, SCREEN_WIDTH - 2 + call TextBoxBorder + hlcoord 2, 2 + ld de, AllOptionsText + call PlaceString + hlcoord 2, 16 + ld de, OptionMenuCancelText + call PlaceString + xor a + ld [wOptionsCursorLocation], a + ld c, 5 ; the number of options to loop through +.loop + push bc + call GetOptionPointer ; updates the next option + pop bc + ld hl, wOptionsCursorLocation + inc [hl] ; moves the cursor for the highlighted option + dec c + jr nz, .loop + xor a + ld [wOptionsCursorLocation], a + inc a + ldh [hAutoBGTransferEnabled], a + call Delay3 + ret + +AllOptionsText: + db "TEXT SPEED :" + next "ANIMATION :" + next "BATTLESTYLE:" + next "SOUND:" + next "PRINT:@" + +OptionMenuCancelText: + db "CANCEL@" diff --git a/engine/menus/party_menu.asm b/engine/menus/party_menu.asm new file mode 100755 index 00000000..32f47f6a --- /dev/null +++ b/engine/menus/party_menu.asm @@ -0,0 +1,314 @@ +DrawPartyMenu_:: + xor a + ldh [hAutoBGTransferEnabled], a + call ClearScreen + call UpdateSprites + farcall LoadMonPartySpriteGfxWithLCDDisabled ; load pokemon icon graphics + +RedrawPartyMenu_:: + ld a, [wPartyMenuTypeOrMessageID] + cp SWAP_MONS_PARTY_MENU + jp z, .printMessage + call ErasePartyMenuCursors + farcall InitPartyMenuBlkPacket + hlcoord 3, 0 + ld de, wPartySpecies + xor a + ld c, a + ldh [hPartyMonIndex], a + ld [wWhichPartyMenuHPBar], a +.loop + ld a, [de] + cp $FF ; reached the terminator? + jp z, .afterDrawingMonEntries + push bc + push de + push hl + ld a, c + push hl + ld hl, wPartyMonNicks + call GetPartyMonName + pop hl + call PlaceString ; print the pokemon's name + ldh a, [hPartyMonIndex] + ld [wWhichPokemon], a + callfar IsThisPartymonStarterPikachu_Party + jr nc, .regularMon + call CheckPikachuFollowingPlayer + jr z, .regularMon + ld a, $ff + ldh [hPartyMonIndex], a +.regularMon + farcall WriteMonPartySpriteOAMByPartyIndex ; place the appropriate pokemon icon + ld a, [wWhichPokemon] + inc a + ldh [hPartyMonIndex], a + call LoadMonData + pop hl + push hl + ld a, [wMenuItemToSwap] + and a ; is the player swapping pokemon positions? + jr z, .skipUnfilledRightArrow +; if the player is swapping pokemon positions + dec a + ld b, a + ld a, [wWhichPokemon] + cp b ; is the player swapping the current pokemon in the list? + jr nz, .skipUnfilledRightArrow +; the player is swapping the current pokemon in the list + dec hl + dec hl + dec hl + ld a, "▷" ; unfilled right arrow menu cursor + ld [hli], a ; place the cursor + inc hl + inc hl +.skipUnfilledRightArrow + ld a, [wPartyMenuTypeOrMessageID] ; menu type + cp TMHM_PARTY_MENU + jr z, .teachMoveMenu + cp EVO_STONE_PARTY_MENU + jr z, .evolutionStoneMenu + push hl + ld bc, 14 ; 14 columns to the right + add hl, bc + ld de, wLoadedMonStatus + call PrintStatusCondition + pop hl + push hl + ld bc, SCREEN_WIDTH + 1 ; down 1 row and right 1 column + ldh a, [hFlagsFFFA] + set 0, a + ldh [hFlagsFFFA], a + add hl, bc + predef DrawHP2 ; draw HP bar and prints current / max HP + ldh a, [hFlagsFFFA] + res 0, a + ldh [hFlagsFFFA], a + call SetPartyMenuHPBarColor ; color the HP bar (on SGB) + pop hl + jr .printLevel +.teachMoveMenu + push hl + predef CanLearnTM ; check if the pokemon can learn the move + pop hl + ld de, .ableToLearnMoveText + ld a, c + and a + jr nz, .placeMoveLearnabilityString + ld de, .notAbleToLearnMoveText +.placeMoveLearnabilityString + push hl + ld bc, 20 + 9 ; down 1 row and right 9 columns + add hl, bc + call PlaceString + pop hl +.printLevel + ld bc, 10 ; move 10 columns to the right + add hl, bc + call PrintLevel + pop hl + pop de + inc de + ld bc, 2 * 20 + add hl, bc + pop bc + inc c + jp .loop +.ableToLearnMoveText + db "ABLE@" +.notAbleToLearnMoveText + db "NOT ABLE@" +.evolutionStoneMenu + push hl + ld hl, EvosMovesPointerTable + ld b, 0 + ld a, [wLoadedMonSpecies] + dec a + add a + rl b + ld c, a + add hl, bc + ld de, wEvosMoves + ld a, BANK(EvosMovesPointerTable) + ld bc, 2 + call FarCopyData + ld hl, wEvosMoves + ld a, [hli] + ld h, [hl] + ld l, a + ld de, wEvosMoves + ld a, BANK(EvosMovesPointerTable) + ld bc, wEvosMoves.end - wEvosMoves + call FarCopyData + ld hl, wEvosMoves + ld de, .notAbleToEvolveText +; loop through the pokemon's evolution entries +.checkEvolutionsLoop + ld a, [hli] + and a ; reached terminator? + jr z, .placeEvolutionStoneString ; if so, place the "NOT ABLE" string + inc hl + inc hl + cp EV_ITEM + jr nz, .checkEvolutionsLoop +; if it's a stone evolution entry + dec hl + dec hl + ld b, [hl] + ld a, [wEvoStoneItemID] ; the stone the player used + inc hl + inc hl + inc hl + cp b ; does the player's stone match this evolution entry's stone? + jr nz, .checkEvolutionsLoop +; if it does match + ld de, .ableToEvolveText +.placeEvolutionStoneString + pop hl + push hl + ld bc, 20 + 9 ; down 1 row and right 9 columns + add hl, bc + call PlaceString + pop hl + jr .printLevel +.ableToEvolveText + db "ABLE@" +.notAbleToEvolveText + db "NOT ABLE@" +.afterDrawingMonEntries + ld b, SET_PAL_PARTY_MENU + call RunPaletteCommand +.printMessage + ld hl, wd730 + ld a, [hl] + push af + push hl + set 6, [hl] ; turn off letter printing delay + ld a, [wPartyMenuTypeOrMessageID] ; message ID + cp FIRST_PARTY_MENU_TEXT_ID + jr nc, .printItemUseMessage + add a + ld hl, PartyMenuMessagePointers + ld b, 0 + ld c, a + add hl, bc + ld a, [hli] + ld h, [hl] + ld l, a + call PrintText +.done + pop hl + pop af + ld [hl], a + ld a, 1 + ldh [hAutoBGTransferEnabled], a + call Delay3 + jp GBPalNormal +.printItemUseMessage + and $0F + ld hl, PartyMenuItemUseMessagePointers + add a + ld c, a + ld b, 0 + add hl, bc + ld a, [hli] + ld h, [hl] + ld l, a + push hl + ld a, [wUsedItemOnWhichPokemon] + ld hl, wPartyMonNicks + call GetPartyMonName + pop hl + call PrintText + jr .done + +PartyMenuItemUseMessagePointers: + dw AntidoteText + dw BurnHealText + dw IceHealText + dw AwakeningText + dw ParlyzHealText + dw PotionText + dw FullHealText + dw ReviveText + dw RareCandyText + +PartyMenuMessagePointers: + dw PartyMenuNormalText + dw PartyMenuItemUseText + dw PartyMenuBattleText + dw PartyMenuUseTMText + dw PartyMenuSwapMonText + dw PartyMenuItemUseText + +PartyMenuNormalText: + text_far _PartyMenuNormalText + text_end + +PartyMenuItemUseText: + text_far _PartyMenuItemUseText + text_end + +PartyMenuBattleText: + text_far _PartyMenuBattleText + text_end + +PartyMenuUseTMText: + text_far _PartyMenuUseTMText + text_end + +PartyMenuSwapMonText: + text_far _PartyMenuSwapMonText + text_end + +PotionText: + text_far _PotionText + text_end + +AntidoteText: + text_far _AntidoteText + text_end + +ParlyzHealText: + text_far _ParlyzHealText + text_end + +BurnHealText: + text_far _BurnHealText + text_end + +IceHealText: + text_far _IceHealText + text_end + +AwakeningText: + text_far _AwakeningText + text_end + +FullHealText: + text_far _FullHealText + text_end + +ReviveText: + text_far _ReviveText + text_end + +RareCandyText: + text_far _RareCandyText + sound_get_item_1 ; probably supposed to play SFX_LEVEL_UP but the wrong music bank is loaded + text_promptbutton + text_end + +SetPartyMenuHPBarColor: + ld hl, wPartyMenuHPBarColors + ld a, [wWhichPartyMenuHPBar] + ld c, a + ld b, 0 + add hl, bc + call GetHealthBarColor + ld b, SET_PAL_PARTY_MENU_HP_BARS + call RunPaletteCommand + ld hl, wWhichPartyMenuHPBar + inc [hl] + ret diff --git a/engine/menus/pc.asm b/engine/menus/pc.asm new file mode 100755 index 00000000..4c340e7b --- /dev/null +++ b/engine/menus/pc.asm @@ -0,0 +1,141 @@ +ActivatePC:: + call SaveScreenTilesToBuffer2 + ld a, SFX_TURN_ON_PC + call PlaySound + ld hl, TurnedOnPC1Text + call PrintText + call WaitForSoundToFinish + ld hl, wFlags_0xcd60 + set 3, [hl] + call LoadScreenTilesFromBuffer2 + call Delay3 +PCMainMenu: + farcall DisplayPCMainMenu + ld hl, wFlags_0xcd60 + set 5, [hl] + call HandleMenuInput + bit 1, a ;if player pressed B + jp nz, LogOff + ld a, [wMaxMenuItem] + cp 2 + jr nz, .next ;if not 2 menu items (not counting log off) (2 occurs before you get the pokedex) + ld a, [wCurrentMenuItem] + and a + jp z, BillsPC ;if current menu item id is 0, it's bills pc + cp 1 + jr z, .playersPC ;if current menu item id is 1, it's players pc + jp LogOff ;otherwise, it's 2, and you're logging off +.next + cp 3 + jr nz, .next2 ;if not 3 menu items (not counting log off) (3 occurs after you get the pokedex, before you beat the pokemon league) + ld a, [wCurrentMenuItem] + and a + jp z, BillsPC ;if current menu item id is 0, it's bills pc + cp 1 + jr z, .playersPC ;if current menu item id is 1, it's players pc + cp 2 + jp z, OaksPC ;if current menu item id is 2, it's oaks pc + jp LogOff ;otherwise, it's 3, and you're logging off +.next2 + ld a, [wCurrentMenuItem] + and a + jp z, BillsPC ;if current menu item id is 0, it's bills pc + cp 1 + jr z, .playersPC ;if current menu item id is 1, it's players pc + cp 2 + jp z, OaksPC ;if current menu item id is 2, it's oaks pc + cp 3 + jp z, PKMNLeague ;if current menu item id is 3, it's pkmnleague + jp LogOff ;otherwise, it's 4, and you're logging off +.playersPC + ld hl, wFlags_0xcd60 + res 5, [hl] + set 3, [hl] + ld a, SFX_ENTER_PC + call PlaySound + call WaitForSoundToFinish + ld hl, AccessedMyPCText + call PrintText + farcall PlayerPC + jr ReloadMainMenu +OaksPC: + ld a, SFX_ENTER_PC + call PlaySound + call WaitForSoundToFinish + farcall OpenOaksPC + jr ReloadMainMenu +PKMNLeague: + ld a, SFX_ENTER_PC + call PlaySound + call WaitForSoundToFinish + farcall PKMNLeaguePC + jr ReloadMainMenu +BillsPC: + ld a, SFX_ENTER_PC + call PlaySound + call WaitForSoundToFinish + CheckEvent EVENT_MET_BILL + jr nz, .billsPC ;if you've met bill, use that bill's instead of someone's + ld hl, AccessedSomeonesPCText + jr .printText +.billsPC + ld hl, AccessedBillsPCText +.printText + call PrintText + farcall BillsPC_ +ReloadMainMenu: + xor a + ld [wDoNotWaitForButtonPressAfterDisplayingText], a + call ReloadMapData + call UpdateSprites + jp PCMainMenu +LogOff: + ld a, SFX_TURN_OFF_PC + call PlaySound + call WaitForSoundToFinish + ld hl, wFlags_0xcd60 + res 3, [hl] + res 5, [hl] + ret + +TurnedOnPC1Text: + text_far _TurnedOnPC1Text + text_end + +AccessedBillsPCText: + text_far _AccessedBillsPCText + text_end + +AccessedSomeonesPCText: + text_far _AccessedSomeonesPCText + text_end + +AccessedMyPCText: + text_far _AccessedMyPCText + text_end + +; removes one of the specified item ID [hItemToRemoveID] from bag (if existent) +RemoveItemByID:: + ld hl, wBagItems + ldh a, [hItemToRemoveID] + ld b, a + xor a + ldh [hItemToRemoveIndex], a +.loop + ld a, [hli] + cp -1 ; reached terminator? + ret z + cp b + jr z, .foundItem + inc hl + ldh a, [hItemToRemoveIndex] + inc a + ldh [hItemToRemoveIndex], a + jr .loop +.foundItem + ld a, $1 + ld [wItemQuantity], a + ldh a, [hItemToRemoveIndex] + ld [wWhichPokemon], a + ld hl, wNumBagItems + jp RemoveItemFromInventory diff --git a/engine/menus/players_pc.asm b/engine/menus/players_pc.asm new file mode 100755 index 00000000..1fac030b --- /dev/null +++ b/engine/menus/players_pc.asm @@ -0,0 +1,302 @@ +PlayerPC:: + ld a, ITEM_NAME + ld [wNameListType], a + call SaveScreenTilesToBuffer1 + xor a + ld [wBagSavedMenuItem], a + ld [wParentMenuItem], a + ld a, [wFlags_0xcd60] + bit 3, a ; accessing player's PC through another PC? + jr nz, PlayerPCMenu +; accessing it directly + ld a, SFX_TURN_ON_PC + call PlaySound + ld hl, TurnedOnPC2Text + call PrintText + +PlayerPCMenu: + ld hl, wd730 + set 6, [hl] + ld a, [wParentMenuItem] + ld [wCurrentMenuItem], a + ld hl, wFlags_0xcd60 + set 5, [hl] + call LoadScreenTilesFromBuffer2 + hlcoord 0, 0 + lb bc, 8, 14 + call TextBoxBorder + call UpdateSprites + hlcoord 2, 2 + ld de, PlayersPCMenuEntries + call PlaceString + ld hl, wTopMenuItemY + ld a, 2 + ld [hli], a ; wTopMenuItemY + dec a + ld [hli], a ; wTopMenuItemX + inc hl + inc hl + ld a, 3 + ld [hli], a ; wMaxMenuItem + ld a, A_BUTTON | B_BUTTON + ld [hli], a ; wMenuWatchedKeys + xor a + ld [hl], a + ld hl, wListScrollOffset + ld [hli], a ; wListScrollOffset + ld [hl], a ; wMenuWatchMovingOutOfBounds + ld [wPlayerMonNumber], a + ld hl, WhatDoYouWantText + call PrintText + call HandleMenuInput + bit 1, a + jp nz, ExitPlayerPC + call PlaceUnfilledArrowMenuCursor + ld a, [wCurrentMenuItem] + ld [wParentMenuItem], a + and a + jp z, PlayerPCWithdraw + dec a + jp z, PlayerPCDeposit + dec a + jp z, PlayerPCToss + +ExitPlayerPC: + ld a, [wFlags_0xcd60] + bit 3, a ; accessing player's PC through another PC? + jr nz, .next +; accessing it directly + ld a, SFX_TURN_OFF_PC + call PlaySound + call WaitForSoundToFinish +.next + ld hl, wFlags_0xcd60 + res 5, [hl] + call LoadScreenTilesFromBuffer2 + xor a + ld [wListScrollOffset], a + ld [wBagSavedMenuItem], a + ld hl, wd730 + res 6, [hl] + xor a + ld [wDoNotWaitForButtonPressAfterDisplayingText], a + ret + +PlayerPCDeposit: + xor a + ld [wCurrentMenuItem], a + ld [wListScrollOffset], a + ld a, [wNumBagItems] + and a + jr nz, .loop + ld hl, NothingToDepositText + call PrintText + jp PlayerPCMenu +.loop + ld hl, WhatToDepositText + call PrintText + ld hl, wNumBagItems + ld a, l + ld [wListPointer], a + ld a, h + ld [wListPointer + 1], a + xor a + ld [wPrintItemPrices], a + ld a, ITEMLISTMENU + ld [wListMenuID], a + call DisplayListMenuID + jp c, PlayerPCMenu + call IsKeyItem + ld a, 1 + ld [wItemQuantity], a + ld a, [wIsKeyItem] + and a + jr nz, .next +; if it's not a key item, there can be more than one of the item + ld hl, DepositHowManyText + call PrintText + call DisplayChooseQuantityMenu + cp $ff + jp z, .loop +.next + ld hl, wNumBoxItems + call AddItemToInventory + jr c, .roomAvailable + ld hl, NoRoomToStoreText + call PrintText + jp .loop +.roomAvailable + ld hl, wNumBagItems + call RemoveItemFromInventory + call WaitForSoundToFinish + ld a, SFX_WITHDRAW_DEPOSIT + call PlaySound + call WaitForSoundToFinish + ld hl, ItemWasStoredText + call PrintText + jp .loop + +PlayerPCWithdraw: + xor a + ld [wCurrentMenuItem], a + ld [wListScrollOffset], a + ld a, [wNumBoxItems] + and a + jr nz, .loop + ld hl, NothingStoredText + call PrintText + jp PlayerPCMenu +.loop + ld hl, WhatToWithdrawText + call PrintText + ld hl, wNumBoxItems + ld a, l + ld [wListPointer], a + ld a, h + ld [wListPointer + 1], a + xor a + ld [wPrintItemPrices], a + ld a, ITEMLISTMENU + ld [wListMenuID], a + call DisplayListMenuID + jp c, PlayerPCMenu + call IsKeyItem + ld a, 1 + ld [wItemQuantity], a + ld a, [wIsKeyItem] + and a + jr nz, .next +; if it's not a key item, there can be more than one of the item + ld hl, WithdrawHowManyText + call PrintText + call DisplayChooseQuantityMenu + cp $ff + jp z, .loop +.next + ld hl, wNumBagItems + call AddItemToInventory + jr c, .roomAvailable + ld hl, CantCarryMoreText + call PrintText + jp .loop +.roomAvailable + ld hl, wNumBoxItems + call RemoveItemFromInventory + call WaitForSoundToFinish + ld a, SFX_WITHDRAW_DEPOSIT + call PlaySound + call WaitForSoundToFinish + ld hl, WithdrewItemText + call PrintText + jp .loop + +PlayerPCToss: + xor a + ld [wCurrentMenuItem], a + ld [wListScrollOffset], a + ld a, [wNumBoxItems] + and a + jr nz, .loop + ld hl, NothingStoredText + call PrintText + jp PlayerPCMenu +.loop + ld hl, WhatToTossText + call PrintText + ld hl, wNumBoxItems + ld a, l + ld [wListPointer], a + ld a, h + ld [wListPointer + 1], a + xor a + ld [wPrintItemPrices], a + ld a, ITEMLISTMENU + ld [wListMenuID], a + push hl + call DisplayListMenuID + pop hl + jp c, PlayerPCMenu + push hl + call IsKeyItem + pop hl + ld a, 1 + ld [wItemQuantity], a + ld a, [wIsKeyItem] + and a + jr nz, .next + ld a, [wcf91] + call IsItemHM + jr c, .next +; if it's not a key item, there can be more than one of the item + push hl + ld hl, TossHowManyText + call PrintText + call DisplayChooseQuantityMenu + pop hl + cp $ff + jp z, .loop +.next + call TossItem ; disallows tossing key items + jp .loop + +PlayersPCMenuEntries: + db "WITHDRAW ITEM" + next "DEPOSIT ITEM" + next "TOSS ITEM" + next "LOG OFF@" + +TurnedOnPC2Text: + text_far _TurnedOnPC2Text + text_end + +WhatDoYouWantText: + text_far _WhatDoYouWantText + text_end + +WhatToDepositText: + text_far _WhatToDepositText + text_end + +DepositHowManyText: + text_far _DepositHowManyText + text_end + +ItemWasStoredText: + text_far _ItemWasStoredText + text_end + +NothingToDepositText: + text_far _NothingToDepositText + text_end + +NoRoomToStoreText: + text_far _NoRoomToStoreText + text_end + +WhatToWithdrawText: + text_far _WhatToWithdrawText + text_end + +WithdrawHowManyText: + text_far _WithdrawHowManyText + text_end + +WithdrewItemText: + text_far _WithdrewItemText + text_end + +NothingStoredText: + text_far _NothingStoredText + text_end + +CantCarryMoreText: + text_far _CantCarryMoreText + text_end + +WhatToTossText: + text_far _WhatToTossText + text_end + +TossHowManyText: + text_far _TossHowManyText + text_end diff --git a/engine/menus/pokedex.asm b/engine/menus/pokedex.asm new file mode 100755 index 00000000..874fe50f --- /dev/null +++ b/engine/menus/pokedex.asm @@ -0,0 +1,745 @@ +ShowPokedexMenu: + call GBPalWhiteOut + call ClearScreen + call UpdateSprites + ld a, [wListScrollOffset] + push af + xor a + ld [wCurrentMenuItem], a + ld [wListScrollOffset], a + ld [wLastMenuItem], a + inc a + ld [wd11e], a + ldh [hJoy7], a +.setUpGraphics + callfar LoadPokedexTilePatterns +.loop + ld b, SET_PAL_GENERIC + call RunPaletteCommand +.doPokemonListMenu + ld hl, wTopMenuItemY + ld a, 3 + ld [hli], a ; top menu item Y + xor a + ld [hli], a ; top menu item X + inc a + ld [wMenuWatchMovingOutOfBounds], a + inc hl + inc hl + ld a, 6 + ld [hli], a ; max menu item ID + ld [hl], D_LEFT | D_RIGHT | B_BUTTON | A_BUTTON + call HandlePokedexListMenu + jr c, .goToSideMenu ; if the player chose a pokemon from the list +.exitPokedex + xor a + ld [wMenuWatchMovingOutOfBounds], a + ld [wCurrentMenuItem], a + ld [wLastMenuItem], a + ldh [hJoy7], a + ld [wWastedByteCD3A], a + ld [wOverrideSimulatedJoypadStatesMask], a + pop af + ld [wListScrollOffset], a + call GBPalWhiteOutWithDelay3 + call RunDefaultPaletteCommand + jp ReloadMapData + +.goToSideMenu + call HandlePokedexSideMenu + dec b + jr z, .exitPokedex ; if the player chose Quit + dec b + jr z, .doPokemonListMenu ; if pokemon not seen or player pressed B button + dec b + jr z, .loop + jp .setUpGraphics ; if pokemon data or area was shown + +; handles the menu on the lower right in the pokedex screen +; OUTPUT: +; b = reason for exiting menu +; 00: showed pokemon data or area +; 01: the player chose Quit +; 02: the pokemon has not been seen yet or the player pressed the B button +HandlePokedexSideMenu: + call PlaceUnfilledArrowMenuCursor + ld a, [wCurrentMenuItem] + push af + ld b, a + ld a, [wLastMenuItem] + push af + ld a, [wListScrollOffset] + push af + add b + inc a + ld [wd11e], a + ld a, [wd11e] + push af + ld a, [wDexMaxSeenMon] + push af ; this doesn't need to be preserved + ld hl, wPokedexSeen + call IsPokemonBitSet + ld b, 2 + jr z, .exitSideMenu + call PokedexToIndex + ld hl, wTopMenuItemY + ld a, 8 + ld [hli], a ; top menu item Y + ld a, 15 + ld [hli], a ; top menu item X + xor a + ld [hli], a ; current menu item ID + inc hl + ld a, 4 + ld [hli], a ; max menu item ID + ld a, A_BUTTON | B_BUTTON + ld [hli], a ; menu watched keys (A button and B button) + xor a + ld [hli], a ; old menu item ID + ld [wMenuWatchMovingOutOfBounds], a + ldh [hJoy7], a +.handleMenuInput + call HandleMenuInput + bit 1, a ; was the B button pressed? + ld b, 2 + jr nz, .buttonBPressed + ld a, [wCurrentMenuItem] + and a + jr z, .choseData + dec a + jr z, .choseCry + dec a + jr z, .choseArea + dec a + jr z, .chosePrint +.choseQuit + ld b, 1 +.exitSideMenu + pop af + ld [wDexMaxSeenMon], a + pop af + ld [wd11e], a + pop af + ld [wListScrollOffset], a + pop af + ld [wLastMenuItem], a + pop af + ld [wCurrentMenuItem], a + ld a, $1 + ldh [hJoy7], a + push bc + hlcoord 0, 3 + ld de, 20 + lb bc, " ", 13 + call DrawTileLine ; cover up the menu cursor in the pokemon list + pop bc + ret + +.buttonBPressed + push bc + hlcoord 15, 8 + ld de, 20 + lb bc, " ", 9 + call DrawTileLine ; cover up the menu cursor in the side menu + pop bc + jr .exitSideMenu + +.choseData + call ShowPokedexDataInternal + ld b, 0 + jr .exitSideMenu + +; play pokemon cry +.choseCry + ld a, [wd11e] + call GetCryData + call PlaySound + jr .handleMenuInput + +.choseArea + predef LoadTownMap_Nest ; display pokemon areas + ld b, 0 + jr .exitSideMenu + +.chosePrint + ldh a, [hTilesetType] + push af + xor a + ldh [hTilesetType], a + ld a, [wd11e] + ld [wcf91], a + callfar PrintPokedexEntry + xor a + ldh [hAutoBGTransferEnabled], a + call ClearScreen + pop af + ldh [hTilesetType], a + ld b, $3 + jr .exitSideMenu + +; handles the list of pokemon on the left of the pokedex screen +; sets carry flag if player presses A, unsets carry flag if player presses B +HandlePokedexListMenu: + call Pokedex_DrawInterface +.loop + call Pokedex_PlacePokemonList + call GBPalNormal + call HandleMenuInput + bit BIT_B_BUTTON, a ; was the B button pressed? + jp nz, .buttonBPressed + bit BIT_A_BUTTON, a ; was the A button pressed? + jp nz, .buttonAPressed +.checkIfUpPressed + bit BIT_D_UP, a ; was Up pressed? + jr z, .checkIfDownPressed +.upPressed ; scroll up one row + ld a, [wListScrollOffset] + and a + jp z, .loop + dec a + ld [wListScrollOffset], a + jp .loop + +.checkIfDownPressed + bit BIT_D_DOWN, a ; was Down pressed? + jr z, .checkIfRightPressed +.downPressed ; scroll down one row + ld a, [wDexMaxSeenMon] + cp a, 7 + jp c, .loop ; can't if the list is shorter than 7 + sub a, 7 + ld b, a + ld a, [wListScrollOffset] + cp b + jp z, .loop + inc a + ld [wListScrollOffset], a + jp .loop + +.checkIfRightPressed + bit BIT_D_RIGHT, a ; was Right pressed? + jr z, .checkIfLeftPressed +.rightPressed ; scroll down 7 rows + ld a, [wDexMaxSeenMon] + cp a, 7 + jp c, .loop ; can't if the list is shorter than 7 + sub a, 6 + ld b, a + ld a, [wListScrollOffset] + add a, 7 + ld [wListScrollOffset], a + cp b + jp c, .loop + dec b + ld a, b + ld [wListScrollOffset], a + jp .loop + +.checkIfLeftPressed ; scroll up 7 rows + bit BIT_D_LEFT, a ; was Left pressed? + jr z, .buttonAPressed +.leftPressed + ld a, [wListScrollOffset] + sub a, 7 + ld [wListScrollOffset], a + jp nc, .loop + xor a + ld [wListScrollOffset], a + jp .loop + +.buttonAPressed + scf + ret + +.buttonBPressed + and a + ret + +Pokedex_DrawInterface: + xor a + ldh [hAutoBGTransferEnabled], a +; draw the horizontal line separating the seen and owned amounts from the menu + hlcoord 15, 6 + ld a, "─" + ld [hli], a + ld [hli], a + ld [hli], a + ld [hli], a + ld [hli], a + hlcoord 14, 0 + ld [hl], $71 ; vertical line tile + hlcoord 14, 1 + call DrawPokedexVerticalLine + hlcoord 14, 9 + call DrawPokedexVerticalLine + ld hl, wPokedexSeen + ld b, wPokedexSeenEnd - wPokedexSeen + call CountSetBits + ld de, wNumSetBits + hlcoord 16, 2 + lb bc, 1, 3 + call PrintNumber ; print number of seen pokemon + ld hl, wPokedexOwned + ld b, wPokedexOwnedEnd - wPokedexOwned + call CountSetBits + ld de, wNumSetBits + hlcoord 16, 5 + lb bc, 1, 3 + call PrintNumber ; print number of owned pokemon + hlcoord 16, 1 + ld de, PokedexSeenText + call PlaceString + hlcoord 16, 4 + ld de, PokedexOwnText + call PlaceString + hlcoord 1, 1 + ld de, PokedexContentsText + call PlaceString + hlcoord 16, 8 + ld de, PokedexMenuItemsText + call PlaceString +; find the highest pokedex number among the pokemon the player has seen + ld hl, wPokedexSeenEnd - 1 + ld b, (wPokedexSeenEnd - wPokedexSeen) * 8 + 1 +.maxSeenPokemonLoop + ld a, [hld] + ld c, 8 +.maxSeenPokemonInnerLoop + dec b + sla a + jr c, .storeMaxSeenPokemon + dec c + jr nz, .maxSeenPokemonInnerLoop + jr .maxSeenPokemonLoop + +.storeMaxSeenPokemon + ld a, b + ld [wDexMaxSeenMon], a + ret + +DrawPokedexVerticalLine: + ld c, 9 ; height of line + ld de, SCREEN_WIDTH ; width of screen + ld a, $71 ; vertical line tile +.loop + ld [hl], a + add hl, de + xor a, 1 ; toggle between vertical line tile and box tile + dec c + jr nz, .loop + ret + +PokedexSeenText: + db "SEEN@" + +PokedexOwnText: + db "OWN@" + +PokedexContentsText: + db "CONTENTS@" + +PokedexMenuItemsText: + db "DATA" + next "CRY" + next "AREA" + next "PRNT" + next "QUIT@" + +Pokedex_PlacePokemonList: + xor a + ldh [hAutoBGTransferEnabled], a + hlcoord 4, 2 + lb bc, 14, 10 + call ClearScreenArea + hlcoord 1, 3 + ld a, [wListScrollOffset] + ld [wd11e], a + ld d, 7 + ld a, [wDexMaxSeenMon] + cp 7 + jr nc, .printPokemonLoop + ld d, a + dec a + ld [wMaxMenuItem], a +; loop to print pokemon pokedex numbers and names +; if the player has owned the pokemon, it puts a pokeball beside the name +.printPokemonLoop + ld a, [wd11e] + inc a + ld [wd11e], a + push af + push de + push hl + ld de, -SCREEN_WIDTH + add hl, de + ld de, wd11e + lb bc, LEADING_ZEROES | 1, 3 + call PrintNumber ; print the pokedex number + ld de, SCREEN_WIDTH + add hl, de + dec hl + push hl + ld hl, wPokedexOwned + call IsPokemonBitSet + pop hl + ld a, " " + jr z, .writeTile + ld a, $72 ; pokeball tile +.writeTile + ld [hl], a ; put a pokeball next to pokemon that the player has owned + push hl + ld hl, wPokedexSeen + call IsPokemonBitSet + jr nz, .getPokemonName ; if the player has seen the pokemon + ld de, .dashedLine ; print a dashed line in place of the name if the player hasn't seen the pokemon + jr .skipGettingName +.dashedLine ; for unseen pokemon in the list + db "----------@" +.getPokemonName + call PokedexToIndex + call GetMonName +.skipGettingName + pop hl + inc hl + call PlaceString + pop hl + ld bc, 2 * SCREEN_WIDTH + add hl, bc + pop de + pop af + ld [wd11e], a + dec d + jr nz, .printPokemonLoop + ld a, 01 + ldh [hAutoBGTransferEnabled], a + call Delay3 + ret + +; tests if a pokemon's bit is set in the seen or owned pokemon bit fields +; INPUT: +; [wd11e] = pokedex number +; hl = address of bit field +IsPokemonBitSet: + ld a, [wd11e] + dec a + ld c, a + ld b, FLAG_TEST + predef FlagActionPredef + ld a, c + and a + ret + +; function to display pokedex data from outside the pokedex +ShowPokedexData: + call GBPalWhiteOutWithDelay3 + call ClearScreen + call UpdateSprites + callfar LoadPokedexTilePatterns ; load pokedex tiles + +; function to display pokedex data from inside the pokedex +ShowPokedexDataInternal: + ld hl, wd72c + set 1, [hl] + ld a, $33 ; 3/7 volume + ldh [rNR50], a + ldh a, [hTilesetType] + push af + xor a + ldh [hTilesetType], a + call GBPalWhiteOut ; zero all palettes + ld a, [wd11e] ; pokemon ID + ld [wcf91], a + push af + ld b, SET_PAL_POKEDEX + call RunPaletteCommand + pop af + ld [wd11e], a + call DrawDexEntryOnScreen + call c, Pokedex_PrintFlavorTextAtRow11 +.waitForButtonPress + call JoypadLowSensitivity + ldh a, [hJoy5] + and a, A_BUTTON | B_BUTTON + jr z, .waitForButtonPress + pop af + ldh [hTilesetType], a + call GBPalWhiteOut + call ClearScreen + call RunDefaultPaletteCommand + call LoadTextBoxTilePatterns + call GBPalNormal + ld hl, wd72c + res 1, [hl] + ld a, $77 ; max volume + ldh [rNR50], a + ret + +HeightWeightText: + db "HT ?′??″" + next "WT ???lb@" + +; XXX does anything point to this? +PokeText: + db "#@" + +; horizontal line that divides the pokedex text description from the rest of the data +PokedexDataDividerLine: + db $68, $69, $6B, $69, $6B, $69, $6B, $69, $6B, $6B + db $6B, $6B, $69, $6B, $69, $6B, $69, $6B, $69, $6A + db "@" + +DrawDexEntryOnScreen: + call ClearScreen + + hlcoord 0, 0 + ld de, 1 + lb bc, $64, SCREEN_WIDTH + call DrawTileLine ; draw top border + + hlcoord 0, 17 + ld b, $6f + call DrawTileLine ; draw bottom border + + hlcoord 0, 1 + ld de, 20 + lb bc, $66, $10 + call DrawTileLine ; draw left border + + hlcoord 19, 1 + ld b, $67 + call DrawTileLine ; draw right border + + ld a, $63 ; upper left corner tile + ldcoord_a 0, 0 + ld a, $65 ; upper right corner tile + ldcoord_a 19, 0 + ld a, $6c ; lower left corner tile + ldcoord_a 0, 17 + ld a, $6e ; lower right corner tile + ldcoord_a 19, 17 + + hlcoord 0, 9 + ld de, PokedexDataDividerLine + call PlaceString ; draw horizontal divider line + + hlcoord 9, 6 + ld de, HeightWeightText + call PlaceString + + call GetMonName + hlcoord 9, 2 + call PlaceString + + ld hl, PokedexEntryPointers + ld a, [wd11e] + dec a + ld e, a + ld d, 0 + add hl, de + add hl, de + ld a, [hli] + ld e, a + ld d, [hl] ; de = address of pokedex entry + + hlcoord 9, 4 + call PlaceString ; print species name + + ld h, b + ld l, c + push de + ld a, [wd11e] + push af + call IndexToPokedex + + hlcoord 2, 8 + ld a, "№" + ld [hli], a + ld a, "" + ld [hli], a + ld de, wd11e + lb bc, LEADING_ZEROES | 1, 3 + call PrintNumber ; print pokedex number + + ld hl, wPokedexOwned + call IsPokemonBitSet + pop af + ld [wd11e], a + ld a, [wcf91] + ld [wd0b5], a + pop de + + push af + push bc + push de + push hl + + call Delay3 + call GBPalNormal + call GetMonHeader ; load pokemon picture location + hlcoord 1, 1 + call LoadFlippedFrontSpriteByMonIndex ; draw pokemon picture + ld a, [wcf91] + call PlayCry ; play pokemon cry + + pop hl + pop de + pop bc + pop af + + ld a, c + and a + ret z ; if the pokemon has not been owned, don't print the height, weight, or description + + inc de ; de = address of feet (height) + ld a, [de] ; reads feet, but a is overwritten without being used + hlcoord 12, 6 + lb bc, 1, 2 + call PrintNumber ; print feet (height) + ld a, "′" + ld [hl], a + inc de + inc de ; de = address of inches (height) + hlcoord 15, 6 + lb bc, LEADING_ZEROES | 1, 2 + call PrintNumber ; print inches (height) + ld a, "″" + ld [hl], a +; now print the weight (note that weight is stored in tenths of pounds internally) + inc de + inc de + inc de ; de = address of upper byte of weight + push de +; put weight in big-endian order at hDexWeight + ld hl, hDexWeight + ld a, [hl] ; save existing value of [hDexWeight] + push af + ld a, [de] ; a = upper byte of weight + ld [hli], a ; store upper byte of weight in [hDexWeight] + ld a, [hl] ; save existing value of [hDexWeight + 1] + push af + dec de + ld a, [de] ; a = lower byte of weight + ld [hl], a ; store lower byte of weight in [hDexWeight + 1] + ld de, hDexWeight + hlcoord 11, 8 + lb bc, 2, 5 ; 2 bytes, 5 digits + call PrintNumber ; print weight + hlcoord 14, 8 + ldh a, [hDexWeight + 1] + sub 10 + ldh a, [hDexWeight] + sbc 0 + jr nc, .next + ld [hl], "0" ; if the weight is less than 10, put a 0 before the decimal point +.next + inc hl + ld a, [hli] + ld [hld], a ; make space for the decimal point by moving the last digit forward one tile + ld [hl], "" ; decimal point tile + pop af + ldh [hDexWeight + 1], a ; restore original value of [hDexWeight + 1] + pop af + ldh [hDexWeight], a ; restore original value of [hDexWeight] + pop hl + inc hl ; hl = address of pokedex description text + scf + ret + +Pokedex_PrintFlavorTextAtRow11: + bccoord 1, 11 +Pokedex_PrintFlavorTextAtBC: + ld a, %10 + ldh [hClearLetterPrintingDelayFlags], a + call TextCommandProcessor ; print pokedex description text + xor a + ldh [hClearLetterPrintingDelayFlags], a + ret + +Pokedex_PrepareDexEntryForPrinting: + hlcoord 0, 0 + ld de, SCREEN_WIDTH + lb bc, $66, $d + call DrawTileLine + hlcoord 19, 0 + ld b, $67 + call DrawTileLine + hlcoord 0, 13 + ld de, $1 + lb bc, $6f, SCREEN_WIDTH + call DrawTileLine + ld a, $6c + ldcoord_a 0, 13 + ld a, $6e + ldcoord_a 19, 13 + ld a, [wPrinterPokedexEntryTextPointer] + ld l, a + ld a, [wPrinterPokedexEntryTextPointer + 1] + ld h, a + bccoord 1, 1 + ldh a, [hFlagsFFFA] + set 3, a + ldh [hFlagsFFFA], a + call Pokedex_PrintFlavorTextAtBC + ldh a, [hFlagsFFFA] + res 3, a + ldh [hFlagsFFFA], a + ret + +; draws a line of tiles +; INPUT: +; b = tile ID +; c = number of tile ID's to write +; de = amount to destination address after each tile (1 for horizontal, 20 for vertical) +; hl = destination address +DrawTileLine: + push bc + push de +.loop + ld [hl], b + add hl, de + dec c + jr nz, .loop + pop de + pop bc + ret + +INCLUDE "data/pokemon/dex_entries.asm" + +PokedexToIndex: + ; converts the Pokédex number at wd11e to an index + push bc + push hl + ld a, [wd11e] + ld b, a + ld c, 0 + ld hl, PokedexOrder + +.loop ; go through the list until we find an entry with a matching dex number + inc c + ld a, [hli] + cp b + jr nz, .loop + + ld a, c + ld [wd11e], a + pop hl + pop bc + ret + +IndexToPokedex: + ; converts the index number at wd11e to a Pokédex number + push bc + push hl + ld a, [wd11e] + dec a + ld hl, PokedexOrder + ld b, 0 + ld c, a + add hl, bc + ld a, [hl] + ld [wd11e], a + pop hl + pop bc + ret + +INCLUDE "data/pokemon/dex_order.asm" diff --git a/engine/menus/save.asm b/engine/menus/save.asm new file mode 100755 index 00000000..bcb27ddf --- /dev/null +++ b/engine/menus/save.asm @@ -0,0 +1,682 @@ +LoadSAV: +;(if carry -> write +;"the file data is destroyed") + call ClearScreen + call LoadFontTilePatterns + call LoadTextBoxTilePatterns + call LoadSAV0 + jr c, .badsum + call LoadSAV1 + jr c, .badsum + call LoadSAV2 + jr c, .badsum + ld a, $2 ; good checksum + jr .goodsum +.badsum + ld hl, wd730 + push hl + set 6, [hl] + ld hl, FileDataDestroyedText + call PrintText + ld c, 100 + call DelayFrames + pop hl + res 6, [hl] + ld a, $1 ; bad checksum +.goodsum + ld [wSaveFileStatus], a + ret + +FileDataDestroyedText: + text_far _FileDataDestroyedText + text_end + +LoadSAV0: + call EnableSRAMAndLatchClockData + ld a, $1 + ld [MBC1SRamBank], a + ld hl, sPlayerName ; hero name located in SRAM + ld bc, sMainDataCheckSum - sPlayerName ; but here checks the full SAV + call SAVCheckSum + ld c, a + ld a, [sMainDataCheckSum] ; SAV's checksum + cp c + jp z, .checkSumsMatched + +; If the computed checksum didn't match the saved on, try again. + ld hl, sPlayerName + ld bc, sMainDataCheckSum - sPlayerName + call SAVCheckSum + ld c, a + ld a, [sMainDataCheckSum] ; SAV's checksum + cp c + jp nz, SAVBadCheckSum + +.checkSumsMatched + ld hl, sPlayerName + ld de, wPlayerName + ld bc, NAME_LENGTH + call CopyData + ld hl, sMainData + ld de, wMainDataStart + ld bc, wMainDataEnd - wMainDataStart + call CopyData + ld hl, wCurMapTileset + set 7, [hl] + ld hl, sSpriteData + ld de, wSpriteDataStart + ld bc, wSpriteDataEnd - wSpriteDataStart + call CopyData + ld a, [sTilesetType] + ldh [hTilesetType], a + ld hl, sCurBoxData + ld de, wBoxDataStart + ld bc, wBoxDataEnd - wBoxDataStart + call CopyData + and a + jp SAVGoodChecksum + +LoadSAV1: + call EnableSRAMAndLatchClockData + ld a, $1 + ld [MBC1SRamBank], a + ld hl, sPlayerName ; hero name located in SRAM + ld bc, sMainDataCheckSum - sPlayerName ; but here checks the full SAV + call SAVCheckSum + ld c, a + ld a, [sMainDataCheckSum] ; SAV's checksum + cp c + jr nz, SAVBadCheckSum + ld hl, sCurBoxData + ld de, wBoxDataStart + ld bc, wBoxDataEnd - wBoxDataStart + call CopyData + and a + jp SAVGoodChecksum + +LoadSAV2: + call EnableSRAMAndLatchClockData + ld a, $1 + ld [MBC1SRamBank], a + ld hl, sPlayerName ; hero name located in SRAM + ld bc, sMainDataCheckSum - sPlayerName ; but here checks the full SAV + call SAVCheckSum + ld c, a + ld a, [sMainDataCheckSum] ; SAV's checksum + cp c + jp nz, SAVBadCheckSum + ld hl, sPartyData + ld de, wPartyDataStart + ld bc, wPartyDataEnd - wPartyDataStart + call CopyData + ld hl, sMainData + ld de, wPokedexOwned + ld bc, wPokedexSeenEnd - wPokedexOwned + call CopyData + and a + jp SAVGoodChecksum + +SAVBadCheckSum: + scf + +SAVGoodChecksum: + call DisableSRAMAndPrepareClockData + ret + +LoadSAVIgnoreBadCheckSum: +; unused function that loads save data and ignores bad checksums + call LoadSAV0 + call LoadSAV1 + jp LoadSAV2 + +SaveSAV: + farcall PrintSaveScreenText + ld c, 10 + call DelayFrames + ld hl, WouldYouLikeToSaveText + call SaveSAVConfirm + and a ;|0 = Yes|1 = No| + ret nz + ld c, 10 + call DelayFrames + ld a, [wSaveFileStatus] + cp $1 + jr z, .save + call SAVCheckRandomID + jr z, .save + ld hl, OlderFileWillBeErasedText + call SaveSAVConfirm + and a + ret nz +.save + call SaveSAVtoSRAM + ld hl, SavingText + call PrintText + ld c, 128 + call DelayFrames + ld hl, GameSavedText + call PrintText + ld c, 10 + call DelayFrames + ld a, SFX_SAVE + call PlaySoundWaitForCurrent + call WaitForSoundToFinish + ld c, 30 + call DelayFrames + ret + +SaveSAVConfirm: + call PrintText + hlcoord 0, 7 + lb bc, 8, 1 + ld a, TWO_OPTION_MENU + ld [wTextBoxID], a + call DisplayTextBoxID ; yes/no menu + ld a, [wCurrentMenuItem] + ret + +WouldYouLikeToSaveText: + text_far _WouldYouLikeToSaveText + text_end + +SavingText: + text_far _SavingText + text_end + +GameSavedText: + text_far _GameSavedText + text_end + +OlderFileWillBeErasedText: + text_far _OlderFileWillBeErasedText + text_end + +SaveSAVtoSRAM0: + call EnableSRAMAndLatchClockData + ld a, $1 + ld [MBC1SRamBank], a + ld hl, wPlayerName + ld de, sPlayerName + ld bc, NAME_LENGTH + call CopyData + ld hl, wMainDataStart + ld de, sMainData + ld bc, wMainDataEnd - wMainDataStart + call CopyData + ld hl, wSpriteDataStart + ld de, sSpriteData + ld bc, wSpriteDataEnd - wSpriteDataStart + call CopyData + ld hl, wBoxDataStart + ld de, sCurBoxData + ld bc, wBoxDataEnd - wBoxDataStart + call CopyData + ldh a, [hTilesetType] + ld [sTilesetType], a + ld hl, sPlayerName + ld bc, sMainDataCheckSum - sPlayerName + call SAVCheckSum + ld [sMainDataCheckSum], a + call DisableSRAMAndPrepareClockData + ret + +SaveSAVtoSRAM1: +; stored pokémon + call EnableSRAMAndLatchClockData + ld a, $1 + ld [MBC1SRamBank], a + ld hl, wBoxDataStart + ld de, sCurBoxData + ld bc, wBoxDataEnd - wBoxDataStart + call CopyData + ld hl, sPlayerName + ld bc, sMainDataCheckSum - sPlayerName + call SAVCheckSum + ld [sMainDataCheckSum], a + call DisableSRAMAndPrepareClockData + ret + +SaveSAVtoSRAM2: + call EnableSRAMAndLatchClockData + ld a, $1 + ld [MBC1SRamBank], a + ld hl, wPartyDataStart + ld de, sPartyData + ld bc, wPartyDataEnd - wPartyDataStart + call CopyData + ld hl, wPokedexOwned ; pokédex only + ld de, sMainData + ld bc, wPokedexSeenEnd - wPokedexOwned + call CopyData + ld hl, wPikachuHappiness + ld de, sMainData + $179 + ld a, [hli] + ld [de], a + inc de + ld a, [hl] + ld [de], a + ld hl, sPlayerName + ld bc, sMainDataCheckSum - sPlayerName + call SAVCheckSum + ld [sMainDataCheckSum], a + call DisableSRAMAndPrepareClockData + ret + +SaveSAVtoSRAM:: + ld a, $2 + ld [wSaveFileStatus], a + call SaveSAVtoSRAM0 + call SaveSAVtoSRAM1 + jp SaveSAVtoSRAM2 + +SAVCheckSum: +;Check Sum (result[1 byte] is complemented) + ld d, 0 +.loop + ld a, [hli] + add d + ld d, a + dec bc + ld a, b + or c + jr nz, .loop + ld a, d + cpl + ret + +CalcIndividualBoxCheckSums: + ld hl, sBox1 ; sBox7 + ld de, sBank2IndividualBoxChecksums ; sBank3IndividualBoxChecksums + ld b, NUM_BOXES / 2 +.loop + push bc + push de + ld bc, wBoxDataEnd - wBoxDataStart + call SAVCheckSum + pop de + ld [de], a + inc de + pop bc + dec b + jr nz, .loop + ret + +GetBoxSRAMLocation: +; in: a = box num +; out: b = box SRAM bank, hl = pointer to start of box + ld hl, BoxSRAMPointerTable + ld a, [wCurrentBoxNum] + and $7f + cp NUM_BOXES / 2 + ld b, 2 + jr c, .next + inc b + sub NUM_BOXES / 2 +.next + ld e, a + ld d, 0 + add hl, de + add hl, de + ld a, [hli] + ld h, [hl] + ld l, a + ret + +BoxSRAMPointerTable: + dw sBox1 ; sBox7 + dw sBox2 ; sBox8 + dw sBox3 ; sBox9 + dw sBox4 ; sBox10 + dw sBox5 ; sBox11 + dw sBox6 ; sBox12 + +ChangeBox:: + ld hl, WhenYouChangeBoxText + call PrintText + call YesNoChoice + ld a, [wCurrentMenuItem] + and a + ret nz ; return if No was chosen + ld hl, wCurrentBoxNum + bit 7, [hl] ; is it the first time player is changing the box? + call z, EmptyAllSRAMBoxes ; if so, empty all boxes in SRAM + call DisplayChangeBoxMenu + call UpdateSprites + ld hl, hFlagsFFFA + set 1, [hl] + call HandleMenuInput + ld hl, hFlagsFFFA + res 1, [hl] + bit 1, a ; pressed b + ret nz + ld a, $b6 + call PlaySoundWaitForCurrent + call WaitForSoundToFinish + call GetBoxSRAMLocation + ld e, l + ld d, h + ld hl, wBoxDataStart + call CopyBoxToOrFromSRAM ; copy old box from WRAM to SRAM + ld a, [wCurrentMenuItem] + set 7, a + ld [wCurrentBoxNum], a + call GetBoxSRAMLocation + ld de, wBoxDataStart + call CopyBoxToOrFromSRAM ; copy new box from SRAM to WRAM + ld hl, wMapTextPtr + ld de, wChangeBoxSavedMapTextPointer + ld a, [hli] + ld [de], a + inc de + ld a, [hl] + ld [de], a + call RestoreMapTextPointer + call SaveSAVtoSRAM + ld hl, wChangeBoxSavedMapTextPointer + call SetMapTextPointer + ret + +WhenYouChangeBoxText: + text_far _WhenYouChangeBoxText + text_end + +CopyBoxToOrFromSRAM: +; copy an entire box from hl to de with b as the SRAM bank + push hl + call EnableSRAMAndLatchClockData + ld a, b + ld [MBC1SRamBank], a + ld bc, wBoxDataEnd - wBoxDataStart + call CopyData + pop hl + +; mark the memory that the box was copied from as am empty box + xor a + ld [hli], a + dec a + ld [hl], a + + ld hl, sBox1 ; sBox7 + ld bc, sBank2AllBoxesChecksum - sBox1 + call SAVCheckSum + ld [sBank2AllBoxesChecksum], a ; sBank3AllBoxesChecksum + call CalcIndividualBoxCheckSums + call DisableSRAMAndPrepareClockData + ret + +DisplayChangeBoxMenu: + xor a + ldh [hAutoBGTransferEnabled], a + ld a, A_BUTTON | B_BUTTON + ld [wMenuWatchedKeys], a + ld a, 11 + ld [wMaxMenuItem], a + ld a, 1 + ld [wTopMenuItemY], a + ld a, 12 + ld [wTopMenuItemX], a + xor a + ld [wMenuWatchMovingOutOfBounds], a + ld a, [wCurrentBoxNum] + and $7f + ld [wCurrentMenuItem], a + ld [wLastMenuItem], a + hlcoord 0, 0 + lb bc, 2, 9 + call TextBoxBorder + ld hl, ChooseABoxText + call PrintText + hlcoord 11, 0 + lb bc, 12, 7 + call TextBoxBorder + ld hl, hFlagsFFFA + set 2, [hl] + ld de, BoxNames + hlcoord 13, 1 + call PlaceString + ld hl, hFlagsFFFA + res 2, [hl] + ld a, [wCurrentBoxNum] + and $7f + cp 9 + jr c, .singleDigitBoxNum + sub 9 + hlcoord 8, 2 + ld [hl], "1" + add "0" + jr .next +.singleDigitBoxNum + add "1" +.next + ldcoord_a 9, 2 + hlcoord 1, 2 + ld de, BoxNoText + call PlaceString + call GetMonCountsForAllBoxes + hlcoord 18, 1 + ld de, wBoxMonCounts + ld bc, SCREEN_WIDTH + ld a, $c +.loop + push af + ld a, [de] + and a ; is the box empty? + jr z, .skipPlacingPokeball + ld [hl], $78 ; place pokeball tile next to box name if box not empty +.skipPlacingPokeball + add hl, bc + inc de + pop af + dec a + jr nz, .loop + ld a, 1 + ldh [hAutoBGTransferEnabled], a + ret + +ChooseABoxText: + text_far _ChooseABoxText + text_end + +BoxNames: + db "BOX 1" + next "BOX 2" + next "BOX 3" + next "BOX 4" + next "BOX 5" + next "BOX 6" + next "BOX 7" + next "BOX 8" + next "BOX 9" + next "BOX10" + next "BOX11" + next "BOX12@" + +BoxNoText: + db "BOX No.@" + +EmptyAllSRAMBoxes: +; marks all boxes in SRAM as empty (initialisation for the first time the +; player changes the box) + call EnableSRAMAndLatchClockData + ld a, 2 + ld [MBC1SRamBank], a + call EmptySRAMBoxesInBank + ld a, 3 + ld [MBC1SRamBank], a + call EmptySRAMBoxesInBank + call DisableSRAMAndPrepareClockData + ret + +EmptySRAMBoxesInBank: +; marks every box in the current SRAM bank as empty + ld hl, sBox1 ; sBox7 + call EmptySRAMBox + ld hl, sBox2 ; sBox8 + call EmptySRAMBox + ld hl, sBox3 ; sBox9 + call EmptySRAMBox + ld hl, sBox4 ; sBox10 + call EmptySRAMBox + ld hl, sBox5 ; sBox11 + call EmptySRAMBox + ld hl, sBox6 ; sBox12 + call EmptySRAMBox + ld hl, sBox1 ; sBox7 + ld bc, sBank2AllBoxesChecksum - sBox1 + call SAVCheckSum + ld [sBank2AllBoxesChecksum], a ; sBank3AllBoxesChecksum + call CalcIndividualBoxCheckSums + ret + +EmptySRAMBox: + xor a + ld [hli], a + dec a + ld [hl], a + ret + +GetMonCountsForAllBoxes: + ld hl, wBoxMonCounts + push hl + call EnableSRAMAndLatchClockData + ld a, $2 + ld [MBC1SRamBank], a + call GetMonCountsForBoxesInBank + ld a, $3 + ld [MBC1SRamBank], a + call GetMonCountsForBoxesInBank + call DisableSRAMAndPrepareClockData + pop hl + +; copy the count for the current box from WRAM + ld a, [wCurrentBoxNum] + and $7f + ld c, a + ld b, 0 + add hl, bc + ld a, [wNumInBox] + ld [hl], a + + ret + +GetMonCountsForBoxesInBank: + ld a, [sBox1] ; sBox7 + ld [hli], a + ld a, [sBox2] ; sBox8 + ld [hli], a + ld a, [sBox3] ; sBox9 + ld [hli], a + ld a, [sBox4] ; sBox10 + ld [hli], a + ld a, [sBox5] ; sBox11 + ld [hli], a + ld a, [sBox6] ; sBox12 + ld [hli], a + ret + +SAVCheckRandomID: +; checks if Sav file is the same by checking player's name 1st letter +; and the two random numbers generated at game beginning +; (which are stored at wPlayerID)s + call EnableSRAMAndLatchClockData + ld a, $01 + ld [MBC1SRamBank], a + ld a, [sPlayerName] + and a + jr z, .next + ld hl, sPlayerName + ld bc, sMainDataCheckSum - sPlayerName + call SAVCheckSum + ld c, a + ld a, [sMainDataCheckSum] + cp c + jr nz, .next + ld hl, sMainData + (wPlayerID - wMainDataStart) ; player ID + ld a, [hli] + ld h, [hl] + ld l, a + ld a, [wPlayerID] + cp l + jr nz, .next + ld a, [wPlayerID + 1] + cp h +.next + ld a, $00 + ld [MBC1SRamBankingMode], a + ld [MBC1SRamEnable], a + ret + +SaveHallOfFameTeams: + ld a, [wNumHoFTeams] + dec a + cp HOF_TEAM_CAPACITY + jr nc, .shiftHOFTeams + ld hl, sHallOfFame + ld bc, HOF_TEAM + call AddNTimes + ld e, l + ld d, h + ld hl, wHallOfFame + ld bc, HOF_TEAM + jr HallOfFame_Copy + +.shiftHOFTeams +; if the space designated for HOF teams is full, then shift all HOF teams to the next slot, making space for the new HOF team +; this deletes the last HOF team though + ld hl, sHallOfFame + HOF_TEAM + ld de, sHallOfFame + ld bc, HOF_TEAM * (HOF_TEAM_CAPACITY - 1) + call HallOfFame_Copy + ld hl, wHallOfFame + ld de, sHallOfFame + HOF_TEAM * (HOF_TEAM_CAPACITY - 1) + ld bc, HOF_TEAM + jr HallOfFame_Copy + +LoadHallOfFameTeams: + ld hl, sHallOfFame + ld bc, HOF_TEAM + ld a, [wHoFTeamIndex] + call AddNTimes + ld de, wHallOfFame + ld bc, HOF_TEAM + ; fallthrough + +HallOfFame_Copy: + call EnableSRAMAndLatchClockData + xor a + ld [MBC1SRamBank], a + call CopyData + call DisableSRAMAndPrepareClockData + ret + +ClearSAV: + call EnableSRAMAndLatchClockData + ld a, $4 +.loop + dec a + push af + call PadSRAM_FF + pop af + jr nz, .loop + call DisableSRAMAndPrepareClockData + ret + +PadSRAM_FF: + ld [MBC1SRamBank], a + ld hl, SRAM_Begin + ld bc, SRAM_End - SRAM_Begin + ld a, $ff + jp FillMemory + +EnableSRAMAndLatchClockData: + ld a, $1 + ld [MBC1SRamBankingMode], a + ld a, SRAM_ENABLE + ld [MBC1SRamEnable], a + ret + +DisableSRAMAndPrepareClockData: + ld a, SRAM_DISABLE + ld [MBC1SRamBankingMode], a + ld [MBC1SRamEnable], a + ret diff --git a/engine/menus/start_sub_menus.asm b/engine/menus/start_sub_menus.asm new file mode 100755 index 00000000..84583a69 --- /dev/null +++ b/engine/menus/start_sub_menus.asm @@ -0,0 +1,825 @@ +StartMenu_Pokedex:: + predef ShowPokedexMenu + call LoadScreenTilesFromBuffer2 ; restore saved screen + call Delay3 + call LoadGBPal + call UpdateSprites + jp RedisplayStartMenu + +StartMenu_Pokemon:: + ld a, [wPartyCount] + and a + jp z, RedisplayStartMenu + xor a + ld [wMenuItemToSwap], a + ld [wPartyMenuTypeOrMessageID], a + ld [wUpdateSpritesEnabled], a + call DisplayPartyMenu + jr .checkIfPokemonChosen +.loop + xor a + ld [wMenuItemToSwap], a + ld [wPartyMenuTypeOrMessageID], a + call GoBackToPartyMenu +.checkIfPokemonChosen + jr nc, .chosePokemon +.exitMenu + call GBPalWhiteOutWithDelay3 + call RestoreScreenTilesAndReloadTilePatterns + call LoadGBPal + jp RedisplayStartMenu +.chosePokemon + call SaveScreenTilesToBuffer1 + ld a, FIELD_MOVE_MON_MENU + ld [wTextBoxID], a + call DisplayTextBoxID ; display pokemon menu options + ld hl, wFieldMoves + lb bc, 2, 12 ; max menu item ID, top menu item Y + ld e, 5 +.adjustMenuVariablesLoop + dec e + jr z, .storeMenuVariables + ld a, [hli] + and a ; end of field moves? + jr z, .storeMenuVariables + inc b + dec c + dec c + jr .adjustMenuVariablesLoop +.storeMenuVariables + ld hl, wTopMenuItemY + ld a, c + ld [hli], a ; top menu item Y + ldh a, [hFieldMoveMonMenuTopMenuItemX] + ld [hli], a ; top menu item X + xor a + ld [hli], a ; current menu item ID + inc hl + ld a, b + ld [hli], a ; max menu item ID + ld a, A_BUTTON | B_BUTTON + ld [hli], a ; menu watched keys + xor a + ld [hl], a + call HandleMenuInput + push af + call LoadScreenTilesFromBuffer1 ; restore saved screen + pop af + bit 1, a ; was the B button pressed? + jp nz, .loop +; if the B button wasn't pressed + ld a, [wMaxMenuItem] + ld b, a + ld a, [wCurrentMenuItem] ; menu selection + cp b + jp z, .exitMenu ; if the player chose Cancel + dec b + cp b + jr z, .choseSwitch + dec b + cp b + jp z, .choseStats + ld c, a + ld b, 0 + ld hl, wFieldMoves + add hl, bc + jp .choseOutOfBattleMove +.choseSwitch + ld a, [wPartyCount] + cp 2 ; is there more than one pokemon in the party? + jp c, StartMenu_Pokemon ; if not, no switching + call SwitchPartyMon_InitVarOrSwapData ; init [wMenuItemToSwap] + ld a, SWAP_MONS_PARTY_MENU + ld [wPartyMenuTypeOrMessageID], a + call GoBackToPartyMenu + jp .checkIfPokemonChosen +.choseStats + call ClearSprites + xor a ; PLAYER_PARTY_DATA + ld [wMonDataLocation], a + predef StatusScreen + predef StatusScreen2 + call ReloadMapData + jp StartMenu_Pokemon +.choseOutOfBattleMove + push hl + ld a, [wWhichPokemon] + ld hl, wPartyMonNicks + call GetPartyMonName + pop hl + ld a, [hl] + dec a + add a + ld b, 0 + ld c, a + ld hl, .outOfBattleMovePointers + add hl, bc + ld a, [hli] + ld h, [hl] + ld l, a + ld a, [wObtainedBadges] ; badges obtained + jp hl +.outOfBattleMovePointers + dw .cut + dw .fly + dw .surf + dw .surf + dw .strength + dw .flash + dw .dig + dw .teleport + dw .softboiled +.fly + bit BIT_THUNDERBADGE, a + jp z, .newBadgeRequired + call CheckIfInOutsideMap + jr z, .canFly + ld a, [wWhichPokemon] + ld hl, wPartyMonNicks + call GetPartyMonName + ld hl, .cannotFlyHereText + call PrintText + jp .loop +.canFly + call ChooseFlyDestination + ld a, [wd732] + bit 3, a ; did the player decide to fly? + jr nz, .asm_5d4c + call LoadFontTilePatterns + ld hl, wd72e + set 1, [hl] + jp StartMenu_Pokemon +.asm_5d4c + call Func_1510 + jp .goBackToMap +.cut + bit BIT_CASCADEBADGE, a + jp z, .newBadgeRequired + predef UsedCut + ld a, [wActionResultOrTookBattleTurn] + and a + jp z, .loop + jp CloseTextDisplay +.surf + bit BIT_SOULBADGE, a + jp z, .newBadgeRequired + farcall IsSurfingAllowed + ld hl, wd728 + bit 1, [hl] + res 1, [hl] + jp z, .loop + ld a, [wcf91] + cp PIKACHU ; is this surfing pikachu? + jr z, .surfingPikachu + ld a, $1 + jr .continue +.surfingPikachu + ld a, $2 +.continue + ld [wd473], a + ld a, SURFBOARD + ld [wcf91], a + ld [wPseudoItemID], a + call UseItem + ld a, [wActionResultOrTookBattleTurn] + and a + jr z, .reloadNormalSprite + call GBPalWhiteOutWithDelay3 + jp .goBackToMap +.reloadNormalSprite + xor a + ld [wd473], a + jp .loop +.strength + bit BIT_RAINBOWBADGE, a + jp z, .newBadgeRequired + predef PrintStrengthTxt + call GBPalWhiteOutWithDelay3 + jp .goBackToMap +.flash + bit BIT_BOULDERBADGE, a + jp z, .newBadgeRequired + xor a + ld [wMapPalOffset], a + ld hl, .flashLightsAreaText + call PrintText + call GBPalWhiteOutWithDelay3 + jp .goBackToMap +.flashLightsAreaText + text_far _FlashLightsAreaText + text_end +.dig + ld a, ESCAPE_ROPE + ld [wcf91], a + ld [wPseudoItemID], a + call UseItem + ld a, [wActionResultOrTookBattleTurn] + and a + jp z, .loop + call GBPalWhiteOutWithDelay3 + jp .goBackToMap +.teleport + call CheckIfInOutsideMap + jr z, .canTeleport + ld a, [wWhichPokemon] + ld hl, wPartyMonNicks + call GetPartyMonName + ld hl, .cannotUseTeleportNowText + call PrintText + jp .loop +.canTeleport + ld hl, .warpToLastPokemonCenterText + call PrintText + ld hl, wd732 + set 3, [hl] + set 6, [hl] + call Func_1510 + ld hl, wd72e + set 1, [hl] + res 4, [hl] + ld c, 60 + call DelayFrames + call GBPalWhiteOutWithDelay3 + jp .goBackToMap +.warpToLastPokemonCenterText + text_far _WarpToLastPokemonCenterText + text_end +.cannotUseTeleportNowText + text_far _CannotUseTeleportNowText + text_end +.cannotFlyHereText + text_far _CannotFlyHereText + text_end +.softboiled + ld hl, wPartyMon1MaxHP + ld a, [wWhichPokemon] + ld bc, wPartyMon2 - wPartyMon1 + call AddNTimes + ld a, [hli] + ldh [hDividend], a + ld a, [hl] + ldh [hDividend + 1], a + ld a, 5 + ldh [hDivisor], a + ld b, 2 ; number of bytes + call Divide + ld bc, wPartyMon1HP - wPartyMon1MaxHP + add hl, bc + ld a, [hld] + ld b, a + ldh a, [hQuotient + 3] + sub b + ld b, [hl] + ldh a, [hQuotient + 2] + sbc b + jp nc, .notHealthyEnough + ld a, [wPartyAndBillsPCSavedMenuItem] + push af + ld a, POTION + ld [wcf91], a + ld [wPseudoItemID], a + call UseItem + pop af + ld [wPartyAndBillsPCSavedMenuItem], a + jp .loop +.notHealthyEnough ; if current HP is less than 1/5 of max HP + ld hl, .notHealthyEnoughText + call PrintText + jp .loop +.notHealthyEnoughText + text_far _NotHealthyEnoughText + text_end +.goBackToMap + call RestoreScreenTilesAndReloadTilePatterns + jp CloseTextDisplay +.newBadgeRequired + ld hl, .newBadgeRequiredText + call PrintText + jp .loop +.newBadgeRequiredText + text_far _NewBadgeRequiredText + text_end + +; writes a blank tile to all possible menu cursor positions on the party menu +ErasePartyMenuCursors:: + hlcoord 0, 1 + ld bc, 2 * 20 ; menu cursor positions are 2 rows apart + ld a, 6 ; 6 menu cursor positions +.loop + ld [hl], " " + add hl, bc + dec a + jr nz, .loop + ret + +ItemMenuLoop: + call LoadScreenTilesFromBuffer2DisableBGTransfer ; restore saved screen + call RunDefaultPaletteCommand + +StartMenu_Item:: + ld a, [wLinkState] + dec a ; is the player in the Colosseum or Trade Centre? + jr nz, .notInCableClubRoom + ld hl, CannotUseItemsHereText + call PrintText + jr .exitMenu +.notInCableClubRoom + ld hl, wListPointer + ld [hl], wNumBagItems & $ff + inc hl + ld [hl], wNumBagItems / $100 ; store item bag pointer in wListPointer (for DisplayListMenuID) + xor a + ld [wPrintItemPrices], a + ld a, ITEMLISTMENU + ld [wListMenuID], a + ld a, [wBagSavedMenuItem] + ld [wCurrentMenuItem], a + call DisplayListMenuID + ld a, [wCurrentMenuItem] + ld [wBagSavedMenuItem], a + jr nc, .choseItem +.exitMenu + call LoadScreenTilesFromBuffer2 ; restore saved screen + call LoadTextBoxTilePatterns + call UpdateSprites + jp RedisplayStartMenu +.choseItem +; erase menu cursor (blank each tile in front of an item name) + ld a, " " + ldcoord_a 5, 4 + ldcoord_a 5, 6 + ldcoord_a 5, 8 + ldcoord_a 5, 10 + call PlaceUnfilledArrowMenuCursor + xor a + ld [wMenuItemToSwap], a + ld a, [wcf91] + cp BICYCLE + jp z, .useOrTossItem +.notBicycle1 + ld a, USE_TOSS_MENU_TEMPLATE + ld [wTextBoxID], a + call DisplayTextBoxID + ld hl, wTopMenuItemY + ld a, 11 + ld [hli], a ; top menu item Y + ld a, 14 + ld [hli], a ; top menu item X + xor a + ld [hli], a ; current menu item ID + inc hl + inc a ; a = 1 + ld [hli], a ; max menu item ID + ld a, A_BUTTON | B_BUTTON + ld [hli], a ; menu watched keys + xor a + ld [hl], a ; old menu item id + call HandleMenuInput + call PlaceUnfilledArrowMenuCursor + bit 1, a ; was the B button pressed? + jr z, .useOrTossItem + jp ItemMenuLoop +.useOrTossItem ; if the player made the choice to use or toss the item + ld a, [wcf91] + ld [wd11e], a + call GetItemName + call CopyStringToCF4B ; copy name to wcf4b + ld a, [wcf91] + cp BICYCLE + jr nz, .notBicycle2 + ld a, [wd732] + bit 5, a + jr z, .useItem_closeMenu + ld hl, CannotGetOffHereText + call PrintText + jp ItemMenuLoop +.notBicycle2 + ld a, [wCurrentMenuItem] + and a + jr nz, .tossItem +; use item + ld [wPseudoItemID], a ; a must be 0 due to above conditional jump + ld a, [wcf91] + cp HM01 + jr nc, .useItem_partyMenu + ld hl, UsableItems_CloseMenu + ld de, 1 + call IsInArray + jr c, .useItem_closeMenu + ld a, [wcf91] + ld hl, UsableItems_PartyMenu + ld de, 1 + call IsInArray + jr c, .useItem_partyMenu + call UseItem + jp ItemMenuLoop +.useItem_closeMenu + xor a + ld [wPseudoItemID], a + call UseItem + ld a, [wActionResultOrTookBattleTurn] + and a + jp z, ItemMenuLoop + jp CloseStartMenu +.useItem_partyMenu + ld a, [wUpdateSpritesEnabled] + push af + call UseItem + ld a, [wActionResultOrTookBattleTurn] + cp $02 + jp z, .partyMenuNotDisplayed + call GBPalWhiteOutWithDelay3 + call RestoreScreenTilesAndReloadTilePatterns + pop af + ld [wUpdateSpritesEnabled], a + jp StartMenu_Item +.partyMenuNotDisplayed + pop af + ld [wUpdateSpritesEnabled], a + jp ItemMenuLoop +.tossItem + call IsKeyItem + ld a, [wIsKeyItem] + and a + jr nz, .skipAskingQuantity + ld a, [wcf91] + call IsItemHM + jr c, .skipAskingQuantity + call DisplayChooseQuantityMenu + inc a + jr z, .tossZeroItems +.skipAskingQuantity + ld hl, wNumBagItems + call TossItem +.tossZeroItems + jp ItemMenuLoop + +CannotUseItemsHereText: + text_far _CannotUseItemsHereText + text_end + +CannotGetOffHereText: + text_far _CannotGetOffHereText + text_end + +INCLUDE "data/items/use_party.asm" + +INCLUDE "data/items/use_overworld.asm" + +StartMenu_TrainerInfo:: + call GBPalWhiteOut + call ClearScreen + call UpdateSprites + ldh a, [hTilesetType] + push af + xor a + ldh [hTilesetType], a + call DrawTrainerInfo + predef DrawBadges ; draw badges + ld b, SET_PAL_TRAINER_CARD + call RunPaletteCommand + call GBPalNormal + call WaitForTextScrollButtonPress ; wait for button press + call GBPalWhiteOut + call LoadFontTilePatterns + call LoadScreenTilesFromBuffer2 ; restore saved screen + call RunDefaultPaletteCommand + call ReloadMapData + farcall DrawStartMenu ; XXX what difference does this make? + call LoadGBPal + pop af + ldh [hTilesetType], a + jp RedisplayStartMenu_DoNotDrawStartMenu + +; loads tile patterns and draws everything except for gym leader faces / badges +DrawTrainerInfo: + ld de, RedPicFront + lb bc, BANK(RedPicFront), $01 + predef DisplayPicCenteredOrUpperRight + call DisableLCD + hlcoord 0, 2 + ld a, " " + call TrainerInfo_DrawVerticalLine + hlcoord 1, 2 + call TrainerInfo_DrawVerticalLine + ld hl, vChars2 tile $07 + ld de, vChars2 tile $00 + ld bc, $1c tiles + call CopyData + ld hl, TrainerInfoTextBoxTileGraphics ; trainer info text box tile patterns + ld de, vChars2 tile $77 + ld bc, 8 tiles + push bc + call TrainerInfo_FarCopyData + ld hl, BlankLeaderNames + ld de, vChars2 tile $60 + ld bc, $17 tiles + call TrainerInfo_FarCopyData + pop bc + ld hl, BadgeNumbersTileGraphics ; badge number tile patterns + ld de, vChars1 tile $58 + call TrainerInfo_FarCopyData + ld hl, GymLeaderFaceAndBadgeTileGraphics ; gym leader face and badge tile patterns + ld de, vChars2 tile $20 + ld bc, 8 * 8 tiles + ld a, BANK(GymLeaderFaceAndBadgeTileGraphics) + call FarCopyData + ld hl, TextBoxGraphics + ld de, 13 tiles + add hl, de ; hl = colon tile pattern + ld de, vChars1 tile $56 + ld bc, 1 tiles + ld a, BANK(TextBoxGraphics) + push bc + call FarCopyData + pop bc + ld hl, TrainerInfoTextBoxTileGraphics tile 8 ; background tile pattern + ld de, vChars1 tile $57 + call TrainerInfo_FarCopyData + call EnableLCD + ld hl, wTrainerInfoTextBoxWidthPlus1 + ld a, 18 + 1 + ld [hli], a + dec a + ld [hli], a + ld [hl], 1 + hlcoord 0, 0 + call TrainerInfo_DrawTextBox + ld hl, wTrainerInfoTextBoxWidthPlus1 + ld a, 16 + 1 + ld [hli], a + dec a + ld [hli], a + ld [hl], 3 + hlcoord 1, 10 + call TrainerInfo_DrawTextBox + hlcoord 0, 10 + ld a, $d7 + call TrainerInfo_DrawVerticalLine + hlcoord 19, 10 + call TrainerInfo_DrawVerticalLine + hlcoord 6, 9 + ld de, TrainerInfo_BadgesText + call PlaceString + hlcoord 2, 2 + ld de, TrainerInfo_NameMoneyTimeText + call PlaceString + hlcoord 7, 2 + ld de, wPlayerName + call PlaceString + hlcoord 8, 4 + ld de, wPlayerMoney + ld c, $e3 + call PrintBCDNumber + hlcoord 9, 6 + ld de, wPlayTimeHours ; hours + lb bc, LEFT_ALIGN | 1, 3 + call PrintNumber + ld [hl], $d6 ; colon tile ID + inc hl + ld de, wPlayTimeMinutes ; minutes + lb bc, LEADING_ZEROES | 1, 2 + jp PrintNumber + +TrainerInfo_FarCopyData: + ld a, BANK(TrainerInfoTextBoxTileGraphics) + jp FarCopyData + +TrainerInfo_NameMoneyTimeText: + db "NAME/" + next "MONEY/" + next "TIME/@" + +; $76 is a circle tile +TrainerInfo_BadgesText: + db $76,"BADGES",$76,"@" + +; draws a text box on the trainer info screen +; height is always 6 +; INPUT: +; hl = destination address +; [wTrainerInfoTextBoxWidthPlus1] = width +; [wTrainerInfoTextBoxWidth] = width - 1 +; [wTrainerInfoTextBoxNextRowOffset] = distance from the end of a text box row to the start of the next +TrainerInfo_DrawTextBox: + ld a, $79 ; upper left corner tile ID + lb de, $7a, $7b ; top edge and upper right corner tile ID's + call TrainerInfo_DrawHorizontalEdge ; draw top edge + call TrainerInfo_NextTextBoxRow + ld a, [wTrainerInfoTextBoxWidthPlus1] + ld e, a + ld d, 0 + ld c, 6 ; height of the text box +.loop + ld [hl], $7c ; left edge tile ID + add hl, de + ld [hl], $78 ; right edge tile ID + call TrainerInfo_NextTextBoxRow + dec c + jr nz, .loop + ld a, $7d ; lower left corner tile ID + lb de, $77, $7e ; bottom edge and lower right corner tile ID's + +TrainerInfo_DrawHorizontalEdge: + ld [hli], a ; place left corner tile + ld a, [wTrainerInfoTextBoxWidth] + ld c, a + ld a, d +.loop + ld [hli], a ; place edge tile + dec c + jr nz, .loop + ld a, e + ld [hl], a ; place right corner tile + ret + +TrainerInfo_NextTextBoxRow: + ld a, [wTrainerInfoTextBoxNextRowOffset] ; distance to the start of the next row +.loop + inc hl + dec a + jr nz, .loop + ret + +; draws a vertical line +; INPUT: +; hl = address of top tile in the line +; a = tile ID +TrainerInfo_DrawVerticalLine: + ld de, SCREEN_WIDTH + ld c, 8 +.loop + ld [hl], a + add hl, de + dec c + jr nz, .loop + ret + +StartMenu_SaveReset:: + ld a, [wd72e] + bit 6, a ; is the player using the link feature? + jp nz, Init + predef SaveSAV ; save the game + call LoadScreenTilesFromBuffer2 ; restore saved screen + jp HoldTextDisplayOpen + +StartMenu_Option:: + xor a + ldh [hAutoBGTransferEnabled], a + call ClearScreen + call UpdateSprites + callfar DisplayOptionMenu + call LoadScreenTilesFromBuffer2 ; restore saved screen + call LoadTextBoxTilePatterns + call UpdateSprites + jp RedisplayStartMenu + +SwitchPartyMon:: + call SwitchPartyMon_InitVarOrSwapData ; swap data + ld a, [wSwappedMenuItem] + call SwitchPartyMon_ClearGfx + ld a, [wCurrentMenuItem] + call SwitchPartyMon_ClearGfx + jp RedrawPartyMenu_ + +SwitchPartyMon_ClearGfx: + push af + hlcoord 0, 0 + ld bc, SCREEN_WIDTH * 2 + call AddNTimes + ld c, SCREEN_WIDTH * 2 + ld a, " " +.clearMonBGLoop ; clear the mon's row in the party menu + ld [hli], a + dec c + jr nz, .clearMonBGLoop + pop af + ld hl, wOAMBuffer + ld bc, $10 + call AddNTimes + ld de, $4 + ld c, e +.clearMonOAMLoop + ld [hl], $a0 + add hl, de + dec c + jr nz, .clearMonOAMLoop + call WaitForSoundToFinish + ld a, SFX_SWAP + jp PlaySound + +SwitchPartyMon_InitVarOrSwapData: +; This is used to initialise [wMenuItemToSwap] and to actually swap the data. + ld a, [wMenuItemToSwap] + and a ; has [wMenuItemToSwap] been initialised yet? + jr nz, .pickedMonsToSwap +; If not, initialise [wMenuItemToSwap] so that it matches the current mon. + ld a, [wWhichPokemon] + inc a ; [wMenuItemToSwap] counts from 1 + ld [wMenuItemToSwap], a + ret +.pickedMonsToSwap + xor a + ld [wPartyMenuTypeOrMessageID], a + ld a, [wMenuItemToSwap] + dec a + ld b, a + ld a, [wCurrentMenuItem] + ld [wSwappedMenuItem], a + cp b ; swapping a mon with itself? + jr nz, .swappingDifferentMons +; can't swap a mon with itself + xor a + ld [wMenuItemToSwap], a + ld [wPartyMenuTypeOrMessageID], a + ret +.swappingDifferentMons + ld a, b + ld [wMenuItemToSwap], a + push hl + push de + ld hl, wPartySpecies + ld d, h + ld e, l + ld a, [wCurrentMenuItem] + add l + ld l, a + jr nc, .noCarry + inc h +.noCarry + ld a, [wMenuItemToSwap] + add e + ld e, a + jr nc, .noCarry2 + inc d +.noCarry2 + ld a, [hl] + ldh [hSwapTemp], a + ld a, [de] + ld [hl], a + ldh a, [hSwapTemp] + ld [de], a + ld hl, wPartyMons + ld bc, wPartyMon2 - wPartyMon1 + ld a, [wCurrentMenuItem] + call AddNTimes + push hl + ld de, wSwitchPartyMonTempBuffer + ld bc, wPartyMon2 - wPartyMon1 + call CopyData + ld hl, wPartyMons + ld bc, wPartyMon2 - wPartyMon1 + ld a, [wMenuItemToSwap] + call AddNTimes + pop de + push hl + ld bc, wPartyMon2 - wPartyMon1 + call CopyData + pop de + ld hl, wSwitchPartyMonTempBuffer + ld bc, wPartyMon2 - wPartyMon1 + call CopyData + ld hl, wPartyMonOT + ld a, [wCurrentMenuItem] + call SkipFixedLengthTextEntries + push hl + ld de, wSwitchPartyMonTempBuffer + ld bc, NAME_LENGTH + call CopyData + ld hl, wPartyMonOT + ld a, [wMenuItemToSwap] + call SkipFixedLengthTextEntries + pop de + push hl + ld bc, NAME_LENGTH + call CopyData + pop de + ld hl, wSwitchPartyMonTempBuffer + ld bc, NAME_LENGTH + call CopyData + ld hl, wPartyMonNicks + ld a, [wCurrentMenuItem] + call SkipFixedLengthTextEntries + push hl + ld de, wSwitchPartyMonTempBuffer + ld bc, NAME_LENGTH + call CopyData + ld hl, wPartyMonNicks + ld a, [wMenuItemToSwap] + call SkipFixedLengthTextEntries + pop de + push hl + ld bc, NAME_LENGTH + call CopyData + pop de + ld hl, wSwitchPartyMonTempBuffer + ld bc, NAME_LENGTH + call CopyData + ld a, [wMenuItemToSwap] + ld [wSwappedMenuItem], a + xor a + ld [wMenuItemToSwap], a + ld [wPartyMenuTypeOrMessageID], a + pop de + pop hl + ret diff --git a/engine/menus/swap_items.asm b/engine/menus/swap_items.asm new file mode 100644 index 00000000..2d506ce2 --- /dev/null +++ b/engine/menus/swap_items.asm @@ -0,0 +1,149 @@ +HandleItemListSwapping:: + ld a, [wListMenuID] + cp ITEMLISTMENU + jp nz, DisplayListMenuIDLoop ; only rearrange item list menus + push hl + ld hl, wListPointer + ld a, [hli] + ld h, [hl] + ld l, a + inc hl ; hl = beginning of list entries + ld a, [wCurrentMenuItem] + ld b, a + ld a, [wListScrollOffset] + add b + add a + ld c, a + ld b, 0 + add hl, bc ; hl = address of currently selected item entry + ld a, [hl] + pop hl + inc a + jp z, DisplayListMenuIDLoop ; ignore attempts to swap the Cancel menu item + ld a, [wMenuItemToSwap] ; ID of item chosen for swapping (counts from 1) + and a ; has the first item to swap already been chosen? + jr nz, .swapItems +; if not, set the currently selected item as the first item + ld a, [wCurrentMenuItem] + inc a + ld b, a + ld a, [wListScrollOffset] ; index of top (visible) menu item within the list + add b + ld [wMenuItemToSwap], a ; ID of item chosen for swapping (counts from 1) + ld c, 20 + call DelayFrames + jp DisplayListMenuIDLoop +.swapItems + ld a, [wCurrentMenuItem] + inc a + ld b, a + ld a, [wListScrollOffset] + add b + ld b, a + ld a, [wMenuItemToSwap] ; ID of item chosen for swapping (counts from 1) + cp b ; is the currently selected item the same as the first item to swap? + jp z, DisplayListMenuIDLoop ; ignore attempts to swap an item with itself + dec a + ld [wMenuItemToSwap], a ; ID of item chosen for swapping (counts from 1) + ld c, 20 + call DelayFrames + push hl + push de + ld hl, wListPointer + ld a, [hli] + ld h, [hl] + ld l, a + inc hl ; hl = beginning of list entries + ld d, h + ld e, l ; de = beginning of list entries + ld a, [wCurrentMenuItem] + ld b, a + ld a, [wListScrollOffset] + add b + add a + ld c, a + ld b, 0 + add hl, bc ; hl = address of currently selected item entry + ld a, [wMenuItemToSwap] ; ID of item chosen for swapping (counts from 1) + add a + add e + ld e, a + jr nc, .noCarry + inc d +.noCarry ; de = address of first item to swap + ld a, [de] + ld b, a + ld a, [hli] + cp b + jr z, .swapSameItemType +.swapDifferentItems + ldh [hSwapItemID], a ; save second item ID + ld a, [hld] + ldh [hSwapItemQuantity], a ; save second item quantity + ld a, [de] + ld [hli], a ; put first item ID in second item slot + inc de + ld a, [de] + ld [hl], a ; put first item quantity in second item slot + ldh a, [hSwapItemQuantity] + ld [de], a ; put second item quantity in first item slot + dec de + ldh a, [hSwapItemID] + ld [de], a ; put second item ID in first item slot + xor a + ld [wMenuItemToSwap], a ; 0 means no item is currently being swapped + pop de + pop hl + jp DisplayListMenuIDLoop +.swapSameItemType + inc de + ld a, [hl] + ld b, a + ld a, [de] + add b ; a = sum of both item quantities + cp 100 ; is the sum too big for one item slot? + jr c, .combineItemSlots +; swap enough items from the first slot to max out the second slot if they can't be combined + sub 99 + ld [de], a + ld a, 99 + ld [hl], a + jr .done +.combineItemSlots + ld [hl], a ; put the sum in the second item slot + ld hl, wListPointer + ld a, [hli] + ld h, [hl] + ld l, a + dec [hl] ; decrease the number of items + ld a, [hl] + ld [wListCount], a ; update number of items variable + cp 1 + jr nz, .skipSettingMaxMenuItemID + ld [wMaxMenuItem], a ; if the number of items is only one now, update the max menu item ID +.skipSettingMaxMenuItemID + dec de + ld h, d + ld l, e + inc hl + inc hl ; hl = address of item after first item to swap +.moveItemsUpLoop ; erase the first item slot and move up all the following item slots to fill the gap + ld a, [hli] + ld [de], a + inc de + inc a ; reached the $ff terminator? + jr z, .afterMovingItemsUp + ld a, [hli] + ld [de], a + inc de + jr .moveItemsUpLoop +.afterMovingItemsUp + xor a + ld [wListScrollOffset], a + ld [wCurrentMenuItem], a +.done + xor a + ld [wMenuItemToSwap], a ; 0 means no item is currently being swapped + pop de + pop hl + jp DisplayListMenuIDLoop diff --git a/engine/menus/text_box.asm b/engine/menus/text_box.asm new file mode 100644 index 00000000..7a315af2 --- /dev/null +++ b/engine/menus/text_box.asm @@ -0,0 +1,533 @@ +; function to draw various text boxes +DisplayTextBoxID_:: + ld a, [wTextBoxID] + cp TWO_OPTION_MENU + jp z, DisplayTwoOptionMenu + ld c, a + ld hl, TextBoxFunctionTable + ld de, 3 + call SearchTextBoxTable + jr c, .functionTableMatch + ld hl, TextBoxCoordTable + ld de, 5 + call SearchTextBoxTable + jr c, .coordTableMatch + ld hl, TextBoxTextAndCoordTable + ld de, 9 + call SearchTextBoxTable + jr c, .textAndCoordTableMatch +.done + ret +.functionTableMatch + ld a, [hli] + ld h, [hl] + ld l, a ; hl = address of function + ld de, .done + push de + jp hl ; jump to the function +.coordTableMatch + call GetTextBoxIDCoords + call GetAddressOfScreenCoords + call TextBoxBorder + ret +.textAndCoordTableMatch + call GetTextBoxIDCoords + push hl + call GetAddressOfScreenCoords + call TextBoxBorder + pop hl + call GetTextBoxIDText + ld a, [wd730] + push af + ld a, [wd730] + set 6, a ; no pauses between printing each letter + ld [wd730], a + call PlaceString + pop af + ld [wd730], a + call UpdateSprites + ret + +; function to search a table terminated with $ff for a byte matching c in increments of de +; sets carry flag if a match is found and clears carry flag if not +SearchTextBoxTable: + dec de +.loop + ld a, [hli] + cp $ff + jr z, .notFound + cp c + jr z, .found + add hl, de + jr .loop +.found + scf +.notFound + ret + +; function to load coordinates from the TextBoxCoordTable or the TextBoxTextAndCoordTable +; INPUT: +; hl = address of coordinates +; OUTPUT: +; b = height +; c = width +; d = row of upper left corner +; e = column of upper left corner +GetTextBoxIDCoords: + ld a, [hli] ; column of upper left corner + ld e, a + ld a, [hli] ; row of upper left corner + ld d, a + ld a, [hli] ; column of lower right corner + sub e + dec a + ld c, a ; c = width + ld a, [hli] ; row of lower right corner + sub d + dec a + ld b, a ; b = height + ret + +; function to load a text address and text coordinates from the TextBoxTextAndCoordTable +GetTextBoxIDText: + ld a, [hli] + ld e, a + ld a, [hli] + ld d, a ; de = address of text + push de ; save text address + ld a, [hli] + ld e, a ; column of upper left corner of text + ld a, [hl] + ld d, a ; row of upper left corner of text + call GetAddressOfScreenCoords + pop de ; restore text address + ret + +; function to point hl to the screen coordinates +; INPUT: +; d = row +; e = column +; OUTPUT: +; hl = address of upper left corner of text box +GetAddressOfScreenCoords: + push bc + hlcoord 0, 0 + ld bc, 20 +.loop ; loop to add d rows to the base address + ld a, d + and a + jr z, .addedRows + add hl, bc + dec d + jr .loop +.addedRows + pop bc + add hl, de + ret + +INCLUDE "data/text_boxes.asm" + +DisplayMoneyBox: + ld hl, wd730 + set 6, [hl] + ld a, MONEY_BOX_TEMPLATE + ld [wTextBoxID], a + call DisplayTextBoxID + hlcoord 13, 1 + lb bc, 1, 6 + call ClearScreenArea + hlcoord 12, 1 + ld de, wPlayerMoney + ld c, $a3 + call PrintBCDNumber + ld hl, wd730 + res 6, [hl] + ret + +CurrencyString: + db " ¥@" + +DoBuySellQuitMenu: + ld a, [wd730] + set 6, a ; no printing delay + ld [wd730], a + xor a + ld [wChosenMenuItem], a + ld a, BUY_SELL_QUIT_MENU_TEMPLATE + ld [wTextBoxID], a + call DisplayTextBoxID + ld a, A_BUTTON | B_BUTTON + ld [wMenuWatchedKeys], a + ld a, $2 + ld [wMaxMenuItem], a + ld a, $1 + ld [wTopMenuItemY], a + ld a, $1 + ld [wTopMenuItemX], a + xor a + ld [wCurrentMenuItem], a + ld [wLastMenuItem], a + ld [wMenuWatchMovingOutOfBounds], a + ld a, [wd730] + res 6, a ; turn on the printing delay + ld [wd730], a + call HandleMenuInput + call PlaceUnfilledArrowMenuCursor + bit 0, a ; was A pressed? + jr nz, .pressedA + bit 1, a ; was B pressed? (always true since only A/B are watched) + jr z, .pressedA + ld a, CANCELLED_MENU + ld [wMenuExitMethod], a + jr .quit +.pressedA + ld a, CHOSE_MENU_ITEM + ld [wMenuExitMethod], a + ld a, [wCurrentMenuItem] + ld [wChosenMenuItem], a + ld b, a + ld a, [wMaxMenuItem] + cp b + jr z, .quit + ret +.quit + ld a, CANCELLED_MENU + ld [wMenuExitMethod], a + ld a, [wCurrentMenuItem] + ld [wChosenMenuItem], a + scf + ret + +; displays a menu with two options to choose from +; b = Y of upper left corner of text region +; c = X of upper left corner of text region +; hl = address where the text box border should be drawn +DisplayTwoOptionMenu: + push hl + ld a, [wd730] + set 6, a ; no printing delay + ld [wd730], a + +; pointless because both values are overwritten before they are read + xor a + ld [wChosenMenuItem], a + ld [wMenuExitMethod], a + + ld a, A_BUTTON | B_BUTTON + ld [wMenuWatchedKeys], a + ld a, $1 + ld [wMaxMenuItem], a + ld a, b + ld [wTopMenuItemY], a + ld a, c + ld [wTopMenuItemX], a + xor a + ld [wLastMenuItem], a + ld [wMenuWatchMovingOutOfBounds], a + push hl + ld hl, wTwoOptionMenuID + bit 7, [hl] ; select second menu item by default? + res 7, [hl] + jr z, .storeCurrentMenuItem + inc a +.storeCurrentMenuItem + ld [wCurrentMenuItem], a + pop hl + push hl + push hl + call TwoOptionMenu_SaveScreenTiles + ld a, [wTwoOptionMenuID] + ld hl, TwoOptionMenuStrings + ld e, a + ld d, $0 + ld a, $5 +.menuStringLoop + add hl, de + dec a + jr nz, .menuStringLoop + ld a, [hli] + ld c, a + ld a, [hli] + ld b, a + ld e, l + ld d, h + pop hl + push de + ld a, [wTwoOptionMenuID] + cp TRADE_CANCEL_MENU + jr nz, .notTradeCancelMenu + call CableClub_TextBoxBorder + jr .afterTextBoxBorder +.notTradeCancelMenu + call TextBoxBorder +.afterTextBoxBorder + call UpdateSprites + pop hl + ld a, [hli] + and a ; put blank line before first menu item? + ld bc, 20 + 2 + jr z, .noBlankLine + ld bc, 2 * 20 + 2 +.noBlankLine + ld a, [hli] + ld e, a + ld a, [hli] + ld d, a + pop hl + add hl, bc + call PlaceString + xor a + ld [wTwoOptionMenuID], a + ld hl, wd730 + res 6, [hl] ; turn on the printing delay + call HandleMenuInput + pop hl + bit 1, a ; A button pressed? + jr nz, .choseSecondMenuItem ; automatically choose the second option if B is pressed +.pressedAButton + ld a, [wCurrentMenuItem] + ld [wChosenMenuItem], a + and a + jr nz, .choseSecondMenuItem +; chose first menu item + ld a, CHOSE_FIRST_ITEM + ld [wMenuExitMethod], a + ld c, 15 + call DelayFrames + call TwoOptionMenu_RestoreScreenTiles + and a + ret +.choseSecondMenuItem + ld a, 1 + ld [wCurrentMenuItem], a + ld [wChosenMenuItem], a + ld a, CHOSE_SECOND_ITEM + ld [wMenuExitMethod], a + ld c, 15 + call DelayFrames + call TwoOptionMenu_RestoreScreenTiles + scf + ret + +; Some of the wider/taller two option menus will not have the screen areas +; they cover be fully saved/restored by the two functions below. +; The bottom and right edges of the menu may remain after the function returns. + +TwoOptionMenu_SaveScreenTiles: + ld de, wBuffer + lb bc, 5, 6 +.loop + ld a, [hli] + ld [de], a + inc de + dec c + jr nz, .loop + push bc + ld bc, SCREEN_WIDTH - 6 + add hl, bc + pop bc + ld c, $6 + dec b + jr nz, .loop + ret + +TwoOptionMenu_RestoreScreenTiles: + ld de, wBuffer + lb bc, 5, 6 +.loop + ld a, [de] + inc de + ld [hli], a + dec c + jr nz, .loop + push bc + ld bc, SCREEN_WIDTH - 6 + add hl, bc + pop bc + ld c, 6 + dec b + jr nz, .loop + call UpdateSprites + ret + +INCLUDE "data/yes_no_menu_strings.asm" + +DisplayFieldMoveMonMenu: + xor a + ld hl, wFieldMoves + ld [hli], a ; wFieldMoves + ld [hli], a ; wFieldMoves + 1 + ld [hli], a ; wFieldMoves + 2 + ld [hli], a ; wFieldMoves + 3 + ld [hli], a ; wNumFieldMoves + ld [hl], 12 ; wFieldMovesLeftmostXCoord + call GetMonFieldMoves + ld a, [wNumFieldMoves] + and a + jr nz, .fieldMovesExist + +; no field moves + hlcoord 11, 11 + lb bc, 5, 7 + call TextBoxBorder + call UpdateSprites + ld a, 12 + ldh [hFieldMoveMonMenuTopMenuItemX], a + hlcoord 13, 12 + ld de, PokemonMenuEntries + jp PlaceString + +.fieldMovesExist + push af + +; Calculate the text box position and dimensions based on the leftmost X coord +; of the field move names before adjusting for the number of field moves. + hlcoord 0, 11 + ld a, [wFieldMovesLeftmostXCoord] + dec a + ld e, a + ld d, 0 + add hl, de + ld b, 5 + ld a, 18 + sub e + ld c, a + pop af + +; For each field move, move the top of the text box up 2 rows while the leaving +; the bottom of the text box at the bottom of the screen. + ld de, -SCREEN_WIDTH * 2 +.textBoxHeightLoop + add hl, de + inc b + inc b + dec a + jr nz, .textBoxHeightLoop + +; Make space for an extra blank row above the top field move. + ld de, -SCREEN_WIDTH + add hl, de + inc b + + call TextBoxBorder + call UpdateSprites + +; Calculate the position of the first field move name to print. + hlcoord 0, 12 + ld a, [wFieldMovesLeftmostXCoord] + inc a + ld e, a + ld d, 0 + add hl, de + ld de, -SCREEN_WIDTH * 2 + ld a, [wNumFieldMoves] +.calcFirstFieldMoveYLoop + add hl, de + dec a + jr nz, .calcFirstFieldMoveYLoop + + xor a + ld [wNumFieldMoves], a + ld de, wFieldMoves +.printNamesLoop + push hl + ld hl, FieldMoveNames + ld a, [de] + and a + jr z, .donePrintingNames + inc de + ld b, a ; index of name +.skipNamesLoop ; skip past names before the name we want + dec b + jr z, .reachedName +.skipNameLoop ; skip past current name + ld a, [hli] + cp "@" + jr nz, .skipNameLoop + jr .skipNamesLoop +.reachedName + ld b, h + ld c, l + pop hl + push de + ld d, b + ld e, c + call PlaceString + ld bc, SCREEN_WIDTH * 2 + add hl, bc + pop de + jr .printNamesLoop + +.donePrintingNames + pop hl + ld a, [wFieldMovesLeftmostXCoord] + ldh [hFieldMoveMonMenuTopMenuItemX], a + hlcoord 0, 12 + ld a, [wFieldMovesLeftmostXCoord] + inc a + ld e, a + ld d, 0 + add hl, de + ld de, PokemonMenuEntries + jp PlaceString + +INCLUDE "data/moves/field_move_names.asm" + +PokemonMenuEntries: + db "STATS" + next "SWITCH" + next "CANCEL@" + +GetMonFieldMoves: + ld a, [wWhichPokemon] + ld hl, wPartyMon1Moves + ld bc, wPartyMon2 - wPartyMon1 + call AddNTimes + ld d, h + ld e, l + ld c, NUM_MOVES + 1 + ld hl, wFieldMoves +.loop + push hl +.nextMove + dec c + jr z, .done + ld a, [de] ; move ID + and a + jr z, .done + ld b, a + inc de + ld hl, FieldMoveDisplayData +.fieldMoveLoop + ld a, [hli] + cp $ff + jr z, .nextMove ; if the move is not a field move + cp b + jr z, .foundFieldMove + inc hl + inc hl + jr .fieldMoveLoop +.foundFieldMove + ld a, b + ld [wLastFieldMoveID], a + ld a, [hli] ; field move name index + ld b, [hl] ; field move leftmost X coordinate + pop hl + ld [hli], a ; store name index in wFieldMoves + ld a, [wNumFieldMoves] + inc a + ld [wNumFieldMoves], a + ld a, [wFieldMovesLeftmostXCoord] + cp b + jr c, .skipUpdatingLeftmostXCoord + ld a, b + ld [wFieldMovesLeftmostXCoord], a +.skipUpdatingLeftmostXCoord + ld a, [wLastFieldMoveID] + ld b, a + jr .loop +.done + pop hl + ret + +INCLUDE "data/moves/field_moves.asm" diff --git a/engine/mon_party_sprites.asm b/engine/mon_party_sprites.asm deleted file mode 100755 index 6f17f876..00000000 --- a/engine/mon_party_sprites.asm +++ /dev/null @@ -1,445 +0,0 @@ -AnimatePartyMon_ForceSpeed1: - xor a - ld [wCurrentMenuItem], a - ld b, a - inc a - jr GetAnimationSpeed - -; wPartyMenuHPBarColors contains the party mon's health bar colors -; 0: green -; 1: yellow -; 2: red -AnimatePartyMon: - ld hl, wPartyMenuHPBarColors - ld a, [wCurrentMenuItem] - ld c, a - ld b, 0 - add hl, bc - ld a, [hl] - -GetAnimationSpeed: - ld c, a - ld hl, PartyMonSpeeds - add hl, bc - ld a, [wOnSGB] - xor $1 - add [hl] - ld c, a - add a - ld b, a - ld a, [wAnimCounter] - and a - jr z, .resetSprites - cp c - jr z, .animateSprite -.incTimer - inc a - cp b - jr nz, .skipResetTimer - xor a ; reset timer -.skipResetTimer - ld [wAnimCounter], a - jp DelayFrame -.resetSprites - push bc - ld hl, wMonPartySpritesSavedOAM - ld de, wOAMBuffer - ld bc, $60 - call CopyData - pop bc - xor a - jr .incTimer -.animateSprite - push bc - ld hl, wOAMBuffer + $02 ; OAM tile id - ld bc, $10 - ld a, [wCurrentMenuItem] - call AddNTimes - ld c, $40 ; amount to increase the tile id by - ld a, [hl] - cp $4 ; tile ID for SPRITE_BALL_M - jr z, .editCoords - cp $8 ; tile ID for SPRITE_HELIX - jr nz, .editTileIDS -; SPRITE_BALL_M and SPRITE_HELIX only shake up and down -.editCoords - dec hl - dec hl ; dec hl to the OAM y coord - ld c, $1 ; amount to increase the y coord by -; otherwise, load a second sprite frame -.editTileIDS - ld b, $4 - ld de, $4 -.loop - ld a, [hl] - add c - ld [hl], a - add hl, de - dec b - jr nz, .loop - pop bc - ld a, c - jr .incTimer - -; Party mon animations cycle between 2 frames. -; The members of the PartyMonSpeeds array specify the number of V-blanks -; that each frame lasts for green HP, yellow HP, and red HP in order. -; On the naming screen, the yellow HP speed is always used. -PartyMonSpeeds: - db 5, 16, 32 - -LoadMonPartySpriteGfx: -; Load mon party sprite tile patterns into VRAM during V-blank. - ld hl, MonPartySpritePointers - ld a, $1e - -LoadAnimSpriteGfx: -; Load animated sprite tile patterns into VRAM during V-blank. hl is the address -; of an array of structures that contain arguments for CopyVideoData and a is -; the number of structures in the array. - ld bc, $0 -.loop - push af - push bc - push hl - add hl, bc - ld a, [hli] - ld e, a - ld a, [hli] - ld d, a - ld a, [hli] - ld c, a - ld a, [hli] - ld b, a - ld a, [hli] - ld h, [hl] - ld l, a - call CopyVideoData - pop hl - pop bc - ld a, $6 - add c - ld c, a - pop af - dec a - jr nz, .loop - ret - -LoadMonPartySpriteGfxWithLCDDisabled: -; Load mon party sprite tile patterns into VRAM immediately by disabling the -; LCD. - call DisableLCD - ld hl, MonPartySpritePointers - ld a, $1e - ld bc, $0 -.loop - push af - push bc - push hl - add hl, bc - ld a, [hli] - ld e, a - ld a, [hli] - ld d, a - push de - ld a, [hli] - ld c, a - swap c - ld b, $0 - ld a, [hli] - ld e, [hl] - inc hl - ld d, [hl] - pop hl - call FarCopyData - pop hl - pop bc - ld a, $6 - add c - ld c, a - pop af - dec a - jr nz, .loop - jp EnableLCD - -MonPartySpritePointers: - dw SlowbroSprite + $c0 - db $40 / $10 ; 40 bytes - db BANK(SlowbroSprite) - dw vSprites - - dw BallSprite - db $80 / $10 ; $80 bytes - db BANK(BallSprite) - dw vSprites + $40 - - dw ClefairySprite + $c0 - db $40 / $10 ; $40 bytes - db BANK(ClefairySprite) - dw vSprites + $c0 - - dw BirdSprite + $c0 - db $40 / $10 ; $40 bytes - db BANK(BirdSprite) - dw vSprites + $100 - - dw SeelSprite - db $40 / $10 ; $40 bytes - db BANK(SeelSprite) - dw vSprites + $140 - - dw MonPartySprites + $40 - db $10 / $10 ; $10 bytes - db BANK(MonPartySprites) - dw vSprites + $180 - - dw MonPartySprites + $50 - db $10 / $10 ; $10 bytes - db BANK(MonPartySprites) - dw vSprites + $1a0 - - dw MonPartySprites + $60 - db $10 / $10 ; $10 bytes - db BANK(MonPartySprites) - dw vSprites + $1c0 - - dw MonPartySprites + $70 - db $10 / $10 ; $10 bytes - db BANK(MonPartySprites) - dw vSprites + $1e0 - - dw MonPartySprites + $80 - db $10 / $10 ; $10 bytes - db BANK(MonPartySprites) - dw vSprites + $200 - - dw MonPartySprites + $90 - db $10 / $10 ; $10 bytes - db BANK(MonPartySprites) - dw vSprites + $220 - - dw MonPartySprites + $A0 - db $10 / $10 ; $10 bytes - db BANK(MonPartySprites) - dw vSprites + $240 - - dw MonPartySprites + $B0 - db $10 / $10 ; $10 bytes - db BANK(MonPartySprites) - dw vSprites + $260 - - dw PikachuSprite - db $40 / $10 ; $40 bytes - db BANK(PikachuSprite) - dw vSprites + $280 - - dw MonPartySprites + $100 - db $40 / $10 ; $40 bytes - db BANK(MonPartySprites) - dw vSprites + $380 - - dw SlowbroSprite - db $40 / $10 ; $40 bytes - db BANK(SlowbroSprite) - dw vSprites + $400 - - dw BallSprite - db $80 / $10 ; $80 bytes - db BANK(BallSprite) - dw vSprites + $440 - - dw ClefairySprite - db $40 / $10 ; $40 bytes - db BANK(ClefairySprite) - dw vSprites + $4c0 - - dw BirdSprite - db $40 / $10 ; $40 bytes - db BANK(BirdSprite) - dw vSprites + $500 - - dw SeelSprite + $C0 - db $40 / $10 ; $40 bytes - db BANK(SeelSprite) - dw vSprites + $540 - - dw MonPartySprites - db $10 / $10 ; $10 bytes - db BANK(MonPartySprites) - dw vSprites + $580 - - dw MonPartySprites + $10 - db $10 / $10 ; $10 bytes - db BANK(MonPartySprites) - dw vSprites + $5a0 - - dw MonPartySprites + $20 - db $10 / $10 ; $10 bytes - db BANK(MonPartySprites) - dw vSprites + $5c0 - - dw MonPartySprites + $30 - db $10 / $10 ; $10 bytes - db BANK(MonPartySprites) - dw vSprites + $5E0 - - dw MonPartySprites + $C0 - db $10 / $10 ; $10 bytes - db BANK(MonPartySprites) - dw vSprites + $600 - - dw MonPartySprites + $D0 - db $10 / $10 ; $10 bytes - db BANK(MonPartySprites) - dw vSprites + $620 - - dw MonPartySprites + $E0 - db $10 / $10 ; $10 bytes - db BANK(MonPartySprites) - dw vSprites + $640 - - dw MonPartySprites + $F0 - db $10 / $10 ; $10 bytes - db BANK(MonPartySprites) - dw vSprites + $660 - - dw PikachuSprite + $C0 - db $40 / $10 ; $40 bytes - db BANK(PikachuSprite) - dw vSprites + $680 - - dw MonPartySprites + $140 - db $40 / $10 ; $40 bytes - db BANK(MonPartySprites) - dw vSprites + $780 - -WriteMonPartySpriteOAMByPartyIndex: -; Write OAM blocks for the party mon in [hPartyMonIndex]. - push hl - push de - push bc - ld a, [hPartyMonIndex] - cp $ff - jr z, .asm_7191f - ld hl, wPartySpecies - ld e, a - ld d, 0 - add hl, de - ld a, [hl] - call GetPartyMonSpriteID - ld [wOAMBaseTile], a - call WriteMonPartySpriteOAM - pop bc - pop de - pop hl - ret - -.asm_7191f - ld hl, wOAMBuffer - ld de, wMonPartySpritesSavedOAM - ld bc, $60 - call CopyData - pop bc - pop de - pop hl - ret - -WriteMonPartySpriteOAMBySpecies: -; Write OAM blocks for the party sprite of the species in -; [wMonPartySpriteSpecies]. - xor a - ld [hPartyMonIndex], a - ld a, [wMonPartySpriteSpecies] - call GetPartyMonSpriteID - ld [wOAMBaseTile], a - jr WriteMonPartySpriteOAM - -UnusedPartyMonSpriteFunction: -; This function is unused and doesn't appear to do anything useful. It looks -; like it may have been intended to load the tile patterns and OAM data for -; the mon party sprite associated with the species in [wcf91]. -; However, its calculations are off and it loads garbage data. - ld a, [wcf91] - call GetPartyMonSpriteID - push af - ld hl, vSprites - call .LoadTilePatterns - pop af - add $5A - ld hl, vSprites + $40 - call .LoadTilePatterns - xor a - ld [wMonPartySpriteSpecies], a - jr WriteMonPartySpriteOAMBySpecies - -.LoadTilePatterns - push hl - add a - ld c, a - ld b, 0 - ld hl, MonPartySpritePointers - add hl, bc - add hl, bc - add hl, bc - ld a, [hli] - ld e, a - ld a, [hli] - ld d, a - ld a, [hli] - ld c, a - ld a, [hli] - ld b, a - pop hl - jp CopyVideoData - -WriteMonPartySpriteOAM: -; Write the OAM blocks for the first animation frame into the OAM buffer and -; make a copy at wMonPartySpritesSavedOAM. - push af - ld c, $10 - ld h, wOAMBuffer / $100 - ld a, [hPartyMonIndex] - swap a - ld l, a - add $10 - ld b, a - pop af - cp SPRITE_HELIX << 2 - jr z, .helix - call WriteSymmetricMonPartySpriteOAM - jr .makeCopy -.helix - call WriteAsymmetricMonPartySpriteOAM -; Make a copy of the OAM buffer with the first animation frame written so that -; we can flip back to it from the second frame by copying it back. -.makeCopy - ld hl, wOAMBuffer - ld de, wMonPartySpritesSavedOAM - ld bc, $60 - jp CopyData - -GetPartyMonSpriteID: - ld [wd11e], a - predef IndexToPokedex - ld a, [wd11e] - ld c, a - dec a - srl a - ld hl, MonPartyData - ld e, a - ld d, 0 - add hl, de - ld a, [hl] - bit 0, c - jr nz, .skipSwap - swap a ; use lower nybble if pokedex num is even -.skipSwap - and $f0 - srl a - srl a - ret - -INCLUDE "data/mon_party_sprites.asm" - -MonPartySprites: - INCBIN "gfx/mon_ow_sprites.2bpp" diff --git a/engine/movie/credits.asm b/engine/movie/credits.asm new file mode 100755 index 00000000..938579f3 --- /dev/null +++ b/engine/movie/credits.asm @@ -0,0 +1,322 @@ +HallOfFamePC: + callfar AnimateHallOfFame + call ClearScreen + ld c, 100 + call DelayFrames + + call DisableLCD + ld a, $a7 + ldh [rWX], a + xor a + ldh [rSCX], a + ldh [rSCY], a + ldh [hSCX], a + ldh [hSCY], a + ldh [hWY], a + ldh [rWY], a + call CreditsLoadFont + hlcoord 0, 0 + call FillFourRowsWithBlack + hlcoord 0, 14 + call FillFourRowsWithBlack + ld a, %11000000 + ldh [rBGP], a + call UpdateGBCPal_BGP + call EnableLCD + call StopAllMusic + ld hl, vBGMap1 + call CreditsCopyTileMapToVRAM + ld hl, vBGMap0 + call CreditsCopyTileMapToVRAM + ld c, BANK(Music_Credits) + ld a, MUSIC_CREDITS + call PlayMusic + ld c, 128 + call DelayFrames + xor a + ld [wHoFMonSpecies], a + ld [wNumCreditsMonsDisplayed], a + jp Credits + +FadeInCreditsText: + ld a, 1 + ldh [hAutoBGTransferEnabled], a + ld hl, HoFGBPalettes + ld b, 4 +.loop + ld a, [hli] + ldh [rBGP], a + call UpdateGBCPal_BGP + ld c, 5 + call DelayFrames + dec b + jr nz, .loop + ret + +HoFGBPalettes: + db %11000000 + db %11010000 + db %11100000 + db %11110000 + +DisplayCreditsMon: + ld hl, vBGMap1 + call CreditsCopyTileMapToVRAM + xor a + ldh [hAutoBGTransferEnabled], a + ld hl, rLCDC + set 3, [hl] + call SaveScreenTilesToBuffer2 + call FillMiddleOfScreenWithWhite + call GetNextCreditsMon + ld hl, vBGMap0 + 12 + call CreditsCopyTileMapToVRAM + xor a + ldh [hAutoBGTransferEnabled], a + call LoadScreenTilesFromBuffer2DisableBGTransfer + ld hl, vBGMap0 + call CreditsCopyTileMapToVRAM + ld a, %11111100 ; make the mon a black silhouette + ldh [rBGP], a + call UpdateGBCPal_BGP + ld hl, rLCDC + res 3, [hl] + ld a, 1 + ldh [hAutoBGTransferEnabled], a + ld b, 0 + ld c, 10 + call ScrollCreditsMonLeft + call FillLeftHalfOfScreenWithWhite + ld c, 10 + call ScrollCreditsMonLeft + call FillRightHalfOfScreenWithWhite + ld c, 8 + call ScrollCreditsMonLeft + ld a, %11000000 + ldh [rBGP], a + call UpdateGBCPal_BGP + xor a + ldh [hSCX], a + ret + +ScrollCreditsMonLeft: + ld a, b + ldh [hSCX], a + add 8 + ld b, a + call DelayFrame + dec c + jr nz, ScrollCreditsMonLeft + ret + +GetNextCreditsMon: + ld hl, wNumCreditsMonsDisplayed + ld c, [hl] + inc [hl] + ld b, 0 + ld hl, CreditsMons + add hl, bc + ld a, [hl] + ld [wcf91], a + ld [wd0b5], a + hlcoord 8, 6 + call GetMonHeader + call LoadFrontSpriteByMonIndex + ret + +INCLUDE "data/credits/credits_mons.asm" + +CreditsCopyTileMapToVRAM: + ld a, l + ldh [hAutoBGTransferDest], a + ld a, h + ldh [hAutoBGTransferDest + 1], a + ld a, 1 + ldh [hAutoBGTransferEnabled], a + jp Delay3 + +CreditsLoadFont: + call LoadFontTilePatterns + ld hl, vChars1 + ld bc, ($80 tiles) / 2 + call ZeroMemory + + call LoadTextBoxTilePatterns + ld hl, vChars2 tile $60 + ld bc, ($20 tiles) / 2 + call ZeroMemory + + ld hl, vChars2 tile $7e + ld bc, 1 tiles + ld a, $ff ; solid black + call FillMemory + ret + +ZeroMemory: +; zero bc bytes at hl + ld [hl], 0 + inc hl + inc hl + dec bc + ld a, b + or c + jr nz, ZeroMemory + ret + +FillFourRowsWithBlack: + ld bc, SCREEN_WIDTH * 4 + ld a, $7e + jp FillMemory + +FillMiddleOfScreenWithWhite: + hlcoord 0, 4 + ld bc, SCREEN_WIDTH * 10 + ld a, " " + jp FillMemory + +FillLeftHalfOfScreenWithWhite: + hlcoord 0, 4 + push bc + call FillHalfOfScreenWithWhite + pop bc + ret + +FillRightHalfOfScreenWithWhite: + hlcoord 10, 4 + push bc + call FillHalfOfScreenWithWhite + pop bc + ret + +FillHalfOfScreenWithWhite: + ld b, 10 + ld c, 10 + ld a, " " +.loop + push bc + push hl +.innerLoop + ld [hli], a + dec c + jr nz, .innerLoop + pop hl + ld bc, SCREEN_WIDTH + add hl, bc + pop bc + dec b + jr nz, .loop + ret + +Credits: ; Roll credits + ld de, CreditsOrder + push de +.nextCreditsScreen + pop de + hlcoord 9, 6 + push hl + call FillMiddleOfScreenWithWhite + pop hl +.nextCreditsCommand + ld a, [de] + inc de + push de + cp CRED_TEXT_FADE_MON + jr z, .fadeInTextAndShowMon + cp CRED_TEXT_MON + jr z, .showTextAndShowMon + cp CRED_TEXT_FADE + jr z, .fadeInText + cp CRED_TEXT + jr z, .showText + cp CRED_COPYRIGHT + jr z, .showCopyrightText + cp CRED_THE_END + jr z, .showTheEnd + call PlaceCreditsText + pop de + jr .nextCreditsCommand + +.showCopyrightText + farcall LoadCopyrightTiles + pop de + jr .nextCreditsCommand + + +.fadeInTextAndShowMon + call FadeInCreditsText + ld c, 102 + jr .next1 + +.showTextAndShowMon + ld c, 122 +.next1 + call DelayFrames + call DisplayCreditsMon + jr .nextCreditsScreen + +.fadeInText + call FadeInCreditsText + ld c, 132 + jr .next2 + +.showText + ld c, 152 +.next2 + call DelayFrames + jr .nextCreditsScreen +.showTheEnd + call ShowTheEndGFX + pop de + ret + +ShowTheEndGFX: + ld c, 24 + call DelayFrames + call FillMiddleOfScreenWithWhite + ld de, TheEndGfx + ld hl, vChars2 tile $60 + lb bc, BANK(TheEndGfx), (TheEndGfxEnd - TheEndGfx) / $10 + call CopyVideoData + hlcoord 4, 8 + ld de, TheEndTextString + call PlaceString + hlcoord 4, 9 + inc de + call PlaceString + jp FadeInCreditsText + +TheEndTextString: +; "T H E E N D" + db $60, " ", $62, " ", $64, " ", $64, " ", $66, " ", $68, "@" + db $61, " ", $63, " ", $65, " ", $65, " ", $67, " ", $69, "@" + +PlaceCreditsText: + push hl + push hl + ld hl, CreditsTextPointers + ld c, a + ld b, 0 + add hl, bc + add hl, bc + ld e, [hl] + inc hl + ld d, [hl] + pop hl + ld a, [de] + inc de + ld c, a + ld b, -1 + add hl, bc + call PlaceString + pop hl + ld bc, SCREEN_WIDTH * 2 + add hl, bc + ret + +INCLUDE "data/credits/credits_order.asm" + +INCLUDE "data/credits/credits_text.asm" + +TheEndGfx: + INCBIN "gfx/credits/the_end.2bpp" +TheEndGfxEnd: diff --git a/engine/movie/evolution.asm b/engine/movie/evolution.asm new file mode 100755 index 00000000..624a7f5f --- /dev/null +++ b/engine/movie/evolution.asm @@ -0,0 +1,156 @@ +EvolveMon: + push hl + push de + push bc + ld a, [wcf91] + push af + ld a, [wd0b5] + push af + xor a + ld [wLowHealthAlarm], a + ld [wChannelSoundIDs + Ch5], a + call StopAllMusic + ld a, $1 + ldh [hAutoBGTransferEnabled], a + ld a, SFX_TINK + call PlaySound + call Delay3 + xor a + ldh [hAutoBGTransferEnabled], a + ldh [hTilesetType], a + ld a, [wEvoOldSpecies] + ld [wWholeScreenPaletteMonSpecies], a + ld c, 0 + call EvolutionSetWholeScreenPalette + ld a, [wEvoNewSpecies] + ld [wcf91], a + ld [wd0b5], a + call Evolution_LoadPic + ld de, vFrontPic + ld hl, vBackPic + ld bc, 7 * 7 + call CopyVideoData + ld a, [wEvoOldSpecies] + ld [wcf91], a + ld [wd0b5], a + call Evolution_LoadPic + ld a, $1 + ldh [hAutoBGTransferEnabled], a + ld a, [wEvoOldSpecies] + call PlayCry + call WaitForSoundToFinish + ld c, BANK(Music_SafariZone) + ld a, MUSIC_SAFARI_ZONE + call PlayMusic + ld c, 80 + call DelayFrames + ld c, 1 ; set PAL_BLACK instead of mon palette + call EvolutionSetWholeScreenPalette + lb bc, $1, $10 +.animLoop + push bc + call Evolution_CheckForCancel + jr c, .evolutionCancelled + call Evolution_BackAndForthAnim + pop bc + inc b + dec c + dec c + jr nz, .animLoop + xor a + ld [wEvoCancelled], a + ld a, $31 + ld [wEvoMonTileOffset], a + call Evolution_ChangeMonPic ; show the new species pic + ld a, [wEvoNewSpecies] +.done + ld [wWholeScreenPaletteMonSpecies], a + call StopAllMusic + ld a, [wWholeScreenPaletteMonSpecies] + call PlayCry + ld c, 0 + call EvolutionSetWholeScreenPalette + pop af + ld [wd0b5], a + pop af + ld [wcf91], a + pop bc + pop de + pop hl + ld a, [wEvoCancelled] + and a + ret z + scf + ret +.evolutionCancelled + pop bc + ld a, 1 + ld [wEvoCancelled], a + ld a, [wEvoOldSpecies] + jr .done + +EvolutionSetWholeScreenPalette: + ld b, SET_PAL_POKEMON_WHOLE_SCREEN + jp RunPaletteCommand + +Evolution_LoadPic: + call GetMonHeader + hlcoord 7, 2 + jp LoadFlippedFrontSpriteByMonIndex + +Evolution_BackAndForthAnim: +; show the mon change back and forth between the new and old species b times + ld a, $31 + ld [wEvoMonTileOffset], a + call Evolution_ChangeMonPic + ld a, -$31 + ld [wEvoMonTileOffset], a + call Evolution_ChangeMonPic + dec b + jr nz, Evolution_BackAndForthAnim + ret + +Evolution_ChangeMonPic: + push bc + xor a + ldh [hAutoBGTransferEnabled], a + hlcoord 7, 2 + lb bc, 7, 7 + ld de, SCREEN_WIDTH - 7 +.loop + push bc +.innerLoop + ld a, [wEvoMonTileOffset] + add [hl] + ld [hli], a + dec c + jr nz, .innerLoop + pop bc + add hl, de + dec b + jr nz, .loop + ld a, 1 + ldh [hAutoBGTransferEnabled], a + call Delay3 + pop bc + ret + +Evolution_CheckForCancel: + call DelayFrame + push bc + call JoypadLowSensitivity + ldh a, [hJoy5] + pop bc + and B_BUTTON + jr nz, .pressedB +.notAllowedToCancel + dec c + jr nz, Evolution_CheckForCancel + and a + ret +.pressedB + ld a, [wForceEvolution] + and a + jr nz, .notAllowedToCancel + scf + ret diff --git a/engine/movie/hall_of_fame.asm b/engine/movie/hall_of_fame.asm new file mode 100755 index 00000000..616a72e3 --- /dev/null +++ b/engine/movie/hall_of_fame.asm @@ -0,0 +1,303 @@ +AnimateHallOfFame: + call HoFFadeOutScreenAndMusic + call ClearScreen + ld c, 100 + call DelayFrames + call LoadFontTilePatterns + call LoadTextBoxTilePatterns + call DisableLCD + ld hl, vBGMap0 + ld bc, $800 + ld a, " " + call FillMemory + call EnableLCD + ld hl, rLCDC + set 3, [hl] + xor a + ld hl, wHallOfFame + ld bc, HOF_TEAM + call FillMemory + xor a + ld [wUpdateSpritesEnabled], a + ldh [hTilesetType], a + ld [wSpriteFlipped], a + ld [wLetterPrintingDelayFlags], a ; no delay + ld [wHoFMonOrPlayer], a ; mon + inc a + ldh [hAutoBGTransferEnabled], a + ld hl, wNumHoFTeams + ld a, [hl] + inc a + jr z, .skipInc ; don't wrap around to 0 + inc [hl] +.skipInc + ld a, $90 + ldh [hWY], a + ld c, BANK(Music_HallOfFame) + ld a, MUSIC_HALL_OF_FAME + call PlayMusic + ld hl, wPartySpecies + ld c, $ff +.partyMonLoop + ld a, [hli] + cp $ff + jr z, .doneShowingParty + inc c + push hl + push bc + ld [wHoFMonSpecies], a + ld a, c + ld [wHoFPartyMonIndex], a + ld hl, wPartyMon1Level + ld bc, wPartyMon2 - wPartyMon1 + call AddNTimes + ld a, [hl] + ld [wHoFMonLevel], a + call HoFShowMonOrPlayer + call HoFDisplayAndRecordMonInfo + ld c, 80 + call DelayFrames + hlcoord 2, 13 + lb bc, 3, 14 + call TextBoxBorder + hlcoord 4, 15 + ld de, HallOfFameText + call PlaceString + ld c, 180 + call DelayFrames + call GBFadeOutToWhite + pop bc + pop hl + jr .partyMonLoop +.doneShowingParty + ld a, c + inc a + ld hl, wHallOfFame + ld bc, HOF_MON + call AddNTimes + ld [hl], $ff + callfar SaveHallOfFameTeams ; useless since in same bank + xor a + ld [wHoFMonSpecies], a + inc a + ld [wHoFMonOrPlayer], a ; player + call HoFShowMonOrPlayer + call HoFDisplayPlayerStats + call HoFFadeOutScreenAndMusic + xor a + ldh [hWY], a + ld hl, rLCDC + res 3, [hl] + ret + +HallOfFameText: + db "HALL OF FAME@" + +HoFShowMonOrPlayer: + call ClearScreen + ld a, $d0 + ldh [hSCY], a + ld a, $c0 + ldh [hSCX], a + ld a, [wHoFMonSpecies] + ld [wcf91], a + ld [wd0b5], a + ld [wBattleMonSpecies2], a + ld [wWholeScreenPaletteMonSpecies], a + ld a, [wHoFMonOrPlayer] + and a + jr z, .showMon +; show player + call HoFLoadPlayerPics + jr .next1 +.showMon + hlcoord 12, 5 + call GetMonHeader + call LoadFrontSpriteByMonIndex + predef LoadMonBackPic +.next1 + ld b, SET_PAL_POKEMON_WHOLE_SCREEN + ld c, 0 + call RunPaletteCommand + ld a, %11100100 + ldh [rBGP], a + call UpdateGBCPal_BGP + ld c, $31 ; back pic + call HoFLoadMonPlayerPicTileIDs + ld d, $a0 + ld e, 4 + ld a, [wOnSGB] + and a + jr z, .next2 + sla e ; scroll more slowly on SGB +.next2 + call .ScrollPic ; scroll back pic left + xor a + ldh [hSCY], a + ld c, a ; front pic + call HoFLoadMonPlayerPicTileIDs + ld d, 0 + ld e, -4 +; scroll front pic right + +.ScrollPic + call DelayFrame + ldh a, [hSCX] + add e + ldh [hSCX], a + cp d + jr nz, .ScrollPic + ret + +HoFDisplayAndRecordMonInfo: + ld a, [wHoFPartyMonIndex] + ld hl, wPartyMonNicks + call GetPartyMonName + call HoFDisplayMonInfo + ld a, [wHoFPartyMonIndex] + ld [wWhichPokemon], a + callfar IsThisPartymonStarterPikachu_Party + jr nc, .asm_70336 + ld e, $22 + callfar PlayPikachuSoundClip + jr .asm_7033c +.asm_70336 + ld a, [wHoFMonSpecies] + call PlayCry +.asm_7033c + jp HoFRecordMonInfo + +Func_7033f: + call HoFDisplayMonInfo + ld a, [wHoFMonSpecies] + jp PlayCry + +HoFDisplayMonInfo: + hlcoord 0, 2 + lb bc, 9, 10 + call TextBoxBorder + hlcoord 2, 6 + ld de, HoFMonInfoText + call PlaceString + hlcoord 1, 4 + ld de, wcd6d + call PlaceString + ld a, [wHoFMonLevel] + hlcoord 8, 7 + call PrintLevelCommon + ld a, [wHoFMonSpecies] + ld [wd0b5], a + hlcoord 3, 9 + predef PrintMonType + ret + +HoFMonInfoText: + db "LEVEL/" + next "TYPE1/" + next "TYPE2/@" + +HoFLoadPlayerPics: + ld de, RedPicFront + ld a, BANK(RedPicFront) + call UncompressSpriteFromDE + ld a, $0 + call SwitchSRAMBankAndLatchClockData + ld hl, sSpriteBuffer1 + ld de, sSpriteBuffer0 + ld bc, $310 + call CopyData + call PrepareRTCDataAndDisableSRAM + ld de, vFrontPic + call InterlaceMergeSpriteBuffers + ld de, RedPicBack + ld a, BANK(RedPicBack) + call UncompressSpriteFromDE + predef ScaleSpriteByTwo + ld de, vBackPic + call InterlaceMergeSpriteBuffers + ld c, $1 + +HoFLoadMonPlayerPicTileIDs: +; c = base tile ID + ld b, TILEMAP_MON_PIC + hlcoord 12, 5 + predef_jump CopyTileIDsFromList + +HoFDisplayPlayerStats: + SetEvent EVENT_HALL_OF_FAME_DEX_RATING + predef DisplayDexRating + hlcoord 0, 4 + lb bc, 6, 10 + call TextBoxBorder + hlcoord 5, 0 + lb bc, 2, 9 + call TextBoxBorder + hlcoord 7, 2 + ld de, wPlayerName + call PlaceString + hlcoord 1, 6 + ld de, HoFPlayTimeText + call PlaceString + hlcoord 5, 7 + ld de, wPlayTimeHours + lb bc, 1, 3 + call PrintNumber + ld [hl], $6d + inc hl + ld de, wPlayTimeMinutes + lb bc, LEADING_ZEROES | 1, 2 + call PrintNumber + hlcoord 1, 9 + ld de, HoFMoneyText + call PlaceString + hlcoord 4, 10 + ld de, wPlayerMoney + ld c, $a3 + call PrintBCDNumber + ld hl, DexSeenOwnedText + call HoFPrintTextAndDelay + ld hl, DexRatingText + call HoFPrintTextAndDelay + ld hl, wDexRatingText + +HoFPrintTextAndDelay: + call PrintText + ld c, 120 + jp DelayFrames + +HoFPlayTimeText: + db "PLAY TIME@" + +HoFMoneyText: + db "MONEY@" + +DexSeenOwnedText: + text_far _DexSeenOwnedText + text_end + +DexRatingText: + text_far _DexRatingText + text_end + +HoFRecordMonInfo: + ld hl, wHallOfFame + ld bc, HOF_MON + ld a, [wHoFPartyMonIndex] + call AddNTimes + ld a, [wHoFMonSpecies] + ld [hli], a + ld a, [wHoFMonLevel] + ld [hli], a + ld e, l + ld d, h + ld hl, wcd6d + ld bc, NAME_LENGTH + jp CopyData + +HoFFadeOutScreenAndMusic: + ld a, 10 + ld [wAudioFadeOutCounterReloadValue], a + ld [wAudioFadeOutCounter], a + ld a, $ff + ld [wAudioFadeOutControl], a + jp GBFadeOutToWhite diff --git a/engine/movie/intro.asm b/engine/movie/intro.asm new file mode 100755 index 00000000..9165113f --- /dev/null +++ b/engine/movie/intro.asm @@ -0,0 +1,157 @@ + const_def -1 + const MOVE_NIDORINO_RIGHT + const MOVE_GENGAR_RIGHT + const MOVE_GENGAR_LEFT + +ANIMATION_END EQU 80 + +PlayIntro: + xor a + ldh [hJoyHeld], a + inc a + ldh [hAutoBGTransferEnabled], a + call PlayShootingStar + callfar PlayIntroScene + xor a + ldh [hSCX], a + ldh [hAutoBGTransferEnabled], a + call ClearSprites + call DelayFrame + ret + +InitIntroNidorinoOAM: + ld hl, wOAMBuffer + ld d, 0 +.loop + push bc + ld a, [wBaseCoordY] + ld e, a +.innerLoop + ld a, e + add 8 + ld e, a + ld [hli], a ; Y + ld a, [wBaseCoordX] + ld [hli], a ; X + ld a, d + ld [hli], a ; tile + ld a, OAM_BEHIND_BG + ld [hli], a ; attributes + inc d + dec c + jr nz, .innerLoop + ld a, [wBaseCoordX] + add 8 + ld [wBaseCoordX], a + pop bc + dec b + jr nz, .loop + ret + +IntroClearScreen: + ld hl, vBGMap1 + ld bc, BG_MAP_WIDTH * SCREEN_HEIGHT + jr IntroClearCommon + +IntroClearMiddleOfScreen: +; clear the area of the tile map between the black bars on the top and bottom + hlcoord 0, 4 + ld bc, SCREEN_WIDTH * 10 + +IntroClearCommon: + ld [hl], 0 + inc hl + dec bc + ld a, b + or c + jr nz, IntroClearCommon + ret + +IntroPlaceBlackTiles: + ld a, 1 +.loop + ld [hli], a + dec c + jr nz, .loop + ret + +CopyTileIDsFromList_ZeroBaseTileID: + ld c, 0 + predef_jump CopyTileIDsFromList + +PlayShootingStar: + ld b, SET_PAL_GAME_FREAK_INTRO + call RunPaletteCommand + farcall LoadCopyrightAndTextBoxTiles + ldPal a, BLACK, DARK_GRAY, LIGHT_GRAY, WHITE + ldh [rBGP], a + call UpdateGBCPal_BGP + ld c, 180 + call DelayFrames + call ClearScreen + call DisableLCD + xor a + ld [wCurOpponent], a + call IntroDrawBlackBars +; write the black and white tiles + ld hl, vChars2 + ld bc, $10 + xor a + call FillMemory + ld hl, vChars2 + $10 + ld bc, $10 + ld a, $ff + call FillMemory +; copy gamefreak logo and others + ld hl, GameFreakIntro + ld de, vChars2 + $600 + ld bc, GameFreakIntroEnd - GameFreakIntro + ld a, BANK(GameFreakIntro) + call FarCopyData + ld hl, GameFreakIntro + ld de, vChars1 + ld bc, GameFreakIntroEnd - GameFreakIntro + ld a, BANK(GameFreakIntro) + call FarCopyData + + call EnableLCD + ld hl, rLCDC + res 5, [hl] + set 3, [hl] + ld c, 64 + call DelayFrames + farcall AnimateShootingStar + push af + pop af + jr c, .next ; skip the delay if the user interrupted the animation + ld c, 40 + call DelayFrames +.next + call IntroClearMiddleOfScreen + call ClearSprites + jp Delay3 + +IntroDrawBlackBars: +; clear the screen and draw black bars on the top and bottom + call IntroClearScreen + hlcoord 0, 0 + ld c, SCREEN_WIDTH * 4 + call IntroPlaceBlackTiles + hlcoord 0, 14 + ld c, SCREEN_WIDTH * 4 + call IntroPlaceBlackTiles + ld hl, vBGMap1 + ld c, BG_MAP_WIDTH * 4 + call IntroPlaceBlackTiles + hlbgcoord 0, 14, vBGMap1 + ld c, BG_MAP_WIDTH * 4 + jp IntroPlaceBlackTiles + +EmptyFunc2: + ret + +GameFreakIntro: + INCBIN "gfx/splash/gamefreak_presents.2bpp" + INCBIN "gfx/splash/gamefreak_logo.2bpp" + ds 16, $00 ; blank tile +GameFreakIntroEnd: diff --git a/engine/movie/oak_speech/clear_save.asm b/engine/movie/oak_speech/clear_save.asm new file mode 100755 index 00000000..2dd5f4a7 --- /dev/null +++ b/engine/movie/oak_speech/clear_save.asm @@ -0,0 +1,27 @@ +DoClearSaveDialogue: + call ClearScreen + call RunDefaultPaletteCommand + call LoadFontTilePatterns + call LoadTextBoxTilePatterns + ld hl, ClearSaveDataText + call PrintText + ld a, B_BUTTON + ld [wJoyIgnore], a + hlcoord 14, 7 + lb bc, 8, 15 + ld a, NO_YES_MENU + ld [wTwoOptionMenuID], a + ld a, TWO_OPTION_MENU + ld [wTextBoxID], a + call DisplayTextBoxID + ld a, 0 + ld [wJoyIgnore], a + ld a, [wCurrentMenuItem] + and a + jp z, Init + farcall ClearSAV + jp Init + +ClearSaveDataText: + text_far _ClearSaveDataText + text_end diff --git a/engine/movie/oak_speech/init_player_data.asm b/engine/movie/oak_speech/init_player_data.asm new file mode 100644 index 00000000..d6745daf --- /dev/null +++ b/engine/movie/oak_speech/init_player_data.asm @@ -0,0 +1,60 @@ +InitPlayerData: +InitPlayerData2: + + call Random + ldh a, [hRandomSub] + ld [wPlayerID], a + + call Random + ldh a, [hRandomAdd] + ld [wPlayerID + 1], a + + ld a, $ff + ld [wUnusedD71B], a + + ld a, 90 ; initialize happiness to 90 + ld [wPikachuHappiness], a + ld a, $80 + ld [wPikachuMood], a ; initialize mood + + ld hl, wPartyCount + call InitializeEmptyList + ld hl, wNumInBox + call InitializeEmptyList + ld hl, wNumBagItems + call InitializeEmptyList + ld hl, wNumBoxItems + call InitializeEmptyList + +START_MONEY EQU $3000 + ld hl, wPlayerMoney + 1 + ld a, HIGH(START_MONEY) + ld [hld], a + xor a ; LOW(START_MONEY) + ld [hli], a + inc hl + ld [hl], a + + ld [wMonDataLocation], a + + ld hl, wObtainedBadges + ld [hli], a + + ld [hl], a + + ld hl, wPlayerCoins + ld [hli], a + ld [hl], a + + ld hl, wGameProgressFlags + ld bc, wGameProgressFlagsEnd - wGameProgressFlags + call FillMemory ; clear all game progress flags + + jp InitializeMissableObjectsFlags + +InitializeEmptyList: + xor a ; count + ld [hli], a + dec a ; terminator + ld [hl], a + ret diff --git a/engine/movie/oak_speech/oak_speech.asm b/engine/movie/oak_speech/oak_speech.asm new file mode 100755 index 00000000..1a327def --- /dev/null +++ b/engine/movie/oak_speech/oak_speech.asm @@ -0,0 +1,244 @@ +SetDefaultNames: + ld a, [wLetterPrintingDelayFlags] + push af + ld a, [wOptions] + push af + ld a, [wd732] + push af + ld a, [wPrinterSettings] + push af + ld hl, wPlayerName + ld bc, wBoxDataEnd - wPlayerName + xor a + call FillMemory + ld hl, wSpriteDataStart + ld bc, wSpriteDataEnd - wSpriteDataStart + xor a + call FillMemory + xor a + ld [wSurfingMinigameHiScore], a + ld [wSurfingMinigameHiScore + 1], a + ld [wSurfingMinigameHiScore + 2], a + pop af + ld [wPrinterSettings], a + pop af + ld [wd732], a + pop af + ld [wOptions], a + pop af + ld [wLetterPrintingDelayFlags], a + ld a, [wOptionsInitialized] + and a + call z, InitOptions + ld hl, NintenText + ld de, wPlayerName + ld bc, NAME_LENGTH + call CopyData + ld hl, SonyText + ld de, wRivalName + ld bc, NAME_LENGTH + call CopyData ; rip optimizations + ret + +OakSpeech: + call StopAllMusic ; stop music + ld a, BANK(Music_Routes2) + ld c, a + ld a, MUSIC_ROUTES2 + call PlayMusic + call ClearScreen + call LoadTextBoxTilePatterns + call SetDefaultNames + predef InitPlayerData2 + ld hl, wNumBoxItems + ld a, POTION + ld [wcf91], a + ld a, 1 + ld [wItemQuantity], a + call AddItemToInventory ; give one potion + ld a, [wDefaultMap] + ld [wDestinationMap], a + call SpecialWarpIn + xor a + ldh [hTilesetType], a + ld a, [wd732] + bit 1, a ; possibly a debug mode bit + jp nz, .skipChoosingNames + ld de, ProfOakPic + lb bc, BANK(ProfOakPic), $00 + call IntroDisplayPicCenteredOrUpperRight + call FadeInIntroPic + ld hl, OakSpeechText1 + call PrintText + call GBFadeOutToWhite + call ClearScreen + ld a, PIKACHU + ld [wd0b5], a + ld [wcf91], a + call GetMonHeader + hlcoord 6, 4 + call LoadFlippedFrontSpriteByMonIndex + call MovePicLeft + ld hl, OakSpeechText2 + call PrintText + call GBFadeOutToWhite + call ClearScreen + ld de, RedPicFront + lb bc, BANK(RedPicFront), $00 + call IntroDisplayPicCenteredOrUpperRight + call MovePicLeft + ld hl, IntroducePlayerText + call PrintText + call ChoosePlayerName + call GBFadeOutToWhite + call ClearScreen + ld de, Rival1Pic + lb bc, BANK(Rival1Pic), $00 + call IntroDisplayPicCenteredOrUpperRight + call FadeInIntroPic + ld hl, IntroduceRivalText + call PrintText + call ChooseRivalName +.skipChoosingNames + call GBFadeOutToWhite + call ClearScreen + ld de, RedPicFront + lb bc, BANK(RedPicFront), $00 + call IntroDisplayPicCenteredOrUpperRight + call GBFadeInFromWhite + ld a, [wd72d] + and a + jr nz, .next + ld hl, OakSpeechText3 + call PrintText +.next + ldh a, [hLoadedROMBank] + push af + ld a, SFX_SHRINK + call PlaySound + pop af + call BankswitchCommon + ld c, 4 + call DelayFrames + ld hl, vSprites + ld de, RedSprite + ld b, BANK(RedSprite) + ld c, $0C + call CopyVideoData + ld de, ShrinkPic1 + lb bc, BANK(ShrinkPic1), $00 + call IntroDisplayPicCenteredOrUpperRight + ld c, 4 + call DelayFrames + ld de, ShrinkPic2 + lb bc, BANK(ShrinkPic2), $00 + call IntroDisplayPicCenteredOrUpperRight + call ResetPlayerSpriteData + ldh a, [hLoadedROMBank] + push af + ld a, BANK(Music_PalletTown) + ld [wAudioROMBank], a + ld [wAudioSavedROMBank], a + ld a, 10 + ld [wAudioFadeOutControl], a + call StopAllMusic + pop af + call BankswitchCommon + ld c, 20 + call DelayFrames + hlcoord 6, 5 + lb bc, 7, 7 + call ClearScreenArea + call LoadTextBoxTilePatterns + ld a, 1 + ld [wUpdateSpritesEnabled], a + ld c, 50 + call DelayFrames + call GBFadeOutToWhite + call ClearScreen ; rip more tail-end optimizations + ret + +OakSpeechText1: + text_far _OakSpeechText1 + text_end +OakSpeechText2: + text_far _OakSpeechText2A + sound_cry_pikachu + text_far _OakSpeechText2B + text_end +IntroducePlayerText: + text_far _IntroducePlayerText + text_end +IntroduceRivalText: + text_far _IntroduceRivalText + text_end +OakSpeechText3: + text_far _OakSpeechText3 + text_end + +FadeInIntroPic: + ld hl, IntroFadePalettes + ld b, 6 +.next + ld a, [hli] + ldh [rBGP], a + call UpdateGBCPal_BGP + ld c, 10 + call DelayFrames + dec b + jr nz, .next + ret + +IntroFadePalettes: + db %01010100 + db %10101000 + db %11111100 + db %11111000 + db %11110100 + db %11100100 + +MovePicLeft: + ld a, 119 + ldh [rWX], a + call DelayFrame + + ld a, %11100100 + ldh [rBGP], a + call UpdateGBCPal_BGP +.next + call DelayFrame + ldh a, [rWX] + sub 8 + cp $FF + ret z + ldh [rWX], a + jr .next + +DisplayPicCenteredOrUpperRight: + call GetPredefRegisters +IntroDisplayPicCenteredOrUpperRight: +; b = bank +; de = address of compressed pic +; c: 0 = centred, non-zero = upper-right + push bc + ld a, b + call UncompressSpriteFromDE + ld a, $0 + call SwitchSRAMBankAndLatchClockData + ld hl, sSpriteBuffer1 + ld de, sSpriteBuffer0 + ld bc, $310 + call CopyData + call PrepareRTCDataAndDisableSRAM + ld de, vFrontPic + call InterlaceMergeSpriteBuffers + pop bc + ld a, c + and a + hlcoord 15, 1 + jr nz, .next + hlcoord 6, 4 +.next + xor a + ldh [hStartTileID], a + predef_jump CopyUncompressedPicToTilemap diff --git a/engine/movie/oak_speech/oak_speech2.asm b/engine/movie/oak_speech/oak_speech2.asm new file mode 100755 index 00000000..af31665b --- /dev/null +++ b/engine/movie/oak_speech/oak_speech2.asm @@ -0,0 +1,219 @@ +ChoosePlayerName: + call OakSpeechSlidePicRight + ld de, DefaultNamesPlayer + call DisplayIntroNameTextBox + ld a, [wCurrentMenuItem] + and a + jr z, .customName + ld hl, DefaultNamesPlayerList + call GetDefaultName + ld de, wPlayerName + call OakSpeechSlidePicLeft + jr .done +.customName + ld hl, wPlayerName + xor a ; NAME_PLAYER_SCREEN + ld [wNamingScreenType], a + call DisplayNamingScreen + ld a, [wcf4b] + cp "@" + jr z, .customName + call ClearScreen + call Delay3 + ld de, RedPicFront + ld b, BANK(RedPicFront) + call IntroDisplayPicCenteredOrUpperRight +.done + ld hl, YourNameIsText + jp PrintText + +YourNameIsText: + text_far _YourNameIsText + text_end + +ChooseRivalName: + call OakSpeechSlidePicRight + ld de, DefaultNamesRival + call DisplayIntroNameTextBox + ld a, [wCurrentMenuItem] + and a + jr z, .customName + ld hl, DefaultNamesRivalList + call GetDefaultName + ld de, wRivalName + call OakSpeechSlidePicLeft + jr .done +.customName + ld hl, wRivalName + ld a, NAME_RIVAL_SCREEN + ld [wNamingScreenType], a + call DisplayNamingScreen + ld a, [wcf4b] + cp "@" + jr z, .customName + call ClearScreen + call Delay3 + ld de, Rival1Pic + ld b, $13 + call IntroDisplayPicCenteredOrUpperRight +.done + ld hl, HisNameIsText + jp PrintText + +HisNameIsText: + text_far _HisNameIsText + text_end + +OakSpeechSlidePicLeft: + push de + hlcoord 0, 0 + lb bc, 12, 11 + call ClearScreenArea ; clear the name list text box + ld c, 10 + call DelayFrames + pop de + ld hl, wcd6d + ld bc, NAME_LENGTH + call CopyData + call Delay3 + hlcoord 12, 4 + lb de, 6, 6 * SCREEN_WIDTH + 5 + ld a, $ff + jr OakSpeechSlidePicCommon + +OakSpeechSlidePicRight: + hlcoord 5, 4 + lb de, 6, 6 * SCREEN_WIDTH + 5 + xor a + +OakSpeechSlidePicCommon: + push hl + push de + push bc + ldh [hSlideDirection], a + ld a, d + ldh [hSlideAmount], a + ld a, e + ldh [hSlidingRegionSize], a + ld c, a + ldh a, [hSlideDirection] + and a + jr nz, .next +; If sliding right, point hl to the end of the pic's tiles. + ld d, 0 + add hl, de +.next + ld d, h + ld e, l +.loop + xor a + ldh [hAutoBGTransferEnabled], a + ldh [hAutoBGTransferPortion], a + ldh a, [hSlideDirection] + and a + jr nz, .slideLeft +; sliding right + ld a, [hli] + ld [hld], a + dec hl + jr .next2 +.slideLeft + ld a, [hld] + ld [hli], a + inc hl +.next2 + dec c + jr nz, .loop + ldh a, [hSlideDirection] + and a + jr z, .next3 +; If sliding left, we need to zero the last tile in the pic (there is no need +; to take a corresponding action when sliding right because hl initially points +; to a 0 tile in that case). + dec hl + xor a + ld [hl], a +.next3 + ld a, 1 + ldh [hAutoBGTransferEnabled], a + call Delay3 + ldh a, [hSlidingRegionSize] + ld c, a + ld h, d + ld l, e + ldh a, [hSlideDirection] + and a + jr nz, .slideLeft2 + inc hl + jr .next4 +.slideLeft2 + dec hl +.next4 + ld d, h + ld e, l + ldh a, [hSlideAmount] + dec a + ldh [hSlideAmount], a + jr nz, .loop + pop bc + pop de + pop hl + ret + +DisplayIntroNameTextBox: + push de + hlcoord 0, 0 + lb bc, 10, 9 + call TextBoxBorder + hlcoord 3, 0 + ld de, .namestring + call PlaceString + pop de + hlcoord 2, 2 + call PlaceString + call UpdateSprites + xor a + ld [wCurrentMenuItem], a + ld [wLastMenuItem], a + inc a + ld [wTopMenuItemX], a + ld [wMenuWatchedKeys], a ; A_BUTTON + inc a + ld [wTopMenuItemY], a + inc a + ld [wMaxMenuItem], a + jp HandleMenuInput + +.namestring + db "NAME@" + +INCLUDE "data/player_names.asm" + +GetDefaultName: +; a = name index +; hl = name list + ld b, a + ld c, 0 +.loop + ld d, h + ld e, l +.innerLoop + ld a, [hli] + cp "@" + jr nz, .innerLoop + ld a, b + cp c + jr z, .foundName + inc c + jr .loop +.foundName + ld h, d + ld l, e + ld de, wcd6d + ld bc, $14 + jp CopyData + +INCLUDE "data/player_names_list.asm" + +LinkMenuEmptyText: + text_end diff --git a/engine/movie/splash.asm b/engine/movie/splash.asm new file mode 100755 index 00000000..4cb0a59a --- /dev/null +++ b/engine/movie/splash.asm @@ -0,0 +1,259 @@ +LoadShootingStarGraphics: + ld a, $f9 + ldh [rOBP0], a + ld a, $a4 + ldh [rOBP1], a + call UpdateGBCPal_OBP0 + call UpdateGBCPal_OBP1 + ld de, AnimationTileset2 tile 3 ; star tile (top left quadrant) + ld hl, vChars1 tile $20 + lb bc, BANK(AnimationTileset2), $01 + call CopyVideoData + ld de, AnimationTileset2 tile 19 ; star tile (bottom left quadrant) + ld hl, vChars1 tile $21 + lb bc, BANK(AnimationTileset2), 1 + call CopyVideoData + ld de, FallingStar + ld hl, vChars1 tile $22 + lb bc, BANK(FallingStar), (FallingStarEnd - FallingStar) / $10 + call CopyVideoData + ld hl, GameFreakLogoOAMData + ld de, wOAMBuffer + $60 + ld bc, GameFreakLogoOAMDataEnd - GameFreakLogoOAMData + call CopyData + ld hl, GameFreakShootingStarOAMData + ld de, wOAMBuffer + ld bc, GameFreakShootingStarOAMDataEnd - GameFreakShootingStarOAMData + jp CopyData + +AnimateShootingStar: + call LoadShootingStarGraphics + ld a, SFX_SHOOTING_STAR + call PlaySound + +; Move the big star down and left across the screen. + ld hl, wOAMBuffer + lb bc, $a0, $4 +.bigStarLoop + push hl + push bc +.bigStarInnerLoop + ld a, [hl] ; Y + add 4 + ld [hli], a + ld a, [hl] ; X + add -4 + ld [hli], a + inc hl + inc hl + dec c + jr nz, .bigStarInnerLoop + ld c, 1 + call CheckForUserInterruption + pop bc + pop hl + ret c + ld a, [hl] + cp 80 + jr nz, .next + jr .bigStarLoop +.next + cp b + jr nz, .bigStarLoop + +; Clear big star OAM. + ld hl, wOAMBuffer + ld c, 4 + ld de, 4 +.clearOAMLoop + ld [hl], 160 + add hl, de + dec c + jr nz, .clearOAMLoop + +; Make Gamefreak logo flash. + ld b, 3 +.flashLogoLoop + ld hl, rOBP0 + rrc [hl] + rrc [hl] + call UpdateGBCPal_OBP0 + ld c, 10 + call CheckForUserInterruption + ret c + dec b + jr nz, .flashLogoLoop + +; Copy 24 instances of the small stars OAM data. +; Note that their coordinates put them off-screen. + ld de, wOAMBuffer + ld a, 24 +.initSmallStarsOAMLoop + push af + ld hl, SmallStarsOAM + ld bc, SmallStarsOAMEnd - SmallStarsOAM + call CopyData + pop af + dec a + jr nz, .initSmallStarsOAMLoop + +; Animate the small stars falling from the Gamefreak logo. + xor a + ld [wMoveDownSmallStarsOAMCount], a + ld hl, SmallStarsWaveCoordsPointerTable + ld c, 6 +.smallStarsLoop + ld a, [hli] + ld e, a + ld a, [hli] + ld d, a + push bc + push hl + ld hl, wOAMBuffer + $50 + ld c, 4 +.smallStarsInnerLoop ; introduce new wave of 4 small stars OAM entries + ld a, [de] + cp -1 + jr z, .next2 + ld [hli], a ; Y + inc de + ld a, [de] + ld [hli], a ; X + inc de + inc hl + push bc + ld a, [de] + ld b, a + ld a, [hl] + and $f0 + or b + ld [hl], a + inc de + pop bc + inc hl + dec c + jr nz, .smallStarsInnerLoop + ld a, [wMoveDownSmallStarsOAMCount] + cp 24 + jr z, .next2 + add 6 ; should be 4, but the extra 2 aren't visible on screen + ld [wMoveDownSmallStarsOAMCount], a +.next2 + call MoveDownSmallStars + push af + +; shift the existing OAM entries down to make room for the next wave + ld hl, wOAMBuffer + $10 + ld de, wOAMBuffer + ld bc, $50 + call CopyData + + pop af + pop hl + pop bc + ret c + dec c + jr nz, .smallStarsLoop + and a + ret + +SmallStarsOAM: + dbsprite 0, 0, 0, 0, $A2, OAM_BEHIND_BG | OAM_OBP1 +SmallStarsOAMEnd: + +SmallStarsWaveCoordsPointerTable: + dw SmallStarsWave1Coords + dw SmallStarsWave2Coords + dw SmallStarsWave3Coords + dw SmallStarsWave4Coords + dw SmallStarsEmptyWave + dw SmallStarsEmptyWave + +; The stars that fall from the Gamefreak logo come in 4 waves of 4 OAM entries. +; These arrays contain the Y and X coordinates of each OAM entry. + +SmallStarsWave1Coords: + db $68, $30 + db $05, $68 + db $40, $05 + db $68, $58 + db $04, $68 + db $78, $07 +SmallStarsWave2Coords: + db $68, $38 + db $05, $68 + db $48, $06 + db $68, $60 + db $04, $68 + db $70, $07 +SmallStarsWave3Coords: + db $68, $34 + db $05, $68 + db $4c, $06 + db $68, $54 + db $06, $68 + db $64, $07 +SmallStarsWave4Coords: + db $68, $3c + db $05, $68 + db $5c, $04 + db $68, $6c + db $07, $68 + db $74, $07 +SmallStarsEmptyWave: + db -1 ; end + +MoveDownSmallStars: + ld b, 8 +.loop + ld hl, wOAMBuffer + $5c + ld a, [wMoveDownSmallStarsOAMCount] + ld de, -4 + ld c, a +.innerLoop + inc [hl] ; Y + add hl, de + dec c + jr nz, .innerLoop +; Toggle the palette so that the lower star in the small stars tile blinks in +; and out. + ldh a, [rOBP1] + xor %10100000 + ldh [rOBP1], a + call UpdateGBCPal_OBP1 + ld c, 3 + call CheckForUserInterruption + ret c + dec b + jr nz, .loop + ret + +GameFreakLogoOAMData: + dbsprite 10, 9, 0, 0, $8d, 0 + dbsprite 11, 9, 0, 0, $8e, 0 + dbsprite 10, 10, 0, 0, $8f, 0 + dbsprite 11, 10, 0, 0, $90, 0 + dbsprite 10, 11, 0, 0, $91, 0 + dbsprite 11, 11, 0, 0, $92, 0 + dbsprite 6, 12, 0, 0, $80, 0 + dbsprite 7, 12, 0, 0, $81, 0 + dbsprite 8, 12, 0, 0, $82, 0 + dbsprite 9, 12, 0, 0, $83, 0 + dbsprite 10, 12, 0, 0, $93, 0 + dbsprite 11, 12, 0, 0, $84, 0 + dbsprite 12, 12, 0, 0, $85, 0 + dbsprite 13, 12, 0, 0, $83, 0 + dbsprite 14, 12, 0, 0, $81, 0 + dbsprite 15, 12, 0, 0, $86, 0 +GameFreakLogoOAMDataEnd: + +GameFreakShootingStarOAMData: + dbsprite 20, 0, 0, 0, $a0, OAM_OBP1 | %100 + dbsprite 21, 0, 0, 0, $a0, OAM_OBP1 | OAM_HFLIP | %100 + dbsprite 20, 1, 0, 0, $a1, OAM_OBP1 | %100 + dbsprite 21, 1, 0, 0, $a1, OAM_OBP1 | OAM_HFLIP | %100 +GameFreakShootingStarOAMDataEnd: + +FallingStar: + INCBIN "gfx/splash/falling_star.2bpp" +FallingStarEnd: diff --git a/engine/movie/title.asm b/engine/movie/title.asm new file mode 100755 index 00000000..1f2723a3 --- /dev/null +++ b/engine/movie/title.asm @@ -0,0 +1,370 @@ +SetDefaultNamesBeforeTitlescreen:: + ld hl, NintenText + ld de, wPlayerName + call CopyFixedLengthText + ld hl, SonyText + ld de, wRivalName + call CopyFixedLengthText + xor a + ldh [hWY], a + ld [wLetterPrintingDelayFlags], a + ld hl, wd732 + ld [hli], a + ld [hli], a + ld [hl], a + ld a, BANK(Music_TitleScreen) + ld [wAudioROMBank], a + ld [wAudioSavedROMBank], a + +DisplayTitleScreen: + call GBPalWhiteOut + ld a, $1 + ldh [hAutoBGTransferEnabled], a + xor a + ldh [hTilesetType], a + ldh [hSCX], a + ld a, $40 + ldh [hSCY], a + ld a, $90 + ldh [hWY], a + call ClearScreen + call DisableLCD + call LoadFontTilePatterns +; todo: fix hl pointers + ld hl, NintendoCopyrightLogoGraphics + ld de, vTitleLogo tile $60 + ld bc, 5 tiles + ld a, BANK(NintendoCopyrightLogoGraphics) + call FarCopyData + ld hl, NineTile + ld de, vTitleLogo tile $6e + ld bc, $10 + ld a, BANK(NineTile) + call FarCopyData + ld hl, GamefreakLogoGraphics + ld de, vTitleLogo tile $65 + ld bc, 9 tiles + ld a, BANK(GamefreakLogoGraphics) + call FarCopyData + callfar LoadYellowTitleScreenGFX + ld hl, vBGMap0 + ld bc, (vBGMap1 tile $40) - vBGMap0 + ld a, " " + call FillMemory + callfar TitleScreen_PlacePokemonLogo + call FillSpriteBuffer0WithAA + call .WriteCopyrightTiles + call SaveScreenTilesToBuffer2 + call LoadScreenTilesFromBuffer2 + call EnableLCD + callfar TitleScreen_PlacePikachu + ld a, HIGH(vBGMap0 + $300) + call TitleScreenCopyTileMapToVRAM + call SaveScreenTilesToBuffer1 + ld a, $40 + ldh [hWY], a + call LoadScreenTilesFromBuffer2 + ld a, HIGH(vBGMap0) + call TitleScreenCopyTileMapToVRAM + ld b, SET_PAL_TITLE_SCREEN + call RunPaletteCommand + call GBPalNormal + ld a, %11100000 + ldh [rOBP0], a + call UpdateGBCPal_OBP0 + +; make pokemon logo bounce up and down + ld bc, hSCY ; background scroll Y + ld hl, .TitleScreenPokemonLogoYScrolls +.bouncePokemonLogoLoop + ld a, [hli] + and a + jr z, .finishedBouncingPokemonLogo + ld d, a + cp -3 + jr nz, .skipPlayingSound + ld a, SFX_INTRO_CRASH + call PlaySound +.skipPlayingSound + ld a, [hli] + ld e, a + call .ScrollTitleScreenPokemonLogo + jr .bouncePokemonLogoLoop + +.TitleScreenPokemonLogoYScrolls: +; Controls the bouncing effect of the Pokemon logo on the title screen + db -4,16 ; y scroll amount, number of times to scroll + db 3,4 + db -3,4 + db 2,2 + db -2,2 + db 1,2 + db -1,2 + db 0 ; terminate list with 0 + +.ScrollTitleScreenPokemonLogo: +; Scrolls the Pokemon logo on the title screen to create the bouncing effect +; Scrolls d pixels e times + call DelayFrame + ld a, [bc] ; background scroll Y + add d + ld [bc], a + dec e + jr nz, .ScrollTitleScreenPokemonLogo + ret + +; place tiles for title screen copyright +.WriteCopyrightTiles + hlcoord 2, 17 + ld de, .tileScreenCopyrightTiles +.titleScreenCopyrightTilesLoop + ld a, [de] + inc de + cp $ff + ret z + ld [hli], a + jr .titleScreenCopyrightTilesLoop + +.tileScreenCopyrightTiles + db $e0,$e1,$e2,$e3,$e1,$e2,$ee,$e5,$e6,$e7,$e8,$e9,$ea,$eb,$ec,$ed,$ff ; ©1995-1999 GAME FREAK inc. + +.finishedBouncingPokemonLogo + call LoadScreenTilesFromBuffer1 + ld c, 36 + call DelayFrames + ld a, SFX_INTRO_WHOOSH + call PlaySound + +; scroll game version in from the right + callfar TitleScreen_PlacePikaSpeechBubble + ld a, SCREEN_HEIGHT_PX + ldh [hWY], a + call Delay3 + ld e, 0 + call TitleScreen_PlayPikachuPCM + call WaitForSoundToFinish + call StopAllMusic + ld a, MUSIC_TITLE_SCREEN + ld [wNewSoundID], a + call PlaySound +.loop + xor a + ld [wUnusedCC5B], a + ld [wTitleScreenScene], a + ld [wTitleScreenScene + 1], a + ld [wTitleScreenScene + 2], a + ld [wTitleScreenScene + 3], a + ld a, $f + ld [wTitleScreenScene + 4], a +.titleScreenLoop + call IncrementResetCounter + jp c, .doTitlescreenReset + call DelayFrame + call JoypadLowSensitivity + ldh a, [hJoyHeld] + cp D_UP | SELECT | B_BUTTON + jr z, .go_to_main_menu + and A_BUTTON | START + jr nz, .go_to_main_menu + call DoTitleScreenFunction + jr .titleScreenLoop + +.go_to_main_menu + ld e, $a + call TitleScreen_PlayPikachuPCM + call GBPalWhiteOutWithDelay3 + call ClearSprites + xor a + ldh [hWY], a + inc a + ldh [hAutoBGTransferEnabled], a + call ClearScreen + ld a, HIGH(vBGMap0) + call TitleScreenCopyTileMapToVRAM + ld a, HIGH(vBGMap1) + call TitleScreenCopyTileMapToVRAM + call Delay3 + call LoadGBPal + ldh a, [hJoyHeld] + ld b, a + and D_UP | SELECT | B_BUTTON + cp D_UP | SELECT | B_BUTTON + jp z, .doClearSaveDialogue + jp MainMenu + +.asm_42f0 +; unreferenced + callfar PrinterDebug + jp .loop + +.asm_42fb +; unreferenced + ld a, [wTitleScreenScene + 4] + inc a + cp $2a + jr c, .asm_4305 + ld a, $f +.asm_4305 + ld [wTitleScreenScene + 4], a + ld e, a + callfar PlayPikachuSoundClip + xor a + ld [wTitleScreenScene + 2], a + ld [wTitleScreenScene + 3], a + jp .titleScreenLoop + +.doTitlescreenReset + ld [wAudioFadeOutControl], a + call StopAllMusic +.audioFadeLoop + ld a, [wAudioFadeOutControl] + and a + jr nz, .audioFadeLoop + jp Init + +.doClearSaveDialogue + farjp DoClearSaveDialogue + + +TitleScreenCopyTileMapToVRAM: + ldh [hAutoBGTransferDest + 1], a + jp Delay3 + +LoadCopyrightAndTextBoxTiles: + xor a + ldh [hWY], a + call ClearScreen + call LoadTextBoxTilePatterns + +LoadCopyrightTiles: + ld de, NintendoCopyrightLogoGraphics + ld hl, vChars2 tile $60 + lb bc, BANK(NintendoCopyrightLogoGraphics), (TextBoxGraphics + $10 - NintendoCopyrightLogoGraphics) / $10 ; bug: overflows into text box graphics and copies the "A" tile + call CopyVideoData + hlcoord 2, 7 + ld de, CopyrightTextString + jp PlaceString + +CopyrightTextString: + db $60,$61,$62,$63,$61,$62,$7c,$7f,$65,$66,$67,$68,$69,$6a ; ©1995-1999 Nintendo + next $60,$61,$62,$63,$61,$62,$7c,$7f,$6b,$6c,$6d,$6e,$6f,$70,$71,$72 ; ©1995-1999 Creatures inc. + next $60,$61,$62,$63,$61,$62,$7c,$7f,$73,$74,$75,$76,$77,$78,$79,$7a,$7b ; ©1995-1999 GAME FREAK inc. + db "@" + +TitleScreen_PlayPikachuPCM: + callfar PlayPikachuSoundClip + ret + +DoTitleScreenFunction: + call .CheckTimer + ld a, [wTitleScreenScene] + ld e, a + ld d, 0 + ld hl, .Jumptable + add hl, de + add hl, de + ld a, [hli] + ld h, [hl] + ld l, a + jp hl + + +.Jumptable: + dw .Nop + dw .BlinkHalf + dw .BlinkWait + dw .BlinkWait + dw .BlinkClosed + dw .BlinkWait + dw .BlinkWait + dw .BlinkHalf + dw .BlinkWait + dw .BlinkWait + dw .BlinkOpen + dw .GoBackToStart + +.GoBackToStart: + xor a + ld [wTitleScreenScene], a +.Nop + ret + +.BlinkOpen: + ld e, 0 + jr .LoadBlinkFrame + +.BlinkHalf: + ld e, 4 + jr .LoadBlinkFrame + +.BlinkClosed: + ld e, 8 +.LoadBlinkFrame: + ld hl, wOAMBuffer + 2 + ld c, 8 +.loop + ld a, [hl] + and $f3 + or e + ld [hli], a + inc hl + inc hl + inc hl + dec c + jr nz, .loop +.BlinkWait: + ld hl, wTitleScreenScene + inc [hl] + ret + +.CheckTimer: + ld hl, wTitleScreenTimer + ld a, [hl] + inc [hl] + and a + jr z, .restart + cp $80 + jr z, .restart + cp $90 + ret nz +.restart + ld a, $1 + ld [wTitleScreenScene], a + ret + +; copy text of fixed length NAME_LENGTH (like player name, rival name, mon names, ...) +CopyFixedLengthText: + ld bc, NAME_LENGTH + jp CopyData + +NintenText: db "NINTEN@" +SonyText: db "SONY@" + +IncrementResetCounter: + ld hl, wTitleScreenScene + 2 + ld e, [hl] + inc hl + ld d, [hl] + inc de + ld a, d + cp $c + jr z, .doReset + ld [hl], d + dec hl + ld [hl], e + and a + ret + +.doReset + scf + ret + +FillSpriteBuffer0WithAA: + xor a + call SwitchSRAMBankAndLatchClockData + ld hl, sSpriteBuffer0 + ld bc, $20 + ld a, $aa + call FillMemory + call PrepareRTCDataAndDisableSRAM + ret diff --git a/engine/movie/title2.asm b/engine/movie/title2.asm new file mode 100755 index 00000000..df630b53 --- /dev/null +++ b/engine/movie/title2.asm @@ -0,0 +1,122 @@ +; Leftover of Red/Blue. Seemingly unused + +TitleScroll_WaitBall: +; Wait around for the TitleBall animation to play out. +; hi: speed +; lo: duration + db $05, $05, 0 + +TitleScroll_In: +; Scroll a TitleMon in from the right. +; hi: speed +; lo: duration + db $a2, $94, $84, $63, $52, $31, $11, 0 + +TitleScroll_Out: +; Scroll a TitleMon out to the left. +; hi: speed +; lo: duration + db $12, $22, $32, $42, $52, $62, $83, $93, 0 + +TitleScroll: + ld a, d + + ld bc, TitleScroll_In + ld d, $88 + ld e, 0 ; don't animate titleball + + and a + jr nz, .ok + + ld bc, TitleScroll_Out + ld d, $00 + ld e, 0 ; don't animate titleball +.ok + +_TitleScroll: + ld a, [bc] + and a + ret z + + inc bc + push bc + + ld b, a + and $f + ld c, a + ld a, b + and $f0 + swap a + ld b, a + +.loop + ld h, d + ld l, $48 + call .ScrollBetween + + ld h, $00 + ld l, $88 + call .ScrollBetween + + ld a, d + add b + ld d, a + + call GetTitleBallY + dec c + jr nz, .loop + + pop bc + jr _TitleScroll + +.ScrollBetween: +.wait + ldh a, [rLY] ; rLY + cp l + jr nz, .wait + + ld a, h + ldh [rSCX], a + +.wait2 + ldh a, [rLY] ; rLY + cp h + jr z, .wait2 + ret + +TitleBallYTable: +; OBJ y-positions for the Poke Ball held by Red in the title screen. +; This is really two 0-terminated lists. Initiated with an index of 1. + db 0, $71, $6f, $6e, $6d, $6c, $6d, $6e, $6f, $71, $74, 0 + +TitleScreenAnimateBallIfStarterOut: +; Animate the TitleBall if a starter just got scrolled out. + ld a, [wTitleScreenScene] + cp STARTER1 + jr z, .ok + cp STARTER2 + jr z, .ok + cp STARTER3 + ret nz +.ok + ld e, 1 ; animate titleball + ld bc, TitleScroll_WaitBall + ld d, 0 + jp _TitleScroll + +GetTitleBallY: +; Get position e from TitleBallYTable + push de + push hl + xor a + ld d, a + ld hl, TitleBallYTable + add hl, de + ld a, [hl] + pop hl + pop de + and a + ret z + ld [wOAMBuffer + $28], a + inc e + ret diff --git a/engine/movie/trade.asm b/engine/movie/trade.asm new file mode 100755 index 00000000..7be100e0 --- /dev/null +++ b/engine/movie/trade.asm @@ -0,0 +1,859 @@ +InternalClockTradeAnim: +; Do the trading animation with the player's gameboy on the left. +; In-game trades and internally clocked link cable trades use this. + ld a, [wTradedPlayerMonSpecies] + ld [wLeftGBMonSpecies], a + ld a, [wTradedEnemyMonSpecies] + ld [wRightGBMonSpecies], a + ld de, InternalClockTradeFuncSequence + jr TradeAnimCommon + +ExternalClockTradeAnim: +; Do the trading animation with the player's gameboy on the right. +; Externally clocked link cable trades use this. + ld a, [wTradedEnemyMonSpecies] + ld [wLeftGBMonSpecies], a + ld a, [wTradedPlayerMonSpecies] + ld [wRightGBMonSpecies], a + ld de, ExternalClockTradeFuncSequence + +TradeAnimCommon: + ld a, [wOptions] + push af + and %110000 ; preserve speaker options + ld [wOptions], a + ldh a, [hSCY] + push af + ldh a, [hSCX] + push af + xor a + ldh [hSCY], a + ldh [hSCX], a + push de +.loop + pop de + ld a, [de] + cp $ff + jr z, .done + inc de + push de + ld hl, TradeFuncPointerTable + add a + ld c, a + ld b, $0 + add hl, bc + ld a, [hli] + ld h, [hl] + ld l, a + ld de, .loop + push de + jp hl ; call trade func, which will return to the top of the loop +.done + pop af + ldh [hSCX], a + pop af + ldh [hSCY], a + pop af + ld [wOptions], a + ret + +addtradefunc: MACRO +\1TradeFunc:: + dw \1 +ENDM + +tradefunc: MACRO + db (\1TradeFunc - TradeFuncPointerTable) / 2 +ENDM + +; The functions in the sequences below are executed in order by TradeFuncCommon. +; They are from opposite perspectives. The external clock one makes use of +; Trade_SwapNames to swap the player and enemy names for some functions. + +InternalClockTradeFuncSequence: + tradefunc LoadTradingGFXAndMonNames + tradefunc Trade_ShowPlayerMon + tradefunc Trade_DrawOpenEndOfLinkCable + tradefunc Trade_AnimateBallEnteringLinkCable + tradefunc Trade_AnimLeftToRight + tradefunc Trade_Delay100 + tradefunc Trade_ShowClearedWindow + tradefunc PrintTradeWentToText + tradefunc PrintTradeForSendsText + tradefunc PrintTradeFarewellText + tradefunc Trade_AnimRightToLeft + tradefunc Trade_ShowClearedWindow + tradefunc Trade_DrawOpenEndOfLinkCable + tradefunc Trade_ShowEnemyMon + tradefunc Trade_Delay100 + tradefunc Trade_Cleanup + db -1 ; end + +ExternalClockTradeFuncSequence: + tradefunc LoadTradingGFXAndMonNames + tradefunc Trade_ShowClearedWindow + tradefunc PrintTradeWillTradeText + tradefunc PrintTradeFarewellText + tradefunc Trade_SwapNames + tradefunc Trade_AnimLeftToRight + tradefunc Trade_SwapNames + tradefunc Trade_ShowClearedWindow + tradefunc Trade_DrawOpenEndOfLinkCable + tradefunc Trade_ShowEnemyMon + tradefunc Trade_SlideTextBoxOffScreen + tradefunc Trade_ShowPlayerMon + tradefunc Trade_DrawOpenEndOfLinkCable + tradefunc Trade_AnimateBallEnteringLinkCable + tradefunc Trade_SwapNames + tradefunc Trade_AnimRightToLeft + tradefunc Trade_SwapNames + tradefunc Trade_Delay100 + tradefunc Trade_ShowClearedWindow + tradefunc PrintTradeWentToText + tradefunc Trade_Cleanup + db -1 ; end + +TradeFuncPointerTable: + addtradefunc LoadTradingGFXAndMonNames + addtradefunc Trade_ShowPlayerMon + addtradefunc Trade_DrawOpenEndOfLinkCable + addtradefunc Trade_AnimateBallEnteringLinkCable + addtradefunc Trade_ShowEnemyMon + addtradefunc Trade_AnimLeftToRight + addtradefunc Trade_AnimRightToLeft + addtradefunc Trade_Delay100 + addtradefunc Trade_ShowClearedWindow + addtradefunc PrintTradeWentToText + addtradefunc PrintTradeForSendsText + addtradefunc PrintTradeFarewellText + addtradefunc PrintTradeTakeCareText + addtradefunc PrintTradeWillTradeText + addtradefunc Trade_Cleanup + addtradefunc Trade_SlideTextBoxOffScreen + addtradefunc Trade_SwapNames + +Trade_Delay100: + ld c, 100 + jp DelayFrames + +Trade_CopyTileMapToVRAM: + ld a, $1 + ldh [hAutoBGTransferEnabled], a + call Delay3 + xor a + ldh [hAutoBGTransferEnabled], a + ret + +Trade_Delay80: + ld c, 80 + jp DelayFrames + +Trade_ClearTileMap: + hlcoord 0, 0 + ld bc, SCREEN_WIDTH * SCREEN_HEIGHT + ld a, " " + jp FillMemory + +LoadTradingGFXAndMonNames: + call Trade_ClearTileMap + call DisableLCD + ld hl, TradingAnimationGraphics + ld de, vChars2 tile $31 + ld bc, TradingAnimationGraphicsEnd - TradingAnimationGraphics + ld a, BANK(TradingAnimationGraphics) + call FarCopyData + ld hl, TradingAnimationGraphics2 + ld de, vSprites tile $7c + ld bc, TradingAnimationGraphics2End - TradingAnimationGraphics2 + ld a, BANK(TradingAnimationGraphics2) + call FarCopyData + ld hl, vBGMap0 + ld bc, $800 + ld a, " " + call FillMemory + call ClearSprites + ld a, $ff + ld [wUpdateSpritesEnabled], a + ld hl, wd730 + set 6, [hl] ; turn on instant text printing + ld a, [wOnSGB] + and a + ld a, $e4 ; non-SGB OBP0 + jr z, .next + ld a, $f0 ; SGB OBP0 +.next + ldh [rOBP0], a + call UpdateGBCPal_OBP0 + call EnableLCD + xor a + ldh [hAutoBGTransferEnabled], a + ld a, [wTradedPlayerMonSpecies] + ld [wd11e], a + call GetMonName + ld hl, wcd6d + ld de, wcf4b + ld bc, NAME_LENGTH + call CopyData + ld a, [wTradedEnemyMonSpecies] + ld [wd11e], a + jp GetMonName + +Trade_LoadMonPartySpriteGfx: + ld a, %11010000 + ldh [rOBP1], a + call UpdateGBCPal_OBP1 + farjp LoadMonPartySpriteGfx + +Trade_SwapNames: + ld hl, wPlayerName + ld de, wBuffer + ld bc, NAME_LENGTH + call CopyData + ld hl, wLinkEnemyTrainerName + ld de, wPlayerName + ld bc, NAME_LENGTH + call CopyData + ld hl, wBuffer + ld de, wLinkEnemyTrainerName + ld bc, NAME_LENGTH + jp CopyData + +Trade_Cleanup: + xor a + call LoadGBPal + ld hl, wd730 + res 6, [hl] ; turn off instant text printing + ret + +Trade_ShowPlayerMon: + ld a, %10101011 + ldh [rLCDC], a + ld a, $50 + ldh [hWY], a + ld a, $86 + ldh [rWX], a + ldh [hSCX], a + xor a + ldh [hAutoBGTransferEnabled], a + hlcoord 4, 0 + lb bc, 6, 10 + call TextBoxBorder + call Trade_PrintPlayerMonInfoText + ld b, HIGH(vBGMap0) + call CopyScreenTileBufferToVRAM + call ClearScreen + ld a, [wTradedPlayerMonSpecies] + call Trade_LoadMonSprite + ld a, $7e +.slideScreenLoop + push af + call DelayFrame + pop af + ldh [rWX], a + ldh [hSCX], a + dec a + dec a + and a + jr nz, .slideScreenLoop + call Trade_Delay80 + ld a, TRADE_BALL_POOF_ANIM + call Trade_ShowAnimation + ld a, TRADE_BALL_DROP_ANIM + call Trade_ShowAnimation ; clears mon pic + ld a, [wTradedPlayerMonSpecies] + call PlayCry + xor a + ldh [hAutoBGTransferEnabled], a + ret + +Trade_DrawOpenEndOfLinkCable: + call Trade_ClearTileMap + ld b, HIGH(vBGMap0) + call CopyScreenTileBufferToVRAM + ld b, SET_PAL_GENERIC + call RunPaletteCommand + +; This function call is pointless. It just copies blank tiles to VRAM that was +; already filled with blank tiles. + ld hl, vBGMap1 + $8c + call Trade_CopyCableTilesOffScreen + + ld a, $a0 + ldh [hSCX], a + call DelayFrame + ld a, %10001011 + ldh [rLCDC], a + hlcoord 6, 2 + ld b, TILEMAP_LINK_CABLE + call CopyTileIDsFromList_ZeroBaseTileID + call Trade_CopyTileMapToVRAM + ld a, SFX_HEAL_HP + call PlaySound + ld c, 20 +.loop + ldh a, [hSCX] + add 4 + ldh [hSCX], a + dec c + jr nz, .loop + ret + +Trade_AnimateBallEnteringLinkCable: + ld a, TRADE_BALL_SHAKE_ANIM + call Trade_ShowAnimation + ld c, 10 + call DelayFrames + ld a, %11100100 + ldh [rOBP0], a + call UpdateGBCPal_OBP0 + xor a + ld [wLinkCableAnimBulgeToggle], a + lb bc, $20, $60 +.moveBallInsideLinkCableLoop + push bc + xor a + ld de, Trade_BallInsideLinkCableOAM + call WriteOAMBlock + ld a, [wLinkCableAnimBulgeToggle] + xor $1 + ld [wLinkCableAnimBulgeToggle], a + add $7e + ld hl, wOAMBuffer + $02 + ld de, 4 + ld c, e +.cycleLinkCableBulgeTile + ld [hl], a + add hl, de + dec c + jr nz, .cycleLinkCableBulgeTile + call Delay3 + pop bc + ld a, c + add $4 + ld c, a + cp $a0 + jr nc, .ballSpriteReachedEdgeOfScreen + ld a, SFX_TINK + call PlaySound + jr .moveBallInsideLinkCableLoop +.ballSpriteReachedEdgeOfScreen + call ClearSprites + ld a, $1 + ldh [hAutoBGTransferEnabled], a + call ClearScreen + ld b, $98 + call CopyScreenTileBufferToVRAM + call Delay3 + xor a + ldh [hAutoBGTransferEnabled], a + ret + +Trade_BallInsideLinkCableOAM: + dbsprite 0, 15, 0, 6, $7e, OAM_HFLIP + dbsprite 8, 15, 0, 6, $7e, OAM_HFLIP | OAM_VFLIP + +Trade_ShowEnemyMon: + ld a, TRADE_BALL_TILT_ANIM + call Trade_ShowAnimation + call Trade_ShowClearedWindow + hlcoord 4, 10 + lb bc, 6, 10 + call TextBoxBorder + call Trade_PrintEnemyMonInfoText + call Trade_CopyTileMapToVRAM + ld a, $1 + ldh [hAutoBGTransferEnabled], a + ld a, [wTradedEnemyMonSpecies] + call Trade_LoadMonSprite + ld a, TRADE_BALL_POOF_ANIM + call Trade_ShowAnimation + ld a, $1 + ldh [hAutoBGTransferEnabled], a + ld a, [wTradedEnemyMonSpecies] + call PlayCry + call Trade_Delay100 + hlcoord 4, 10 + lb bc, 8, 12 + call ClearScreenArea + jp PrintTradeTakeCareText + +Trade_AnimLeftToRight: +; Animates the mon moving from the left GB to the right one. + call Trade_InitGameboyTransferGfx + ld a, $1 + ld [wTradedMonMovingRight], a + ld a, %11100100 + ldh [rOBP0], a + call UpdateGBCPal_OBP0 + ld a, $54 + ld [wBaseCoordX], a + ld a, $1c + ld [wBaseCoordY], a + ld a, [wLeftGBMonSpecies] + ld [wMonPartySpriteSpecies], a + call Trade_WriteCircledMonOAM + call Trade_DrawLeftGameboy + call Trade_CopyTileMapToVRAM + call Trade_DrawCableAcrossScreen + ld hl, vBGMap1 + $8c + call Trade_CopyCableTilesOffScreen + ld b, $6 + call Trade_AnimMonMoveHorizontal + ld a, $1 + ldh [hAutoBGTransferEnabled], a + call Trade_DrawCableAcrossScreen + ld b, $4 + call Trade_AnimMonMoveHorizontal + call Trade_DrawRightGameboy + ld b, $6 + call Trade_AnimMonMoveHorizontal + xor a + ldh [hAutoBGTransferEnabled], a + call Trade_AnimMonMoveVertical + jp ClearSprites + +Trade_AnimRightToLeft: +; Animates the mon moving from the right GB to the left one. + call Trade_InitGameboyTransferGfx + xor a + ld [wTradedMonMovingRight], a + ld a, $64 + ld [wBaseCoordX], a + ld a, $44 + ld [wBaseCoordY], a + ld a, [wRightGBMonSpecies] + ld [wMonPartySpriteSpecies], a + call Trade_WriteCircledMonOAM + call Trade_DrawRightGameboy + call Trade_CopyTileMapToVRAM + call Trade_DrawCableAcrossScreen + ld hl, vBGMap1 + $94 + call Trade_CopyCableTilesOffScreen + call Trade_AnimMonMoveVertical + ld b, $6 + call Trade_AnimMonMoveHorizontal + ld a, $1 + ldh [hAutoBGTransferEnabled], a + call Trade_DrawCableAcrossScreen + ld b, $4 + call Trade_AnimMonMoveHorizontal + call Trade_DrawLeftGameboy + ld b, $6 + call Trade_AnimMonMoveHorizontal + xor a + ldh [hAutoBGTransferEnabled], a + jp ClearSprites + +Trade_InitGameboyTransferGfx: +; Initialises the graphics for showing a mon moving between gameboys. + ld a, $1 + ldh [hAutoBGTransferEnabled], a + call ClearScreen + ld b, SET_PAL_GENERIC + call RunPaletteCommand + xor a + ldh [hAutoBGTransferEnabled], a + call Trade_LoadMonPartySpriteGfx + call DelayFrame + ld a, %10101011 + ldh [rLCDC], a + xor a + ldh [hSCX], a + ld a, $90 + ldh [hWY], a + ret + +Trade_DrawLeftGameboy: + call Trade_ClearTileMap + +; draw link cable + hlcoord 11, 4 + ld a, $5d + ld [hli], a + ld a, $5e + ld c, 8 +.loop + ld [hli], a + dec c + jr nz, .loop + +; draw gameboy pic + hlcoord 5, 3 + ld b, TILEMAP_GAME_BOY + call CopyTileIDsFromList_ZeroBaseTileID + +; draw text box with player name below gameboy pic + hlcoord 4, 12 + lb bc, 2, 7 + call TextBoxBorder + hlcoord 5, 14 + ld de, wPlayerName + call PlaceString + + jp DelayFrame + +Trade_DrawRightGameboy: + call Trade_ClearTileMap + +; draw horizontal segment of link cable + hlcoord 0, 4 + ld a, $5e + ld c, $e +.loop + ld [hli], a + dec c + jr nz, .loop + +; draw vertical segment of link cable + ld a, $5f + ld [hl], a + ld de, SCREEN_WIDTH + add hl, de + ld a, $61 + ld [hl], a + add hl, de + ld [hl], a + add hl, de + ld [hl], a + add hl, de + ld [hl], a + add hl, de + ld a, $60 + ld [hld], a + ld a, $5d + ld [hl], a + +; draw gameboy pic + hlcoord 7, 8 + ld b, TILEMAP_GAME_BOY + call CopyTileIDsFromList_ZeroBaseTileID + +; draw text box with enemy name above link cable + hlcoord 6, 0 + lb bc, 2, 7 + call TextBoxBorder + hlcoord 7, 2 + ld de, wLinkEnemyTrainerName + call PlaceString + + jp DelayFrame + +Trade_DrawCableAcrossScreen: +; Draws the link cable across the screen. + call Trade_ClearTileMap + hlcoord 0, 4 + ld a, $5e + ld c, SCREEN_WIDTH +.loop + ld [hli], a + dec c + jr nz, .loop + ret + +Trade_CopyCableTilesOffScreen: +; This is used to copy the link cable tiles off screen so that the cable +; continues when the screen is scrolled. + push hl + hlcoord 0, 4 + call CopyToRedrawRowOrColumnSrcTiles + pop hl + ld a, h + ldh [hRedrawRowOrColumnDest + 1], a + ld a, l + ldh [hRedrawRowOrColumnDest], a + ld a, REDRAW_ROW + ldh [hRedrawRowOrColumnMode], a + ld c, 10 + jp DelayFrames + +Trade_AnimMonMoveHorizontal: +; Animates the mon going through the link cable horizontally over a distance of +; b 16-pixel units. + ld a, [wTradedMonMovingRight] + ld e, a + ld d, $8 +.scrollLoop + ld a, e + dec a + jr z, .movingRight +; moving left + ldh a, [hSCX] + sub $2 + jr .next +.movingRight + ldh a, [hSCX] + add $2 +.next + ldh [hSCX], a + call DelayFrame + dec d + jr nz, .scrollLoop + call Trade_AnimCircledMon + dec b + jr nz, Trade_AnimMonMoveHorizontal + ret + +Trade_AnimCircledMon: +; Cycles between the two animation frames of the mon party sprite, cycles +; between a circle and an oval around the mon sprite, and makes the cable flash. + push de + push bc + push hl + ldh a, [rBGP] + xor $3c ; make link cable flash + ldh [rBGP], a + call UpdateGBCPal_BGP + ld hl, wOAMBuffer + $02 + ld de, $4 + ld c, $14 +.loop + ld a, [hl] + xor ICONOFFSET + ld [hl], a + add hl, de + dec c + jr nz, .loop + pop hl + pop bc + pop de + ret + +Trade_WriteCircledMonOAM: + farcall WriteMonPartySpriteOAMBySpecies + call Trade_WriteCircleOAM + +Trade_AddOffsetsToOAMCoords: + ld hl, wOAMBuffer + ld c, $14 ; SCREEN_WIDTH? +.loop + ld a, [wBaseCoordY] + add [hl] + ld [hli], a + ld a, [wBaseCoordX] + add [hl] + ld [hli], a + inc hl + inc hl + dec c + jr nz, .loop + ret + +Trade_AnimMonMoveVertical: +; Animates the mon going through the link cable vertically as well as +; horizontally for a bit. The last bit of horizontal movement (when moving +; right) or the first bit of horizontal movement (when moving left) are done +; here instead of Trade_AnimMonMoveHorizontal because this function moves the +; sprite itself rather than scrolling the screen around the sprite. Moving the +; sprite itself is necessary because the vertical segment of the link cable is +; to the right of the screen position that the mon sprite has when +; Trade_AnimMonMoveHorizontal is executing. + ld a, [wTradedMonMovingRight] + and a + jr z, .movingLeft +; moving right + lb bc, 4, 0 ; move right + call .doAnim + lb bc, 0, 10 ; move down + jr .doAnim +.movingLeft + lb bc, 0, -10 ; move up + call .doAnim + lb bc, -4, 0 ; move left +.doAnim + ld a, b + ld [wBaseCoordX], a + ld a, c + ld [wBaseCoordY], a + ld d, $4 +.loop + call Trade_AddOffsetsToOAMCoords + call Trade_AnimCircledMon + ld c, 8 + call DelayFrames + dec d + jr nz, .loop + ret + +Trade_WriteCircleOAM: +; Writes the OAM blocks for the circle around the traded mon as it passes +; the link cable. + ld hl, Trade_CircleOAMPointers + ld c, $4 + xor a +.loop + push bc + ld e, [hl] + inc hl + ld d, [hl] + inc hl + ld c, [hl] + inc hl + ld b, [hl] + inc hl + push hl + inc a + push af + call WriteOAMBlock + pop af + pop hl + pop bc + dec c + jr nz, .loop + ret + +trade_circle_oam: MACRO + dw \1 + db \2, \3 +ENDM + +Trade_CircleOAMPointers: + ; oam pointer, upper-left x coord, upper-left y coord + trade_circle_oam Trade_CircleOAM0, $08, $08 + trade_circle_oam Trade_CircleOAM1, $18, $08 + trade_circle_oam Trade_CircleOAM2, $08, $18 + trade_circle_oam Trade_CircleOAM3, $18, $18 + +Trade_CircleOAM0: + dbsprite 2, 7, 0, 0, ICON_TRADEBUBBLE << 2 + 1, OAM_OBP1 + dbsprite 2, 7, 0, 2, ICON_TRADEBUBBLE << 2 + 3, OAM_OBP1 + +Trade_CircleOAM1: + dbsprite 6, 7, 0, 1, ICON_TRADEBUBBLE << 2 + 0, OAM_OBP1 | OAM_HFLIP + dbsprite 6, 7, 0, 3, ICON_TRADEBUBBLE << 2 + 2, OAM_OBP1 | OAM_HFLIP + +Trade_CircleOAM2: + dbsprite 10, 7, 0, 2, ICON_TRADEBUBBLE << 2 + 3, OAM_OBP1 | OAM_VFLIP + dbsprite 10, 7, 0, 0, ICON_TRADEBUBBLE << 2 + 1, OAM_OBP1 | OAM_VFLIP + +Trade_CircleOAM3: + dbsprite 14, 7, 0, 3, ICON_TRADEBUBBLE << 2 + 2, OAM_OBP1 | OAM_HFLIP | OAM_VFLIP + dbsprite 14, 7, 0, 1, ICON_TRADEBUBBLE << 2 + 0, OAM_OBP1 | OAM_HFLIP | OAM_VFLIP + +; a = species +Trade_LoadMonSprite: + ld [wcf91], a + ld [wd0b5], a + ld [wWholeScreenPaletteMonSpecies], a + ld b, SET_PAL_POKEMON_WHOLE_SCREEN + ld c, 0 + call RunPaletteCommand + ldh a, [hAutoBGTransferEnabled] + xor $1 + ldh [hAutoBGTransferEnabled], a + call GetMonHeader + hlcoord 7, 2 + call LoadFlippedFrontSpriteByMonIndex + ld c, 10 + jp DelayFrames + +Trade_ShowClearedWindow: +; clears the window and covers the BG entirely with the window + ld a, $1 + ldh [hAutoBGTransferEnabled], a + call ClearScreen + ld a, %11100011 + ldh [rLCDC], a + ld a, $7 + ldh [rWX], a + xor a + ldh [hWY], a + ld a, $90 + ldh [hSCX], a + ret + +Trade_SlideTextBoxOffScreen: +; Slides the window right until it's off screen. The window usually just has +; a text box at the bottom when this is called. However, when this is called +; after Trade_ShowEnemyMon in the external clock sequence, there is a mon pic +; above the text box and it is also scrolled off the screen. + ld c, 50 + call DelayFrames +.loop + call DelayFrame + ldh a, [rWX] + inc a + inc a + ldh [rWX], a + cp $a1 + jr nz, .loop + call Trade_ClearTileMap + ld c, 10 + call DelayFrames + ld a, $7 + ldh [rWX], a + ret + +PrintTradeWentToText: + ld hl, TradeWentToText + call PrintText + ld c, 200 + call DelayFrames + jp Trade_SlideTextBoxOffScreen + +TradeWentToText: + text_far _TradeWentToText + text_end + +PrintTradeForSendsText: + ld hl, TradeForText + call PrintText + call Trade_Delay80 + ld hl, TradeSendsText + call PrintText + jp Trade_Delay80 + +TradeForText: + text_far _TradeForText + text_end + +TradeSendsText: + text_far _TradeSendsText + text_end + +PrintTradeFarewellText: + ld hl, TradeWavesFarewellText + call PrintText + call Trade_Delay80 + ld hl, TradeTransferredText + call PrintText + call Trade_Delay80 + jp Trade_SlideTextBoxOffScreen + +TradeWavesFarewellText: + text_far _TradeWavesFarewellText + text_end + +TradeTransferredText: + text_far _TradeTransferredText + text_end + +PrintTradeTakeCareText: + ld hl, TradeTakeCareText + call PrintText + jp Trade_Delay80 + +TradeTakeCareText: + text_far _TradeTakeCareText + text_end + +PrintTradeWillTradeText: + ld hl, TradeWillTradeText + call PrintText + call Trade_Delay80 + ld hl, TradeforText + call PrintText + jp Trade_Delay80 + +TradeWillTradeText: + text_far _TradeWillTradeText + text_end + +TradeforText: + text_far _TradeforText + text_end + +Trade_ShowAnimation: + ld [wAnimationID], a + xor a + ld [wAnimationType], a + predef_jump MoveAnimation diff --git a/engine/movie/trade2.asm b/engine/movie/trade2.asm new file mode 100755 index 00000000..f0d91846 --- /dev/null +++ b/engine/movie/trade2.asm @@ -0,0 +1,49 @@ +Trade_PrintPlayerMonInfoText: + hlcoord 5, 0 + ld de, Trade_MonInfoText + call PlaceString + ld a, [wTradedPlayerMonSpecies] + ld [wd11e], a + predef IndexToPokedex + hlcoord 9, 0 + ld de, wd11e + lb bc, LEADING_ZEROES | 1, 3 + call PrintNumber + hlcoord 5, 2 + ld de, wcf4b + call PlaceString + hlcoord 8, 4 + ld de, wTradedPlayerMonOT + call PlaceString + hlcoord 8, 6 + ld de, wTradedPlayerMonOTID + lb bc, LEADING_ZEROES | 2, 5 + jp PrintNumber + +Trade_PrintEnemyMonInfoText: + hlcoord 5, 10 + ld de, Trade_MonInfoText + call PlaceString + ld a, [wTradedEnemyMonSpecies] + ld [wd11e], a + predef IndexToPokedex + hlcoord 9, 10 + ld de, wd11e + lb bc, LEADING_ZEROES | 1, 3 + call PrintNumber + hlcoord 5, 12 + ld de, wcd6d + call PlaceString + hlcoord 8, 14 + ld de, wTradedEnemyMonOT + call PlaceString + hlcoord 8, 16 + ld de, wTradedEnemyMonOTID + lb bc, LEADING_ZEROES | 2, 5 + jp PrintNumber + +Trade_MonInfoText: + db "──№" + next "" + next "OT/" + next "@" diff --git a/engine/multiply_divide.asm b/engine/multiply_divide.asm deleted file mode 100755 index d664c9d4..00000000 --- a/engine/multiply_divide.asm +++ /dev/null @@ -1,144 +0,0 @@ -_Multiply: - ld a, $8 - ld b, a - xor a - ld [H_PRODUCT], a - ld [H_MULTIPLYBUFFER], a - ld [H_MULTIPLYBUFFER+1], a - ld [H_MULTIPLYBUFFER+2], a - ld [H_MULTIPLYBUFFER+3], a -.multiplyLoop - ld a, [H_MULTIPLIER] - srl a - ld [H_MULTIPLIER], a - jr nc, .smallMultiplier ; less than $80 -; code to possibly multiply the multiplicand by 2 and divide the multiplier by 2? - ld a, [H_MULTIPLYBUFFER+3] - ld c, a - ld a, [H_MULTIPLICAND+2] - add c - ld [H_MULTIPLYBUFFER+3], a - ld a, [H_MULTIPLYBUFFER+2] - ld c, a - ld a, [H_MULTIPLICAND+1] - adc c - ld [H_MULTIPLYBUFFER+2], a - ld a, [H_MULTIPLYBUFFER+1] - ld c, a - ld a, [H_MULTIPLICAND] - adc c - ld [H_MULTIPLYBUFFER+1], a - ld a, [H_MULTIPLYBUFFER] - ld c, a - ld a, [H_PRODUCT] - adc c - ld [H_MULTIPLYBUFFER], a -.smallMultiplier - dec b - jr z, .done - ld a, [H_MULTIPLICAND+2] - sla a - ld [H_MULTIPLICAND+2], a - ld a, [H_MULTIPLICAND+1] - rl a - ld [H_MULTIPLICAND+1], a - ld a, [H_MULTIPLICAND] - rl a - ld [H_MULTIPLICAND], a - ld a, [H_PRODUCT] - rl a - ld [H_PRODUCT], a - jr .multiplyLoop -.done - ld a, [H_MULTIPLYBUFFER+3] - ld [H_PRODUCT+3], a - ld a, [H_MULTIPLYBUFFER+2] - ld [H_PRODUCT+2], a - ld a, [H_MULTIPLYBUFFER+1] - ld [H_PRODUCT+1], a - ld a, [H_MULTIPLYBUFFER] - ld [H_PRODUCT], a - ret - -_Divide: - xor a - ld [H_DIVIDEBUFFER], a - ld [H_DIVIDEBUFFER+1], a - ld [H_DIVIDEBUFFER+2], a - ld [H_DIVIDEBUFFER+3], a - ld [H_DIVIDEBUFFER+4], a - ld a, $9 - ld e, a -.asm_f6680 - ld a, [H_DIVIDEBUFFER] - ld c, a - ld a, [H_DIVIDEND+1] - sub c - ld d, a - ld a, [H_DIVISOR] - ld c, a - ld a, [H_DIVIDEND] - sbc c - jr c, .asm_f669b - ld [H_DIVIDEND], a - ld a, d - ld [H_DIVIDEND+1], a - ld a, [H_DIVIDEBUFFER+4] - inc a - ld [H_DIVIDEBUFFER+4], a - jr .asm_f6680 -.asm_f669b - ld a, b - cp $1 - jr z, .done - ld a, [H_DIVIDEBUFFER+4] - sla a - ld [H_DIVIDEBUFFER+4], a - ld a, [H_DIVIDEBUFFER+3] - rl a - ld [H_DIVIDEBUFFER+3], a - ld a, [H_DIVIDEBUFFER+2] - rl a - ld [H_DIVIDEBUFFER+2], a - ld a, [H_DIVIDEBUFFER+1] - rl a - ld [H_DIVIDEBUFFER+1], a - dec e - jr nz, .asm_f66d1 - ld a, $8 - ld e, a - ld a, [H_DIVIDEBUFFER] - ld [H_DIVISOR], a - xor a - ld [H_DIVIDEBUFFER], a - ld a, [H_DIVIDEND+1] - ld [H_DIVIDEND], a - ld a, [H_DIVIDEND+2] - ld [H_DIVIDEND+1], a - ld a, [H_DIVIDEND+3] - ld [H_DIVIDEND+2], a -.asm_f66d1 - ld a, e - cp $1 - jr nz, .asm_f66d7 - dec b -.asm_f66d7 - ld a, [H_DIVISOR] - srl a - ld [H_DIVISOR], a - ld a, [H_DIVIDEBUFFER] - rr a - ld [H_DIVIDEBUFFER], a - jr .asm_f6680 -.done - ld a, [H_DIVIDEND+1] - ld [H_REMAINDER], a - ld a, [H_DIVIDEBUFFER+4] - ld [H_QUOTIENT+3], a - ld a, [H_DIVIDEBUFFER+3] - ld [H_QUOTIENT+2], a - ld a, [H_DIVIDEBUFFER+2] - ld [H_QUOTIENT+1], a - ld a, [H_DIVIDEBUFFER+1] - ld [H_QUOTIENT], a - ret diff --git a/engine/oak_speech.asm b/engine/oak_speech.asm deleted file mode 100755 index 8a537579..00000000 --- a/engine/oak_speech.asm +++ /dev/null @@ -1,244 +0,0 @@ -SetDefaultNames: - ld a, [wLetterPrintingDelayFlags] - push af - ld a, [wOptions] - push af - ld a, [wd732] - push af - ld a, [wPrinterSettings] - push af - ld hl, wPlayerName - ld bc, wBoxDataEnd - wPlayerName - xor a - call FillMemory - ld hl, wSpriteStateData1 - ld bc, $200 - xor a - call FillMemory - xor a - ld [wSurfingMinigameHiScore], a - ld [wSurfingMinigameHiScore + 1], a - ld [wSurfingMinigameHiScore + 2], a - pop af - ld [wPrinterSettings], a - pop af - ld [wd732], a - pop af - ld [wOptions], a - pop af - ld [wLetterPrintingDelayFlags], a - ld a, [wOptionsInitialized] - and a - call z, InitOptions - ld hl, NintenText - ld de, wPlayerName - ld bc, NAME_LENGTH - call CopyData - ld hl, SonyText - ld de, wRivalName - ld bc, NAME_LENGTH - call CopyData ; rip optimizations - ret - -OakSpeech: - call StopAllMusic ; stop music - ld a, BANK(Music_Routes2) - ld c, a - ld a, MUSIC_ROUTES2 - call PlayMusic - call ClearScreen - call LoadTextBoxTilePatterns - call SetDefaultNames - predef InitPlayerData2 - ld hl, wNumBoxItems - ld a, POTION - ld [wcf91], a - ld a, 1 - ld [wItemQuantity], a - call AddItemToInventory ; give one potion - ld a, [wDefaultMap] - ld [wDestinationMap], a - call SpecialWarpIn - xor a - ld [hTilesetType], a - ld a, [wd732] - bit 1, a ; possibly a debug mode bit - jp nz, .skipChoosingNames - ld de, ProfOakPic - lb bc, Bank(ProfOakPic), $00 - call IntroDisplayPicCenteredOrUpperRight - call FadeInIntroPic - ld hl, OakSpeechText1 - call PrintText - call GBFadeOutToWhite - call ClearScreen - ld a, PIKACHU - ld [wd0b5], a - ld [wcf91], a - call GetMonHeader - coord hl, 6, 4 - call LoadFlippedFrontSpriteByMonIndex - call MovePicLeft - ld hl, OakSpeechText2 - call PrintText - call GBFadeOutToWhite - call ClearScreen - ld de, RedPicFront - lb bc, Bank(RedPicFront), $00 - call IntroDisplayPicCenteredOrUpperRight - call MovePicLeft - ld hl, IntroducePlayerText - call PrintText - call ChoosePlayerName - call GBFadeOutToWhite - call ClearScreen - ld de, Rival1Pic - lb bc, Bank(Rival1Pic), $00 - call IntroDisplayPicCenteredOrUpperRight - call FadeInIntroPic - ld hl, IntroduceRivalText - call PrintText - call ChooseRivalName -.skipChoosingNames - call GBFadeOutToWhite - call ClearScreen - ld de, RedPicFront - lb bc, Bank(RedPicFront), $00 - call IntroDisplayPicCenteredOrUpperRight - call GBFadeInFromWhite - ld a, [wd72d] - and a - jr nz, .next - ld hl, OakSpeechText3 - call PrintText -.next - ld a, [H_LOADEDROMBANK] - push af - ld a, SFX_SHRINK - call PlaySound - pop af - call BankswitchCommon - ld c, 4 - call DelayFrames - ld hl, vSprites - ld de, RedSprite - ld b, BANK(RedSprite) - ld c, $0C - call CopyVideoData - ld de, ShrinkPic1 - lb bc, BANK(ShrinkPic1), $00 - call IntroDisplayPicCenteredOrUpperRight - ld c, 4 - call DelayFrames - ld de, ShrinkPic2 - lb bc, BANK(ShrinkPic2), $00 - call IntroDisplayPicCenteredOrUpperRight - call ResetPlayerSpriteData - ld a, [H_LOADEDROMBANK] - push af - ld a, BANK(Music_PalletTown) - ld [wAudioROMBank], a - ld [wAudioSavedROMBank], a - ld a, 10 - ld [wAudioFadeOutControl], a - call StopAllMusic ; stop music - pop af - call BankswitchCommon - ld c, 20 - call DelayFrames - coord hl, 6, 5 - lb bc, 7, 7 - call ClearScreenArea - call LoadTextBoxTilePatterns - ld a, 1 - ld [wUpdateSpritesEnabled], a - ld c, 50 - call DelayFrames - call GBFadeOutToWhite - call ClearScreen ; rip more tail-end optimizations - ret - -OakSpeechText1: - TX_FAR _OakSpeechText1 - db "@" -OakSpeechText2: - TX_FAR _OakSpeechText2A - TX_CRY_NIDORINA - TX_FAR _OakSpeechText2B - db "@" -IntroducePlayerText: - TX_FAR _IntroducePlayerText - db "@" -IntroduceRivalText: - TX_FAR _IntroduceRivalText - db "@" -OakSpeechText3: - TX_FAR _OakSpeechText3 - db "@" - -FadeInIntroPic: - ld hl, IntroFadePalettes - ld b, 6 -.next - ld a, [hli] - ld [rBGP], a - call UpdateGBCPal_BGP - ld c, 10 - call DelayFrames - dec b - jr nz, .next - ret - -IntroFadePalettes: - db %01010100 - db %10101000 - db %11111100 - db %11111000 - db %11110100 - db %11100100 - -MovePicLeft: - ld a, 119 - ld [rWX], a - call DelayFrame - - ld a, %11100100 - ld [rBGP], a - call UpdateGBCPal_BGP -.next - call DelayFrame - ld a, [rWX] - sub 8 - cp $FF - ret z - ld [rWX], a - jr .next - -DisplayPicCenteredOrUpperRight: - call GetPredefRegisters -IntroDisplayPicCenteredOrUpperRight: -; b = bank -; de = address of compressed pic -; c: 0 = centred, non-zero = upper-right - push bc - ld a, b - call UncompressSpriteFromDE - ld a, $0 - call SwitchSRAMBankAndLatchClockData - ld hl, sSpriteBuffer1 - ld de, sSpriteBuffer0 - ld bc, $310 - call CopyData - call PrepareRTCDataAndDisableSRAM - ld de, vFrontPic - call InterlaceMergeSpriteBuffers - pop bc - ld a, c - and a - coord hl, 15, 1 - jr nz, .next - coord hl, 6, 4 -.next - xor a - ld [hStartTileID], a - predef_jump CopyUncompressedPicToTilemap diff --git a/engine/oak_speech2.asm b/engine/oak_speech2.asm deleted file mode 100755 index 80f1bafc..00000000 --- a/engine/oak_speech2.asm +++ /dev/null @@ -1,241 +0,0 @@ -ChoosePlayerName: - call OakSpeechSlidePicRight - ld de, DefaultNamesPlayer - call DisplayIntroNameTextBox - ld a, [wCurrentMenuItem] - and a - jr z, .customName - ld hl, DefaultNamesPlayerList - call GetDefaultName - ld de, wPlayerName - call OakSpeechSlidePicLeft - jr .done -.customName - ld hl, wPlayerName - xor a ; NAME_PLAYER_SCREEN - ld [wNamingScreenType], a - call DisplayNamingScreen - ld a, [wcf4b] - cp "@" - jr z, .customName - call ClearScreen - call Delay3 - ld de, RedPicFront - ld b, BANK(RedPicFront) - call IntroDisplayPicCenteredOrUpperRight -.done - ld hl, YourNameIsText - jp PrintText - -YourNameIsText: - TX_FAR _YourNameIsText - db "@" - -ChooseRivalName: - call OakSpeechSlidePicRight - ld de, DefaultNamesRival - call DisplayIntroNameTextBox - ld a, [wCurrentMenuItem] - and a - jr z, .customName - ld hl, DefaultNamesRivalList - call GetDefaultName - ld de, wRivalName - call OakSpeechSlidePicLeft - jr .done -.customName - ld hl, wRivalName - ld a, NAME_RIVAL_SCREEN - ld [wNamingScreenType], a - call DisplayNamingScreen - ld a, [wcf4b] - cp "@" - jr z, .customName - call ClearScreen - call Delay3 - ld de, Rival1Pic - ld b, $13 - call IntroDisplayPicCenteredOrUpperRight -.done - ld hl, HisNameIsText - jp PrintText - -HisNameIsText: - TX_FAR _HisNameIsText - db "@" - -OakSpeechSlidePicLeft: - push de - coord hl, 0, 0 - lb bc, 12, 11 - call ClearScreenArea ; clear the name list text box - ld c, 10 - call DelayFrames - pop de - ld hl, wcd6d - ld bc, NAME_LENGTH - call CopyData - call Delay3 - coord hl, 12, 4 - lb de, 6, 6 * SCREEN_WIDTH + 5 - ld a, $ff - jr OakSpeechSlidePicCommon - -OakSpeechSlidePicRight: - coord hl, 5, 4 - lb de, 6, 6 * SCREEN_WIDTH + 5 - xor a - -OakSpeechSlidePicCommon: - push hl - push de - push bc - ld [hSlideDirection], a - ld a, d - ld [hSlideAmount], a - ld a, e - ld [hSlidingRegionSize], a - ld c, a - ld a, [hSlideDirection] - and a - jr nz, .next -; If sliding right, point hl to the end of the pic's tiles. - ld d, 0 - add hl, de -.next - ld d, h - ld e, l -.loop - xor a - ld [H_AUTOBGTRANSFERENABLED], a - ld [H_AUTOBGTRANSFERPORTION], a - ld a, [hSlideDirection] - and a - jr nz, .slideLeft -; sliding right - ld a, [hli] - ld [hld], a - dec hl - jr .next2 -.slideLeft - ld a, [hld] - ld [hli], a - inc hl -.next2 - dec c - jr nz, .loop - ld a, [hSlideDirection] - and a - jr z, .next3 -; If sliding left, we need to zero the last tile in the pic (there is no need -; to take a corresponding action when sliding right because hl initially points -; to a 0 tile in that case). - dec hl - xor a - ld [hl], a -.next3 - ld a, 1 - ld [H_AUTOBGTRANSFERENABLED], a - call Delay3 - ld a, [hSlidingRegionSize] - ld c, a - ld h, d - ld l, e - ld a, [hSlideDirection] - and a - jr nz, .slideLeft2 - inc hl - jr .next4 -.slideLeft2 - dec hl -.next4 - ld d, h - ld e, l - ld a, [hSlideAmount] - dec a - ld [hSlideAmount], a - jr nz, .loop - pop bc - pop de - pop hl - ret - -DisplayIntroNameTextBox: - push de - coord hl, 0, 0 - lb bc, 10, 9 - call TextBoxBorder - coord hl, 3, 0 - ld de, .namestring - call PlaceString - pop de - coord hl, 2, 2 - call PlaceString - call UpdateSprites - xor a - ld [wCurrentMenuItem], a - ld [wLastMenuItem], a - inc a - ld [wTopMenuItemX], a - ld [wMenuWatchedKeys], a ; A_BUTTON - inc a - ld [wTopMenuItemY], a - inc a - ld [wMaxMenuItem], a - jp HandleMenuInput - -.namestring - db "NAME@" - -DefaultNamesPlayer: - db "NEW NAME" - next "YELLOW" - next "ASH" - next "JACK" - db "@" - -DefaultNamesRival: - db "NEW NAME" - next "BLUE" - next "GARY" - next "JOHN" - db "@" - -GetDefaultName: -; a = name index -; hl = name list - ld b, a - ld c, 0 -.loop - ld d, h - ld e, l -.innerLoop - ld a, [hli] - cp "@" - jr nz, .innerLoop - ld a, b - cp c - jr z, .foundName - inc c - jr .loop -.foundName - ld h, d - ld l, e - ld de, wcd6d - ld bc, $14 - jp CopyData - -DefaultNamesPlayerList: - db "NEW NAME@" - db "YELLOW@" - db "ASH@" - db "JACK@" - -DefaultNamesRivalList: - db "NEW NAME@" - db "BLUE@" - db "GARY@" - db "JOHN@" - -TextTerminator_6b20: - db "@" diff --git a/engine/oam_dma.asm b/engine/oam_dma.asm deleted file mode 100644 index 7326445e..00000000 --- a/engine/oam_dma.asm +++ /dev/null @@ -1,26 +0,0 @@ -WriteDMACodeToHRAM: -; Since no other memory is available during OAM DMA, -; DMARoutine is copied to HRAM and executed there. - ld c, $ff80 % $100 - ld b, DMARoutineEnd - DMARoutine - ld hl, DMARoutine -.copy - ld a, [hli] - ld [$ff00+c], a - inc c - dec b - jr nz, .copy - ret - -DMARoutine: - ; initiate DMA - ld a, wOAMBuffer / $100 - ld [rDMA], a - - ; wait for DMA to finish - ld a, $28 -.wait - dec a - jr nz, .wait - ret -DMARoutineEnd: diff --git a/engine/overworld/advance_player_sprite.asm b/engine/overworld/advance_player_sprite.asm index 6b4a0cbb..4ebdac84 100644 --- a/engine/overworld/advance_player_sprite.asm +++ b/engine/overworld/advance_player_sprite.asm @@ -1,241 +1,244 @@ _AdvancePlayerSprite:: - ld a,[wSpriteStateData1 + 3] ; delta Y - ld b,a - ld a,[wSpriteStateData1 + 5] ; delta X - ld c,a - ld hl,wWalkCounter ; walking animation counter + ld a, [wSpritePlayerStateData1YStepVector] + ld b, a + ld a, [wSpritePlayerStateData1XStepVector] + ld c, a + ld hl, wWalkCounter ; walking animation counter dec [hl] - jr nz,.afterUpdateMapCoords + jr nz, .afterUpdateMapCoords ; if it's the end of the animation, update the player's map coordinates ld hl, wPikachuOverworldStateFlags res 5, [hl] - ld a,[wYCoord] + ld a, [wYCoord] add b - ld [wYCoord],a - ld a,[wXCoord] + ld [wYCoord], a + ld a, [wXCoord] add c - ld [wXCoord],a + ld [wXCoord], a .afterUpdateMapCoords - ld a,[wWalkCounter] ; walking animation counter - cp a,$07 - jp nz,.scrollBackgroundAndSprites + ld a, [wWalkCounter] ; walking animation counter + cp $07 + jp nz, .scrollBackgroundAndSprites ; if this is the first iteration of the animation - ld a,c - cp a,$01 - jr nz,.checkIfMovingWest + ld a, c + cp $01 + jr nz, .checkIfMovingWest ; moving east - ld a,[wMapViewVRAMPointer] - ld e,a + ld a, [wMapViewVRAMPointer] + ld e, a and $e0 - ld d,a - ld a,e + ld d, a + ld a, e add $02 and $1f or d - ld [wMapViewVRAMPointer],a + ld [wMapViewVRAMPointer], a jr .adjustXCoordWithinBlock .checkIfMovingWest - cp a,$ff - jr nz,.checkIfMovingSouth + cp $ff + jr nz, .checkIfMovingSouth ; moving west - ld a,[wMapViewVRAMPointer] - ld e,a - and a,$e0 - ld d,a - ld a,e + ld a, [wMapViewVRAMPointer] + ld e, a + and $e0 + ld d, a + ld a, e sub $02 and $1f or d - ld [wMapViewVRAMPointer],a + ld [wMapViewVRAMPointer], a jr .adjustXCoordWithinBlock .checkIfMovingSouth - ld a,b - cp a,$01 - jr nz,.checkIfMovingNorth + ld a, b + cp $01 + jr nz, .checkIfMovingNorth ; moving south - ld a,[wMapViewVRAMPointer] + ld a, [wMapViewVRAMPointer] add $40 - ld [wMapViewVRAMPointer],a - jr nc,.adjustXCoordWithinBlock - ld a,[wMapViewVRAMPointer + 1] + ld [wMapViewVRAMPointer], a + jr nc, .adjustXCoordWithinBlock + ld a, [wMapViewVRAMPointer + 1] inc a and $03 or $98 - ld [wMapViewVRAMPointer + 1],a + ld [wMapViewVRAMPointer + 1], a jr .adjustXCoordWithinBlock .checkIfMovingNorth - cp a,$ff - jr nz,.adjustXCoordWithinBlock + cp $ff + jr nz, .adjustXCoordWithinBlock ; moving north - ld a,[wMapViewVRAMPointer] + ld a, [wMapViewVRAMPointer] sub $40 - ld [wMapViewVRAMPointer],a - jr nc,.adjustXCoordWithinBlock - ld a,[wMapViewVRAMPointer + 1] + ld [wMapViewVRAMPointer], a + jr nc, .adjustXCoordWithinBlock + ld a, [wMapViewVRAMPointer + 1] dec a and $03 or $98 - ld [wMapViewVRAMPointer + 1],a + ld [wMapViewVRAMPointer + 1], a .adjustXCoordWithinBlock - ld a,c + ld a, c and a - jr z,.pointlessJump ; mistake? + jr z, .pointlessJump ; mistake? .pointlessJump - ld hl,wXBlockCoord - ld a,[hl] + ld hl, wXBlockCoord + ld a, [hl] add c - ld [hl],a + ld [hl], a cp $02 - jr nz,.checkForMoveToWestBlock + jr nz, .checkForMoveToWestBlock ; moved into the tile block to the east xor a - ld [hl],a - ld hl,wXOffsetSinceLastSpecialWarp + ld [hl], a + ld hl, wXOffsetSinceLastSpecialWarp inc [hl] - ld de,wCurrentTileBlockMapViewPointer + ld de, wCurrentTileBlockMapViewPointer call MoveTileBlockMapPointerEast jr .updateMapView .checkForMoveToWestBlock - cp a,$ff - jr nz,.adjustYCoordWithinBlock + cp $ff + jr nz, .adjustYCoordWithinBlock ; moved into the tile block to the west - ld a,$1 - ld [hl],a - ld hl,wXOffsetSinceLastSpecialWarp + ld a, $01 + ld [hl], a + ld hl, wXOffsetSinceLastSpecialWarp dec [hl] - ld de,wCurrentTileBlockMapViewPointer + ld de, wCurrentTileBlockMapViewPointer call MoveTileBlockMapPointerWest jr .updateMapView .adjustYCoordWithinBlock - ld hl,wYBlockCoord - ld a,[hl] + ld hl, wYBlockCoord + ld a, [hl] add b - ld [hl],a - cp $2 - jr nz,.checkForMoveToNorthBlock + ld [hl], a + cp $02 + jr nz, .checkForMoveToNorthBlock ; moved into the tile block to the south xor a - ld [hl],a - ld hl,wYOffsetSinceLastSpecialWarp + ld [hl], a + ld hl, wYOffsetSinceLastSpecialWarp inc [hl] - ld de,wCurrentTileBlockMapViewPointer - ld a,[wCurMapWidth] + ld de, wCurrentTileBlockMapViewPointer + ld a, [wCurMapWidth] call MoveTileBlockMapPointerSouth jr .updateMapView .checkForMoveToNorthBlock - cp a,$ff - jr nz,.updateMapView + cp $ff + jr nz, .updateMapView ; moved into the tile block to the north - ld a,$1 - ld [hl],a - ld hl,wYOffsetSinceLastSpecialWarp + ld a, $01 + ld [hl], a + ld hl, wYOffsetSinceLastSpecialWarp dec [hl] - ld de,wCurrentTileBlockMapViewPointer - ld a,[wCurMapWidth] + ld de, wCurrentTileBlockMapViewPointer + ld a, [wCurMapWidth] call MoveTileBlockMapPointerNorth .updateMapView call LoadCurrentMapView - ld a,[wSpriteStateData1 + 3] ; delta Y - cp $1 - jr nz,.checkIfMovingNorth2 + ld a, [wSpritePlayerStateData1YStepVector] + cp $01 + jr nz, .checkIfMovingNorth2 ; if moving south call ScheduleSouthRowRedraw jr .scrollBackgroundAndSprites .checkIfMovingNorth2 cp $ff - jr nz,.checkIfMovingEast2 + jr nz, .checkIfMovingEast2 ; if moving north call ScheduleNorthRowRedraw jr .scrollBackgroundAndSprites .checkIfMovingEast2 - ld a,[wSpriteStateData1 + 5] ; delta X - cp $1 - jr nz,.checkIfMovingWest2 + ld a, [wSpritePlayerStateData1XStepVector] + cp $01 + jr nz, .checkIfMovingWest2 ; if moving east call ScheduleEastColumnRedraw jr .scrollBackgroundAndSprites .checkIfMovingWest2 cp $ff - jr nz,.scrollBackgroundAndSprites + jr nz, .scrollBackgroundAndSprites ; if moving west call ScheduleWestColumnRedraw .scrollBackgroundAndSprites - ld a,[wSpriteStateData1 + 3] ; delta Y + ld a, [wSpritePlayerStateData1YStepVector] add a - ld b,a - ld a,[wSpriteStateData1 + 5] ; delta X + ld b, a + ld a, [wSpritePlayerStateData1XStepVector] add a - ld c,a + ld c, a ; shift all the sprites in the direction opposite of the player's motion ; so that the player appears to move relative to them - ld hl,wSpriteStateData1 + $14 - ld e,15 + ld hl, wSprite01StateData1YPixels + ld e, 15 .spriteShiftLoop - ld a,[hl] + ld a, [hl] sub b - ld [hli],a + ld [hli], a inc l - ld a,[hl] + ld a, [hl] sub c - ld [hl],a - ld a,$0e + ld [hl], a + ld a, $0e add l - ld l,a + ld l, a dec e - jr nz,.spriteShiftLoop + jr nz, .spriteShiftLoop .done - ld a,[hSCY] + ldh a, [hSCY] add b - ld [hSCY],a ; update background scroll Y - ld a,[hSCX] + ldh [hSCY], a ; update background scroll Y + ldh a, [hSCX] add c - ld [hSCX],a ; update background scroll X + ldh [hSCX], a ; update background scroll X ret +; the following four functions are used to move the pointer to the upper left +; corner of the tile block map in the direction of motion + MoveTileBlockMapPointerEast:: - ld a,[de] - add $1 - ld [de],a + ld a, [de] + add $01 + ld [de], a ret nc inc de - ld a,[de] + ld a, [de] inc a - ld [de],a + ld [de], a ret MoveTileBlockMapPointerWest:: - ld a,[de] - sub $1 - ld [de],a + ld a, [de] + sub $01 + ld [de], a ret nc inc de - ld a,[de] + ld a, [de] dec a - ld [de],a + ld [de], a ret MoveTileBlockMapPointerSouth:: - add $6 - ld b,a - ld a,[de] + add MAP_BORDER * 2 + ld b, a + ld a, [de] add b - ld [de],a + ld [de], a ret nc inc de - ld a,[de] + ld a, [de] inc a - ld [de],a + ld [de], a ret MoveTileBlockMapPointerNorth:: - add $6 - ld b,a - ld a,[de] + add MAP_BORDER * 2 + ld b, a + ld a, [de] sub b - ld [de],a + ld [de], a ret nc inc de - ld a,[de] + ld a, [de] dec a - ld [de],a + ld [de], a ret diff --git a/engine/overworld/auto_movement.asm b/engine/overworld/auto_movement.asm new file mode 100755 index 00000000..a68da55f --- /dev/null +++ b/engine/overworld/auto_movement.asm @@ -0,0 +1,270 @@ +PlayerStepOutFromDoor:: + ld hl, wd730 + res 1, [hl] + call IsPlayerStandingOnDoorTile + jr nc, .notStandingOnDoor + ld a, $fc + ld [wJoyIgnore], a + ld hl, wd736 + set 1, [hl] + ld a, $1 + ld [wSimulatedJoypadStatesIndex], a + ld a, D_DOWN + ld [wSimulatedJoypadStatesEnd], a + xor a + ld [wSpritePlayerStateData1ImageIndex], a + call StartSimulatingJoypadStates + ret +.notStandingOnDoor + xor a + ld [wWastedByteCD3A], a + ld [wSimulatedJoypadStatesIndex], a + ld [wSimulatedJoypadStatesEnd], a + ld hl, wd736 + res 0, [hl] + res 1, [hl] + ld hl, wd730 + res 7, [hl] + ret + +_EndNPCMovementScript:: + ld hl, wd730 + res 7, [hl] + ld hl, wd72e + res 7, [hl] + ld hl, wd736 + res 0, [hl] + res 1, [hl] + xor a + ld [wNPCMovementScriptSpriteOffset], a + ld [wNPCMovementScriptFunctionNum], a + ld [wNPCMovementScriptPointerTableNum], a + ld [wWastedByteCD3A], a + ld [wSimulatedJoypadStatesIndex], a + ld [wSimulatedJoypadStatesEnd], a + ret + +PalletMovementScriptPointerTable:: + dw PalletMovementScript_OakMoveLeft + dw PalletMovementScript_PlayerMoveLeft + dw PalletMovementScript_WaitAndWalkToLab + dw PalletMovementScript_WalkToLab + dw PalletMovementScript_Done + +PalletMovementScript_OakMoveLeft: + ld a, [wXCoord] + sub $a + ld [wNumStepsToTake], a + jr z, .playerOnLeftTile +; The player is on the right tile of the northern path out of Pallet Town and +; Prof. Oak is below. +; Make Prof. Oak step to the left. + ld b, 0 + ld c, a + ld hl, wNPCMovementDirections2 + ld a, NPC_MOVEMENT_LEFT + call FillMemory + ld [hl], $ff + ld a, [wSpriteIndex] + ldh [hSpriteIndex], a + ld de, wNPCMovementDirections2 + call MoveSprite + ld a, $1 + ld [wNPCMovementScriptFunctionNum], a + jr .done +; The player is on the left tile of the northern path out of Pallet Town and +; Prof. Oak is below. +; Prof. Oak is already where he needs to be. +.playerOnLeftTile + ld a, $3 + ld [wNPCMovementScriptFunctionNum], a +.done + ld a, BANK(Music_MuseumGuy) + ld c, a + ld a, MUSIC_MUSEUM_GUY + call PlayMusic + ld hl, wFlags_D733 + set 1, [hl] + ld a, $fc + ld [wJoyIgnore], a + ret + +PalletMovementScript_PlayerMoveLeft: + ld a, [wd730] + bit 0, a ; is an NPC being moved by a script? + ret nz ; return if Oak is still moving + ld a, [wNumStepsToTake] + ld [wSimulatedJoypadStatesIndex], a + ldh [hNPCMovementDirections2Index], a + predef ConvertNPCMovementDirectionsToJoypadMasks + call StartSimulatingJoypadStates + ld a, $2 + ld [wNPCMovementScriptFunctionNum], a + ret + +PalletMovementScript_WaitAndWalkToLab: + ld a, [wSimulatedJoypadStatesIndex] + and a ; is the player done moving left yet? + ret nz + +PalletMovementScript_WalkToLab: + xor a + ld [wOverrideSimulatedJoypadStatesMask], a + ld a, [wSpriteIndex] + swap a + ld [wNPCMovementScriptSpriteOffset], a + xor a + ld [wSpritePlayerStateData2MovementByte1], a + ld hl, wSimulatedJoypadStatesEnd + ld de, RLEList_PlayerWalkToLab + call DecodeRLEList + dec a + ld [wSimulatedJoypadStatesIndex], a + ld hl, wNPCMovementDirections2 + ld de, RLEList_ProfOakWalkToLab + call DecodeRLEList + ld hl, wd72e + res 7, [hl] + ld hl, wd730 + set 7, [hl] + ld a, $4 + ld [wNPCMovementScriptFunctionNum], a + ret + + +RLEList_ProfOakWalkToLab: + db NPC_MOVEMENT_DOWN, 6 ; differs from red + db NPC_MOVEMENT_LEFT, 1 + db NPC_MOVEMENT_DOWN, 5 + db NPC_MOVEMENT_RIGHT, 3 + db NPC_MOVEMENT_UP, 1 + db NPC_CHANGE_FACING, 1 + db -1 ; end + +RLEList_PlayerWalkToLab: + db D_UP, 2 + db D_RIGHT, 3 + db D_DOWN, 5 + db D_LEFT, 1 + db D_DOWN, 7 ; differs from red + db -1 ; end + +PalletMovementScript_Done: + ld a, [wSimulatedJoypadStatesIndex] + and a + ret nz + ld a, HS_PALLET_TOWN_OAK + ld [wMissableObjectIndex], a + predef HideObject + ld hl, wd730 + res 7, [hl] + ld hl, wd72e + res 7, [hl] + jp EndNPCMovementScript + +PewterMuseumGuyMovementScriptPointerTable:: + dw PewterMovementScript_WalkToMuseum + dw PewterMovementScript_Done + +PewterMovementScript_WalkToMuseum: + ld a, BANK(Music_MuseumGuy) + ld c, a + ld a, MUSIC_MUSEUM_GUY + call PlayMusic + ld a, [wSpriteIndex] + swap a + ld [wNPCMovementScriptSpriteOffset], a + call StartSimulatingJoypadStates + ld hl, wSimulatedJoypadStatesEnd + ld de, RLEList_PewterMuseumPlayer + call DecodeRLEList + dec a + ld [wSimulatedJoypadStatesIndex], a + xor a + ld [wWhichPewterGuy], a + call PewterGuys + ld hl, wNPCMovementDirections2 + ld de, RLEList_PewterMuseumGuy + call DecodeRLEList + ld hl, wd72e + res 7, [hl] + ld a, $1 + ld [wNPCMovementScriptFunctionNum], a + ret + +RLEList_PewterMuseumPlayer: + db NO_INPUT, 1 + db D_UP, 3 + db D_LEFT, 13 + db D_UP, 6 + db -1 ; end + +RLEList_PewterMuseumGuy: + db NPC_MOVEMENT_UP, 6 + db NPC_MOVEMENT_LEFT, 13 + db NPC_MOVEMENT_UP, 3 + db NPC_MOVEMENT_LEFT, 1 + db -1 ; end + +PewterMovementScript_Done: + ld a, [wSimulatedJoypadStatesIndex] + and a + ret nz + ld hl, wd730 + res 7, [hl] + ld hl, wd72e + res 7, [hl] + jp EndNPCMovementScript + +PewterGymGuyMovementScriptPointerTable:: + dw PewterMovementScript_WalkToGym + dw PewterMovementScript_Done + +PewterMovementScript_WalkToGym: + ld a, BANK(Music_MuseumGuy) + ld c, a + ld a, MUSIC_MUSEUM_GUY + call PlayMusic + ld a, [wSpriteIndex] + swap a + ld [wNPCMovementScriptSpriteOffset], a + xor a + ld [wSpritePlayerStateData2MovementByte1], a + ld hl, wSimulatedJoypadStatesEnd + ld de, RLEList_PewterGymPlayer + call DecodeRLEList + dec a + ld [wSimulatedJoypadStatesIndex], a + ld a, 1 + ld [wWhichPewterGuy], a + call PewterGuys + ld hl, wNPCMovementDirections2 + ld de, RLEList_PewterGymGuy + call DecodeRLEList + ld hl, wd72e + res 7, [hl] + ld hl, wd730 + set 7, [hl] + ld a, $1 + ld [wNPCMovementScriptFunctionNum], a + ret + +RLEList_PewterGymPlayer: + db NO_INPUT, 1 + db D_RIGHT, 2 + db D_DOWN, 5 + db D_LEFT, 11 + db D_UP, 5 + db D_LEFT, 15 + db -1 ; end + +RLEList_PewterGymGuy: + db NPC_MOVEMENT_DOWN, 2 + db NPC_MOVEMENT_LEFT, 15 + db NPC_MOVEMENT_UP, 5 + db NPC_MOVEMENT_LEFT, 11 + db NPC_MOVEMENT_DOWN, 5 + db NPC_MOVEMENT_RIGHT, 3 + db -1 ; end + +INCLUDE "engine/events/pewter_guys.asm" diff --git a/engine/overworld/cable_club_npc.asm b/engine/overworld/cable_club_npc.asm deleted file mode 100755 index 12ce64a4..00000000 --- a/engine/overworld/cable_club_npc.asm +++ /dev/null @@ -1,208 +0,0 @@ -CableClubNPC: - ld hl, CableClubNPCWelcomeText - call PrintText - call CheckPikachuFollowingPlayer - jr nz, .asm_7048 - CheckEvent EVENT_GOT_POKEDEX - jp nz, .receivedPokedex -; if the player hasn't received the pokedex -.asm_7048 - ld c, 60 - call DelayFrames - ld hl, CableClubNPCMakingPreparationsText - call PrintText - jp .didNotConnect -.receivedPokedex - ld a, $1 - ld [wMenuJoypadPollCount], a - ld a, 90 - ld [wLinkTimeoutCounter], a -.establishConnectionLoop - ld a, [hSerialConnectionStatus] - cp USING_INTERNAL_CLOCK - jr z, .establishedConnection - cp USING_EXTERNAL_CLOCK - jr z, .establishedConnection - ld a, CONNECTION_NOT_ESTABLISHED - ld [hSerialConnectionStatus], a - ld a, ESTABLISH_CONNECTION_WITH_EXTERNAL_CLOCK - ld [rSB], a - xor a - ld [hSerialReceiveData], a - ld a, START_TRANSFER_EXTERNAL_CLOCK - ld [rSC], a - ld a, [wLinkTimeoutCounter] - dec a - ld [wLinkTimeoutCounter], a - jr z, .failedToEstablishConnection - ld a, ESTABLISH_CONNECTION_WITH_INTERNAL_CLOCK - ld [rSB], a - ld a, START_TRANSFER_INTERNAL_CLOCK - ld [rSC], a - call DelayFrame - jr .establishConnectionLoop -.establishedConnection - call Serial_SendZeroByte - call DelayFrame - call Serial_SendZeroByte - ld c, 50 - call DelayFrames - ld hl, CableClubNPCPleaseApplyHereHaveToSaveText - call PrintText - xor a - ld [wMenuJoypadPollCount], a - call YesNoChoice - ld a, $1 - ld [wMenuJoypadPollCount], a - ld a, [wCurrentMenuItem] - and a - jr nz, .choseNo - callab SaveSAVtoSRAM - call WaitForSoundToFinish - ld a, SFX_SAVE - call PlaySoundWaitForCurrent - ld hl, CableClubNPCPleaseWaitText - call PrintText - ld hl, wUnknownSerialCounter - ld a, $3 - ld [hli], a - xor a - ld [hl], a - ld [hSerialReceivedNewData], a - ld [wSerialExchangeNybbleSendData], a - call Serial_SyncAndExchangeNybble - ld hl, wUnknownSerialCounter - ld a, [hli] - inc a - jr nz, .connected - ld a, [hl] - inc a - jr nz, .connected - ld b, 10 -.syncLoop - call DelayFrame - call Serial_SendZeroByte - dec b - jr nz, .syncLoop - call CloseLinkConnection - ld hl, CableClubNPCLinkClosedBecauseOfInactivityText - call PrintText - jr .didNotConnect -.failedToEstablishConnection - ld hl, CableClubNPCAreaReservedFor2FriendsLinkedByCableText - call PrintText - jr .didNotConnect -.choseNo - call CloseLinkConnection - ld hl, CableClubNPCPleaseComeAgainText - call PrintText -.didNotConnect - xor a - ld hl, wUnknownSerialCounter - ld [hli], a - ld [hl], a - ld hl, wd72e - res 6, [hl] - xor a - ld [wMenuJoypadPollCount], a - ret -.connected - xor a - ld [hld], a - ld [hl], a - ld a, [wLetterPrintingDelayFlags] - push af - callab LinkMenu - pop af - ld [wLetterPrintingDelayFlags], a - ret - -; seems to be similar of Serial_SyncAndExchangeNybble -Serial_SyncAndExchangeNybbleDouble: - ld a, $ff - ld [wSerialExchangeNybbleReceiveData], a -.loop - call Serial_ExchangeNybble - call DelayFrame - push hl - ld hl, wUnknownSerialCounter + 1 - dec [hl] - jr nz, .next - dec hl - dec [hl] - jr nz, .next - pop hl - jr .setUnknownSerialCounterToFFFF -.next - pop hl - ld a, [wSerialExchangeNybbleReceiveData] - inc a - jr z, .loop - call DelayFrame - ld a, $ff - ld [wSerialExchangeNybbleReceiveData], a - call Serial_ExchangeNybble - ld a, [wSerialExchangeNybbleReceiveData] - inc a - jr z, .loop - ld b, 10 -.syncLoop1 - call DelayFrame - call Serial_ExchangeNybble - dec b - jr nz, .syncLoop1 - ld b, 10 -.syncLoop2 - call DelayFrame - call Serial_SendZeroByte - dec b - jr nz, .syncLoop2 - ld a, [wSerialExchangeNybbleReceiveData] - ld [wSerialSyncAndExchangeNybbleReceiveData], a - ret -.setUnknownSerialCounterToFFFF - ld a, $ff - ld [wUnknownSerialCounter], a - ld [wUnknownSerialCounter + 1], a - ret - -CableClubNPCAreaReservedFor2FriendsLinkedByCableText: - TX_FAR _CableClubNPCAreaReservedFor2FriendsLinkedByCableText - db "@" - -CableClubNPCWelcomeText: - TX_FAR _CableClubNPCWelcomeText - db "@" - -CableClubNPCPleaseApplyHereHaveToSaveText: - TX_FAR _CableClubNPCPleaseApplyHereHaveToSaveText - db "@" - -CableClubNPCPleaseWaitText: - TX_FAR _CableClubNPCPleaseWaitText - TX_DELAY - db "@" - -CableClubNPCLinkClosedBecauseOfInactivityText: - TX_FAR _CableClubNPCLinkClosedBecauseOfInactivityText - db "@" - -CableClubNPCPleaseComeAgainText: - TX_FAR _CableClubNPCPleaseComeAgainText - db "@" - -CableClubNPCMakingPreparationsText: - TX_FAR _CableClubNPCMakingPreparationsText - db "@" - -CloseLinkConnection: - call Delay3 - ld a, CONNECTION_NOT_ESTABLISHED - ld [hSerialConnectionStatus], a - ld a, ESTABLISH_CONNECTION_WITH_EXTERNAL_CLOCK - ld [rSB], a - xor a - ld [hSerialReceiveData], a - ld a, START_TRANSFER_EXTERNAL_CLOCK - ld [rSC], a - ret diff --git a/engine/overworld/card_key.asm b/engine/overworld/card_key.asm deleted file mode 100755 index a4452b4a..00000000 --- a/engine/overworld/card_key.asm +++ /dev/null @@ -1,113 +0,0 @@ -PrintCardKeyText: - ld hl, SilphCoMapList - ld a, [wCurMap] - ld b, a -.silphCoMapListLoop - ld a, [hli] - cp $ff - ret z - cp b - jr nz, .silphCoMapListLoop -; does not check for tile in front of player. This might be buggy - ;predef GetTileAndCoordsInFrontOfPlayer - ld a, [wTileInFrontOfPlayer] - cp $18 - jr z, .cardKeyDoorInFrontOfPlayer - cp $24 - jr z, .cardKeyDoorInFrontOfPlayer - ld b, a - ld a, [wCurMap] - cp SILPH_CO_11F - ret nz - ld a, b - cp $5e - ret nz -.cardKeyDoorInFrontOfPlayer - ld b, CARD_KEY - call IsItemInBag - jr z, .noCardKey - xor a - ld [wPlayerMovingDirection], a - tx_pre_id CardKeySuccessText - ld [hSpriteIndexOrTextID], a - call PrintPredefTextID - call GetCoordsInFrontOfPlayer - srl d - ld a, d - ld b, a - ld [wCardKeyDoorY], a - srl e - ld a, e - ld c, a - ld [wCardKeyDoorX], a - ld a, [wCurMap] - cp SILPH_CO_11F - jr nz, .notSilphCo11F - ld a, $3 - jr .replaceCardKeyDoorTileBlock -.notSilphCo11F - ld a, $e -.replaceCardKeyDoorTileBlock - ld [wNewTileBlockID], a - predef ReplaceTileBlock - ld hl, wCurrentMapScriptFlags - set 5, [hl] - ld a, SFX_GO_INSIDE - jp PlaySound -.noCardKey - tx_pre_id CardKeyFailText - ld [hSpriteIndexOrTextID], a - jp PrintPredefTextID - -SilphCoMapList: - db SILPH_CO_2F - db SILPH_CO_3F - db SILPH_CO_4F - db SILPH_CO_5F - db SILPH_CO_6F - db SILPH_CO_7F - db SILPH_CO_8F - db SILPH_CO_9F - db SILPH_CO_10F - db SILPH_CO_11F - db $FF - -CardKeySuccessText: - TX_FAR _CardKeySuccessText1 - TX_SFX_ITEM_1 - TX_FAR _CardKeySuccessText2 - db "@" - -CardKeyFailText: - TX_FAR _CardKeyFailText - db "@" - -; d = Y -; e = X -GetCoordsInFrontOfPlayer: - ld a, [wYCoord] - ld d, a - ld a, [wXCoord] - ld e, a - ld a, [wSpritePlayerStateData1FacingDirection] ; player's sprite facing direction - and a - jr nz, .notFacingDown -; facing down - inc d - ret -.notFacingDown - cp SPRITE_FACING_UP - jr nz, .notFacingUp -; facing up - dec d - ret -.notFacingUp - cp SPRITE_FACING_LEFT - jr nz, .notFacingLeft -; facing left - dec e - ret -.notFacingLeft -; facing right - inc e - ret diff --git a/engine/overworld/cinnabar_lab.asm b/engine/overworld/cinnabar_lab.asm deleted file mode 100755 index 13313746..00000000 --- a/engine/overworld/cinnabar_lab.asm +++ /dev/null @@ -1,123 +0,0 @@ -GiveFossilToCinnabarLab: - ld hl, wd730 - set 6, [hl] - xor a - ld [wCurrentMenuItem], a - ld a, A_BUTTON | B_BUTTON - ld [wMenuWatchedKeys], a - ld a, [wFilteredBagItemsCount] - dec a - ld [wMaxMenuItem], a - ld a, 2 - ld [wTopMenuItemY], a - ld a, 1 - ld [wTopMenuItemX], a - ld a, [wFilteredBagItemsCount] - dec a - ld bc, 2 - ld hl, 3 - call AddNTimes - dec l - ld b, l - ld c, $d - coord hl, 0, 0 - call TextBoxBorder - call UpdateSprites - call PrintFossilsInBag - ld hl, wd730 - res 6, [hl] - call HandleMenuInput - bit 1, a ; pressed B? - jr nz, .cancelledGivingFossil - ld hl, wFilteredBagItems - ld a, [wCurrentMenuItem] - ld d, 0 - ld e, a - add hl, de - ld a, [hl] - ld [$ffdb], a - cp DOME_FOSSIL - jr z, .choseDomeFossil - cp HELIX_FOSSIL - jr z, .choseHelixFossil - ld b, AERODACTYL - jr .fossilSelected -.choseHelixFossil - ld b, OMANYTE - jr .fossilSelected -.choseDomeFossil - ld b, KABUTO -.fossilSelected - ld [wFossilItem], a - ld a, b - ld [wFossilMon], a - call LoadFossilItemAndMonName - ld hl, LabFossil_610ae - call PrintText - call YesNoChoice - ld a, [wCurrentMenuItem] - and a - jr nz, .cancelledGivingFossil - ld hl, LabFossil_610b3 - call PrintText - ld a, [wFossilItem] - ld [hItemToRemoveID], a - callba RemoveItemByID - ld hl, LabFossil_610b8 - call PrintText - SetEvents EVENT_GAVE_FOSSIL_TO_LAB, EVENT_LAB_STILL_REVIVING_FOSSIL - ret -.cancelledGivingFossil - ld hl, LabFossil_610bd - call PrintText - ret - -LabFossil_610ae: - TX_FAR _Lab4Text_610ae - db "@" - -LabFossil_610b3: - TX_FAR _Lab4Text_610b3 - db "@" - -LabFossil_610b8: - TX_FAR _Lab4Text_610b8 - db "@" - -LabFossil_610bd: - TX_FAR _Lab4Text_610bd - db "@" - -PrintFossilsInBag: -; Prints each fossil in the player's bag on a separate line in the menu. - ld hl, wFilteredBagItems - xor a - ld [hItemCounter], a -.loop - ld a, [hli] - cp $ff - ret z - push hl - ld [wd11e], a - call GetItemName - coord hl, 2, 2 - ld a, [hItemCounter] - ld bc, SCREEN_WIDTH * 2 - call AddNTimes - ld de, wcd6d - call PlaceString - ld hl, hItemCounter - inc [hl] - pop hl - jr .loop - -; loads the names of the fossil item and the resulting mon -LoadFossilItemAndMonName: - ld a, [wFossilMon] - ld [wd11e], a - call GetMonName - call CopyStringToCF4B - ld a, [wFossilItem] - ld [wd11e], a - call GetItemName - ret diff --git a/engine/overworld/clear_variables.asm b/engine/overworld/clear_variables.asm index 9a59cc7c..bbb7c986 100644 --- a/engine/overworld/clear_variables.asm +++ b/engine/overworld/clear_variables.asm @@ -1,14 +1,14 @@ -ClearVariablesOnEnterMap: - ld a, SCREEN_HEIGHT_PIXELS - ld [hWY], a - ld [rWY], a +ClearVariablesOnEnterMap:: + ld a, SCREEN_HEIGHT_PX + ldh [hWY], a + ldh [rWY], a xor a - ld [H_AUTOBGTRANSFERENABLED], a + ldh [hAutoBGTransferEnabled], a ld [wStepCounter], a ld [wLoneAttackNo], a - ld [hJoyPressed], a - ld [hJoyReleased], a - ld [hJoyHeld], a + ldh [hJoyPressed], a + ldh [hJoyReleased], a + ldh [hJoyHeld], a ld [wActionResultOrTookBattleTurn], a ld [wUnusedD5A3], a ld hl, wCardKeyDoorY diff --git a/engine/overworld/cut.asm b/engine/overworld/cut.asm index bc7d092d..e36b8d88 100755 --- a/engine/overworld/cut.asm +++ b/engine/overworld/cut.asm @@ -22,8 +22,8 @@ UsedCut: jp PrintText .NothingToCutText - TX_FAR _NothingToCutText - db "@" + text_far _NothingToCutText + text_end .canCut ld [wCutTile], a @@ -37,15 +37,15 @@ UsedCut: call GBPalWhiteOutWithDelay3 call ClearSprites call RestoreScreenTilesAndReloadTilePatterns - ld a, SCREEN_HEIGHT_PIXELS - ld [hWY], a + ld a, SCREEN_HEIGHT_PX + ldh [hWY], a call Delay3 call LoadGBPal call LoadCurrentMapView call SaveScreenTilesToBuffer2 call Delay3 xor a - ld [hWY], a + ldh [hWY], a ld hl, UsedCutText call PrintText call LoadScreenTilesFromBuffer2 @@ -57,47 +57,47 @@ UsedCut: ld de, CutTreeBlockSwaps call ReplaceTreeTileBlock call RedrawMapView - callba AnimCut + farcall AnimCut ld a, $1 ld [wUpdateSpritesEnabled], a ld a, SFX_CUT call PlaySound ld a, $90 - ld [hWY], a + ldh [hWY], a call UpdateSprites jp RedrawMapView UsedCutText: - TX_FAR _UsedCutText - db "@" + text_far _UsedCutText + text_end InitCutAnimOAM: xor a ld [wWhichAnimationOffsets], a ld a, %11100100 - ld [rOBP1], a + ldh [rOBP1], a call UpdateGBCPal_OBP1 ld a, [wCutTile] cp $52 jr z, .grass ; tree - ld de, Overworld_GFX + $2d0 ; cuttable tree sprite top row - ld hl, vChars1 + $7c0 - lb bc, BANK(Overworld_GFX), $02 + ld de, Overworld_GFX tile $2d ; cuttable tree sprite top row + ld hl, vChars1 tile $7c + lb bc, BANK(Overworld_GFX), 2 call CopyVideoData - ld de, Overworld_GFX + $3d0 ; cuttable tree sprite bottom row - ld hl, vChars1 + $7e0 - lb bc, BANK(Overworld_GFX), $02 + ld de, Overworld_GFX tile $3d ; cuttable tree sprite bottom row + ld hl, vChars1 tile $7e + lb bc, BANK(Overworld_GFX), 2 call CopyVideoData jr WriteCutOrBoulderDustAnimationOAMBlock .grass - ld hl, vChars1 + $7c0 + ld hl, vChars1 tile $7c call LoadCutGrassAnimationTilePattern - ld hl, vChars1 + $7d0 + ld hl, vChars1 tile $7d call LoadCutGrassAnimationTilePattern - ld hl, vChars1 + $7e0 + ld hl, vChars1 tile $7e call LoadCutGrassAnimationTilePattern - ld hl, vChars1 + $7f0 + ld hl, vChars1 tile $7f call LoadCutGrassAnimationTilePattern call WriteCutOrBoulderDustAnimationOAMBlock ld hl, wOAMBuffer + $93 @@ -113,8 +113,8 @@ InitCutAnimOAM: ret LoadCutGrassAnimationTilePattern: - ld de, AnimationTileset2 + $60 ; tile depicting a leaf - lb bc, BANK(AnimationTileset2), $01 + ld de, AnimationTileset2 tile 6 ; tile depicting a leaf + lb bc, BANK(AnimationTileset2), 1 jp CopyVideoData WriteCutOrBoulderDustAnimationOAMBlock: @@ -124,11 +124,11 @@ WriteCutOrBoulderDustAnimationOAMBlock: jp WriteOAMBlock CutOrBoulderDustAnimationTilesAndAttributes: - db $FC,$14,$FD,$14 - db $FE,$14,$FF,$14 + dbsprite 2, -1, 4, 4, $fd, OAM_OBP1 | %100 + dbsprite 2, -1, 4, 6, $ff, OAM_OBP1 | %100 GetCutOrBoulderDustAnimationOffsets: - ld hl, wSpriteStateData1 + 4 + ld hl, wSpritePlayerStateData1YPixels ld a, [hli] ; player's sprite screen Y position ld b, a inc hl @@ -188,7 +188,7 @@ ReplaceTreeTileBlock: ld h, [hl] ld l, a add hl, bc - ld a, [wSpritePlayerStateData1FacingDirection] ; player sprite's facing direction + ld a, [wSpritePlayerStateData1FacingDirection] and a jr z, .down cp SPRITE_FACING_UP @@ -249,16 +249,4 @@ ReplaceTreeTileBlock: ld [hl], a ret -CutTreeBlockSwaps: -; first byte = tileset block containing the cut tree -; second byte = corresponding tileset block after the cut animation happens - db $32, $6D - db $33, $6C - db $34, $6F - db $35, $4C - db $60, $6E - db $0B, $0A - db $3C, $35 - db $3F, $35 - db $3D, $36 - db $FF ; list terminator +INCLUDE "data/tilesets/cut_tree_blocks.asm" diff --git a/engine/overworld/cut2.asm b/engine/overworld/cut2.asm index 37490f95..1f691eef 100755 --- a/engine/overworld/cut2.asm +++ b/engine/overworld/cut2.asm @@ -15,9 +15,9 @@ AnimCut: ld [wCoordAdjustmentAmount], a ld c, 2 call AdjustOAMBlockXPos2 - ld a, [rOBP1] + ldh a, [rOBP1] xor $64 - ld [rOBP1], a + ldh [rOBP1], a call UpdateGBCPal_OBP1 call DelayFrame pop bc @@ -66,9 +66,9 @@ AnimCutGrass_UpdateOAMEntries: ld [wCoordAdjustmentAmount], a ld c, 1 call AdjustOAMBlockXPos2 - ld a, [rOBP1] + ldh a, [rOBP1] xor $64 - ld [rOBP1], a + ldh [rOBP1], a call UpdateGBCPal_OBP1 call DelayFrame pop bc diff --git a/engine/overworld/doors.asm b/engine/overworld/doors.asm index 8bde8600..d38818fa 100755 --- a/engine/overworld/doors.asm +++ b/engine/overworld/doors.asm @@ -11,7 +11,7 @@ IsPlayerStandingOnDoorTile: ld a, [hli] ld h, [hl] ld l, a - aCoord 8, 9 ; a = lower left background tile under player's sprite + lda_coord 8, 9 ; a = lower left background tile under player's sprite ld b, a .loop ld a, [hli] @@ -25,55 +25,4 @@ IsPlayerStandingOnDoorTile: and a ret -DoorTileIDPointers: - dbw OVERWORLD, OverworldDoorTileIDs - dbw FOREST, ForestDoorTileIDs - dbw MART, MartDoorTileIDs - dbw HOUSE, HouseDoorTileIDs - dbw FOREST_GATE, TilesetMuseumDoorTileIDs - dbw MUSEUM, TilesetMuseumDoorTileIDs - dbw GATE, TilesetMuseumDoorTileIDs - dbw SHIP, ShipDoorTileIDs - dbw LOBBY, LobbyDoorTileIDs - dbw MANSION, MansionDoorTileIDs - dbw LAB, LabDoorTileIDs - dbw FACILITY, FacilityDoorTileIDs - dbw PLATEAU, PlateauDoorTileIDs - dbw INTERIOR, InteriorDoorTileIDs - db $ff - -OverworldDoorTileIDs: - db $1B,$58,$00 - -ForestDoorTileIDs: - db $3a,$00 - -MartDoorTileIDs: - db $5e,$00 - -HouseDoorTileIDs: - db $54,$00 - -TilesetMuseumDoorTileIDs: - db $3b,$00 - -ShipDoorTileIDs: - db $1e,$00 - -LobbyDoorTileIDs: - db $1c,$38,$1a,$00 - -MansionDoorTileIDs: - db $1a,$1c,$53,$00 - -LabDoorTileIDs: - db $34,$00 - -FacilityDoorTileIDs: - db $43,$58,$1b,$00 - -PlateauDoorTileIDs: - db $3b,$1b,$00 - -InteriorDoorTileIDs: - db $04,$15,$00 +INCLUDE "data/tilesets/door_tile_ids.asm" diff --git a/engine/overworld/dungeon_warps.asm b/engine/overworld/dungeon_warps.asm index f47dfb01..7641c688 100644 --- a/engine/overworld/dungeon_warps.asm +++ b/engine/overworld/dungeon_warps.asm @@ -1,4 +1,4 @@ -IsPlayerOnDungeonWarp: +IsPlayerOnDungeonWarp:: xor a ld [wWhichDungeonWarp], a ld a, [wd72d] diff --git a/engine/overworld/dust_smoke.asm b/engine/overworld/dust_smoke.asm new file mode 100755 index 00000000..773def96 --- /dev/null +++ b/engine/overworld/dust_smoke.asm @@ -0,0 +1,95 @@ +AnimateBoulderDust: + ld a, $1 + ld [wWhichAnimationOffsets], a ; select the boulder dust offsets + ld a, [wUpdateSpritesEnabled] + push af + ld a, $ff + ld [wUpdateSpritesEnabled], a + ld a, %11100100 + ldh [rOBP1], a + call UpdateGBCPal_OBP1 + call LoadSmokeTileFourTimes + farcall WriteCutOrBoulderDustAnimationOAMBlock + ld c, 8 ; number of steps in animation +.loop + push bc + call GetMoveBoulderDustFunctionPointer + ld bc, .returnAddress + push bc + ld c, 4 + jp hl +.returnAddress + ldh a, [rOBP1] + xor %01100100 + ldh [rOBP1], a + call UpdateGBCPal_OBP1 + call Delay3 + pop bc + dec c + jr nz, .loop + pop af + ld [wUpdateSpritesEnabled], a + jp LoadPlayerSpriteGraphics + +GetMoveBoulderDustFunctionPointer: + ld a, [wSpritePlayerStateData1FacingDirection] + ld hl, MoveBoulderDustFunctionPointerTable + ld c, a + ld b, $0 + add hl, bc + ld a, [hli] + ld [wCoordAdjustmentAmount], a + ld a, [hli] + ld e, a + ld a, [hli] + ld h, [hl] + ld l, a + push hl + ld hl, wOAMBuffer + $90 + ld d, $0 + add hl, de + ld e, l + ld d, h + pop hl + ret + +MoveBoulderDustFunctionPointerTable: +; facing down + db $FF,$00 + dw AdjustOAMBlockYPos + +; facing up + db $01,$00 + dw AdjustOAMBlockYPos + +; facing left + db $01,$01 + dw AdjustOAMBlockXPos + +; facing right + db $FF,$01 + dw AdjustOAMBlockXPos + +LoadSmokeTileFourTimes:: + ld hl, vChars1 tile $7c + ld c, 4 +.loop + push bc + push hl + call LoadSmokeTile + pop hl + ld bc, 1 tiles + add hl, bc + pop bc + dec c + jr nz, .loop + ret + +LoadSmokeTile: + ld de, SSAnneSmokePuffTile + lb bc, BANK(SSAnneSmokePuffTile), (SSAnneSmokePuffTileEnd - SSAnneSmokePuffTile) / $10 + jp CopyVideoData + +SSAnneSmokePuffTile: + INCBIN "gfx/overworld/smoke.2bpp" +SSAnneSmokePuffTileEnd: diff --git a/engine/overworld/elevator.asm b/engine/overworld/elevator.asm index 47ec78f9..b873ffad 100755 --- a/engine/overworld/elevator.asm +++ b/engine/overworld/elevator.asm @@ -1,11 +1,11 @@ -ShakeElevator: +ShakeElevator:: ld de, -$20 call ShakeElevatorRedrawRow ld de, SCREEN_HEIGHT * $20 call ShakeElevatorRedrawRow call Delay3 call StopAllMusic - ld a, [hSCY] + ldh a, [hSCY] ld d, a ld e, $1 ld b, 100 @@ -14,7 +14,7 @@ ShakeElevator: xor $fe ld e, a add d - ld [hSCY], a + ldh [hSCY], a push bc ld c, BANK(SFX_Collision_1) ld a, SFX_COLLISION @@ -25,7 +25,7 @@ ShakeElevator: dec b jr nz, .shakeLoop ld a, d - ld [hSCY], a + ldh [hSCY], a call StopAllMusic ld c, BANK(SFX_Safari_Zone_PA) ld a, SFX_SAFARI_ZONE_PA @@ -54,7 +54,7 @@ ShakeElevatorRedrawRow: add hl, de ld a, h and $3 - or vBGMap0 / $100 + or HIGH(vBGMap0) ld d, a ld a, l pop hl diff --git a/engine/overworld/emotion_bubbles.asm b/engine/overworld/emotion_bubbles.asm index 3b02fd55..3ad714e9 100755 --- a/engine/overworld/emotion_bubbles.asm +++ b/engine/overworld/emotion_bubbles.asm @@ -11,8 +11,8 @@ EmotionBubble: add hl, bc ld e, l ld d, h - ld hl, vChars1 + $780 - lb bc, BANK(EmotionBubbles), $04 + ld hl, vChars1 tile $78 + lb bc, BANK(EmotionBubbles), 4 call CopyVideoData ld a, [wUpdateSpritesEnabled] push af @@ -41,7 +41,7 @@ EmotionBubble: jr nz, .loop ; get the screen coordinates of the sprite the bubble is to be displayed above - ld hl, wSpriteStateData1 + 4 + ld hl, wSpritePlayerStateData1YPixels ld a, [wEmotionBubbleSpriteIndex] swap a ld c, a @@ -67,8 +67,15 @@ EmotionBubble: EmotionBubblesOAM: - db $F8,$00,$F9,$00 - db $FA,$00,$FB,$00 + dbsprite 0, -1, 0, 0, $f9, 0 + dbsprite 0, -1, 0, 2, $fb, 0 EmotionBubbles: - INCBIN "gfx/emotion_bubbles.2bpp" +ShockEmote: INCBIN "gfx/emotes/shock.2bpp" +QuestionEmote: INCBIN "gfx/emotes/question.2bpp" +HappyEmote: INCBIN "gfx/emotes/happy.2bpp" +SkullEmote: INCBIN "gfx/emotes/skull.2bpp" +HeartEmote: INCBIN "gfx/emotes/heart.2bpp" +BoltEmote: INCBIN "gfx/emotes/bolt.2bpp" +ZzzEmote: INCBIN "gfx/emotes/zzz.2bpp" +FishEmote: INCBIN "gfx/emotes/fish.2bpp" diff --git a/engine/overworld/field_move_messages.asm b/engine/overworld/field_move_messages.asm index 1d111917..520ef8ad 100644 --- a/engine/overworld/field_move_messages.asm +++ b/engine/overworld/field_move_messages.asm @@ -7,16 +7,16 @@ PrintStrengthTxt: jp PrintText UsedStrengthText: - TX_FAR _UsedStrengthText - TX_ASM + text_far _UsedStrengthText + text_asm ld a, [wcf91] call PlayCry call Delay3 jp TextScriptEnd CanMoveBouldersText: - TX_FAR _CanMoveBouldersText - db "@" + text_far _CanMoveBouldersText + text_end IsSurfingAllowed: ; Returns whether surfing is allowed in bit 1 of wd728. @@ -32,7 +32,7 @@ IsSurfingAllowed: ret nz CheckBothEventsSet EVENT_SEAFOAM4_BOULDER1_DOWN_HOLE, EVENT_SEAFOAM4_BOULDER2_DOWN_HOLE ret z - ld hl, CoordsData_f5b64 + ld hl, CoordsData_cdf7 call ArePlayerCoordsInArray ret nc ld hl, wd728 @@ -45,13 +45,14 @@ IsSurfingAllowed: ld hl, CyclingIsFunText jp PrintText -CoordsData_f5b64: - db $0B,$07,$FF +CoordsData_cdf7: + dbmapcoord 7, 11 + db -1 ; end CurrentTooFastText: - TX_FAR _CurrentTooFastText - db "@" + text_far _CurrentTooFastText + text_end CyclingIsFunText: - TX_FAR _CyclingIsFunText - db "@" + text_far _CyclingIsFunText + text_end diff --git a/engine/overworld/healing_machine.asm b/engine/overworld/healing_machine.asm index e5ba004e..e5fba7e1 100755 --- a/engine/overworld/healing_machine.asm +++ b/engine/overworld/healing_machine.asm @@ -1,17 +1,17 @@ AnimateHealingMachine: ld de, PokeCenterFlashingMonitorAndHealBall - ld hl, vChars0 + $7c0 - lb bc, BANK(PokeCenterFlashingMonitorAndHealBall), $03 ; loads one too many tiles + ld hl, vChars0 tile $7c + lb bc, BANK(PokeCenterFlashingMonitorAndHealBall), 3 ; should be 2 call CopyVideoData ld hl, wUpdateSpritesEnabled ld a, [hl] push af ld [hl], $ff push hl - ld a, [rOBP1] + ldh a, [rOBP1] push af ld a, $e0 - ld [rOBP1], a + ldh [rOBP1], a call UpdateGBCPal_OBP1 ld hl, wOAMBuffer + $84 ld de, PokeCenterOAMData @@ -53,7 +53,7 @@ AnimateHealingMachine: ld c, 32 call DelayFrames pop af - ld [rOBP1], a + ldh [rOBP1], a call UpdateGBCPal_OBP1 pop hl pop af @@ -61,24 +61,26 @@ AnimateHealingMachine: jp UpdateSprites PokeCenterFlashingMonitorAndHealBall: - INCBIN "gfx/pokecenter_ball.2bpp" + INCBIN "gfx/overworld/heal_machine.2bpp" PokeCenterOAMData: - db $24,$34,$7C,$14 ; heal machine monitor - db $2B,$30,$7D,$14 ; pokeballs 1-6 - db $2B,$38,$7D,$34 - db $30,$30,$7D,$14 - db $30,$38,$7D,$34 - db $35,$30,$7D,$14 - db $35,$38,$7D,$34 + ; heal machine monitor + dbsprite 6, 4, 4, 4, $7c, OAM_OBP1 | %100 + ; poke balls 1-6 + dbsprite 6, 5, 0, 3, $7d, OAM_OBP1 | %100 + dbsprite 7, 5, 0, 3, $7d, OAM_OBP1 | OAM_HFLIP | %100 + dbsprite 6, 6, 0, 0, $7d, OAM_OBP1 | %100 + dbsprite 7, 6, 0, 0, $7d, OAM_OBP1 | OAM_HFLIP | %100 + dbsprite 6, 6, 0, 5, $7d, OAM_OBP1 | %100 + dbsprite 7, 6, 0, 5, $7d, OAM_OBP1 | OAM_HFLIP | %100 ; d = value to xor with palette FlashSprite8Times: ld b, 8 .loop - ld a, [rOBP1] + ldh a, [rOBP1] xor d - ld [rOBP1], a + ldh [rOBP1], a call UpdateGBCPal_OBP1 ld c, 10 call DelayFrames @@ -88,16 +90,9 @@ FlashSprite8Times: CopyHealingMachineOAM: ; copy one OAM entry and advance the pointers + REPT 4 ld a, [de] inc de ld [hli], a - ld a, [de] - inc de - ld [hli], a - ld a, [de] - inc de - ld [hli], a - ld a, [de] - inc de - ld [hli], a + ENDR ret diff --git a/engine/overworld/hidden_items.asm b/engine/overworld/hidden_items.asm deleted file mode 100755 index b64411c7..00000000 --- a/engine/overworld/hidden_items.asm +++ /dev/null @@ -1,172 +0,0 @@ -HiddenItems: - ld hl, HiddenItemCoords - call FindHiddenItemOrCoinsIndex - ld [wHiddenItemOrCoinsIndex], a - ld hl, wObtainedHiddenItemsFlags - ld a, [wHiddenItemOrCoinsIndex] - ld c, a - ld b, FLAG_TEST - predef FlagActionPredef - ld a, c - and a - jr nz, .itemAlreadyFound - call EnableAutoTextBoxDrawing - ld a, 1 - ld [wDoNotWaitForButtonPressAfterDisplayingText], a - ld a, [wHiddenObjectFunctionArgument] ; item ID - ld [wd11e], a - call GetItemName - tx_pre_jump FoundHiddenItemText - -.itemAlreadyFound - ld a, $ff - ld [hItemAlreadyFound], a - ret - -INCLUDE "data/hidden_item_coords.asm" - -FoundHiddenItemText: - TX_FAR _FoundHiddenItemText - TX_ASM - ld a, [wHiddenObjectFunctionArgument] ; item ID - ld b, a - ld c, 1 - call GiveItem - jr nc, .bagFull - ld hl, wObtainedHiddenItemsFlags - ld a, [wHiddenItemOrCoinsIndex] - ld c, a - ld b, FLAG_SET - predef FlagActionPredef - ld a, SFX_GET_ITEM_2 - call PlaySoundWaitForCurrent - call WaitForSoundToFinish - jp TextScriptEnd -.bagFull - call WaitForTextScrollButtonPress ; wait for button press - xor a - ld [wDoNotWaitForButtonPressAfterDisplayingText], a - ld hl, HiddenItemBagFullText - call PrintText - jp TextScriptEnd - -HiddenItemBagFullText: - TX_FAR _HiddenItemBagFullText - db "@" - -HiddenCoins: - ld b, COIN_CASE - predef GetQuantityOfItemInBag - ld a, b - and a - jr z, .doNotPickUpCoins - ld hl, HiddenCoinCoords - call FindHiddenItemOrCoinsIndex - ld [wHiddenItemOrCoinsIndex], a - ld hl, wObtainedHiddenCoinsFlags - ld a, [wHiddenItemOrCoinsIndex] - ld c, a - ld b, FLAG_TEST - predef FlagActionPredef - ld a, c - and a - jr nz, .doNotPickUpCoins - xor a - ld [hUnusedCoinsByte], a - ld [hCoins], a - ld [hCoins + 1], a - ld a, [wHiddenObjectFunctionArgument] - sub COIN - cp 10 - jr z, .bcd10 - cp 20 - jr z, .bcd20 - cp 40 - jr z, .bcd20 ; should be bcd40 - jr .bcd100 - -.doNotPickUpCoins - ld a, $ff - ld [hItemAlreadyFound], a - ret - -.bcd10 - ld a, $10 - ld [hCoins + 1], a - jr .bcdDone -.bcd20 - ld a, $20 - ld [hCoins + 1], a - jr .bcdDone -.bcd40 ; due to a typo, this is never used - ld a, $40 - ld [hCoins + 1], a - jr .bcdDone -.bcd100 - ld a, $1 - ld [hCoins], a -.bcdDone - ld de, wPlayerCoins + 1 - ld hl, hCoins + 1 - ld c, $2 - predef AddBCDPredef - ld hl, wObtainedHiddenCoinsFlags - ld a, [wHiddenItemOrCoinsIndex] - ld c, a - ld b, FLAG_SET - predef FlagActionPredef - call EnableAutoTextBoxDrawing - ld a, [wPlayerCoins] - cp $99 - jr nz, .roomInCoinCase - ld a, [wPlayerCoins + 1] - cp $99 - jr nz, .roomInCoinCase - tx_pre_id DroppedHiddenCoinsText - jr .done -.roomInCoinCase - tx_pre_id FoundHiddenCoinsText -.done - jp PrintPredefTextID - -INCLUDE "data/hidden_coins.asm" - -FoundHiddenCoinsText: - TX_FAR _FoundHiddenCoinsText - TX_SFX_ITEM_2 - db "@" - -DroppedHiddenCoinsText: - TX_FAR _FoundHiddenCoins2Text - TX_SFX_ITEM_2 - TX_FAR _DroppedHiddenCoinsText - db "@" - -FindHiddenItemOrCoinsIndex: - ld a, [wHiddenObjectY] - ld d, a - ld a, [wHiddenObjectX] - ld e, a - ld a, [wCurMap] - ld b, a - ld c, -1 -.loop - inc c - ld a, [hli] - cp $ff ; end of the list? - ret z ; if so, we're done here - cp b - jr nz, .next1 - ld a, [hli] - cp d - jr nz, .next2 - ld a, [hli] - cp e - jr nz, .loop - ld a, c - ret -.next1 - inc hl -.next2 - inc hl - jr .loop diff --git a/engine/overworld/hidden_objects.asm b/engine/overworld/hidden_objects.asm index 66815b60..84108986 100755 --- a/engine/overworld/hidden_objects.asm +++ b/engine/overworld/hidden_objects.asm @@ -1,11 +1,11 @@ ; if a hidden object was found, stores $00 in [hDidntFindAnyHiddenObject], else stores $ff -CheckForHiddenObject: +CheckForHiddenObject:: ld hl, hItemAlreadyFound xor a - ld [hli], a - ld [hli], a - ld [hli], a - ld [hl], a + ld [hli], a ; [hItemAlreadyFound] + ld [hli], a ; [hSavedMapTextPtr] + ld [hli], a ; [hSavedMapTextPtr + 1] + ld [hl], a ; [hDidntFindAnyHiddenObject] ld hl, HiddenObjectMaps ld de, 3 ld a, [wCurMap] @@ -32,7 +32,7 @@ CheckForHiddenObject: ld [wHiddenObjectX], a ld c, a call CheckIfCoordsInFrontOfPlayerMatch - ld a, [hCoordsInFrontOfPlayerMatch] + ldh a, [hCoordsInFrontOfPlayerMatch] and a jr z, .foundMatchingObject inc hl @@ -55,13 +55,13 @@ CheckForHiddenObject: ret .noMatch ld a, $ff - ld [hDidntFindAnyHiddenObject], a + ldh [hDidntFindAnyHiddenObject], a ret ; checks if the coordinates in front of the player's sprite match Y in b and X in c ; [hCoordsInFrontOfPlayerMatch] = $00 if they match, $ff if they don't match CheckIfCoordsInFrontOfPlayerMatch: - ld a, [wSpritePlayerStateData1FacingDirection] ; player's sprite facing direction + ld a, [wSpritePlayerStateData1FacingDirection] cp SPRITE_FACING_UP jr z, .facingUp cp SPRITE_FACING_LEFT @@ -101,7 +101,7 @@ CheckIfCoordsInFrontOfPlayerMatch: .didNotMatch ld a, $ff .done - ld [hCoordsInFrontOfPlayerMatch], a + ldh [hCoordsInFrontOfPlayerMatch], a ret -INCLUDE "data/hidden_objects.asm" +INCLUDE "data/events/hidden_objects.asm" diff --git a/engine/overworld/item.asm b/engine/overworld/item.asm deleted file mode 100644 index 9f19100a..00000000 --- a/engine/overworld/item.asm +++ /dev/null @@ -1,54 +0,0 @@ -PickUpItem: - call EnableAutoTextBoxDrawing - - ld a, [hSpriteIndexOrTextID] - ld b, a - ld hl, wMissableObjectList -.missableObjectsListLoop - ld a, [hli] - cp $ff - ret z - cp b - jr z, .isMissable - inc hl - jr .missableObjectsListLoop - -.isMissable - ld a, [hl] - ld [$ffdb], a - - ld hl, wMapSpriteExtraData - ld a, [hSpriteIndexOrTextID] - dec a - add a - ld d, 0 - ld e, a - add hl, de - ld a, [hl] - ld b, a ; item - ld c, 1 ; quantity - call GiveItem - jr nc, .BagFull - - ld a, [$ffdb] - ld [wMissableObjectIndex], a - predef HideObject - ld a, 1 - ld [wDoNotWaitForButtonPressAfterDisplayingText], a - ld hl, FoundItemText - jr .print - -.BagFull - ld hl, NoMoreRoomForItemText -.print - call PrintText - ret - -FoundItemText: - TX_FAR _FoundItemText - TX_SFX_ITEM_1 - db "@" - -NoMoreRoomForItemText: - TX_FAR _NoMoreRoomForItemText - db "@" diff --git a/engine/overworld/ledges.asm b/engine/overworld/ledges.asm index a44ddf8b..9925c528 100755 --- a/engine/overworld/ledges.asm +++ b/engine/overworld/ledges.asm @@ -1,4 +1,4 @@ -HandleLedges: +HandleLedges:: ld a, [wd736] bit 6, a ; already jumping down ledge ret nz @@ -8,7 +8,7 @@ HandleLedges: predef GetTileAndCoordsInFrontOfPlayer ld a, [wSpritePlayerStateData1FacingDirection] ld b, a - aCoord 8, 9 + lda_coord 8, 9 ld c, a ld a, [wTileInFrontOfPlayer] ld d, a @@ -36,7 +36,7 @@ HandleLedges: inc hl jr .loop .foundMatch - ld a, [hJoyHeld] + ldh a, [hJoyHeld] and e ret z ld a, $ff @@ -54,20 +54,10 @@ HandleLedges: call PlaySound ret - ; (player direction) (tile player standing on) (ledge tile) (input required) -LedgeTiles: - db SPRITE_FACING_DOWN, $2C,$37,D_DOWN - db SPRITE_FACING_DOWN, $39,$36,D_DOWN - db SPRITE_FACING_DOWN, $39,$37,D_DOWN - db SPRITE_FACING_LEFT, $2C,$27,D_LEFT - db SPRITE_FACING_LEFT, $39,$27,D_LEFT - db SPRITE_FACING_RIGHT,$2C,$0D,D_RIGHT - db SPRITE_FACING_RIGHT,$2C,$1D,D_RIGHT - db SPRITE_FACING_RIGHT,$39,$0D,D_RIGHT - db $FF +INCLUDE "data/tilesets/ledge_tiles.asm" LoadHoppingShadowOAM: - ld hl, vChars1 + $7f0 + ld hl, vChars1 tile $7f ld de, LedgeHoppingShadow lb bc, BANK(LedgeHoppingShadow), (LedgeHoppingShadowEnd - LedgeHoppingShadow) / $8 call CopyVideoDataDouble @@ -81,10 +71,10 @@ LoadHoppingShadowOAM: ret LedgeHoppingShadow: - INCBIN "gfx/ledge_hopping_shadow.1bpp" + INCBIN "gfx/overworld/shadow.1bpp" LedgeHoppingShadowEnd: LedgeHoppingShadowOAM: - db $58,$48,$FF,$00 - db $58,$50,$FF,$20 + dbsprite 9, 11, 0, 0, $ff, 0 + dbsprite 10, 11, 0, 0, $ff, OAM_HFLIP LedgeHoppingShadowOAMEnd: diff --git a/engine/overworld/map_sprite_functions1.asm b/engine/overworld/map_sprite_functions1.asm deleted file mode 100644 index 2ad923fb..00000000 --- a/engine/overworld/map_sprite_functions1.asm +++ /dev/null @@ -1,390 +0,0 @@ -_UpdateSprites: - ld h, wSpriteStateData1 / $100 - inc h - ld a, $e ; (wSpriteStateData2 + $0e) & $ff -.spriteLoop - ld l, a - sub $e - ld c, a - ld [H_CURRENTSPRITEOFFSET], a - ld a, [hl] - and a - jr z, .skipSprite ; tests $c2Xe - push hl - push de - push bc - call .updateCurrentSprite - pop bc - pop de - pop hl -.skipSprite - ld a, l - add $10 ; move to next sprite - cp $e ; test for overflow (back at $0e) - jr nz, .spriteLoop - ret -.updateCurrentSprite - ld a, [H_CURRENTSPRITEOFFSET] - and a - jp z, UpdatePlayerSprite - cp $f0 ; pikachu - jp z, SpawnPikachu - ld a, [hl] - -UpdateNonPlayerSprite: - dec a - swap a - ld [$ff93], a ; $10 * sprite# - ld a, [wNPCMovementScriptSpriteOffset] ; some sprite offset? - ld b, a - ld a, [H_CURRENTSPRITEOFFSET] - cp b - jr nz, .unequal - jp DoScriptedNPCMovement -.unequal - jp UpdateNPCSprite - -; This detects if the current sprite (whose offset is at H_CURRENTSPRITEOFFSET) -; is going to collide with another sprite by looping over the other sprites. -; The current sprite's offset will be labelled with i (e.g. $c1i0). -; The loop sprite's offset will labelled with j (e.g. $c1j0). -; -; Note that the Y coordinate of the sprite (in [$c1k4]) is one of the following -; 9 values when the sprite is aligned with the grid: $fc, $0c, $1c, $2c, ..., $7c. -; The reason that 4 is added below to the coordinate is to make it align with a -; multiple of $10 to make comparisons easier. -DetectCollisionBetweenSprites: - ; nop - - ld h, wSpriteStateData1 / $100 - ld a, [H_CURRENTSPRITEOFFSET] - ld l, a - - ld a, [hl] ; a = [$c1i0] (picture) (0 if slot is unused) - and a ; is this sprite slot slot used? - ret z ; return if not used - - ld a, l - add 3 - ld l, a - - ld a, [hli] ; a = [$c1i3] (delta Y) (-1, 0, or 1) - call SetSpriteCollisionValues - - ld a, [hli] ; a = [$C1i4] (Y screen coordinate) - add 4 ; align with multiple of $10 - -; The effect of the following 3 lines is to -; add 7 to a if moving south or -; subtract 7 from a if moving north. - add b - and $f0 - or c - - ld [$ff90], a ; store Y coordinate adjusted for direction of movement - - ld a, [hli] ; a = [$c1i5] (delta X) (-1, 0, or 1) - call SetSpriteCollisionValues - ld a, [hl] ; a = [$C1i6] (X screen coordinate) - -; The effect of the following 3 lines is to -; add 7 to a if moving east or -; subtract 7 from a if moving west. - add b - and $f0 - or c - - ld [$ff91], a ; store X coordinate adjusted for direction of movement - - ld a, l - add 7 - ld l, a - - xor a - ld [hld], a ; zero [$c1id] XXX what's [$c1id] for? - ld [hld], a ; zero [$c1ic] (directions in which collisions occurred) - - ld a, [$ff91] - ld [hld], a ; [$c1ib] = adjusted X coordinate - ld a, [$ff90] - ld [hl], a ; [$c1ia] = adjusted Y coordinate - - xor a ; zero the loop counter - -.loop - ld [$ff8f], a ; store loop counter - swap a - ld e, a - ld a, [H_CURRENTSPRITEOFFSET] - cp e ; does the loop sprite match the current sprite? - jp z, .next ; go to the next sprite if they match - - ld d, h - ld a, [de] ; a = [$c1j0] (picture) (0 if slot is unused) - and a ; is this sprite slot slot used? - jp z, .next ; go the next sprite if not used - - inc e - inc e - ld a, [de] ; a = [$c1j2] ($ff means the sprite is offscreen) - inc a - jp z, .next ; go the next sprite if offscreen - - ld a, [H_CURRENTSPRITEOFFSET] - add 10 - ld l, a - - inc e - ld a, [de] ; a = [$c1j3] (delta Y) - call SetSpriteCollisionValues - - inc e - ld a, [de] ; a = [$C1j4] (Y screen coordinate) - add 4 ; align with multiple of $10 - -; The effect of the following 3 lines is to -; add 7 to a if moving south or -; subtract 7 from a if moving north. - add b - and $f0 - or c - - sub [hl] ; subtract the adjusted Y coordinate of sprite i ([$c1ia]) from that of sprite j - -; calculate the absolute value of the difference to get the distance - jr nc, .noCarry1 - cpl - inc a -.noCarry1 - ld [$ff90], a ; store the distance between the two sprites' adjusted Y values - -; Use the carry flag set by the above subtraction to determine which sprite's -; Y coordinate is larger. This information is used later to set [$c1ic], -; which stores which direction the collision occurred in. -; The following 5 lines set the lowest 2 bits of c, which are later shifted left by 2. -; If sprite i's Y is larger, set lowest 2 bits of c to 10. -; If sprite j's Y is larger or both are equal, set lowest 2 bits of c to 01. - push af - rl c - pop af - ccf - rl c - -; If sprite i's delta Y is 0, then b = 7, else b = 9. - ld b, 7 - ld a, [hl] ; a = [$c1ia] (adjusted Y coordinate) - and $f - jr z, .next1 - ld b, 9 - -.next1 - ld a, [$ff90] ; a = distance between adjusted Y coordinates - sub b - ld [$ff92], a ; store distance adjusted using sprite i's direction - ld a, b - ld [$ff90], a ; store 7 or 9 depending on sprite i's delta Y - jr c, .checkXDistance - -; If sprite j's delta Y is 0, then b = 7, else b = 9. - ld b, 7 - dec e - ld a, [de] ; a = [$c1j3] (delta Y) - inc e - and a - jr z, .next2 - ld b, 9 - -.next2 - ld a, [$ff92] ; a = distance adjusted using sprite i's direction - sub b ; adjust distance using sprite j's direction - jr z, .checkXDistance - jr nc, .next ; go to next sprite if distance is still positive after both adjustments - -.checkXDistance - inc e - inc l - ld a, [de] ; a = [$c1j5] (delta X) - - push bc - - call SetSpriteCollisionValues - inc e - ld a, [de] ; a = [$c1j6] (X screen coordinate) - -; The effect of the following 3 lines is to -; add 7 to a if moving east or -; subtract 7 from a if moving west. - add b - and $f0 - or c - - pop bc - - sub [hl] ; subtract the adjusted X coordinate of sprite i ([$c1ib]) from that of sprite j - -; calculate the absolute value of the difference to get the distance - jr nc, .noCarry2 - cpl - inc a -.noCarry2 - ld [$ff91], a ; store the distance between the two sprites' adjusted X values - -; Use the carry flag set by the above subtraction to determine which sprite's -; X coordinate is larger. This information is used later to set [$c1ic], -; which stores which direction the collision occurred in. -; The following 5 lines set the lowest 2 bits of c. -; If sprite i's X is larger, set lowest 2 bits of c to 10. -; If sprite j's X is larger or both are equal, set lowest 2 bits of c to 01. - push af - rl c - pop af - ccf - rl c - -; If sprite i's delta X is 0, then b = 7, else b = 9. - ld b, 7 - ld a, [hl] ; a = [$c1ib] (adjusted X coordinate) - and $f - jr z, .next3 - ld b, 9 - -.next3 - ld a, [$ff91] ; a = distance between adjusted X coordinates - sub b - ld [$ff92], a ; store distance adjusted using sprite i's direction - ld a, b - ld [$ff91], a ; store 7 or 9 depending on sprite i's delta X - jr c, .collision - -; If sprite j's delta X is 0, then b = 7, else b = 9. - ld b, 7 - dec e - ld a, [de] ; a = [$c1j5] (delta X) - inc e - and a - jr z, .next4 - ld b, 9 - -.next4 - ld a, [$ff92] ; a = distance adjusted using sprite i's direction - sub b ; adjust distance using sprite j's direction - jr z, .collision - jr nc, .next ; go to next sprite if distance is still positive after both adjustments - -.collision - ld a, l - and $f0 ; collision with pikachu? - jr nz, .asm_4cd9 - xor a - ld [wd434], a - ld a, [$ff8f] - cp $f - jr nz, .asm_4cd9 - call Func_4d0a - jr .asm_4cef -.asm_4cd9 - ld a, [$ff91] ; a = 7 or 9 depending on sprite i's delta X - ld b, a - ld a, [$ff90] ; a = 7 or 9 depending on sprite i's delta Y - inc l - -; If delta X isn't 0 and delta Y is 0, then b = %0011, else b = %1100. -; (note that normally if delta X isn't 0, then delta Y must be 0 and vice versa) - cp b - jr c, .next5 - ld b, %1100 - jr .next6 -.next5 - ld b, %0011 - -.next6 - ld a, c ; c has 2 bits set (one of bits 0-1 is set for the X axis and one of bits 2-3 for the Y axis) - and b ; we select either the bit in bits 0-1 or bits 2-3 based on the calculation immediately above - or [hl] ; or with existing collision direction bits in [$c1ic] - ld [hl], a ; store new value - ld a, c ; useless code because a is overwritten before being used again - -; set bit in [$c1ie] or [$c1if] to indicate which sprite the collision occurred with - inc l - inc l -.asm_4cef - ld a, [$ff8f] ; a = loop counter - ld de, SpriteCollisionBitTable - add a - add e - ld e, a - jr nc, .noCarry3 - inc d -.noCarry3 - ld a, [de] - or [hl] - ld [hli], a - inc de - ld a, [de] - or [hl] - ld [hl], a - -.next - ld a, [$ff8f] ; a = loop counter - inc a - cp $10 - jp nz, .loop - ret - -; takes delta X or delta Y in a -; b = delta X/Y -; c = 0 if delta X/Y is 0 -; c = 7 if delta X/Y is 1 -; c = 9 if delta X/Y is -1 -Func_4d0a: - ld a, [$ff91] - ld b, a - ld a, [$ff90] - inc l - cp b - jr c, .asm_4d17 - ld b, %1100 - jr .asm_4d19 -.asm_4d17 - ld b, %11 -.asm_4d19 - ld a, c - and b - ld [wd434], a - ld a, c - inc l - inc l - ret - -SetSpriteCollisionValues: - and a - ld b, 0 - ld c, 0 - jr z, .done - ld c, 9 - cp -1 - jr z, .ok - ld c, 7 - ld a, 0 -.ok - ld b, a -.done - ret - -SpriteCollisionBitTable: - db %00000000,%00000001 - db %00000000,%00000010 - db %00000000,%00000100 - db %00000000,%00001000 - db %00000000,%00010000 - db %00000000,%00100000 - db %00000000,%01000000 - db %00000000,%10000000 - db %00000001,%00000000 - db %00000010,%00000000 - db %00000100,%00000000 - db %00001000,%00000000 - db %00010000,%00000000 - db %00100000,%00000000 - db %01000000,%00000000 - db %10000000,%00000000 diff --git a/engine/overworld/map_sprites.asm b/engine/overworld/map_sprites.asm index 3e2c3912..e31c0bd2 100755 --- a/engine/overworld/map_sprites.asm +++ b/engine/overworld/map_sprites.asm @@ -8,7 +8,7 @@ ; fields, respectively, within loops. The X is the loop index. ; If there is an inner loop, Y is the inner loop index, i.e. $C1Y* and $C2Y* ; denote fields of the sprite slots iterated over in the inner loop. -_InitMapSprites: +_InitMapSprites:: call InitOutsideMapSprites ret c ; return if the map is an outside map (already handled by above call) ; if the map is an inside map (i.e. mapID >= $25) @@ -21,7 +21,7 @@ _InitMapSprites: ; sets carry if the map is a city or route, unsets carry if not InitOutsideMapSprites: ld a, [wCurMap] - cp a, REDS_HOUSE_1F ; is the map a city or a route (map ID less than $25)? + cp FIRST_INDOOR_MAP ; is the map a city or a route? ret nc ; if not, return call GetSplitMapSpriteSetID ; if so, choose the appropriate one @@ -68,7 +68,7 @@ LoadSpriteSetFromMapHeader: ld a, 14 .storeVRAMSlotsLoop push af - ld a, [hl] ; $C1X0 (picture ID) (zero if sprite slot is not used) + ld a, [hl] ; [x#SPRITESTATEDATA1_PICTUREID] (zero if sprite slot is not used) and a ; is the sprite slot used? jr z, .continue ; if the sprite slot is not used ld c, a @@ -125,7 +125,7 @@ CheckForFourTileSprite: cp SPRITE_PIKACHU ; is this the Pikachu Sprite? ret z ; return if yes - cp SPRITE_BALL ; is this a four tile sprite? + cp FIRST_STILL_SPRITE ; is this a four tile sprite? jr nc, .notYellowSprite ; set carry if yes ; regular sprite and a @@ -138,7 +138,7 @@ CheckForFourTileSprite: LoadMapSpriteTilePatterns: ld a, 0 .loop - ld [hVRAMSlot], a + ldh [hVRAMSlot], a cp 9 jr nc, .fourTileSprite call LoadStillTilePattern @@ -148,7 +148,7 @@ LoadMapSpriteTilePatterns: .fourTileSprite call LoadStillTilePattern .continue - ld a, [hVRAMSlot] + ldh a, [hVRAMSlot] inc a cp 11 jr nz, .loop @@ -157,12 +157,12 @@ LoadMapSpriteTilePatterns: ReloadWalkingTilePatterns: xor a .loop - ld [hVRAMSlot], a + ldh [hVRAMSlot], a cp 9 jr nc, .fourTileSprite call LoadWalkingTilePattern .fourTileSprite - ld a, [hVRAMSlot] + ldh a, [hVRAMSlot] inc a cp 11 jr nz, .loop @@ -192,7 +192,7 @@ LoadWalkingTilePattern: GetSpriteVRAMAddress: push bc - ld a, [hVRAMSlot] + ldh a, [hVRAMSlot] ld c, a ld b, 0 ld hl, SpriteVRAMAddresses @@ -220,7 +220,7 @@ SpriteVRAMAddresses: dw vChars0 + $7c0 ; 4-tile sprites ReadSpriteSheetData: - ld a, [hVRAMSlot] + ldh a, [hVRAMSlot] ld e, a ld d, 0 ld hl, wSpriteSet @@ -257,20 +257,20 @@ Func_14150: ld a, $e ld hl, wSprite01StateData1 .loop - ld [hVRAMSlot], a ; store current sprite set slot as a counter - ld a, [hl] ; $c1x0 (picture ID) + ldh [hVRAMSlot], a ; store current sprite set slot as a counter + ld a, [hl] ; [x#SPRITESTATEDATA1_PICTUREID] and a ; is the sprite unused? jr z, .spriteUnused call Func_14179 push hl ld de, (wSpritePlayerStateData2ImageBaseOffset) - (wSpriteStateData1) ; $10e - add hl, de ; get $c2xe (sprite image base offset) + add hl, de ; [x#SPRITESTATEDATA2_IMAGEBASEOFFSET] ld [hl], a ; write offset pop hl .spriteUnused ld de, wSprite02StateData1 - wSprite01StateData1 add hl, de - ld a, [hVRAMSlot] + ldh a, [hVRAMSlot] dec a jr nz, .loop ret @@ -364,4 +364,6 @@ GetSplitMapSpriteSetID: ld a, $01 ret -INCLUDE "data/sprite_sets.asm" +INCLUDE "data/maps/sprite_sets.asm" + +INCLUDE "data/sprites/sprites.asm" diff --git a/engine/overworld/missable_objects.asm b/engine/overworld/missable_objects.asm index dd601451..358a9b9f 100644 --- a/engine/overworld/missable_objects.asm +++ b/engine/overworld/missable_objects.asm @@ -1,6 +1,6 @@ -MarkTownVisitedAndLoadMissableObjects: +MarkTownVisitedAndLoadMissableObjects:: ld a, [wCurMap] - cp ROUTE_1 + cp FIRST_ROUTE_MAP jr nc, .notInTown ld c, a ld b, FLAG_SET @@ -22,31 +22,31 @@ MarkTownVisitedAndLoadMissableObjects: ld l, a push hl ld a, l - sub MapHS00 & $ff ; calculate difference between out pointer and the base pointer + sub MissableObjects & $ff ; calculate difference between out pointer and the base pointer ld l, a ld a, h - sbc MapHS00 / $100 + sbc MissableObjects / $100 ld h, a ld a, h - ld [H_DIVIDEND], a + ldh [hDividend], a ld a, l - ld [H_DIVIDEND + 1], a + ldh [hDividend+1], a xor a - ld [H_DIVIDEND + 2], a - ld [H_DIVIDEND + 3], a + ldh [hDividend+2], a + ldh [hDividend+3], a ld a, $3 - ld [H_DIVISOR], a + ldh [hDivisor], a ld b, $2 call Divide ; divide difference by 3, resulting in the global offset (number of missable items before ours) ld a, [wCurMap] ld b, a - ld a, [H_DIVIDEND + 3] + ldh a, [hDividend+3] ld c, a ; store global offset in c ld de, wMissableObjectList pop hl .writeMissableObjectsListLoop ld a, [hli] - cp $ff + cp -1 jr z, .done ; end of list cp b jr nz, .done ; not for current map anymore @@ -60,7 +60,7 @@ MarkTownVisitedAndLoadMissableObjects: inc de jr .writeMissableObjectsListLoop .done - ld a, $ff + ld a, -1 ld [de], a ; write sentinel ret @@ -69,17 +69,17 @@ InitializeMissableObjectsFlags: ld bc, wMissableObjectFlagsEnd - wMissableObjectFlags xor a call FillMemory ; clear missable objects flags - ld hl, MapHS00 + ld hl, MissableObjects xor a ld [wMissableObjectCounter], a .missableObjectsLoop ld a, [hli] - cp $ff ; end of list + cp -1 ; end of list ret z push hl inc hl ld a, [hl] - cp Hide + cp HIDE jr nz, .skip ld hl, wMissableObjectFlags ld a, [wMissableObjectCounter] @@ -96,13 +96,13 @@ InitializeMissableObjectsFlags: ; tests if current sprite is a missable object that is hidden/has been removed IsObjectHidden: - ld a, [H_CURRENTSPRITEOFFSET] + ldh a, [hCurrentSpriteOffset] swap a ld b, a ld hl, wMissableObjectList .loop ld a, [hli] - cp $ff + cp -1 jr z, .notHidden ; not missable -> not hidden cp b ld a, [hli] @@ -117,7 +117,7 @@ IsObjectHidden: .notHidden xor a .hidden - ld [$ffe5], a + ldh [hIsHiddenMissableObject], a ret ; adds missable object (items, leg. pokemon, etc.) to the map diff --git a/engine/overworld/movement.asm b/engine/overworld/movement.asm index f2334479..dadf2194 100644 --- a/engine/overworld/movement.asm +++ b/engine/overworld/movement.asm @@ -1,25 +1,25 @@ MAP_TILESET_SIZE EQU $60 UpdatePlayerSprite: - ld a, [wSpriteStateData2] + ld a, [wSpritePlayerStateData2WalkAnimationCounter] and a jr z, .checkIfTextBoxInFrontOfSprite cp $ff jr z, .disableSprite dec a - ld [wSpriteStateData2], a + ld [wSpritePlayerStateData2WalkAnimationCounter], a jr .disableSprite ; check if a text box is in front of the sprite by checking if the lower left ; background tile the sprite is standing on is greater than $5F, which is ; the maximum number for map tiles .checkIfTextBoxInFrontOfSprite - aCoord 8, 9 - ld [hTilePlayerStandingOn], a + lda_coord 8, 9 + ldh [hTilePlayerStandingOn], a cp MAP_TILESET_SIZE jr c, .lowerLeftTileIsMapTile .disableSprite ld a, $ff - ld [wSpriteStateData1 + 2], a + ld [wSpritePlayerStateData1ImageIndex], a ret .lowerLeftTileIsMapTile ld a, [wUpdateSpritesEnabled] @@ -29,7 +29,7 @@ UpdatePlayerSprite: call DetectCollisionBetweenSprites pop af ld [wUpdateSpritesEnabled], a - ld h, wSpriteStateData1 / $100 + ld h, HIGH(wSpriteStateData1) ld a, [wWalkCounter] and a jr nz, .moving @@ -62,8 +62,8 @@ UpdatePlayerSprite: .notMoving ; zero the animation counters xor a - ld [wSpriteStateData1 + 7], a - ld [wSpriteStateData1 + 8], a + ld [wSpritePlayerStateData1IntraAnimFrameCounter], a + ld [wSpritePlayerStateData1AnimFrameCounter], a call Func_4e32 jr .skipSpriteAnim .moving @@ -77,27 +77,27 @@ UpdatePlayerSprite: ; lower priority than the background so that it's partially obscured by the ; grass. Only the lower half of the sprite is permitted to have the priority ; bit set by later logic. - ld a, [hTilePlayerStandingOn] + ldh a, [hTilePlayerStandingOn] ld c, a ld a, [wGrassTile] cp c - ld a, $0 + ld a, 0 jr nz, .next2 - ld a, $80 + ld a, OAM_BEHIND_BG .next2 - ld [wSpriteStateData2 + $07], a + ld [wSpritePlayerStateData2GrassPriority], a ret Func_4e32: - ld a, [wSpriteStateData1 + 8] + ld a, [wSpritePlayerStateData1AnimFrameCounter] ld b, a ld a, [wSpritePlayerStateData1FacingDirection] add b - ld [wSpriteStateData1 + 2], a + ld [wSpritePlayerStateData1ImageIndex], a ret UpdateNPCSprite: - ld a, [H_CURRENTSPRITEOFFSET] + ldh a, [hCurrentSpriteOffset] swap a dec a add a @@ -106,20 +106,20 @@ UpdateNPCSprite: ld l, a ld a, [hl] ; read movement byte 2 ld [wCurSpriteMovement2], a - ld h, wSpriteStateData1 / $100 - ld a, [H_CURRENTSPRITEOFFSET] + ld h, HIGH(wSpriteStateData1) + ldh a, [hCurrentSpriteOffset] ld l, a inc l - ld a, [hl] ; c1x1 + ld a, [hl] ; x#SPRITESTATEDATA1_MOVEMENTSTATUS and a jp z, InitializeSpriteStatus call CheckSpriteAvailability ret c ; if sprite is invisible, on tile >=MAP_TILESET_SIZE, in grass or player is currently walking - ld h, wSpriteStateData1 / $100 - ld a, [H_CURRENTSPRITEOFFSET] + ld h, HIGH(wSpriteStateData1) + ldh a, [hCurrentSpriteOffset] ld l, a inc l - ld a, [hl] ; c1x1 + ld a, [hl] ; x#SPRITESTATEDATA1_MOVEMENTSTATUS bit 7, a ; is the face player flag set? jp nz, MakeNPCFacePlayer ld b, a @@ -128,24 +128,24 @@ UpdateNPCSprite: jp nz, notYetMoving ld a, b cp $2 - jp z, UpdateSpriteMovementDelay ; c1x1 == 2 + jp z, UpdateSpriteMovementDelay ; [x#SPRITESTATEDATA1_MOVEMENTSTATUS] == 2 cp $3 - jp z, UpdateSpriteInWalkingAnimation ; c1x1 == 3 + jp z, UpdateSpriteInWalkingAnimation ; [x#SPRITESTATEDATA1_MOVEMENTSTATUS] == 3 cp $4 jp z, Func_5357 ld a, [wWalkCounter] and a ret nz ; don't do anything yet if player is currently moving (redundant, already tested in CheckSpriteAvailability) call InitializeSpriteScreenPosition - ld h, wSpriteStateData2 / $100 - ld a, [H_CURRENTSPRITEOFFSET] + ld h, HIGH(wSpriteStateData2) + ldh a, [hCurrentSpriteOffset] add $6 ld l, a - ld a, [hl] ; c2x6: movement byte 1 + ld a, [hl] ; x#SPRITESTATEDATA2_MOVEMENTBYTE1 inc a - jp z, .randomMovement ; value $FF + jp z, .randomMovement ; value STAY inc a - jp z, .randomMovement ; value $FE + jp z, .randomMovement ; value WALK ; scripted movement dec a ld [hl], a ; increment movement byte 1 (movement data index) @@ -156,7 +156,7 @@ UpdateNPCSprite: pop hl ld de, wNPCMovementDirections call LoadDEPlusA ; a = [wNPCMovementDirections + movement byte 1] - cp $e0 + cp NPC_CHANGE_FACING jp z, ChangeFacingDirection cp STAY jr nz, .next @@ -171,7 +171,7 @@ UpdateNPCSprite: .next cp WALK jr nz, .asm_4ecb -; current NPC movement data is $fe. this seems buggy +; current NPC movement data is WALK ($fe). this seems buggy ld [hl], $1 ; set movement byte 1 to $1 ld de, wNPCMovementDirections call LoadDEPlusA ; a = [wNPCMovementDirections + $fe] (?) @@ -188,20 +188,20 @@ UpdateNPCSprite: .determineDirection ld b, a ld a, [wCurSpriteMovement2] - cp $d0 - jr z, .moveDown ; movement byte 2 = $d0 forces down - cp $d1 - jr z, .moveUp ; movement byte 2 = $d1 forces up - cp $d2 - jr z, .moveLeft ; movement byte 2 = $d2 forces left - cp $d3 - jr z, .moveRight ; movement byte 2 = $d3 forces right + cp DOWN + jr z, .moveDown + cp UP + jr z, .moveUp + cp LEFT + jr z, .moveLeft + cp RIGHT + jr z, .moveRight ld a, b - cp $40 ; a < $40: down (or left) + cp NPC_MOVEMENT_UP ; NPC_MOVEMENT_DOWN <= a < NPC_MOVEMENT_UP: down (or left) jr nc, .notDown ld a, [wCurSpriteMovement2] - cp $2 - jr z, .moveLeft ; movement byte 2 = $2 only allows left or right + cp LEFT_RIGHT + jr z, .moveLeft .moveDown ld de, 2*SCREEN_WIDTH add hl, de ; move tile pointer two rows down @@ -209,11 +209,11 @@ UpdateNPCSprite: lb bc, 4, SPRITE_FACING_DOWN jr TryWalking .notDown - cp $80 ; $40 <= a < $80: up (or right) + cp NPC_MOVEMENT_LEFT ; NPC_MOVEMENT_UP <= a < NPC_MOVEMENT_LEFT: up (or right) jr nc, .notUp ld a, [wCurSpriteMovement2] - cp $2 - jr z, .moveRight ; movement byte 2 = $2 only allows left or right + cp LEFT_RIGHT + jr z, .moveRight .moveUp ld de, -2*SCREEN_WIDTH add hl, de ; move tile pointer two rows up @@ -221,21 +221,21 @@ UpdateNPCSprite: lb bc, 8, SPRITE_FACING_UP jr TryWalking .notUp - cp $c0 ; $80 <= a < $c0: left (or up) + cp NPC_MOVEMENT_RIGHT ; NPC_MOVEMENT_LEFT <= a < NPC_MOVEMENT_RIGHT: left (or up) jr nc, .notLeft ld a, [wCurSpriteMovement2] - cp $1 - jr z, .moveUp ; movement byte 2 = $1 only allows up or down + cp UP_DOWN + jr z, .moveUp .moveLeft dec hl dec hl ; move tile pointer two columns left lb de, 0, -1 lb bc, 2, SPRITE_FACING_LEFT jr TryWalking -.notLeft ; $c0 <= a: right (or down) +.notLeft ; NPC_MOVEMENT_RIGHT <= a: right (or down) ld a, [wCurSpriteMovement2] - cp $1 - jr z, .moveDown ; movement byte 2 = $1 only allows up or down + cp UP_DOWN + jr z, .moveDown .moveRight inc hl inc hl ; move tile pointer two columns right @@ -262,103 +262,104 @@ TryWalking: ld c, [hl] call CanWalkOntoTile pop de - ret c + ret c ; cannot walk there (reinitialization of delay values already done) call Func_5349 - ld a, [H_CURRENTSPRITEOFFSET] + ldh a, [hCurrentSpriteOffset] ld l, a - ld [hl], $10 ; c1x9 (update facing direction) + ld [hl], $10 ; [x#SPRITESTATEDATA2_WALKANIMATIONCOUNTER] = 16 dec h inc l - ld [hl], $3 + ld [hl], $3 ; x#SPRITESTATEDATA1_MOVEMENTSTATUS jp UpdateSpriteImage ; update the walking animation parameters for a sprite that is currently walking UpdateSpriteInWalkingAnimation: call Func_5274 -.noNextAnimationFrame - ld a, [H_CURRENTSPRITEOFFSET] + ldh a, [hCurrentSpriteOffset] add $3 ld l, a - ld a, [hli] ; c1x3 (movement Y delta) + ld a, [hli] ; x#SPRITESTATEDATA1_YSTEPVECTOR ld b, a - ld a, [hl] ; c1x4 (screen Y position) + ld a, [hl] ; x#SPRITESTATEDATA1_YPIXELS add b - ld [hli], a ; update screen Y position - ld a, [hli] ; c1x5 (movement X delta) + ld [hli], a ; update [x#SPRITESTATEDATA1_YPIXELS] + ld a, [hli] ; x#SPRITESTATEDATA1_XSTEPVECTOR ld b, a - ld a, [hl] ; c1x6 (screen X position) + ld a, [hl] ; x#SPRITESTATEDATA1_XPIXELS add b - ld [hl], a ; update screen X position - ld a, [H_CURRENTSPRITEOFFSET] + ld [hl], a ; update [x#SPRITESTATEDATA1_XPIXELS] + ldh a, [hCurrentSpriteOffset] ld l, a inc h - ld a, [hl] ; c2x0 (walk animation counter) + ld a, [hl] ; x#SPRITESTATEDATA2_WALKANIMATIONCOUNTER dec a ld [hl], a ; update walk animation counter ret nz ld a, $6 ; walking finished, update state add l ld l, a - ld a, [hl] ; c2x6 (movement byte 1) - cp $fe - jr nc, .initNextMovementCounter ; values $fe and $ff - ld a, [H_CURRENTSPRITEOFFSET] + ld a, [hl] ; x#SPRITESTATEDATA2_MOVEMENTBYTE1 + cp WALK + jr nc, .initNextMovementCounter ; values WALK or STAY + ldh a, [hCurrentSpriteOffset] inc a ld l, a dec h - ld [hl], $1 ; c1x1 = 1 (movement status ready) + ld [hl], $1 ; [x#SPRITESTATEDATA1_MOVEMENTSTATUS] = 1 (movement status ready) ret .initNextMovementCounter call Random - ld a, [H_CURRENTSPRITEOFFSET] + ldh a, [hCurrentSpriteOffset] add $8 ld l, a - ld a, [hRandomAdd] + ldh a, [hRandomAdd] and $7f - ld [hl], a ; c2x8: set next movement delay to a random value in [0,$7f] - dec h ; note that value 0 actually makes the delay $100 (bug?) - ld a, [H_CURRENTSPRITEOFFSET] + ld [hl], a ; x#SPRITESTATEDATA2_MOVEMENTDELAY: + ; set next movement delay to a random value in [0,$7f] + ; note that value 0 actually makes the delay $100 (bug?) + dec h ; HIGH(wSpriteStateData1) + ldh a, [hCurrentSpriteOffset] inc a ld l, a - ld [hl], $2 ; c1x1 = 2 (movement status) + ld [hl], $2 ; [x#SPRITESTATEDATA1_MOVEMENTSTATUS] = 2 (movement status) inc l inc l xor a - ld b, [hl] ; c1x3 (movement Y delta) - ld [hli], a ; reset movement Y delta + ld b, [hl] ; x#SPRITESTATEDATA1_YSTEPVECTOR + ld [hli], a ; [x#SPRITESTATEDATA1_YSTEPVECTOR] = 0 inc l - ld c, [hl] ; c1x5 (movement X delta) - ld [hl], a ; reset movement X delta + ld c, [hl] ; x#SPRITESTATEDATA1_XSTEPVECTOR + ld [hl], a ; [x#SPRITESTATEDATA1_XSTEPVECTOR] = 0 ret -; update delay value (c2x8) for sprites in the delayed state (c1x1) +; update [x#SPRITESTATEDATA2_MOVEMENTDELAY] for sprites in the delayed state (x#SPRITESTATEDATA1_MOVEMENTSTATUS) UpdateSpriteMovementDelay: - ld h, $c2 - ld a, [H_CURRENTSPRITEOFFSET] + ld h, HIGH(wSpriteStateData2) + ldh a, [hCurrentSpriteOffset] add $6 ld l, a - ld a, [hl] ; c2x6: movement byte 1 + ld a, [hl] ; x#SPRITESTATEDATA2_MOVEMENTBYTE1 inc l inc l - cp $fe - jr nc, .tickMoveCounter ; values $fe or $ff + cp WALK + jr nc, .tickMoveCounter ; values WALK or STAY ld [hl], $0 jr .moving .tickMoveCounter - dec [hl] ; c2x8: frame counter until next movement + dec [hl] ; x#SPRITESTATEDATA2_MOVEMENTDELAY jr nz, notYetMoving .moving dec h - ld a, [H_CURRENTSPRITEOFFSET] + ldh a, [hCurrentSpriteOffset] inc a ld l, a - ld [hl], $1 ; c1x1 = 1 (mark as ready to move) + ld [hl], $1 ; [x#SPRITESTATEDATA1_MOVEMENTSTATUS] = 1 (mark as ready to move) notYetMoving: - ld h, wSpriteStateData1 / $100 - ld a, [H_CURRENTSPRITEOFFSET] - add $8 + ld h, HIGH(wSpriteStateData1) + ldh a, [hCurrentSpriteOffset] + add SPRITESTATEDATA1_ANIMFRAMECOUNTER ld l, a - ld [hl], $0 ; c1x8 = 0 (walk animation frame) + ld [hl], $0 ; [x#SPRITESTATEDATA1_ANIMFRAMECOUNTER] = 0 (walk animation frame) jp UpdateSpriteImage MakeNPCFacePlayer: @@ -388,48 +389,48 @@ MakeNPCFacePlayer: .notFacingRight ld c, SPRITE_FACING_LEFT .facingDirectionDetermined - ld a, [H_CURRENTSPRITEOFFSET] + ldh a, [hCurrentSpriteOffset] add $9 ld l, a - ld [hl], c ; c1x9: set facing direction + ld [hl], c ; [x#SPRITESTATEDATA1_FACINGDIRECTION]: set facing direction jr notYetMoving InitializeSpriteStatus: - ld [hl], $1 ; $c1x1: set movement status to ready + ld [hl], $1 ; [x#SPRITESTATEDATA1_MOVEMENTSTATUS] = ready inc l - ld [hl], $ff ; $c1x2: set sprite image to $ff (invisible/off screen) - inc h - ld a, [H_CURRENTSPRITEOFFSET] + ld [hl], $ff ; [x#SPRITESTATEDATA1_IMAGEINDEX] = invisible/off screen + inc h ; HIGH(wSpriteStateData2) + ldh a, [hCurrentSpriteOffset] add $2 ld l, a ld a, $8 - ld [hli], a ; $c2x2: set Y displacement to 8 - ld [hl], a ; $c2x3: set X displacement to 8 + ld [hli], a ; [x#SPRITESTATEDATA2_YDISPLACEMENT] = 8 + ld [hl], a ; [x#SPRITESTATEDATA2_XDISPLACEMENT] = 8 call InitializeSpriteScreenPosition ; could have done fallthrough here ret -; calculates the sprite's screen position form its map position and the player position +; calculates the sprite's screen position from its map position and the player position InitializeSpriteScreenPosition: - ld h, wSpriteStateData2 / $100 - ld a, [H_CURRENTSPRITEOFFSET] - add $4 + ld h, HIGH(wSpriteStateData2) + ldh a, [hCurrentSpriteOffset] + add SPRITESTATEDATA2_MAPY ld l, a ld a, [wYCoord] ld b, a - ld a, [hl] ; c2x4 (Y position + 4) + ld a, [hl] ; x#SPRITESTATEDATA2_MAPY sub b ; relative to player position call Func_5033 sub $4 ; - 4 dec h - ld [hli], a ; c1x4 (screen Y position) + ld [hli], a ; [x#SPRITESTATEDATA1_YPIXELS] inc h ld a, [wXCoord] ld b, a - ld a, [hli] ; c2x6 (X position + 4) + ld a, [hli] ; x#SPRITESTATEDATA2_MAPX sub b ; relative to player position call Func_5033 dec h - ld [hl], a ; c1x6 (screen X position) + ld [hl], a ; [x#SPRITESTATEDATA1_XPIXELS] ret Func_5033: @@ -447,35 +448,35 @@ Func_5033: ; tests if sprite is off screen or otherwise unable to do anything CheckSpriteAvailability: predef IsObjectHidden - ld a, [$ffe5] + ldh a, [hIsHiddenMissableObject] and a jp nz, .spriteInvisible - ld h, wSpriteStateData2 / $100 - ld a, [H_CURRENTSPRITEOFFSET] - add $6 + ld h, HIGH(wSpriteStateData2) + ldh a, [hCurrentSpriteOffset] + add SPRITESTATEDATA2_MOVEMENTBYTE1 ld l, a - ld a, [hl] ; c2x6: movement byte 1 - cp $fe - jr c, .skipXVisibilityTest ; movement byte 1 < $fe (i.e. the sprite's movement is scripted) - ld a, [H_CURRENTSPRITEOFFSET] - add $4 + ld a, [hl] ; x#SPRITESTATEDATA2_MOVEMENTBYTE1 + cp WALK + jr c, .skipXVisibilityTest ; movement byte 1 < WALK (i.e. the sprite's movement is scripted) + ldh a, [hCurrentSpriteOffset] + add SPRITESTATEDATA2_MAPY ld l, a - ld b, [hl] ; c2x4: Y pos (+4) + ld b, [hl] ; x#SPRITESTATEDATA2_MAPY ld a, [wYCoord] cp b jr z, .skipYVisibilityTest jr nc, .spriteInvisible ; above screen region - add $8 ; screen is 9 tiles high + add SCREEN_HEIGHT / 2 - 1 cp b jr c, .spriteInvisible ; below screen region .skipYVisibilityTest inc l - ld b, [hl] ; c2x5: X pos (+4) + ld b, [hl] ; x#SPRITESTATEDATA2_MAPX ld a, [wXCoord] cp b jr z, .skipXVisibilityTest jr nc, .spriteInvisible ; left of screen region - add $9 ; screen is 10 tiles wide + add SCREEN_WIDTH / 2 - 1 cp b jr c, .spriteInvisible ; right of screen region .skipXVisibilityTest @@ -489,7 +490,7 @@ CheckSpriteAvailability: ld a, [hld] cp d jr nc, .spriteInvisible ; standing on tile with ID >=MAP_TILESET_SIZE (bottom right tile) - ld bc, -20 + ld bc, -SCREEN_WIDTH add hl, bc ; go back one row of tiles ld a, [hli] cp d @@ -498,11 +499,11 @@ CheckSpriteAvailability: cp d jr c, .spriteVisible ; standing on tile with ID >=MAP_TILESET_SIZE (top right tile) .spriteInvisible - ld h, wSpriteStateData1 / $100 - ld a, [H_CURRENTSPRITEOFFSET] - add $2 + ld h, HIGH(wSpriteStateData1) + ldh a, [hCurrentSpriteOffset] + add SPRITESTATEDATA1_IMAGEINDEX ld l, a - ld [hl], $ff ; c1x2 + ld [hl], $ff ; x#SPRITESTATEDATA1_IMAGEINDEX scf jr .done .spriteVisible @@ -512,37 +513,37 @@ CheckSpriteAvailability: jr nz, .done ; if player is currently walking, we're done call UpdateSpriteImage inc h - ld a, [H_CURRENTSPRITEOFFSET] + ldh a, [hCurrentSpriteOffset] add $7 ld l, a ld a, [wGrassTile] cp c - ld a, $0 + ld a, 0 jr nz, .notInGrass - ld a, $80 + ld a, OAM_BEHIND_BG .notInGrass - ld [hl], a ; c2x7 + ld [hl], a ; x#SPRITESTATEDATA2_GRASSPRIORITY and a .done ret UpdateSpriteImage: - ld h, $c1 - ld a, [H_CURRENTSPRITEOFFSET] + ld h, HIGH(wSpriteStateData1) + ldh a, [hCurrentSpriteOffset] add $8 ld l, a - ld a, [hli] ; c1x8: walk animation frame + ld a, [hli] ; x#SPRITESTATEDATA1_ANIMFRAMECOUNTER ld b, a - ld a, [hl] ; c1x9: facing direction + ld a, [hl] ; x#SPRITESTATEDATA1_FACINGDIRECTION add b ld b, a - ld a, [$ff93] ; current sprite offset + ldh a, [hTilePlayerStandingOn] add b ld b, a - ld a, [H_CURRENTSPRITEOFFSET] + ldh a, [hCurrentSpriteOffset] add $2 ld l, a - ld [hl], b ; c1x2: sprite to display + ld [hl], b ; x#SPRITESTATEDATA1_IMAGEINDEX ret ; tests if sprite can walk the specified direction @@ -552,37 +553,37 @@ UpdateSpriteImage: ; e: X movement delta (-1, 0 or 1) ; set carry on failure, clears carry on success CanWalkOntoTile: - ld h, wSpriteStateData2 / $100 - ld a, [H_CURRENTSPRITEOFFSET] - add $6 + ld h, HIGH(wSpriteStateData2) + ldh a, [hCurrentSpriteOffset] + add SPRITESTATEDATA2_MOVEMENTBYTE1 ld l, a - ld a, [hl] ; c2x6 (movement byte 1) - cp $fe - jr nc, .notScripted ; values $fe and $ff + ld a, [hl] ; x#SPRITESTATEDATA2_MOVEMENTBYTE1 + cp WALK + jr nc, .notScripted ; values WALK or STAY ; always allow walking if the movement is scripted and a ret .notScripted call _IsTilePassable jr c, .impassable - ld h, wSpriteStateData2 / $100 - ld a, [H_CURRENTSPRITEOFFSET] + ld h, HIGH(wSpriteStateData2) + ldh a, [hCurrentSpriteOffset] add $6 ld l, a - ld a, [hl] ; $c2x6 (movement byte 1) + ld a, [hl] ; x#SPRITESTATEDATA2_MOVEMENTBYTE1 inc a jr z, .impassable ; if $ff, no movement allowed (however, changing direction is) - ld h, wSpriteStateData1 / $100 - ld a, [H_CURRENTSPRITEOFFSET] - add $4 + ld h, HIGH(wSpriteStateData1) + ldh a, [hCurrentSpriteOffset] + add SPRITESTATEDATA1_YPIXELS ld l, a - ld a, [hli] ; c1x4 (screen Y pos) + ld a, [hli] ; x#SPRITESTATEDATA1_YPIXELS add $4 ; align to blocks (Y pos is always 4 pixels off) add d ; add Y delta cp $80 ; if value is >$80, the destination is off screen (either $81 or $FF underflow) jr nc, .impassable ; don't walk off screen inc l - ld a, [hl] ; c1x6 (screen X pos) + ld a, [hl] ; x#SPRITESTATEDATA1_XPIXELS add e ; add X delta cp $90 ; if value is >$90, the destination is off screen (either $91 or $FF underflow) jr nc, .impassable ; don't walk off screen @@ -597,30 +598,36 @@ CanWalkOntoTile: ld [wUpdateSpritesEnabled], a pop bc pop de - ld h, wSpriteStateData1 / $100 - ld a, [H_CURRENTSPRITEOFFSET] + ld h, HIGH(wSpriteStateData1) + ldh a, [hCurrentSpriteOffset] add $c ld l, a - ld a, [hl] ; c1xc (directions in which sprite collision would occur) + ld a, [hl] ; x#SPRITESTATEDATA1_COLLISIONDATA (directions in which sprite collision would occur) and b ; check against chosen direction (1,2,4 or 8) jr nz, .impassable ; collision between sprites, don't go there - ld h, wSpriteStateData2 / $100 - ld a, [H_CURRENTSPRITEOFFSET] - add $2 + ld h, HIGH(wSpriteStateData2) + ldh a, [hCurrentSpriteOffset] + add SPRITESTATEDATA2_YDISPLACEMENT ld l, a - ld a, [hli] ; c2x2 (sprite Y displacement, initialized at $8, keep track of where a sprite did go) + ld a, [hli] ; x#SPRITESTATEDATA2_YDISPLACEMENT (initialized at $8, keep track of where a sprite did go) bit 7, d ; check if going upwards (d=$ff) jr nz, .upwards add d + ; bug: these tests against $5 probably were supposed to prevent + ; sprites from walking out too far, but this line makes sprites get + ; stuck whenever they walked upwards 5 steps + ; on the other hand, the amount a sprite can walk out to the + ; right of bottom is not limited (until the counter overflows) + ; this was fixed in Yellow cp $5 - ;jr c, .impassable (bugfix) ; if c2x2+d < 5, don't go ;bug: this tests probably were supposed to prevent sprites - jr .checkHorizontal ; from walking out too far, but this line makes sprites get stuck -.upwards ; whenever they walked upwards 5 steps - sub $1 ; on the other hand, the amount a sprite can walk out to the - jr c, .impassable ; if d2x2 == 0, don't go ; right of bottom is not limited (until the counter overflows) + ;jr c, .impassable ; if [x#SPRITESTATEDATA2_YDISPLACEMENT]+d < 5, don't go + jr .checkHorizontal +.upwards + sub $1 + jr c, .impassable ; if [x#SPRITESTATEDATA2_YDISPLACEMENT] == 0, don't go .checkHorizontal ld d, a - ld a, [hl] ; c2x3 (sprite X displacement, initialized at $8, keep track of where a sprite did go) + ld a, [hl] ; x#SPRITESTATEDATA2_XDISPLACEMENT (initialized at $8, keep track of where a sprite did go) bit 7, e ; check if going left (e=$ff) jr nz, .left add e @@ -628,32 +635,32 @@ CanWalkOntoTile: jr .passable .left sub $1 - jr c, .impassable ; if d2x3 == 0, don't go + jr c, .impassable ; if [x#SPRITESTATEDATA2_XDISPLACEMENT] == 0, don't go .passable - ld [hld], a ; update c2x3 - ld [hl], d ; update c2x2 + ld [hld], a ; update x#SPRITESTATEDATA2_XDISPLACEMENT + ld [hl], d ; update x#SPRITESTATEDATA2_YDISPLACEMENT and a ; clear carry (marking success) ret .impassable - ld h, wSpriteStateData1 / $100 - ld a, [H_CURRENTSPRITEOFFSET] + ld h, HIGH(wSpriteStateData1) + ldh a, [hCurrentSpriteOffset] inc a ld l, a - ld [hl], $2 ; c1x1 = 2 (set movement status to delayed) + ld [hl], $2 ; [x#SPRITESTATEDATA1_MOVEMENTSTATUS] = 2 (delayed) inc l inc l xor a - ld [hli], a ; c1x3 = 0 (clear Y movement delta) + ld [hli], a ; [x#SPRITESTATEDATA1_YSTEPVECTOR] = 0 inc l - ld [hl], a ; c1x5 = 0 (clear X movement delta) + ld [hl], a ; [x#SPRITESTATEDATA1_XSTEPVECTOR] = 0 inc h - ld a, [H_CURRENTSPRITEOFFSET] + ldh a, [hCurrentSpriteOffset] add $8 ld l, a call Random - ld a, [hRandomAdd] + ldh a, [hRandomAdd] and $7f - ld [hl], a ; c2x8: set next movement delay to a random value in [0,$7f] (again with delay $100 if value is 0) + ld [hl], a ; x#SPRITESTATEDATA2_MOVEMENTDELAY: set to a random value in [0,$7f] (again with delay $100 if value is 0) scf ; set carry (marking failure to walk) ret @@ -661,25 +668,25 @@ CanWalkOntoTile: ; this is always the lower left tile of the 2x2 tile blocks all sprites are snapped to ; hl: output pointer GetTileSpriteStandsOn: - ld h, wSpriteStateData1 / $100 - ld a, [H_CURRENTSPRITEOFFSET] - add $4 + ld h, HIGH(wSpriteStateData1) + ldh a, [hCurrentSpriteOffset] + add SPRITESTATEDATA1_YPIXELS ld l, a - ld a, [hli] ; c1x4: screen Y position + ld a, [hli] ; x#SPRITESTATEDATA1_YPIXELS add $4 ; align to 2*2 tile blocks (Y position is always off 4 pixels to the top) and $f8 ; in case object is currently moving (XXX why changed to $f8?) srl a ; screen Y tile * 4 ld c, a ld b, $0 inc l - ld a, [hl] ; c1x6: screen X position + ld a, [hl] ; x#SPRITESTATEDATA1_XPIXELS srl a srl a srl a ; screen X tile add SCREEN_WIDTH ; screen X tile + 20 ld d, $0 ld e, a - coord hl, 0, 0 + hlcoord 0, 0 add hl, bc add hl, bc add hl, bc @@ -754,7 +761,7 @@ DoScriptedNPCMovement: ld a, [hl] add b ld [hl], a - ld a, [H_CURRENTSPRITEOFFSET] + ldh a, [hCurrentSpriteOffset] add $9 ld l, a ld a, c @@ -777,17 +784,17 @@ InitScriptedNPCMovement: jp AnimScriptedNPCMovement GetSpriteScreenYPointer: - ld a, $4 + ld a, SPRITESTATEDATA1_YPIXELS ld b, a jr GetSpriteScreenXYPointerCommon GetSpriteScreenXPointer: - ld a, $6 + ld a, SPRITESTATEDATA1_XPIXELS ld b, a GetSpriteScreenXYPointerCommon: ld hl, wSpriteStateData1 - ld a, [H_CURRENTSPRITEOFFSET] + ldh a, [hCurrentSpriteOffset] add l add b ld l, a @@ -795,16 +802,16 @@ GetSpriteScreenXYPointerCommon: AnimScriptedNPCMovement: ld hl, wSpriteStateData2 - ld a, [H_CURRENTSPRITEOFFSET] - add $e + ldh a, [hCurrentSpriteOffset] + add SPRITESTATEDATA2_IMAGEBASEOFFSET ld l, a ld a, [hl] ; VRAM slot dec a swap a ld b, a ld hl, wSpriteStateData1 - ld a, [H_CURRENTSPRITEOFFSET] - add $9 + ldh a, [hCurrentSpriteOffset] + add SPRITESTATEDATA1_FACINGDIRECTION ld l, a ld a, [hl] ; facing direction cp SPRITE_FACING_DOWN @@ -819,42 +826,42 @@ AnimScriptedNPCMovement: .anim add b ld b, a - ld [hSpriteVRAMSlotAndFacing], a + ldh [hSpriteVRAMSlotAndFacing], a call AdvanceScriptedNPCAnimFrameCounter ld hl, wSpriteStateData1 - ld a, [H_CURRENTSPRITEOFFSET] - add $2 + ldh a, [hCurrentSpriteOffset] + add SPRITESTATEDATA1_IMAGEINDEX ld l, a - ld a, [hSpriteVRAMSlotAndFacing] + ldh a, [hSpriteVRAMSlotAndFacing] ld b, a - ld a, [hSpriteAnimFrameCounter] + ldh a, [hSpriteAnimFrameCounter] add b ld [hl], a ret AdvanceScriptedNPCAnimFrameCounter: call Func_5274 - ld h, wSpriteStateData1 / $100 - ld a, [H_CURRENTSPRITEOFFSET] + ld h, HIGH(wSpriteStateData1) + ldh a, [hCurrentSpriteOffset] add $8 ld l, a ld a, [hl] ; intra-animation frame counter and $3 - ld [hSpriteAnimFrameCounter], a + ldh [hSpriteAnimFrameCounter], a ret Func_5274: - ld a, [H_CURRENTSPRITEOFFSET] + ldh a, [hCurrentSpriteOffset] add $7 ld l, a - ld h, wSpriteStateData1 / $100 - ld a, [hl] ; c1x7 (counter until next walk animation frame) + ld h, HIGH(wSpriteStateData1) + ld a, [hl] ; x#SPRITESTATEDATA1_INTRAANIMFRAMECOUNTER inc a and $3 - ld [hl], a ; c1x7 += 1 - ret nz ; c1x7 = 0 + ld [hl], a ; [x#SPRITESTATEDATA1_INTRAANIMFRAMECOUNTER]++ + ret nz inc l - ld a, [hl] ; c1x8 (walk animation frame) + ld a, [hl] ; x#SPRITESTATEDATA1_ANIMFRAMECOUNTER inc a and $3 ld [hl], a ; advance to next animation frame every 4 ticks (16 ticks total for one step) @@ -924,7 +931,7 @@ Func_5288: .asm_52e6 call Func_5337 call Func_5349 - ld a, [H_CURRENTSPRITEOFFSET] + ldh a, [hCurrentSpriteOffset] ld l, a ld [hl], $8 dec h @@ -936,7 +943,7 @@ Func_5288: .asm_52fa call Func_5337 - ld a, [H_CURRENTSPRITEOFFSET] + ldh a, [hCurrentSpriteOffset] ld l, a ld [hl], $8 dec h @@ -949,7 +956,7 @@ Func_5288: .asm_530b call Func_5337 call Func_5349 - ld a, [H_CURRENTSPRITEOFFSET] + ldh a, [hCurrentSpriteOffset] ld l, a ld [hl], $8 dec h @@ -980,39 +987,39 @@ Func_5331: ret Func_5337: - ld a, [H_CURRENTSPRITEOFFSET] + ldh a, [hCurrentSpriteOffset] add $9 ld l, a - ld h, wSpriteStateData1 / $100 - ld [hl], c ; c1x9 (update facing direction) - ld a, [H_CURRENTSPRITEOFFSET] + ld h, HIGH(wSpriteStateData1) + ld [hl], c ; x#SPRITESTATEDATA1_FACINGDIRECTION + ldh a, [hCurrentSpriteOffset] add $3 ld l, a - ld [hl], d ; c1x3 (update Y movement delta) + ld [hl], d ; x#SPRITESTATEDATA1_YSTEPVECTOR inc l inc l - ld [hl], e ; c1x5 (update X movement delta) + ld [hl], e ; x#SPRITESTATEDATA1_XSTEPVECTOR ret Func_5349: - ld h, wSpriteStateData2 / $100 - ld a, [H_CURRENTSPRITEOFFSET] + ld h, HIGH(wSpriteStateData2) + ldh a, [hCurrentSpriteOffset] add $4 ld l, a - ld a, [hl] ; c2x4: Y position + ld a, [hl] ; x#SPRITESTATEDATA2_MAPY add d ld [hli], a ; update Y position - ld a, [hl] ; c2x5: X position + ld a, [hl] ; x#SPRITESTATEDATA2_MAPX add e ld [hl], a ; update X position ret Func_5357: call Func_5274 - ld a, [H_CURRENTSPRITEOFFSET] + ldh a, [hCurrentSpriteOffset] add $3 ld l, a - ld h, wSpriteStateData1 / $100 + ld h, HIGH(wSpriteStateData1) ld a, [hli] add a ld b, a @@ -1025,9 +1032,9 @@ Func_5357: ld a, [hl] add b ld [hl], a - ld a, [H_CURRENTSPRITEOFFSET] + ldh a, [hCurrentSpriteOffset] ld l, a - ld h, wSpriteStateData2 / $100 + ld h, HIGH(wSpriteStateData2) dec [hl] ret nz ld a, $6 @@ -1036,23 +1043,23 @@ Func_5357: ld a, [hl] cp $fe jr nc, .asm_5386 - ld a, [H_CURRENTSPRITEOFFSET] + ldh a, [hCurrentSpriteOffset] inc a ld l, a - ld h, wSpriteStateData1 / $100 + ld h, HIGH(wSpriteStateData1) ld [hl], $1 ret .asm_5386 call Random - ld a, [H_CURRENTSPRITEOFFSET] + ldh a, [hCurrentSpriteOffset] add $8 ld l, a - ld h, wSpriteStateData2 / $100 - ld a, [hRandomAdd] + ld h, HIGH(wSpriteStateData2) + ldh a, [hRandomAdd] and $7f ld [hl], a dec h - ld a, [H_CURRENTSPRITEOFFSET] + ldh a, [hCurrentSpriteOffset] inc a ld l, a ld [hl], $2 diff --git a/engine/overworld/npc_movement.asm b/engine/overworld/npc_movement.asm deleted file mode 100755 index 670cb121..00000000 --- a/engine/overworld/npc_movement.asm +++ /dev/null @@ -1,270 +0,0 @@ -PlayerStepOutFromDoor: - ld hl, wd730 - res 1, [hl] - call IsPlayerStandingOnDoorTile - jr nc, .notStandingOnDoor - ld a, $fc - ld [wJoyIgnore], a - ld hl, wd736 - set 1, [hl] - ld a, $1 - ld [wSimulatedJoypadStatesIndex], a - ld a, D_DOWN - ld [wSimulatedJoypadStatesEnd], a - xor a - ld [wSpriteStateData1 + 2], a - call StartSimulatingJoypadStates - ret -.notStandingOnDoor - xor a - ld [wWastedByteCD3A], a - ld [wSimulatedJoypadStatesIndex], a - ld [wSimulatedJoypadStatesEnd], a - ld hl, wd736 - res 0, [hl] - res 1, [hl] - ld hl, wd730 - res 7, [hl] - ret - -_EndNPCMovementScript: - ld hl, wd730 - res 7, [hl] - ld hl, wd72e - res 7, [hl] - ld hl, wd736 - res 0, [hl] - res 1, [hl] - xor a - ld [wNPCMovementScriptSpriteOffset], a - ld [wNPCMovementScriptFunctionNum], a - ld [wNPCMovementScriptPointerTableNum], a - ld [wWastedByteCD3A], a - ld [wSimulatedJoypadStatesIndex], a - ld [wSimulatedJoypadStatesEnd], a - ret - -PalletMovementScriptPointerTable: - dw PalletMovementScript_OakMoveLeft - dw PalletMovementScript_PlayerMoveLeft - dw PalletMovementScript_WaitAndWalkToLab - dw PalletMovementScript_WalkToLab - dw PalletMovementScript_Done - -PalletMovementScript_OakMoveLeft: - ld a, [wXCoord] - sub $a - ld [wNumStepsToTake], a - jr z, .playerOnLeftTile -; The player is on the right tile of the northern path out of Pallet Town and -; Prof. Oak is below. -; Make Prof. Oak step to the left. - ld b, 0 - ld c, a - ld hl, wNPCMovementDirections2 - ld a, NPC_MOVEMENT_LEFT - call FillMemory - ld [hl], $ff - ld a, [wSpriteIndex] - ld [H_SPRITEINDEX], a - ld de, wNPCMovementDirections2 - call MoveSprite - ld a, $1 - ld [wNPCMovementScriptFunctionNum], a - jr .done -; The player is on the left tile of the northern path out of Pallet Town and -; Prof. Oak is below. -; Prof. Oak is already where he needs to be. -.playerOnLeftTile - ld a, $3 - ld [wNPCMovementScriptFunctionNum], a -.done - ld a, BANK(Music_MuseumGuy) - ld c, a - ld a, MUSIC_MUSEUM_GUY - call PlayMusic - ld hl, wFlags_D733 - set 1, [hl] - ld a, $fc - ld [wJoyIgnore], a - ret - -PalletMovementScript_PlayerMoveLeft: - ld a, [wd730] - bit 0, a ; is an NPC being moved by a script? - ret nz ; return if Oak is still moving - ld a, [wNumStepsToTake] - ld [wSimulatedJoypadStatesIndex], a - ld [hNPCMovementDirections2Index], a - predef ConvertNPCMovementDirectionsToJoypadMasks - call StartSimulatingJoypadStates - ld a, $2 - ld [wNPCMovementScriptFunctionNum], a - ret - -PalletMovementScript_WaitAndWalkToLab: - ld a, [wSimulatedJoypadStatesIndex] - and a ; is the player done moving left yet? - ret nz - -PalletMovementScript_WalkToLab: - xor a - ld [wOverrideSimulatedJoypadStatesMask], a - ld a, [wSpriteIndex] - swap a - ld [wNPCMovementScriptSpriteOffset], a - xor a - ld [wSpriteStateData2 + $06], a - ld hl, wSimulatedJoypadStatesEnd - ld de, RLEList_PlayerWalkToLab - call DecodeRLEList - dec a - ld [wSimulatedJoypadStatesIndex], a - ld hl, wNPCMovementDirections2 - ld de, RLEList_ProfOakWalkToLab - call DecodeRLEList - ld hl, wd72e - res 7, [hl] - ld hl, wd730 - set 7, [hl] - ld a, $4 - ld [wNPCMovementScriptFunctionNum], a - ret - - -RLEList_ProfOakWalkToLab: - db NPC_MOVEMENT_DOWN, $06 ; differs from red - db NPC_MOVEMENT_LEFT, $01 - db NPC_MOVEMENT_DOWN, $05 - db NPC_MOVEMENT_RIGHT, $03 - db NPC_MOVEMENT_UP, $01 - db $E0, $01 ; stand still - db $FF - -RLEList_PlayerWalkToLab: - db D_UP, $02 - db D_RIGHT, $03 - db D_DOWN, $05 - db D_LEFT, $01 - db D_DOWN, $07 ; differs from red - db $FF - -PalletMovementScript_Done: - ld a, [wSimulatedJoypadStatesIndex] - and a - ret nz - ld a, HS_PALLET_TOWN_OAK - ld [wMissableObjectIndex], a - predef HideObject - ld hl, wd730 - res 7, [hl] - ld hl, wd72e - res 7, [hl] - jp EndNPCMovementScript - -PewterMuseumGuyMovementScriptPointerTable: - dw PewterMovementScript_WalkToMuseum - dw PewterMovementScript_Done - -PewterMovementScript_WalkToMuseum: - ld a, BANK(Music_MuseumGuy) - ld c, a - ld a, MUSIC_MUSEUM_GUY - call PlayMusic - ld a, [wSpriteIndex] - swap a - ld [wNPCMovementScriptSpriteOffset], a - call StartSimulatingJoypadStates - ld hl, wSimulatedJoypadStatesEnd - ld de, RLEList_PewterMuseumPlayer - call DecodeRLEList - dec a - ld [wSimulatedJoypadStatesIndex], a - xor a - ld [wWhichPewterGuy], a - call PewterGuys - ld hl, wNPCMovementDirections2 - ld de, RLEList_PewterMuseumGuy - call DecodeRLEList - ld hl, wd72e - res 7, [hl] - ld a, $1 - ld [wNPCMovementScriptFunctionNum], a - ret - -RLEList_PewterMuseumPlayer: - db 0, $01 - db D_UP, $03 - db D_LEFT, $0D - db D_UP, $06 - db $FF - -RLEList_PewterMuseumGuy: - db NPC_MOVEMENT_UP, $06 - db NPC_MOVEMENT_LEFT, $0D - db NPC_MOVEMENT_UP, $03 - db NPC_MOVEMENT_LEFT, $01 - db $FF - -PewterMovementScript_Done: - ld a, [wSimulatedJoypadStatesIndex] - and a - ret nz - ld hl, wd730 - res 7, [hl] - ld hl, wd72e - res 7, [hl] - jp EndNPCMovementScript - -PewterGymGuyMovementScriptPointerTable: - dw PewterMovementScript_WalkToGym - dw PewterMovementScript_Done - -PewterMovementScript_WalkToGym: - ld a, BANK(Music_MuseumGuy) - ld c, a - ld a, MUSIC_MUSEUM_GUY - call PlayMusic - ld a, [wSpriteIndex] - swap a - ld [wNPCMovementScriptSpriteOffset], a - xor a - ld [wSpriteStateData2 + $06], a - ld hl, wSimulatedJoypadStatesEnd - ld de, RLEList_PewterGymPlayer - call DecodeRLEList - dec a - ld [wSimulatedJoypadStatesIndex], a - ld a, 1 - ld [wWhichPewterGuy], a - call PewterGuys - ld hl, wNPCMovementDirections2 - ld de, RLEList_PewterGymGuy - call DecodeRLEList - ld hl, wd72e - res 7, [hl] - ld hl, wd730 - set 7, [hl] - ld a, $1 - ld [wNPCMovementScriptFunctionNum], a - ret - -RLEList_PewterGymPlayer: - db 0, $01 - db D_RIGHT, $02 - db D_DOWN, $05 - db D_LEFT, $0B - db D_UP, $05 - db D_LEFT, $0F - db $FF - -RLEList_PewterGymGuy: - db NPC_MOVEMENT_DOWN, $02 - db NPC_MOVEMENT_LEFT, $0F - db NPC_MOVEMENT_UP, $05 - db NPC_MOVEMENT_LEFT, $0B - db NPC_MOVEMENT_DOWN, $05 - db NPC_MOVEMENT_RIGHT, $03 - db $FF - -INCLUDE "engine/overworld/pewter_guys.asm" diff --git a/engine/overworld/npc_movement_2.asm b/engine/overworld/npc_movement_2.asm index 93d1afce..2ced9da6 100755 --- a/engine/overworld/npc_movement_2.asm +++ b/engine/overworld/npc_movement_2.asm @@ -1,4 +1,4 @@ -FreezeEnemyTrainerSprite: +FreezeEnemyTrainerSprite:: ld a, [wCurMap] cp POKEMON_TOWER_7F ret z ; the Rockets on Pokemon Tower 7F leave after battling, so don't freeze them @@ -7,18 +7,18 @@ FreezeEnemyTrainerSprite: ld b, a .loop ld a, [hli] - cp $ff + cp -1 jr z, .notRival cp b ret z ; the rival leaves after battling, so don't freeze him jr .loop .notRival ld a, [wSpriteIndex] - ld [H_SPRITEINDEX], a + ldh [hSpriteIndex], a jp SetSpriteMovementBytesToFF RivalIDs: - db OPP_SONY1 - db OPP_SONY2 - db OPP_SONY3 - db $ff + db OPP_RIVAL1 + db OPP_RIVAL2 + db OPP_RIVAL3 + db -1 ; end diff --git a/engine/overworld/oaks_aide.asm b/engine/overworld/oaks_aide.asm deleted file mode 100755 index f5068fda..00000000 --- a/engine/overworld/oaks_aide.asm +++ /dev/null @@ -1,71 +0,0 @@ -OaksAideScript: - ld hl, OaksAideHiText - call PrintText - call YesNoChoice - ld a, [wCurrentMenuItem] - and a - jr nz, .choseNo - ld hl, wPokedexOwned - ld b, wPokedexOwnedEnd - wPokedexOwned - call CountSetBits - ld a, [wNumSetBits] - ld [hOaksAideNumMonsOwned], a - ld b, a - ld a, [hOaksAideRequirement] - cp b - jr z, .giveItem - jr nc, .notEnoughOwnedMons -.giveItem - ld hl, OaksAideHereYouGoText - call PrintText - ld a, [hOaksAideRewardItem] - ld b, a - ld c, 1 - call GiveItem - jr nc, .bagFull - ld hl, OaksAideGotItemText - call PrintText - ld a, $1 - jr .done -.bagFull - ld hl, OaksAideNoRoomText - call PrintText - xor a - jr .done -.notEnoughOwnedMons - ld hl, OaksAideUhOhText - call PrintText - ld a, $80 - jr .done -.choseNo - ld hl, OaksAideComeBackText - call PrintText - ld a, $ff -.done - ld [hOaksAideResult], a - ret - -OaksAideHiText: - TX_FAR _OaksAideHiText - db "@" - -OaksAideUhOhText: - TX_FAR _OaksAideUhOhText - db "@" - -OaksAideComeBackText: - TX_FAR _OaksAideComeBackText - db "@" - -OaksAideHereYouGoText: - TX_FAR _OaksAideHereYouGoText - db "@" - -OaksAideGotItemText: - TX_FAR _OaksAideGotItemText - TX_SFX_ITEM_1 - db "@" - -OaksAideNoRoomText: - TX_FAR _OaksAideNoRoomText - db "@" diff --git a/engine/overworld/oam.asm b/engine/overworld/oam.asm deleted file mode 100644 index 5a831327..00000000 --- a/engine/overworld/oam.asm +++ /dev/null @@ -1,232 +0,0 @@ -PrepareOAMData: -; Determine OAM data for currently visible -; sprites and write it to wOAMBuffer. -; Yellow code has been changed to use registers more efficiently -; as well as tweaking the code to show gbc palettes - - ld a, [wUpdateSpritesEnabled] - dec a - jr z, .updateEnabled - - cp -1 - ret nz - ld [wUpdateSpritesEnabled], a - jp HideSprites - -.updateEnabled - xor a - ld [hOAMBufferOffset], a - -.spriteLoop - ld [hSpriteOffset2], a - - ld e, a - ld d, wSpriteStateData1 / $100 - - ld a, [de] ; c1x0 - and a - jp z, .nextSprite - - inc e - inc e - ld a, [de] ; c1x2 (facing/anim) - ld [wd5cd], a - cp $ff ; off-screen (don't draw) - jr nz, .visible - - call GetSpriteScreenXY - jr .nextSprite - -.visible - cp $a0 ; is the sprite unchanging like an item ball or boulder? - jr c, .usefacing - -; unchanging - ld a, $0 - jr .next - -.usefacing - and $f - -.next -; read the entry from the table - ld c, a - ld b, 0 - ld hl, SpriteFacingAndAnimationTable - add hl, bc - add hl, bc - ld a, [hli] - ld h, [hl] - ld l, a -; get sprite priority - push de - inc d - ld a, e - add $5 - ld e, a - ld a, [de] ; c2x7 - and $80 - ld [hSpritePriority], a ; temp store sprite priority - pop de - - - call GetSpriteScreenXY - - ld a, [hOAMBufferOffset] - add [hl] - cp $a0 - jr z, .hidden - jr nc, .asm_4a41 -.hidden - call Func_4a7b - ld [wd5cd], a - ld a, [hOAMBufferOffset] - - ld e, a - ld d, wOAMBuffer / $100 - -.tileLoop - ld a, [hli] - ld c, a -.loop - ld a, [hSpriteScreenY] ; temp for sprite Y position - add $10 ; Y=16 is top of screen (Y=0 is invisible) - add [hl] ; add Y offset from table - ld [de], a ; write new sprite OAM Y position - inc hl - inc e - ld a, [hSpriteScreenX] ; temp for sprite X position - add $8 ; X=8 is left of screen (X=0 is invisible) - add [hl] ; add X offset from table - ld [de], a - inc hl - inc e - ld a, [wd5cd] - add [hl] - cp $80 - jr c, .asm_4a1c - ld b, a - ld a, [$fffc] - add b -.asm_4a1c - ld [de], a ; tile id - inc hl - inc e - ld a, [hl] - bit 1, a ; is the tile allowed to set the sprite priority bit? - jr z, .skipPriority - ld a, [hSpritePriority] - or [hl] -.skipPriority - and $f0 - bit 4, a ; OBP0 or OBP1 - jr z, .spriteusesOBP0 - or %100 ; palettes 4-7 are OBP1 -.spriteusesOBP0 - ld [de], a - inc hl - inc e - dec c - jr nz, .loop - - ld a, e - ld [hOAMBufferOffset], a -.nextSprite - ld a, [hSpriteOffset2] - add $10 - cp $100 % $100 - jp nz, .spriteLoop - - ; Clear unused OAM. -.asm_4a41 - ld a, [wd736] - bit 6, a ; jumping down ledge or fishing animation? - ld c, $a0 - jr z, .clear - -; Don't clear the last 4 entries because they are used for the shadow in the -; jumping down ledge animation and the rod in the fishing animation. - ld c, $90 - -.clear - ld a, [hOAMBufferOffset] - cp c - ret nc - ld l, a - ld h, wOAMBuffer / $100 - ld a, c - ld de, $4 ; entry size - ld b, $a0 -.clearLoop - ld [hl], b - add hl, de - cp l - jr nz, .clearLoop - ret - -GetSpriteScreenXY: - inc e - inc e - ld a, [de] ; c1x4 - ld [hSpriteScreenY], a - inc e - inc e - ld a, [de] ; c1x6 - ld [hSpriteScreenX], a - ld a, 4 - add e - ld e, a - ld a, [hSpriteScreenY] - add 4 - and $f0 - ld [de], a ; c1xa (y) - inc e - ld a, [hSpriteScreenX] - and $f0 - ld [de], a ; c1xb (x) - ret - -Func_4a7b: - push bc - ld a, [wd5cd] ; temp copy of c1x2 - swap a ; high nybble determines sprite used (0 is always player sprite, next are some npcs) - and $f - - ; Sprites $a and $b have one face (and therefore 4 tiles instead of 12). - ; As a result, sprite $b's tile offset is less than normal. - cp $b - jr nz, .notFourTileSprite - ld a, $a * 12 + 4 ; $7c - jr .done - -.notFourTileSprite - ; a *= 12 - add a - add a - ld c, a - add a - add c -.done - pop bc - ret - -INCLUDE "engine/oam_dma.asm" - -_IsTilePassable:: - ld hl,wTilesetCollisionPtr ; pointer to list of passable tiles - ld a,[hli] - ld h,[hl] - ld l,a ; hl now points to passable tiles -.loop - ld a,[hli] - cp a,$ff - jr z,.tileNotPassable - cp c - jr nz,.loop - xor a - ret -.tileNotPassable - scf - ret - -INCLUDE "data/collision.asm" ; probably diff --git a/engine/overworld/pathfinding.asm b/engine/overworld/pathfinding.asm new file mode 100644 index 00000000..a824d337 --- /dev/null +++ b/engine/overworld/pathfinding.asm @@ -0,0 +1,201 @@ +FindPathToPlayer: + xor a + ld hl, hFindPathNumSteps + ld [hli], a ; hFindPathNumSteps + ld [hli], a ; hFindPathFlags + ld [hli], a ; hFindPathYProgress + ld [hl], a ; hFindPathXProgress + ld hl, wNPCMovementDirections2 + ld de, $0 +.loop + ldh a, [hFindPathYProgress] + ld b, a + ldh a, [hNPCPlayerYDistance] ; Y distance in steps + call CalcDifference + ld d, a + and a + jr nz, .asm_f76a + ldh a, [hFindPathFlags] + set 0, a ; current end of path matches the player's Y coordinate + ldh [hFindPathFlags], a +.asm_f76a + ldh a, [hFindPathXProgress] + ld b, a + ldh a, [hNPCPlayerXDistance] ; X distance in steps + call CalcDifference + ld e, a + and a + jr nz, .asm_f77c + ldh a, [hFindPathFlags] + set 1, a ; current end of path matches the player's X coordinate + ldh [hFindPathFlags], a +.asm_f77c + ldh a, [hFindPathFlags] + cp $3 ; has the end of the path reached the player's position? + jr z, .done +; Compare whether the X distance between the player and the current of the path +; is greater or if the Y distance is. Then, try to reduce whichever is greater. + ld a, e + cp d + jr c, .yDistanceGreater +; x distance is greater + ldh a, [hNPCPlayerRelativePosFlags] + bit 1, a + jr nz, .playerIsLeftOfNPC + ld d, NPC_MOVEMENT_RIGHT + jr .next1 +.playerIsLeftOfNPC + ld d, NPC_MOVEMENT_LEFT +.next1 + ldh a, [hFindPathXProgress] + add 1 + ldh [hFindPathXProgress], a + jr .storeDirection +.yDistanceGreater + ldh a, [hNPCPlayerRelativePosFlags] + bit 0, a + jr nz, .playerIsAboveNPC + ld d, NPC_MOVEMENT_DOWN + jr .next2 +.playerIsAboveNPC + ld d, NPC_MOVEMENT_UP +.next2 + ldh a, [hFindPathYProgress] + add 1 + ldh [hFindPathYProgress], a +.storeDirection + ld a, d + ld [hli], a + ldh a, [hFindPathNumSteps] + inc a + ldh [hFindPathNumSteps], a + jp .loop +.done + ld [hl], $ff + ret + +CalcPositionOfPlayerRelativeToNPC: + xor a + ldh [hNPCPlayerRelativePosFlags], a + ld a, [wSpritePlayerStateData1YPixels] + ld d, a + ld a, [wSpritePlayerStateData1XPixels] + ld e, a + ld hl, wSpriteStateData1 + ldh a, [hNPCSpriteOffset] + add l + add SPRITESTATEDATA1_YPIXELS + ld l, a + jr nc, .noCarry + inc h +.noCarry + ld a, d + ld b, a + ld a, [hli] ; NPC sprite screen Y position in pixels + call CalcDifference + jr nc, .NPCSouthOfOrAlignedWithPlayer +.NPCNorthOfPlayer + push hl + ld hl, hNPCPlayerRelativePosFlags + bit 0, [hl] + set 0, [hl] + pop hl + jr .divideYDistance +.NPCSouthOfOrAlignedWithPlayer + push hl + ld hl, hNPCPlayerRelativePosFlags + bit 0, [hl] + res 0, [hl] + pop hl +.divideYDistance + push hl + ld hl, hDividend2 + ld [hli], a + ld a, 16 + ld [hli], a + call DivideBytes ; divide Y absolute distance by 16 + ld a, [hl] ; quotient + ldh [hNPCPlayerYDistance], a + pop hl + inc hl + ld b, e + ld a, [hl] ; NPC sprite screen X position in pixels + call CalcDifference + jr nc, .NPCEastOfOrAlignedWithPlayer +.NPCWestOfPlayer + push hl + ld hl, hNPCPlayerRelativePosFlags + bit 1, [hl] + set 1, [hl] + pop hl + jr .divideXDistance +.NPCEastOfOrAlignedWithPlayer + push hl + ld hl, hNPCPlayerRelativePosFlags + bit 1, [hl] + res 1, [hl] + pop hl +.divideXDistance + ldh [hDividend2], a + ld a, 16 + ldh [hDivisor2], a + call DivideBytes ; divide X absolute distance by 16 + ldh a, [hQuotient2] + ldh [hNPCPlayerXDistance], a + ldh a, [hNPCPlayerRelativePosPerspective] + and a + ret z + ldh a, [hNPCPlayerRelativePosFlags] + cpl + and $3 + ldh [hNPCPlayerRelativePosFlags], a + ret + +ConvertNPCMovementDirectionsToJoypadMasks: + ldh a, [hNPCMovementDirections2Index] + ld [wNPCMovementDirections2Index], a + dec a + ld de, wSimulatedJoypadStatesEnd + ld hl, wNPCMovementDirections2 + add l + ld l, a + jr nc, .loop + inc h +.loop + ld a, [hld] + call ConvertNPCMovementDirectionToJoypadMask + ld [de], a + inc de + ldh a, [hNPCMovementDirections2Index] + dec a + ldh [hNPCMovementDirections2Index], a + jr nz, .loop + ret + +ConvertNPCMovementDirectionToJoypadMask: + push hl + ld b, a + ld hl, NPCMovementDirectionsToJoypadMasksTable +.loop + ld a, [hli] + cp $ff + jr z, .done + cp b + jr z, .loadJoypadMask + inc hl + jr .loop +.loadJoypadMask + ld a, [hl] +.done + pop hl + ret + +NPCMovementDirectionsToJoypadMasksTable: + db NPC_MOVEMENT_UP, D_UP + db NPC_MOVEMENT_DOWN, D_DOWN + db NPC_MOVEMENT_LEFT, D_LEFT + db NPC_MOVEMENT_RIGHT, D_RIGHT + db $ff + +; unreferenced + ret diff --git a/engine/overworld/pewter_guys.asm b/engine/overworld/pewter_guys.asm deleted file mode 100755 index 532fa4bf..00000000 --- a/engine/overworld/pewter_guys.asm +++ /dev/null @@ -1,102 +0,0 @@ -PewterGuys: - ld hl, wSimulatedJoypadStatesEnd - ld a, [wSimulatedJoypadStatesIndex] - dec a ; this decrement causes it to overwrite the last byte before $FF in the list - ld [wSimulatedJoypadStatesIndex], a - ld d, 0 - ld e, a - add hl, de - ld d, h - ld e, l - ld hl, PointerTable_37ce6 - ld a, [wWhichPewterGuy] - add a - ld b, 0 - ld c, a - add hl, bc - ld a, [hli] - ld h, [hl] - ld l, a - ld a, [wYCoord] - ld b, a - ld a, [wXCoord] - ld c, a -.findMatchingCoordsLoop - ld a, [hli] - cp b - jr nz, .nextEntry1 - ld a, [hli] - cp c - jr nz, .nextEntry2 - ld a, [hli] - ld h, [hl] - ld l, a -.copyMovementDataLoop - ld a, [hli] - cp $ff - ret z - ld [de], a - inc de - ld a, [wSimulatedJoypadStatesIndex] - inc a - ld [wSimulatedJoypadStatesIndex], a - jr .copyMovementDataLoop -.nextEntry1 - inc hl -.nextEntry2 - inc hl - inc hl - jr .findMatchingCoordsLoop - -PointerTable_37ce6: - dw PewterMuseumGuyCoords - dw PewterGymGuyCoords - -; these are the four coordinates of the spaces below, above, to the left and -; to the right of the museum guy, and pointers to different movements for -; the player to make to get positioned before the main movement. -PewterMuseumGuyCoords: - db 18, 27 - dw .down - db 16, 27 - dw .up - db 17, 26 - dw .left - db 17, 28 - dw .right - -.down - db D_UP, D_UP, $ff -.up - db D_RIGHT, D_LEFT, $ff -.left - db D_UP, D_RIGHT, $ff -.right - db D_UP, D_LEFT, $ff - -; these are the five coordinates which trigger the gym guy and pointers to -; different movements for the player to make to get positioned before the -; main movement -; $00 is a pause -PewterGymGuyCoords: - db 16, 34 - dw .one - db 17, 35 - dw .two - db 18, 37 - dw .three - db 19, 37 - dw .four - db 17, 36 - dw .five - -.one - db D_LEFT, D_DOWN, D_DOWN, D_RIGHT, $ff -.two - db D_LEFT, D_DOWN, D_RIGHT, D_LEFT, $ff -.three - db D_LEFT, D_LEFT, D_LEFT, $00, $00, $00, $00, $00, $00, $00, $00, $ff -.four - db D_LEFT, D_LEFT, D_UP, D_LEFT, $ff -.five - db D_LEFT, D_DOWN, D_LEFT, $00, $00, $00, $00, $00, $00, $00, $00, $ff diff --git a/engine/overworld/player_animations.asm b/engine/overworld/player_animations.asm index d4ecec53..5056c0b2 100755 --- a/engine/overworld/player_animations.asm +++ b/engine/overworld/player_animations.asm @@ -1,7 +1,7 @@ -EnterMapAnim: +EnterMapAnim:: call InitFacingDirectionList ld a, $ec - ld [wSpriteStateData1 + 4], a ; player's sprite Y screen position + ld [wSpritePlayerStateData1YPixels], a call Delay3 push hl call GBFadeInFromWhite @@ -94,7 +94,7 @@ PlayerSpinWhileMovingDown: jp PlayerSpinWhileMovingUpOrDown -_LeaveMapAnim: +_LeaveMapAnim:: call Func_1510 call InitFacingDirectionList call IsPlayerStandingOnWarpPadOrHole @@ -232,19 +232,19 @@ DoFlyAnimation: ld a, [wFlyAnimBirdSpriteImageIndex] xor $1 ; make the bird flap its wings ld [wFlyAnimBirdSpriteImageIndex], a - ld [wSpriteStateData1 + 2], a + ld [wSpritePlayerStateData1ImageIndex], a call Delay3 ld a, [wFlyAnimUsingCoordList] cp $ff jr z, .skipCopyingCoords ; if the bird is flapping its wings in place - ld hl, wSpriteStateData1 + 4 + ld hl, wSpritePlayerStateData1YPixels ld a, [de] inc de - ld [hli], a + ld [hli], a ; y inc hl ld a, [de] inc de - ld [hl], a + ld [hl], a ; x .skipCopyingCoords ld a, [wFlyAnimCounter] dec a @@ -258,22 +258,22 @@ LoadBirdSpriteGraphics: ld c, $c ld hl, vNPCSprites call CopyVideoData - ld de, BirdSprite + $c0 ; moving animation sprite + ld de, BirdSprite tile 12 ; moving animation sprite ld b, BANK(BirdSprite) - ld c, $0c + ld c, 12 ld hl, vNPCSprites2 jp CopyVideoData InitFacingDirectionList: - ld a, [wSpriteStateData1 + 2] ; player's sprite facing direction (image index is locked to standing images) + ld a, [wSpritePlayerStateData1ImageIndex] ; (image index is locked to standing images) ld [wSavedPlayerFacingDirection], a - ld a, [wSpriteStateData1 + 4] ; player's sprite Y screen position + ld a, [wSpritePlayerStateData1YPixels] ld [wSavedPlayerScreenY], a ld hl, PlayerSpinningFacingOrder ld de, wFacingDirectionList ld bc, 4 call CopyData - ld a, [wSpriteStateData1 + 2] ; player's sprite facing direction (image index is locked to standing images) + ld a, [wSpritePlayerStateData1ImageIndex] ; (image index is locked to standing images) ld hl, wFacingDirectionList ; find the place in the list that matches the current facing direction .loop @@ -291,7 +291,7 @@ PlayerSpinningFacingOrder: SpinPlayerSprite: ; copy the current value from the list into the sprite data and rotate the list ld a, [hl] - ld [wSpriteStateData1 + 2], a ; player's sprite facing direction (image index is locked to standing images) + ld [wSpritePlayerStateData1ImageIndex], a ; (image index is locked to standing images) push hl ld hl, wFacingDirectionList ld de, wFacingDirectionList - 1 @@ -327,9 +327,9 @@ PlayerSpinWhileMovingUpOrDown: call SpinPlayerSprite ld a, [wPlayerSpinWhileMovingUpOrDownAnimDeltaY] ld c, a - ld a, [wSpriteStateData1 + 4] ; player's sprite Y screen position + ld a, [wSpritePlayerStateData1YPixels] add c - ld [wSpriteStateData1 + 4], a + ld [wSpritePlayerStateData1YPixels], a ld c, a ld a, [wPlayerSpinWhileMovingUpOrDownAnimMaxY] cp c @@ -341,9 +341,9 @@ PlayerSpinWhileMovingUpOrDown: RestoreFacingDirectionAndYScreenPos: ld a, [wSavedPlayerScreenY] - ld [wSpriteStateData1 + 4], a + ld [wSpritePlayerStateData1YPixels], a ld a, [wSavedPlayerFacingDirection] - ld [wSpriteStateData1 + 2], a + ld [wSpritePlayerStateData1ImageIndex], a ; (image index is locked to standing images) ret ; if SGB, 2 frames, else 3 frames @@ -354,9 +354,9 @@ GetPlayerTeleportAnimFrameDelay: inc a ret -IsPlayerStandingOnWarpPadOrHole: +IsPlayerStandingOnWarpPadOrHole:: ld b, 0 - ld hl, .warpPadAndHoleData + ld hl, WarpPadAndHoleData ld a, [wCurMapTileset] ld c, a .loop @@ -365,7 +365,7 @@ IsPlayerStandingOnWarpPadOrHole: jr z, .done cp c jr nz, .nextEntry - aCoord 8, 9 + lda_coord 8, 9 cp [hl] jr z, .foundMatch .nextEntry @@ -380,13 +380,7 @@ IsPlayerStandingOnWarpPadOrHole: ld [wStandingOnWarpPadOrHole], a ret -; format: db tileset id, tile id, value to be put in [wStandingOnWarpPadOrHole] -.warpPadAndHoleData: - db FACILITY, $20, 1 ; warp pad - db FACILITY, $11, 2 ; hole - db CAVERN, $22, 2 ; hole - db INTERIOR, $55, 1 ; warp pad - db $FF +INCLUDE "data/tilesets/warp_pad_hole_tile_ids.asm" FishingAnim: ld c, 10 @@ -396,12 +390,12 @@ FishingAnim: ld hl, vNPCSprites ld de, RedSprite ld b, BANK(RedSprite) - ld c, $c + ld c, 12 call CopyVideoData ld a, $4 ld hl, RedFishingTiles call LoadAnimSpriteGfx - ld a, [wSpriteStateData1 + 2] + ld a, [wSpritePlayerStateData1ImageIndex] ld c, a ld b, $0 ld hl, FishingRodOAM @@ -424,7 +418,7 @@ FishingAnim: ; shake the player's sprite vertically ld b, 10 .loop - ld hl, wSpriteStateData1 + 4 ; player's sprite Y screen position + ld hl, wSpritePlayerStateData1YPixels call .ShakePlayerSprite ld hl, wOAMBuffer + $9c call .ShakePlayerSprite @@ -434,7 +428,7 @@ FishingAnim: ; If the player is facing up, hide the fishing rod so it doesn't overlap with ; the exclamation bubble that will be shown next. - ld a, [wSpriteStateData1 + 2] ; player's sprite facing direction + ld a, [wSpritePlayerStateData1ImageIndex] ; (image index is locked to standing images) cp SPRITE_FACING_UP jr nz, .skipHidingFishingRod ld a, $a0 @@ -448,7 +442,7 @@ FishingAnim: predef EmotionBubble ; If the player is facing up, unhide the fishing rod. - ld a, [wSpriteStateData1 + 2] ; player's sprite facing direction + ld a, [wSpritePlayerStateData1ImageIndex] ; (image index is locked to standing images) cp SPRITE_FACING_UP jr nz, .skipUnhidingFishingRod ld a, $44 @@ -471,46 +465,38 @@ FishingAnim: ret NoNibbleText: - TX_FAR _NoNibbleText - db "@" + text_far _NoNibbleText + text_end NothingHereText: - TX_FAR _NothingHereText - db "@" + text_far _NothingHereText + text_end ItsABiteText: - TX_FAR _ItsABiteText - db "@" + text_far _ItsABiteText + text_end FishingRodOAM: ; specifies how the fishing rod should be drawn on the screen -; first byte = screen y coordinate -; second byte = screen x coordinate -; third byte = tile number -; fourth byte = sprite properties - db $5B, $4C, $FD, $00 ; player facing down - db $44, $4C, $FD, $00 ; player facing up - db $50, $40, $FE, $00 ; player facing left - db $50, $58, $FE, $20 ; player facing right ($20 means "horizontally flip the tile") + dbsprite 9, 11, 4, 3, $fd, 0 ; down + dbsprite 9, 8, 4, 4, $fd, 0 ; up + dbsprite 8, 10, 0, 0, $fe, 0 ; left + dbsprite 11, 10, 0, 0, $fe, OAM_HFLIP ; right + +fishing_gfx: MACRO + dw \1 + db \2 + db BANK(\1) + dw vNPCSprites tile \3 +ENDM RedFishingTiles: - dw RedFishingTilesFront - db 2, BANK(RedFishingTilesFront) - dw vNPCSprites + $20 - - dw RedFishingTilesBack - db 2, BANK(RedFishingTilesBack) - dw vNPCSprites + $60 - - dw RedFishingTilesSide - db 2, BANK(RedFishingTilesSide) - dw vNPCSprites + $a0 - - dw RedFishingRodTiles - db 3, BANK(RedFishingRodTiles) - dw vNPCSprites2 + $7d0 + fishing_gfx RedFishingTilesFront, 2, $02 + fishing_gfx RedFishingTilesBack, 2, $06 + fishing_gfx RedFishingTilesSide, 2, $0a + fishing_gfx RedFishingRodTiles, 3, $fd -_HandleMidJump: +_HandleMidJump:: ld a, [wPlayerJumpingYScreenCoordsIndex] ld c, a inc a @@ -521,7 +507,7 @@ _HandleMidJump: ld hl, PlayerJumpingYScreenCoords add hl, bc ld a, [hl] - ld [wSpriteStateData1 + 4], a ; player's sprite y coordinate + ld [wSpritePlayerStateData1YPixels], a ret .finishedJump ld a, [wWalkCounter] @@ -530,9 +516,9 @@ _HandleMidJump: call UpdateSprites call Delay3 xor a - ld [hJoyHeld], a - ld [hJoyPressed], a - ld [hJoyReleased], a + ldh [hJoyHeld], a + ldh [hJoyPressed], a + ldh [hJoyReleased], a ld [wPlayerJumpingYScreenCoordsIndex], a ld hl, wd736 res 6, [hl] ; not jumping down a ledge any more diff --git a/engine/overworld/player_state.asm b/engine/overworld/player_state.asm index 8cbacc61..c966c128 100644 --- a/engine/overworld/player_state.asm +++ b/engine/overworld/player_state.asm @@ -1,5 +1,5 @@ ; only used for setting bit 2 of wd736 upon entering a new map -IsPlayerStandingOnWarp: +IsPlayerStandingOnWarp:: ld a, [wNumberOfWarps] and a ret z @@ -17,7 +17,7 @@ IsPlayerStandingOnWarp: ld a, [hli] ; target warp ld [wDestinationWarpID], a ld a, [hl] ; target map - ld [hWarpDestinationMap], a + ldh [hWarpDestinationMap], a ld hl, wd736 set 2, [hl] ; standing on warp flag ret @@ -31,7 +31,7 @@ IsPlayerStandingOnWarp: jr nz, .loop ret -CheckForceBikeOrSurf: +CheckForceBikeOrSurf:: ld hl, wd732 bit 5, [hl] ret nz @@ -84,13 +84,13 @@ CheckForceBikeOrSurf: call ForceBikeOrSurf ret -INCLUDE "data/force_bike_surf.asm" +INCLUDE "data/maps/force_bike_surf.asm" -IsPlayerFacingEdgeOfMap: +IsPlayerFacingEdgeOfMap:: push hl push de push bc - ld a, [wSpriteStateData1 + 9] ; player sprite's facing direction + ld a, [wSpritePlayerStateData1FacingDirection] srl a ld c, a ld b, $0 @@ -152,19 +152,19 @@ IsPlayerFacingEdgeOfMap: scf ret -IsWarpTileInFrontOfPlayer: +IsWarpTileInFrontOfPlayer:: push hl push de push bc call _GetTileAndCoordsInFrontOfPlayer ld a, [wCurMap] cp SS_ANNE_BOW - jr z, .ssAnne5 - ld a, [wSpriteStateData1 + 9] ; player sprite's facing direction + jr z, IsSSAnneBowWarpTileInFrontOfPlayer + ld a, [wSpritePlayerStateData1FacingDirection] srl a ld c, a ld b, 0 - ld hl, .warpTileListPointers + ld hl, WarpTileListPointers add hl, bc ld a, [hli] ld h, [hl] @@ -178,39 +178,23 @@ IsWarpTileInFrontOfPlayer: pop hl ret -.warpTileListPointers: - dw .facingDownWarpTiles - dw .facingUpWarpTiles - dw .facingLeftWarpTiles - dw .facingRightWarpTiles +INCLUDE "data/tilesets/warp_carpet_tile_ids.asm" -.facingDownWarpTiles - db $01,$12,$17,$3D,$04,$18,$33,$FF - -.facingUpWarpTiles - db $01,$5C,$FF - -.facingLeftWarpTiles - db $1A,$4B,$FF - -.facingRightWarpTiles - db $0F,$4E,$FF - -.ssAnne5 +IsSSAnneBowWarpTileInFrontOfPlayer: ld a, [wTileInFrontOfPlayer] cp $15 jr nz, .notSSAnne5Warp scf - jr .done + jr IsWarpTileInFrontOfPlayer.done .notSSAnne5Warp and a - jr .done + jr IsWarpTileInFrontOfPlayer.done -IsPlayerStandingOnDoorTileOrWarpTile: +IsPlayerStandingOnDoorTileOrWarpTile:: push hl push de push bc - callba IsPlayerStandingOnDoorTile + farcall IsPlayerStandingOnDoorTile jr c, .done ld a, [wCurMapTileset] add a @@ -222,7 +206,7 @@ IsPlayerStandingOnDoorTileOrWarpTile: ld h, [hl] ld l, a ld de, $1 - aCoord 8, 9 + lda_coord 8, 9 call IsInArray jr nc, .done ld hl, wd736 @@ -233,35 +217,35 @@ IsPlayerStandingOnDoorTileOrWarpTile: pop hl ret -INCLUDE "data/warp_tile_ids.asm" +INCLUDE "data/tilesets/warp_tile_ids.asm" -PrintSafariZoneSteps: +PrintSafariZoneSteps:: ld a, [wCurMap] cp SAFARI_ZONE_EAST ret c cp CERULEAN_CAVE_2F ret nc - coord hl, 0, 0 + hlcoord 0, 0 lb bc, 3, 7 call TextBoxBorder - coord hl, 1, 1 + hlcoord 1, 1 ld de, wSafariSteps lb bc, 2, 3 call PrintNumber - coord hl, 4, 1 + hlcoord 4, 1 ld de, SafariSteps call PlaceString - coord hl, 1, 3 + hlcoord 1, 3 ld de, SafariBallText call PlaceString ld a, [wNumSafariBalls] cp 10 jr nc, .numSafariBallsTwoDigits - coord hl, 5, 3 + hlcoord 5, 3 ld a, " " ld [hl], a .numSafariBallsTwoDigits - coord hl, 6, 3 + hlcoord 6, 3 ld de, wNumSafariBalls lb bc, 1, 2 jp PrintNumber @@ -280,32 +264,32 @@ _GetTileAndCoordsInFrontOfPlayer: ld d, a ld a, [wXCoord] ld e, a - ld a, [wSpriteStateData1 + 9] ; player's sprite facing direction + ld a, [wSpritePlayerStateData1FacingDirection] and a ; cp SPRITE_FACING_DOWN jr nz, .notFacingDown ; facing down - aCoord 8, 11 + lda_coord 8, 11 inc d jr .storeTile .notFacingDown cp SPRITE_FACING_UP jr nz, .notFacingUp ; facing up - aCoord 8, 7 + lda_coord 8, 7 dec d jr .storeTile .notFacingUp cp SPRITE_FACING_LEFT jr nz, .notFacingLeft ; facing left - aCoord 6, 9 + lda_coord 6, 9 dec e jr .storeTile .notFacingLeft cp SPRITE_FACING_RIGHT jr nz, .storeTile ; facing right - aCoord 10, 9 + lda_coord 10, 9 inc e .storeTile ld c, a @@ -314,45 +298,45 @@ _GetTileAndCoordsInFrontOfPlayer: GetTileTwoStepsInFrontOfPlayer: xor a - ld [$ffdb], a + ldh [hPlayerFacing], a ld hl, wYCoord ld a, [hli] ld d, a ld e, [hl] - ld a, [wSpriteStateData1 + 9] ; player's sprite facing direction + ld a, [wSpritePlayerStateData1FacingDirection] and a ; cp SPRITE_FACING_DOWN jr nz, .notFacingDown ; facing down - ld hl, $ffdb + ld hl, hPlayerFacing set 0, [hl] - aCoord 8, 13 + lda_coord 8, 13 inc d jr .storeTile .notFacingDown cp SPRITE_FACING_UP jr nz, .notFacingUp ; facing up - ld hl, $ffdb + ld hl, hPlayerFacing set 1, [hl] - aCoord 8, 5 + lda_coord 8, 5 dec d jr .storeTile .notFacingUp cp SPRITE_FACING_LEFT jr nz, .notFacingLeft ; facing left - ld hl, $ffdb + ld hl, hPlayerFacing set 2, [hl] - aCoord 4, 9 + lda_coord 4, 9 dec e jr .storeTile .notFacingLeft cp SPRITE_FACING_RIGHT jr nz, .storeTile ; facing right - ld hl, $ffdb + ld hl, hPlayerFacing set 3, [hl] - aCoord 12, 9 + lda_coord 12, 9 inc e .storeTile ld c, a @@ -384,36 +368,36 @@ CheckForBoulderCollisionWithSprites: swap a ld d, 0 ld e, a - ld hl, wSpriteStateData2 + $14 + ld hl, wSprite01StateData2MapY add hl, de ld a, [hli] ; map Y position - ld [$ffdc], a + ldh [hPlayerYCoord], a ld a, [hl] ; map X position - ld [$ffdd], a + ldh [hPlayerXCoord], a ld a, [wNumSprites] ld c, a ld de, $f - ld hl, wSpriteStateData2 + $14 - ld a, [$ffdb] + ld hl, wSprite01StateData2MapY + ldh a, [hPlayerFacing] and $3 ; facing up or down? jr z, .pushingHorizontallyLoop .pushingVerticallyLoop inc hl - ld a, [$ffdd] + ldh a, [hPlayerXCoord] cp [hl] jr nz, .nextSprite1 ; if X coordinates don't match dec hl ld a, [hli] ld b, a - ld a, [$ffdb] + ldh a, [hPlayerFacing] rrca jr c, .pushingDown ; pushing up - ld a, [$ffdc] + ldh a, [hPlayerYCoord] dec a jr .compareYCoords .pushingDown - ld a, [$ffdc] + ldh a, [hPlayerYCoord] inc a .compareYCoords cp b @@ -426,19 +410,19 @@ CheckForBoulderCollisionWithSprites: .pushingHorizontallyLoop ld a, [hli] ld b, a - ld a, [$ffdc] + ldh a, [hPlayerYCoord] cp b jr nz, .nextSprite2 ld b, [hl] - ld a, [$ffdb] + ldh a, [hPlayerFacing] bit 2, a jr nz, .pushingLeft ; pushing right - ld a, [$ffdd] + ldh a, [hPlayerXCoord] inc a jr .compareXCoords .pushingLeft - ld a, [$ffdd] + ldh a, [hPlayerXCoord] dec a .compareXCoords cp b diff --git a/engine/overworld/poison.asm b/engine/overworld/poison.asm deleted file mode 100644 index 03fb8a65..00000000 --- a/engine/overworld/poison.asm +++ /dev/null @@ -1,151 +0,0 @@ -ApplyOutOfBattlePoisonDamage: - ld a, [wd730] - add a - jp c, .noBlackOut ; no black out if joypad states are being simulated - ld a, [wd492] - bit 7, a - jp nz, .noBlackOut - ld a, [wd72e] - bit 6, a - jp nz, .noBlackOut - ld a, [wPartyCount] - and a - jp z, .noBlackOut - call IncrementDayCareMonExp - call Func_c4c7 - ld a, [wStepCounter] - and $3 ; is the counter a multiple of 4? - jp nz, .skipPoisonEffectAndSound ; only apply poison damage every fourth step - ld [wWhichPokemon], a - ld hl, wPartyMon1Status - ld de, wPartySpecies -.applyDamageLoop - ld a, [hl] - and (1 << PSN) - jr z, .nextMon2 ; not poisoned - dec hl - dec hl - ld a, [hld] - ld b, a - ld a, [hli] - or b - jr z, .nextMon ; already fainted -; subtract 1 from HP - ld a, [hl] - dec a - ld [hld], a - inc a - jr nz, .noBorrow -; borrow 1 from upper byte of HP - dec [hl] - inc hl - jr .nextMon -.noBorrow - ld a, [hli] - or [hl] - jr nz, .nextMon ; didn't faint from damage -; the mon fainted from the damage - push hl - inc hl - inc hl - ld [hl], a - ld a, [de] - ld [wd11e], a - push de - ld a, [wWhichPokemon] - ld hl, wPartyMonNicks - call GetPartyMonName - xor a - ld [wJoyIgnore], a - call EnableAutoTextBoxDrawing - ld a, TEXT_MON_FAINTED - ld [hSpriteIndexOrTextID], a - call DisplayTextID - callab IsThisPartymonStarterPikachu_Party - jr nc, .curMonNotPlayerPikachu - ld e, $3 - callab PlayPikachuSoundClip - calladb_ModifyPikachuHappiness PIKAHAPPY_PSNFNT -.curMonNotPlayerPikachu - pop de - pop hl -.nextMon - inc hl - inc hl -.nextMon2 - inc de - ld a, [de] - inc a - jr z, .applyDamageLoopDone - ld bc, wPartyMon2 - wPartyMon1 - add hl, bc - push hl - ld hl, wWhichPokemon - inc [hl] - pop hl - jr .applyDamageLoop -.applyDamageLoopDone - ld hl, wPartyMon1Status - ld a, [wPartyCount] - ld d, a - ld e, 0 -.countPoisonedLoop - ld a, [hl] - and (1 << PSN) - or e - ld e, a - ld bc, wPartyMon2 - wPartyMon1 - add hl, bc - dec d - jr nz, .countPoisonedLoop - ld a, e - and a ; are any party members poisoned? - jr z, .skipPoisonEffectAndSound - ld b, $2 - predef ChangeBGPalColor0_4Frames ; change BG white to dark grey for 4 frames - ld a, SFX_POISONED - call PlaySound -.skipPoisonEffectAndSound - predef AnyPartyAlive - ld a, d - and a - jr nz, .noBlackOut - call EnableAutoTextBoxDrawing - ld a, TEXT_BLACKED_OUT - ld [hSpriteIndexOrTextID], a - call DisplayTextID - ld hl, wd72e - set 5, [hl] - ld a, $ff - jr .done -.noBlackOut - xor a -.done - ld [wOutOfBattleBlackout], a - ret - -Func_c4c7: - ld a, [wStepCounter] - and a - jr nz, .asm_c4de - call Random - and $1 - jr z, .asm_c4de - calladb_ModifyPikachuHappiness $6 -.asm_c4de - ld hl, wPikachuMood - ld a, [hl] - cp $80 - jr z, .asm_c4ef - jr c, .asm_c4ea - dec a - dec a -.asm_c4ea - inc a - ld [hl], a - cp $80 - ret nz -.asm_c4ef - xor a - ld [wd49c], a - ret diff --git a/engine/overworld/pokecenter.asm b/engine/overworld/pokecenter.asm deleted file mode 100755 index cf0159f9..00000000 --- a/engine/overworld/pokecenter.asm +++ /dev/null @@ -1,149 +0,0 @@ -DisplayPokemonCenterDialogue_: - ld a, [wCurMap] - cp PEWTER_POKECENTER - jr nz, .regularCenter - call CheckPikachuFollowingPlayer - jr z, .regularCenter - ld hl, LooksContentText ; if pikachu is sleeping, don't heal - call PrintText - ret -.regularCenter - call SaveScreenTilesToBuffer1 ; save screen - ld hl, PokemonCenterWelcomeText - call PrintText - ld hl, wd72e - bit 2, [hl] - set 1, [hl] - set 2, [hl] - jr nz, .skipShallWeHealYourPokemon - ld hl, ShallWeHealYourPokemonText - call PrintText -.skipShallWeHealYourPokemon - call YesNoChoicePokeCenter ; yes/no menu - call UpdateSprites - ld a, [wCurrentMenuItem] - and a - jp nz, .declinedHealing ; if the player chose No - call SetLastBlackoutMap - callab IsStarterPikachuInOurParty - jr nc, .notHealingPlayerPikachu - call CheckPikachuFollowingPlayer - jr nz, .notHealingPlayerPikachu - call LoadCurrentMapView - call Delay3 - call UpdateSprites - callab PikachuWalksToNurseJoy ; todo -.notHealingPlayerPikachu - ld hl, NeedYourPokemonText - call PrintText - ld c, 64 - call DelayFrames - call CheckPikachuFollowingPlayer - jr nz, .playerPikachuNotOnScreen - call DisablePikachuOverworldSpriteDrawing - callab IsStarterPikachuInOurParty - call c, Func_6eaa -.playerPikachuNotOnScreen - lb bc, 1, 8 - call Func_6ebb - ld c, 30 - call DelayFrames - callba AnimateHealingMachine ; do the healing machine animation - predef HealParty - xor a - ld [wAudioFadeOutControl], a - ld a, [wAudioSavedROMBank] - ld [wAudioROMBank], a - ld a, [wMapMusicSoundID] - ld [wLastMusicSoundID], a - ld [wNewSoundID], a - call PlaySound - call CheckPikachuFollowingPlayer - jr nz, .doNotReturnPikachu - callab IsStarterPikachuInOurParty - call c, Func_6eaa - ld a, $5 - ld [wPikachuSpawnState], a - call EnablePikachuOverworldSpriteDrawing -.doNotReturnPikachu - lb bc, 1, 0 - call Func_6ebb - ld hl, PokemonFightingFitText - call PrintText - callab IsStarterPikachuInOurParty - jr nc, .notInParty - lb bc, 15, 0 - call Func_6ebb -.notInParty - call LoadCurrentMapView - call Delay3 - call UpdateSprites - callab ReloadWalkingTilePatterns - ld a, $1 - ld [H_SPRITEINDEX], a - ld a, $1 - ld [hSpriteImageIndex], a - call SpriteFunc_34a1 - ld c, 40 - call DelayFrames - call UpdateSprites - call LoadFontTilePatterns - jr .done -.declinedHealing - call LoadScreenTilesFromBuffer1 ; restore screen -.done - ld hl, PokemonCenterFarewellText - call PrintText - call UpdateSprites - ret - -Func_6eaa: - ld a, $1 - ld [H_SPRITEINDEX], a - ld a, $4 - ld [hSpriteImageIndex], a - call SpriteFunc_34a1 - ld c, 64 - call DelayFrames - ret - -Func_6ebb: - ld a, b - ld [H_SPRITEINDEX], a - ld a, c - ld [hSpriteImageIndex], a - push bc - call SetSpriteFacingDirectionAndDelay - pop bc - ld a, b - ld [H_SPRITEINDEX], a - ld a, c - ld [hSpriteImageIndex], a - call SpriteFunc_34a1 - ret - -PokemonCenterWelcomeText: - TX_FAR _PokemonCenterWelcomeText - db "@" - -ShallWeHealYourPokemonText: - TX_DELAY - TX_FAR _ShallWeHealYourPokemonText - db "@" - -NeedYourPokemonText: - TX_FAR _NeedYourPokemonText - db "@" - -PokemonFightingFitText: - TX_FAR _PokemonFightingFitText - db "@" - -PokemonCenterFarewellText: - TX_DELAY - TX_FAR _PokemonCenterFarewellText - db "@" - -LooksContentText: - TX_FAR _LooksContentText - db "@" diff --git a/engine/overworld/pokemart.asm b/engine/overworld/pokemart.asm deleted file mode 100755 index dc5b29b5..00000000 --- a/engine/overworld/pokemart.asm +++ /dev/null @@ -1,272 +0,0 @@ -DisplayPokemartDialogue_: - ld a, [wListScrollOffset] - ld [wSavedListScrollOffset], a - call UpdateSprites - xor a - ld [wBoughtOrSoldItemInMart], a -.loop - xor a - ld [wListScrollOffset], a - ld [wCurrentMenuItem], a - ld [wPlayerMonNumber], a - inc a - ld [wPrintItemPrices], a - ld a, MONEY_BOX - ld [wTextBoxID], a - call DisplayTextBoxID - ld a, BUY_SELL_QUIT_MENU - ld [wTextBoxID], a - call DisplayTextBoxID - -; This code is useless. It copies the address of the pokemart's inventory to hl, -; but the address is never used. - ld hl, wItemListPointer - ld a, [hli] - ld l, [hl] - ld h, a - - ld a, [wMenuExitMethod] - cp CANCELLED_MENU - jp z, .done - ld a, [wChosenMenuItem] - and a ; buying? - jp z, .buyMenu - dec a ; selling? - jp z, .sellMenu - dec a ; quitting? - jp z, .done -.sellMenu - -; the same variables are set again below, so this code has no effect - xor a - ld [wPrintItemPrices], a - ld a, INIT_BAG_ITEM_LIST - ld [wInitListType], a - callab InitList - - ld a, [wNumBagItems] - and a - jp z, .bagEmpty - ld hl, PokemonSellingGreetingText - call PrintText - call SaveScreenTilesToBuffer1 ; save screen -.sellMenuLoop - call LoadScreenTilesFromBuffer1 ; restore saved screen - ld a, MONEY_BOX - ld [wTextBoxID], a - call DisplayTextBoxID ; draw money text box - ld hl, wNumBagItems - ld a, l - ld [wListPointer], a - ld a, h - ld [wListPointer + 1], a - xor a - ld [wPrintItemPrices], a - ld [wCurrentMenuItem], a - ld a, ITEMLISTMENU - ld [wListMenuID], a - call DisplayListMenuID - jp c, .returnToMainPokemartMenu ; if the player closed the menu -.confirmItemSale ; if the player is trying to sell a specific item - call IsKeyItem - ld a, [wIsKeyItem] - and a - jr nz, .unsellableItem - ld a, [wcf91] - call IsItemHM - jr c, .unsellableItem - ld a, PRICEDITEMLISTMENU - ld [wListMenuID], a - ld [hHalveItemPrices], a ; halve prices when selling - call DisplayChooseQuantityMenu - inc a - jr z, .sellMenuLoop ; if the player closed the choose quantity menu with the B button - ld hl, PokemartTellSellPriceText - lb bc, 14, 1 ; location that PrintText always prints to, this is useless - call PrintText - coord hl, 14, 7 - lb bc, 8, 15 - ld a, TWO_OPTION_MENU - ld [wTextBoxID], a - call DisplayTextBoxID ; yes/no menu - ld a, [wMenuExitMethod] - cp CHOSE_SECOND_ITEM - jr z, .sellMenuLoop ; if the player chose No or pressed the B button - -; The following code is supposed to check if the player chose No, but the above -; check already catches it. - ld a, [wChosenMenuItem] - dec a - jr z, .sellMenuLoop - -.sellItem - ld a, [wBoughtOrSoldItemInMart] - and a - jr nz, .skipSettingFlag1 - inc a - ld [wBoughtOrSoldItemInMart], a -.skipSettingFlag1 - call AddAmountSoldToMoney - ld hl, wNumBagItems - call RemoveItemFromInventory - jp .sellMenuLoop -.unsellableItem - ld hl, PokemartUnsellableItemText - call PrintText - jp .returnToMainPokemartMenu -.bagEmpty - ld hl, PokemartItemBagEmptyText - call PrintText - call SaveScreenTilesToBuffer1 - jp .returnToMainPokemartMenu -.buyMenu - -; the same variables are set again below, so this code has no effect - ld a, 1 - ld [wPrintItemPrices], a - ld a, INIT_OTHER_ITEM_LIST - ld [wInitListType], a - callab InitList - - ld hl, PokemartBuyingGreetingText - call PrintText - call SaveScreenTilesToBuffer1 -.buyMenuLoop - call LoadScreenTilesFromBuffer1 - ld a, MONEY_BOX - ld [wTextBoxID], a - call DisplayTextBoxID - ld hl, wItemList - ld a, l - ld [wListPointer], a - ld a, h - ld [wListPointer + 1], a - xor a - ld [wCurrentMenuItem], a - inc a - ld [wPrintItemPrices], a - inc a ; a = 2 (PRICEDITEMLISTMENU) - ld [wListMenuID], a - call DisplayListMenuID - jr c, .returnToMainPokemartMenu ; if the player closed the menu - ld a, 99 - ld [wMaxItemQuantity], a - xor a - ld [hHalveItemPrices], a ; don't halve item prices when buying - call DisplayChooseQuantityMenu - inc a - jr z, .buyMenuLoop ; if the player closed the choose quantity menu with the B button - ld a, [wcf91] ; item ID - ld [wd11e], a ; store item ID for GetItemName - call GetItemName - call CopyStringToCF4B ; copy name to wcf4b - ld hl, PokemartTellBuyPriceText - call PrintText - coord hl, 14, 7 - lb bc, 8, 15 - ld a, TWO_OPTION_MENU - ld [wTextBoxID], a - call DisplayTextBoxID ; yes/no menu - ld a, [wMenuExitMethod] - cp CHOSE_SECOND_ITEM - jp z, .buyMenuLoop ; if the player chose No or pressed the B button - -; The following code is supposed to check if the player chose No, but the above -; check already catches it. - ld a, [wChosenMenuItem] - dec a - jr z, .buyMenuLoop - -.buyItem - call .isThereEnoughMoney - jr c, .notEnoughMoney - ld hl, wNumBagItems - call AddItemToInventory - jr nc, .bagFull - call SubtractAmountPaidFromMoney - ld a, [wBoughtOrSoldItemInMart] - and a - jr nz, .skipSettingFlag2 - ld a, 1 - ld [wBoughtOrSoldItemInMart], a -.skipSettingFlag2 - ld a, SFX_PURCHASE - call PlaySoundWaitForCurrent - call WaitForSoundToFinish - ld hl, PokemartBoughtItemText - call PrintText - jp .buyMenuLoop -.returnToMainPokemartMenu - call LoadScreenTilesFromBuffer1 - ld a, MONEY_BOX - ld [wTextBoxID], a - call DisplayTextBoxID - ld hl, PokemartAnythingElseText - call PrintText - jp .loop -.isThereEnoughMoney - ld de, wPlayerMoney - ld hl, hMoney - ld c, 3 ; length of money in bytes - jp StringCmp -.notEnoughMoney - ld hl, PokemartNotEnoughMoneyText - call PrintText - jr .returnToMainPokemartMenu -.bagFull - ld hl, PokemartItemBagFullText - call PrintText - jr .returnToMainPokemartMenu -.done - ld hl, PokemartThankYouText - call PrintText - ld a, 1 - ld [wUpdateSpritesEnabled], a - call UpdateSprites - ld a, [wSavedListScrollOffset] - ld [wListScrollOffset], a - ret - -PokemartBuyingGreetingText: - TX_FAR _PokemartBuyingGreetingText - db "@" - -PokemartTellBuyPriceText: - TX_FAR _PokemartTellBuyPriceText - db "@" - -PokemartBoughtItemText: - TX_FAR _PokemartBoughtItemText - db "@" - -PokemartNotEnoughMoneyText: - TX_FAR _PokemartNotEnoughMoneyText - db "@" - -PokemartItemBagFullText: - TX_FAR _PokemartItemBagFullText - db "@" - -PokemonSellingGreetingText: - TX_FAR _PokemonSellingGreetingText - db "@" - -PokemartTellSellPriceText: - TX_FAR _PokemartTellSellPriceText - db "@" - -PokemartItemBagEmptyText: - TX_FAR _PokemartItemBagEmptyText - db "@" - -PokemartUnsellableItemText: - TX_FAR _PokemartUnsellableItemText - db "@" - -PokemartThankYouText: - TX_FAR _PokemartThankYouText - db "@" - -PokemartAnythingElseText: - TX_FAR _PokemartAnythingElseText - db "@" diff --git a/engine/overworld/push_boulder.asm b/engine/overworld/push_boulder.asm index 8a385345..09911ca3 100644 --- a/engine/overworld/push_boulder.asm +++ b/engine/overworld/push_boulder.asm @@ -1,4 +1,4 @@ -TryPushingBoulder: +TryPushingBoulder:: ld a, [wd728] bit 0, a ; using Strength? ret z @@ -8,15 +8,15 @@ Func_f0a7: bit 1, a ; has boulder dust animation from previous push played yet? ret nz xor a - ld [hSpriteIndexOrTextID], a + ldh [hSpriteIndexOrTextID], a call IsSpriteInFrontOfPlayer - ld a, [hSpriteIndexOrTextID] + ldh a, [hSpriteIndexOrTextID] ld [wBoulderSpriteIndex], a and a jp z, ResetBoulderPushFlags - ld hl, wSpriteStateData1 + 1 + ld hl, wSpritePlayerStateData1MovementStatus ld d, $0 - ld a, [hSpriteIndexOrTextID] + ldh a, [hSpriteIndexOrTextID] swap a ld e, a add hl, de @@ -29,16 +29,16 @@ Func_f0a7: bit 6, [hl] set 6, [hl] ; indicate that the player has tried pushing ret z ; the player must try pushing twice before the boulder will move - ld a, [hJoyHeld] + ldh a, [hJoyHeld] and D_RIGHT | D_LEFT | D_UP | D_DOWN ret z predef CheckForCollisionWhenPushingBoulder ld a, [wTileInFrontOfBoulderAndBoulderCollisionResult] and a ; was there a collision? jp nz, ResetBoulderPushFlags - ld a, [hJoyHeld] + ldh a, [hJoyHeld] ld b, a - ld a, [wSpritePlayerStateData1FacingDirection] ; player's sprite facing direction + ld a, [wSpritePlayerStateData1FacingDirection] cp SPRITE_FACING_UP jr z, .pushBoulderUp cp SPRITE_FACING_LEFT @@ -73,28 +73,32 @@ Func_f0a7: ret PushBoulderUpMovementData: - db NPC_MOVEMENT_UP,$FF + db NPC_MOVEMENT_UP + db -1 ; end PushBoulderDownMovementData: - db NPC_MOVEMENT_DOWN,$FF + db NPC_MOVEMENT_DOWN + db -1 ; end PushBoulderLeftMovementData: - db NPC_MOVEMENT_LEFT,$FF + db NPC_MOVEMENT_LEFT + db -1 ; end PushBoulderRightMovementData: - db NPC_MOVEMENT_RIGHT,$FF + db NPC_MOVEMENT_RIGHT + db -1 ; end -DoBoulderDustAnimation: +DoBoulderDustAnimation:: ld a, [wd730] bit 0, a ret nz - callab AnimateBoulderDust + callfar AnimateBoulderDust call DiscardButtonPresses ld [wJoyIgnore], a call ResetBoulderPushFlags set 7, [hl] ld a, [wBoulderSpriteIndex] - ld [H_SPRITEINDEX], a + ldh [hSpriteIndex], a call GetSpriteMovementByte2Pointer ld [hl], $10 ld a, SFX_CUT diff --git a/engine/overworld/saffron_guards.asm b/engine/overworld/saffron_guards.asm deleted file mode 100755 index 3b26b6f8..00000000 --- a/engine/overworld/saffron_guards.asm +++ /dev/null @@ -1,16 +0,0 @@ -RemoveGuardDrink: - ld hl, GuardDrinksList -.drinkLoop - ld a, [hli] - ld [$ffdb], a - and a - ret z - push hl - ld b, a - call IsItemInBag - pop hl - jr z, .drinkLoop - jpba RemoveItemByID - -GuardDrinksList: - db FRESH_WATER, SODA_POP, LEMONADE, $00 diff --git a/engine/overworld/set_blackout_map.asm b/engine/overworld/set_blackout_map.asm deleted file mode 100644 index bac2f0ca..00000000 --- a/engine/overworld/set_blackout_map.asm +++ /dev/null @@ -1,29 +0,0 @@ -SetLastBlackoutMap: -; Set the map to return to when -; blacking out or using Teleport or Dig. -; Safari rest houses don't count. - - push hl - ld hl, SafariZoneRestHouses - ld a, [wCurMap] - ld b, a -.loop - ld a, [hli] - cp -1 - jr z, .notresthouse - cp b - jr nz, .loop - jr .done - -.notresthouse - ld a, [wLastMap] - ld [wLastBlackoutMap], a -.done - pop hl - ret - -SafariZoneRestHouses: - db SAFARI_ZONE_WEST_REST_HOUSE - db SAFARI_ZONE_EAST_REST_HOUSE - db SAFARI_ZONE_NORTH_REST_HOUSE - db -1 diff --git a/engine/overworld/special_warps.asm b/engine/overworld/special_warps.asm new file mode 100644 index 00000000..61356a03 --- /dev/null +++ b/engine/overworld/special_warps.asm @@ -0,0 +1,149 @@ +SpecialWarpIn:: + call LoadSpecialWarpData + predef LoadTilesetHeader + ld hl, wd732 + bit 2, [hl] ; dungeon warp or fly warp? + res 2, [hl] + jr z, .next +; if dungeon warp or fly warp + ld a, [wDestinationMap] + jr .next2 +.next + bit 1, [hl] + jr z, .next3 + call DebugStart +.next3 + ld a, 0 +.next2 + ld b, a + ld a, [wd72d] + and a + jr nz, .next4 + ld a, b +.next4 + ld hl, wd732 + bit 4, [hl] ; dungeon warp? + ret nz +; if not dungeon warp + ld [wLastMap], a + ret + +; gets the map ID, tile block map view pointer, tileset, and coordinates +LoadSpecialWarpData: + ld a, [wd72d] + cp TRADE_CENTER + jr nz, .notTradeCenter + ld hl, TradeCenterSpec1 + ldh a, [hSerialConnectionStatus] + cp USING_INTERNAL_CLOCK ; which gameboy is clocking determines who is on the left and who is on the right + jr z, .copyWarpData + ld hl, TradeCenterSpec2 + jr .copyWarpData +.notTradeCenter + cp COLOSSEUM + jr nz, .notColosseum + ld hl, ColosseumSpec1 + ldh a, [hSerialConnectionStatus] + cp USING_INTERNAL_CLOCK + jr z, .copyWarpData + ld hl, ColosseumSpec2 + jr .copyWarpData +.notColosseum + ld a, [wd732] + bit 1, a + jr nz, .notFirstMap + bit 2, a + jr nz, .notFirstMap + ld hl, FirstMapSpec +.copyWarpData + ld de, wCurMap + ld c, $7 +.copyWarpDataLoop + ld a, [hli] + ld [de], a + inc de + dec c + jr nz, .copyWarpDataLoop + ld a, [hli] + ld [wCurMapTileset], a + xor a + jr .done +.notFirstMap + ld a, [wLastMap] ; this value is overwritten before it's ever read + ld hl, wd732 + bit 4, [hl] ; used dungeon warp (jumped down hole/waterfall)? + jr nz, .usedDunegonWarp + bit 6, [hl] ; return to last pokemon center (or player's house)? + res 6, [hl] + jr z, .otherDestination +; return to last pokemon center or player's house + ld a, [wLastBlackoutMap] + jr .usedFlyWarp +.usedDunegonWarp + ld hl, wd72d + res 4, [hl] + ld a, [wDungeonWarpDestinationMap] + ld b, a + ld [wCurMap], a + ld a, [wWhichDungeonWarp] + ld c, a + ld hl, DungeonWarpList + ld de, 0 + ld a, 6 + ld [wDungeonWarpDataEntrySize], a +.dungeonWarpListLoop + ld a, [hli] + cp b + jr z, .matchedDungeonWarpDestinationMap + inc hl + jr .nextDungeonWarp +.matchedDungeonWarpDestinationMap + ld a, [hli] + cp c + jr z, .matchedDungeonWarpID +.nextDungeonWarp + ld a, [wDungeonWarpDataEntrySize] + add e + ld e, a + jr .dungeonWarpListLoop +.matchedDungeonWarpID + ld hl, DungeonWarpData + add hl, de + jr .copyWarpData2 +.otherDestination + ld a, [wDestinationMap] +.usedFlyWarp + ld b, a + ld [wCurMap], a + ld hl, FlyWarpDataPtr +.flyWarpDataPtrLoop + ld a, [hli] + inc hl + cp b + jr z, .foundFlyWarpMatch + inc hl + inc hl + jr .flyWarpDataPtrLoop +.foundFlyWarpMatch + ld a, [hli] + ld h, [hl] + ld l, a +.copyWarpData2 + ld de, wCurrentTileBlockMapViewPointer + ld c, $6 +.copyWarpDataLoop2 + ld a, [hli] + ld [de], a + inc de + dec c + jr nz, .copyWarpDataLoop2 + xor a ; OVERWORLD + ld [wCurMapTileset], a +.done + ld [wYOffsetSinceLastSpecialWarp], a + ld [wXOffsetSinceLastSpecialWarp], a + ld a, $ff ; the player's coordinates have already been updated using a special warp, so don't use any of the normal warps + ld [wDestinationWarpID], a + ret + +INCLUDE "data/maps/special_warps.asm" diff --git a/engine/overworld/spinners.asm b/engine/overworld/spinners.asm new file mode 100644 index 00000000..0ac6380d --- /dev/null +++ b/engine/overworld/spinners.asm @@ -0,0 +1,65 @@ +LoadSpinnerArrowTiles:: + ld a, [wSpritePlayerStateData1ImageIndex] + srl a + srl a + ld hl, SpinnerPlayerFacingDirections + ld c, a + ld b, $0 + add hl, bc + ld a, [hl] + ld [wSpritePlayerStateData1ImageIndex], a + ld a, [wCurMapTileset] + cp FACILITY + ld hl, FacilitySpinnerArrows + jr z, .asm_44ff6 + ld hl, GymSpinnerArrows +.asm_44ff6 + ld a, [wSimulatedJoypadStatesIndex] + bit 0, a + jr nz, .asm_45001 + ld de, $18 + add hl, de +.asm_45001 + ld a, $4 + ld bc, $0 +.asm_45006 + push af + push hl + push bc + add hl, bc + ld a, [hli] + ld e, a + ld a, [hli] + ld d, a + ld a, [hli] + ld c, a + ld a, [hli] + ld b, a + ld a, [hli] + ld h, [hl] + ld l, a + call CopyVideoData + pop bc + ld a, $6 + add c + ld c, a + pop hl + pop af + dec a + jr nz, .asm_45006 + ret + +INCLUDE "data/tilesets/spinner_tiles.asm" + +SpinnerPlayerFacingDirections: +; This isn't the order of the facing directions. Rather, it's a list of +; the facing directions that come next. For example, when the player is +; facing down (00), the next facing direction is left (08). + db $08 ; down -> left + db $0C ; up -> right + db $04 ; left -> up + db $00 ; right -> down + +; these tiles are the animation for the tiles that push the player in dungeons like Rocket HQ +SpinnerArrowAnimTiles: + INCBIN "gfx/overworld/spinners.2bpp" diff --git a/engine/overworld/sprite_collisions.asm b/engine/overworld/sprite_collisions.asm new file mode 100644 index 00000000..db81977b --- /dev/null +++ b/engine/overworld/sprite_collisions.asm @@ -0,0 +1,392 @@ +_UpdateSprites:: + ld h, wSpriteStateData1 / $100 + inc h + ld a, SPRITESTATEDATA2_IMAGEBASEOFFSET +.spriteLoop + ld l, a + sub SPRITESTATEDATA2_IMAGEBASEOFFSET + ld c, a + ldh [hCurrentSpriteOffset], a + ld a, [hl] + and a + jr z, .skipSprite ; tests SPRITESTATEDATA2_IMAGEBASEOFFSET + push hl + push de + push bc + call .updateCurrentSprite + pop bc + pop de + pop hl +.skipSprite + ld a, l + add $10 ; move to next sprite + cp SPRITESTATEDATA2_IMAGEBASEOFFSET ; test for overflow (back at beginning) + jr nz, .spriteLoop + ret +.updateCurrentSprite + ldh a, [hCurrentSpriteOffset] + and a + jp z, UpdatePlayerSprite + cp $f0 ; pikachu + jp z, SpawnPikachu + ld a, [hl] + +UpdateNonPlayerSprite: + dec a + swap a + ldh [hTilePlayerStandingOn], a ; $10 * sprite# + ld a, [wNPCMovementScriptSpriteOffset] ; some sprite offset? + ld b, a + ldh a, [hCurrentSpriteOffset] + cp b + jr nz, .unequal + jp DoScriptedNPCMovement +.unequal + jp UpdateNPCSprite + +; This detects if the current sprite (whose offset is at hCurrentSpriteOffset) +; is going to collide with another sprite by looping over the other sprites. +; The current sprite's offset will be labelled with i (e.g. i#SPRITESTATEDATA1_PICTUREID). +; The loop sprite's offset will labelled with j (e.g. j#SPRITESTATEDATA1_PICTUREID). +; +; Note that the Y coordinate of the sprite (in [k#SPRITESTATEDATA1_YPIXELS]) +; is one of the following 9 values when the sprite is aligned with the grid: +; $fc, $0c, $1c, $2c, ..., $7c. +; The reason that 4 is added below to the coordinate is to make it align with a +; multiple of $10 to make comparisons easier. +DetectCollisionBetweenSprites: + ; nop + + ld h, HIGH(wSpriteStateData1) + ldh a, [hCurrentSpriteOffset] + ld l, a + + ld a, [hl] ; a = [i#SPRITESTATEDATA1_PICTUREID] (0 if slot is unused) + and a ; is this sprite slot slot used? + ret z ; return if not used + + ld a, l + add 3 + ld l, a + + ld a, [hli] ; a = [i#SPRITESTATEDATA1_YSTEPVECTOR] (-1, 0, or 1) + call SetSpriteCollisionValues + + ld a, [hli] ; a = [i#SPRITESTATEDATA1_YPIXELS] + add 4 ; align with multiple of $10 + +; The effect of the following 3 lines is to +; add 7 to a if moving south or +; subtract 7 from a if moving north. + add b + and $f0 + or c + + ldh [hFF90], a ; store Y coordinate adjusted for direction of movement + + ld a, [hli] ; a = [i#SPRITESTATEDATA1_XSTEPVECTOR] (-1, 0, or 1) + call SetSpriteCollisionValues + ld a, [hl] ; a = [i#SPRITESTATEDATA1_XPIXELS] + +; The effect of the following 3 lines is to +; add 7 to a if moving east or +; subtract 7 from a if moving west. + add b + and $f0 + or c + + ldh [hFF91], a ; store X coordinate adjusted for direction of movement + + ld a, l + add 7 + ld l, a + + xor a + ld [hld], a ; zero [i#SPRITESTATEDATA1_0D] XXX what's this for? + ld [hld], a ; zero [i#SPRITESTATEDATA1_COLLISIONDATA] + + ldh a, [hFF91] + ld [hld], a ; [i#SPRITESTATEDATA1_XADJUSTED] + ldh a, [hFF90] + ld [hl], a ; [i#SPRITESTATEDATA1_YADJUSTED] + + xor a ; zero the loop counter + +.loop + ldh [hFF8F], a ; store loop counter + swap a + ld e, a + ldh a, [hCurrentSpriteOffset] + cp e ; does the loop sprite match the current sprite? + jp z, .next ; go to the next sprite if they match + + ld d, h + ld a, [de] ; a = [j#SPRITESTATEDATA1_PICTUREID] (0 if slot is unused) + and a ; is this sprite slot slot used? + jp z, .next ; go the next sprite if not used + + inc e + inc e + ld a, [de] ; a = [j#SPRITESTATEDATA1_IMAGEINDEX] ($ff means the sprite is offscreen) + inc a + jp z, .next ; go the next sprite if offscreen + + ldh a, [hCurrentSpriteOffset] + add 10 + ld l, a + + inc e + ld a, [de] ; a = [j#SPRITESTATEDATA1_YSTEPVECTOR] + call SetSpriteCollisionValues + + inc e + ld a, [de] ; a = [j#SPRITESTATEDATA1_YPIXELS] + add 4 ; align with multiple of $10 + +; The effect of the following 3 lines is to +; add 7 to a if moving south or +; subtract 7 from a if moving north. + add b + and $f0 + or c + + sub [hl] ; subtract [i#SPRITESTATEDATA1_YADJUSTED] from [j#SPRITESTATEDATA1_YADJUSTED] + +; calculate the absolute value of the difference to get the distance + jr nc, .noCarry1 + cpl + inc a +.noCarry1 + ldh [hFF90], a ; store the distance between the two sprites' adjusted Y values + +; Use the carry flag set by the above subtraction to determine which sprite's +; Y coordinate is larger. This information is used later to set +; [i#SPRITESTATEDATA1_COLLISIONDATA]. +; The following 5 lines set the lowest 2 bits of c, which are later shifted left by 2. +; If sprite i's Y is larger, set lowest 2 bits of c to 10. +; If sprite j's Y is larger or both are equal, set lowest 2 bits of c to 01. + push af + rl c + pop af + ccf + rl c + +; If sprite i's delta Y is 0, then b = 7, else b = 9. + ld b, 7 + ld a, [hl] ; a = [i#SPRITESTATEDATA1_YADJUSTED] + and $f + jr z, .next1 + ld b, 9 + +.next1 + ldh a, [hFF90] ; a = distance between adjusted Y coordinates + sub b + ldh [hFF92], a ; store distance adjusted using sprite i's direction + ld a, b + ldh [hFF90], a ; store 7 or 9 depending on sprite i's delta Y + jr c, .checkXDistance + +; If sprite j's delta Y is 0, then b = 7, else b = 9. + ld b, 7 + dec e + ld a, [de] ; a = [j#SPRITESTATEDATA1_YSTEPVECTOR] + inc e + and a + jr z, .next2 + ld b, 9 + +.next2 + ldh a, [hFF92] ; a = distance adjusted using sprite i's direction + sub b ; adjust distance using sprite j's direction + jr z, .checkXDistance + jr nc, .next ; go to next sprite if distance is still positive after both adjustments + +.checkXDistance + inc e + inc l + ld a, [de] ; a = [j#SPRITESTATEDATA1_XSTEPVECTOR] + + push bc + + call SetSpriteCollisionValues + inc e + ld a, [de] ; a = [j#SPRITESTATEDATA1_XPIXELS] + +; The effect of the following 3 lines is to +; add 7 to a if moving east or +; subtract 7 from a if moving west. + add b + and $f0 + or c + + pop bc + + sub [hl] ; subtract [i#SPRITESTATEDATA1_XADJUSTED] from [j#SPRITESTATEDATA1_XADJUSTED] + +; calculate the absolute value of the difference to get the distance + jr nc, .noCarry2 + cpl + inc a +.noCarry2 + ldh [hFF91], a ; store the distance between the two sprites' adjusted X values + +; Use the carry flag set by the above subtraction to determine which sprite's +; X coordinate is larger. This information is used later to set +; [i#SPRITESTATEDATA1_COLLISIONDATA]. +; The following 5 lines set the lowest 2 bits of c. +; If sprite i's X is larger, set lowest 2 bits of c to 10. +; If sprite j's X is larger or both are equal, set lowest 2 bits of c to 01. + push af + rl c + pop af + ccf + rl c + +; If sprite i's delta X is 0, then b = 7, else b = 9. + ld b, 7 + ld a, [hl] ; a = [i#SPRITESTATEDATA1_XADJUSTED] + and $f + jr z, .next3 + ld b, 9 + +.next3 + ldh a, [hFF91] ; a = distance between adjusted X coordinates + sub b + ldh [hFF92], a ; store distance adjusted using sprite i's direction + ld a, b + ldh [hFF91], a ; store 7 or 9 depending on sprite i's delta X + jr c, .collision + +; If sprite j's delta X is 0, then b = 7, else b = 9. + ld b, 7 + dec e + ld a, [de] ; a = [j#SPRITESTATEDATA1_XSTEPVECTOR] + inc e + and a + jr z, .next4 + ld b, 9 + +.next4 + ldh a, [hFF92] ; a = distance adjusted using sprite i's direction + sub b ; adjust distance using sprite j's direction + jr z, .collision + jr nc, .next ; go to next sprite if distance is still positive after both adjustments + +.collision + ld a, l + and $f0 ; collision with pikachu? + jr nz, .asm_4cd9 + xor a + ld [wd434], a + ldh a, [hFF8F] + cp $f + jr nz, .asm_4cd9 + call Func_4d0a + jr .asm_4cef +.asm_4cd9 + ldh a, [hFF91] ; a = 7 or 9 depending on sprite i's delta X + ld b, a + ldh a, [hFF90] ; a = 7 or 9 depending on sprite i's delta Y + inc l + +; If delta X isn't 0 and delta Y is 0, then b = %0011, else b = %1100. +; (note that normally if delta X isn't 0, then delta Y must be 0 and vice versa) + cp b + jr c, .next5 + ld b, %1100 + jr .next6 +.next5 + ld b, %0011 + +.next6 + ld a, c ; c has 2 bits set (one of bits 0-1 is set for the X axis and one of bits 2-3 for the Y axis) + and b ; we select either the bit in bits 0-1 or bits 2-3 based on the calculation immediately above + or [hl] ; or with existing collision direction bits in [i#SPRITESTATEDATA1_COLLISIONDATA] + ld [hl], a ; store new value + ld a, c ; useless code because a is overwritten before being used again + +; set bit in [i#SPRITESTATEDATA1_0E] or [i#SPRITESTATEDATA1_0F] +; to indicate which sprite the collision occurred with + inc l + inc l +.asm_4cef + ldh a, [hFF8F] ; a = loop counter + ld de, SpriteCollisionBitTable + add a + add e + ld e, a + jr nc, .noCarry3 + inc d +.noCarry3 + ld a, [de] + or [hl] + ld [hli], a + inc de + ld a, [de] + or [hl] + ld [hl], a + +.next + ldh a, [hFF8F] ; a = loop counter + inc a + cp $10 + jp nz, .loop + ret + +; takes delta X or delta Y in a +; b = delta X/Y +; c = 0 if delta X/Y is 0 +; c = 7 if delta X/Y is 1 +; c = 9 if delta X/Y is -1 +Func_4d0a: + ldh a, [hFF91] + ld b, a + ldh a, [hFF90] + inc l + cp b + jr c, .asm_4d17 + ld b, %1100 + jr .asm_4d19 +.asm_4d17 + ld b, %11 +.asm_4d19 + ld a, c + and b + ld [wd434], a + ld a, c + inc l + inc l + ret + +SetSpriteCollisionValues: + and a + ld b, 0 + ld c, 0 + jr z, .done + ld c, 9 + cp -1 + jr z, .ok + ld c, 7 + ld a, 0 +.ok + ld b, a +.done + ret + +SpriteCollisionBitTable: + db %00000000,%00000001 + db %00000000,%00000010 + db %00000000,%00000100 + db %00000000,%00001000 + db %00000000,%00010000 + db %00000000,%00100000 + db %00000000,%01000000 + db %00000000,%10000000 + db %00000001,%00000000 + db %00000010,%00000000 + db %00000100,%00000000 + db %00001000,%00000000 + db %00010000,%00000000 + db %00100000,%00000000 + db %01000000,%00000000 + db %10000000,%00000000 diff --git a/engine/overworld/ssanne.asm b/engine/overworld/ssanne.asm deleted file mode 100755 index cf3b1284..00000000 --- a/engine/overworld/ssanne.asm +++ /dev/null @@ -1,95 +0,0 @@ -AnimateBoulderDust: - ld a, $1 - ld [wWhichAnimationOffsets], a ; select the boulder dust offsets - ld a, [wUpdateSpritesEnabled] - push af - ld a, $ff - ld [wUpdateSpritesEnabled], a - ld a, %11100100 - ld [rOBP1], a - call UpdateGBCPal_OBP1 - call LoadSmokeTileFourTimes - callba WriteCutOrBoulderDustAnimationOAMBlock - ld c, 8 ; number of steps in animation -.loop - push bc - call GetMoveBoulderDustFunctionPointer - ld bc, .returnAddress - push bc - ld c, 4 - jp hl -.returnAddress - ld a, [rOBP1] - xor %01100100 - ld [rOBP1], a - call UpdateGBCPal_OBP1 - call Delay3 - pop bc - dec c - jr nz, .loop - pop af - ld [wUpdateSpritesEnabled], a - jp LoadPlayerSpriteGraphics - -GetMoveBoulderDustFunctionPointer: - ld a, [wSpritePlayerStateData1FacingDirection] ; player's sprite facing direction - ld hl, MoveBoulderDustFunctionPointerTable - ld c, a - ld b, $0 - add hl, bc - ld a, [hli] - ld [wCoordAdjustmentAmount], a - ld a, [hli] - ld e, a - ld a, [hli] - ld h, [hl] - ld l, a - push hl - ld hl, wOAMBuffer + $90 - ld d, $0 - add hl, de - ld e, l - ld d, h - pop hl - ret - -MoveBoulderDustFunctionPointerTable: -; facing down - db $FF,$00 - dw AdjustOAMBlockYPos - -; facing up - db $01,$00 - dw AdjustOAMBlockYPos - -; facing left - db $01,$01 - dw AdjustOAMBlockXPos - -; facing right - db $FF,$01 - dw AdjustOAMBlockXPos - -LoadSmokeTileFourTimes: - ld hl, vChars1 + $7c0 - ld c, $4 -.loop - push bc - push hl - call LoadSmokeTile - pop hl - ld bc, $10 - add hl, bc - pop bc - dec c - jr nz, .loop - ret - -LoadSmokeTile: - ld de, SSAnneSmokePuffTile - lb bc, BANK(SSAnneSmokePuffTile), (SSAnneSmokePuffTileEnd - SSAnneSmokePuffTile) / $10 - jp CopyVideoData - -SSAnneSmokePuffTile: - INCBIN "gfx/ss_anne_smoke_puff.2bpp" -SSAnneSmokePuffTileEnd: diff --git a/engine/overworld/tileset_header.asm b/engine/overworld/tileset_header.asm deleted file mode 100644 index 05061651..00000000 --- a/engine/overworld/tileset_header.asm +++ /dev/null @@ -1,51 +0,0 @@ -LoadTilesetHeader: - call GetPredefRegisters - push hl - ld d, 0 - ld a, [wCurMapTileset] - add a - add a - ld e, a - ld hl, Tilesets - add hl, de - add hl, de - add hl, de - ld de, wTilesetBank - ld bc, $b - call CopyData - ld a, [hl] - ld [hTilesetType], a - xor a - ld [$ffd8], a - pop hl - ld a, [wCurMapTileset] - push hl - push de - ld hl, DungeonTilesets - ld de, $1 - call IsInArray - pop de - pop hl - jr c, .notDungeonTileset - ld a, [wCurMapTileset] - ld b, a - ld a, [hPreviousTileset] - cp b - jr z, .done -.notDungeonTileset - ld a, [wDestinationWarpID] - cp $ff - jr z, .done - call LoadDestinationWarpPosition - ld a, [wYCoord] - and $1 - ld [wYBlockCoord], a - ld a, [wXCoord] - and $1 - ld [wXBlockCoord], a -.done - ret - -INCLUDE "data/dungeon_tilesets.asm" - -INCLUDE "data/tileset_headers.asm" diff --git a/engine/overworld/tilesets.asm b/engine/overworld/tilesets.asm new file mode 100644 index 00000000..686fa50c --- /dev/null +++ b/engine/overworld/tilesets.asm @@ -0,0 +1,51 @@ +LoadTilesetHeader: + call GetPredefRegisters + push hl + ld d, 0 + ld a, [wCurMapTileset] + add a + add a + ld e, a + ld hl, Tilesets + add hl, de + add hl, de + add hl, de + ld de, wTilesetBank + ld bc, $b + call CopyData + ld a, [hl] + ldh [hTilesetType], a + xor a + ldh [hMovingBGTilesCounter1], a + pop hl + ld a, [wCurMapTileset] + push hl + push de + ld hl, DungeonTilesets + ld de, $1 + call IsInArray + pop de + pop hl + jr c, .notDungeonTileset + ld a, [wCurMapTileset] + ld b, a + ldh a, [hPreviousTileset] + cp b + jr z, .done +.notDungeonTileset + ld a, [wDestinationWarpID] + cp $ff + jr z, .done + call LoadDestinationWarpPosition + ld a, [wYCoord] + and $1 + ld [wYBlockCoord], a + ld a, [wXCoord] + and $1 + ld [wXBlockCoord], a +.done + ret + +INCLUDE "data/tilesets/dungeon_tilesets.asm" + +INCLUDE "data/tilesets/tileset_headers.asm" diff --git a/engine/overworld/trainer_sight.asm b/engine/overworld/trainer_sight.asm new file mode 100755 index 00000000..816dea7f --- /dev/null +++ b/engine/overworld/trainer_sight.asm @@ -0,0 +1,349 @@ +_GetSpritePosition1:: + ld hl, wSpriteStateData1 + ld de, SPRITESTATEDATA1_YPIXELS + ld a, [wSpriteIndex] + ldh [hSpriteIndex], a + call GetSpriteDataPointer + ld a, [hli] ; x#SPRITESTATEDATA1_YPIXELS + ldh [hSpriteScreenYCoord], a + inc hl + ld a, [hl] ; x#SPRITESTATEDATA1_XPIXELS + ldh [hSpriteScreenXCoord], a + ld de, wSpritePlayerStateData2MapY - wSpritePlayerStateData1XPixels + add hl, de + ld a, [hli] ; x#SPRITESTATEDATA2_MAPY + ldh [hSpriteMapYCoord], a + ld a, [hl] ; x#SPRITESTATEDATA2_MAPX + ldh [hSpriteMapXCoord], a + ret + +_GetSpritePosition2:: + ld hl, wSpriteStateData1 + ld de, SPRITESTATEDATA1_YPIXELS + ld a, [wSpriteIndex] + ldh [hSpriteIndex], a + call GetSpriteDataPointer + ld a, [hli] ; x#SPRITESTATEDATA1_YPIXELS + ld [wSavedSpriteScreenY], a + inc hl + ld a, [hl] ; x#SPRITESTATEDATA1_XPIXELS + ld [wSavedSpriteScreenX], a + ld de, wSpritePlayerStateData2MapY - wSpritePlayerStateData1XPixels + add hl, de + ld a, [hli] ; x#SPRITESTATEDATA2_MAPY + ld [wSavedSpriteMapY], a + ld a, [hl] ; x#SPRITESTATEDATA2_MAPX + ld [wSavedSpriteMapX], a + ret + +_SetSpritePosition1:: + ld hl, wSpriteStateData1 + ld de, SPRITESTATEDATA1_YPIXELS + ld a, [wSpriteIndex] + ldh [hSpriteIndex], a + call GetSpriteDataPointer + ldh a, [hSpriteScreenYCoord] ; x#SPRITESTATEDATA1_YPIXELS + ld [hli], a + inc hl + ldh a, [hSpriteScreenXCoord] ; x#SPRITESTATEDATA1_XPIXELS + ld [hl], a + ld de, wSpritePlayerStateData2MapY - wSpritePlayerStateData1XPixels + add hl, de + ldh a, [hSpriteMapYCoord] ; x#SPRITESTATEDATA2_MAPY + ld [hli], a + ldh a, [hSpriteMapXCoord] ; x#SPRITESTATEDATA2_MAPX + ld [hl], a + ret + +_SetSpritePosition2:: + ld hl, wSpriteStateData1 + ld de, SPRITESTATEDATA1_YPIXELS + ld a, [wSpriteIndex] + ldh [hSpriteIndex], a + call GetSpriteDataPointer + ld a, [wSavedSpriteScreenY] + ld [hli], a ; x#SPRITESTATEDATA1_YPIXELS + inc hl + ld a, [wSavedSpriteScreenX] + ld [hl], a ; x#SPRITESTATEDATA1_XPIXELS + ld de, wSpritePlayerStateData2MapY - wSpritePlayerStateData1XPixels + add hl, de + ld a, [wSavedSpriteMapY] + ld [hli], a ; x#SPRITESTATEDATA2_MAPY + ld a, [wSavedSpriteMapX] + ld [hl], a ; x#SPRITESTATEDATA2_MAPX + ret + +TrainerWalkUpToPlayer:: + ld a, [wSpriteIndex] + swap a + ld [wTrainerSpriteOffset], a + call ReadTrainerScreenPosition + ld a, [wTrainerFacingDirection] + and a ; SPRITE_FACING_DOWN + jr z, .facingDown + cp SPRITE_FACING_UP + jr z, .facingUp + cp SPRITE_FACING_LEFT + jr z, .facingLeft + jr .facingRight +.facingDown + ld a, [wTrainerScreenY] + ld b, a + ld a, $3c ; (fixed) player screen Y pos + call CalcDifference + cp $10 ; trainer is right above player + ret z + swap a + dec a + ld c, a ; bc = steps yet to go to reach player + xor a + ld b, a ; a = direction to go to + jr .writeWalkScript +.facingUp + ld a, [wTrainerScreenY] + ld b, a + ld a, $3c ; (fixed) player screen Y pos + call CalcDifference + cp $10 ; trainer is right below player + ret z + swap a + dec a + ld c, a ; bc = steps yet to go to reach player + ld b, $0 + ld a, $40 ; a = direction to go to + jr .writeWalkScript +.facingRight + ld a, [wTrainerScreenX] + ld b, a + ld a, $40 ; (fixed) player screen X pos + call CalcDifference + cp $10 ; trainer is directly left of player + ret z + swap a + dec a + ld c, a ; bc = steps yet to go to reach player + ld b, $0 + ld a, $c0 ; a = direction to go to + jr .writeWalkScript +.facingLeft + ld a, [wTrainerScreenX] + ld b, a + ld a, $40 ; (fixed) player screen X pos + call CalcDifference + cp $10 ; trainer is directly right of player + ret z + swap a + dec a + ld c, a ; bc = steps yet to go to reach player + ld b, $0 + ld a, $80 ; a = direction to go to +.writeWalkScript + ld hl, wNPCMovementDirections2 + ld de, wNPCMovementDirections2 + call FillMemory ; write the necessary steps to reach player + ld [hl], $ff ; write end of list sentinel + ld a, [wSpriteIndex] + ldh [hSpriteIndex], a + jp MoveSprite_ + +; input: de = offset within sprite entry +; output: hl = pointer to sprite data +GetSpriteDataPointer: + push de + add hl, de + ldh a, [hSpriteIndex] + swap a + ld d, $0 + ld e, a + add hl, de + pop de + ret + +; tests if this trainer is in the right position to engage the player and do so if she is. +TrainerEngage: + push hl + push de + ld a, [wTrainerSpriteOffset] + add SPRITESTATEDATA1_IMAGEINDEX + ld d, $0 + ld e, a + ld hl, wSpriteStateData1 + add hl, de + ld a, [hl] ; x#SPRITESTATEDATA1_IMAGEINDEX + sub $ff + jr nz, .spriteOnScreen ; test if sprite is on screen + jp .noEngage +.spriteOnScreen + ld a, [wTrainerSpriteOffset] + add SPRITESTATEDATA1_FACINGDIRECTION + ld d, $0 + ld e, a + ld hl, wSpriteStateData1 + add hl, de + ld a, [hl] ; x#SPRITESTATEDATA1_FACINGDIRECTION + ld [wTrainerFacingDirection], a + call ReadTrainerScreenPosition + ld a, [wTrainerScreenY] ; sprite screen Y pos + ld b, a + ld a, $3c + cp b + jr z, .linedUpY + ld a, [wTrainerScreenX] ; sprite screen X pos + ld b, a + ld a, $40 + cp b + jr z, .linedUpX + xor a + jp .noEngage +.linedUpY + ld a, [wTrainerScreenX] ; sprite screen X pos + ld b, a + ld a, $40 ; (fixed) player X position + call CalcDifference ; calc distance + jr z, .noEngage ; exact same position as player + call CheckSpriteCanSeePlayer + jr c, .engage + xor a + jr .noEngage +.linedUpX + ld a, [wTrainerScreenY] ; sprite screen Y pos + ld b, a + ld a, $3c ; (fixed) player Y position + call CalcDifference ; calc distance + jr z, .noEngage ; exact same position as player + call CheckSpriteCanSeePlayer + jr c, .engage + xor a + jp .noEngage +.engage + call CheckPlayerIsInFrontOfSprite + ld a, [wTrainerSpriteOffset] + and a + jr z, .noEngage + ld hl, wFlags_0xcd60 + set 0, [hl] + call EngageMapTrainer + ld a, $ff +.noEngage + ld [wTrainerSpriteOffset], a + pop de + pop hl + ret + +; reads trainer's Y position to wTrainerScreenY and X position to wTrainerScreenX +ReadTrainerScreenPosition: + ld a, [wTrainerSpriteOffset] + add SPRITESTATEDATA1_YPIXELS + ld d, $0 + ld e, a + ld hl, wSpriteStateData1 + add hl, de + ld a, [hl] ; x#SPRITESTATEDATA1_YPIXELS + ld [wTrainerScreenY], a + ld a, [wTrainerSpriteOffset] + add SPRITESTATEDATA1_XPIXELS + ld d, $0 + ld e, a + ld hl, wSpriteStateData1 + add hl, de + ld a, [hl] ; x#SPRITESTATEDATA1_XPIXELS + ld [wTrainerScreenX], a + ret + +; checks if the sprite is properly lined up with the player with respect to the direction it's looking. Also checks the distance between player and sprite +; note that this does not necessarily mean the sprite is seeing the player, he could be behind it's back +; a: distance player to sprite +CheckSpriteCanSeePlayer: + ld b, a + ld a, [wTrainerEngageDistance] ; how far the trainer can see + cp b + jr nc, .checkIfLinedUp + jr .notInLine ; player too far away +.checkIfLinedUp + ld a, [wTrainerFacingDirection] ; sprite facing direction + cp SPRITE_FACING_DOWN + jr z, .checkXCoord + cp SPRITE_FACING_UP + jr z, .checkXCoord + cp SPRITE_FACING_LEFT + jr z, .checkYCoord + cp SPRITE_FACING_RIGHT + jr z, .checkYCoord + jr .notInLine +.checkXCoord + ld a, [wTrainerScreenX] ; sprite screen X position + ld b, a + cp $40 + jr z, .inLine + jr .notInLine +.checkYCoord + ld a, [wTrainerScreenY] ; sprite screen Y position + ld b, a + cp $3c + jr nz, .notInLine +.inLine + scf + ret +.notInLine + and a + ret + +; tests if the player is in front of the sprite (rather than behind it) +CheckPlayerIsInFrontOfSprite: + ld a, [wCurMap] + cp POWER_PLANT + jp z, .engage ; bypass this for power plant to get voltorb fake items to work + ld a, [wTrainerSpriteOffset] + add SPRITESTATEDATA1_YPIXELS + ld d, $0 + ld e, a + ld hl, wSpriteStateData1 + add hl, de + ld a, [hl] ; x#SPRITESTATEDATA1_YPIXELS + cp $fc + jr nz, .notOnTopmostTile ; special case if sprite is on topmost tile (Y = $fc (-4)), make it come down a block + ld a, $c +.notOnTopmostTile + ld [wTrainerScreenY], a + ld a, [wTrainerSpriteOffset] + add SPRITESTATEDATA1_XPIXELS + ld d, $0 + ld e, a + ld hl, wSpriteStateData1 + add hl, de + ld a, [hl] ; x#SPRITESTATEDATA1_XPIXELS + ld [wTrainerScreenX], a + ld a, [wTrainerFacingDirection] ; facing direction + cp SPRITE_FACING_DOWN + jr nz, .notFacingDown + ld a, [wTrainerScreenY] ; sprite screen Y pos + cp $3c + jr c, .engage ; sprite above player + jr .noEngage ; sprite below player +.notFacingDown + cp SPRITE_FACING_UP + jr nz, .notFacingUp + ld a, [wTrainerScreenY] ; sprite screen Y pos + cp $3c + jr nc, .engage ; sprite below player + jr .noEngage ; sprite above player +.notFacingUp + cp SPRITE_FACING_LEFT + jr nz, .notFacingLeft + ld a, [wTrainerScreenX] ; sprite screen X pos + cp $40 + jr nc, .engage ; sprite right of player + jr .noEngage ; sprite left of player +.notFacingLeft + ld a, [wTrainerScreenX] ; sprite screen X pos + cp $40 + jr nc, .noEngage ; sprite right of player +.engage + ld a, $ff + jr .done +.noEngage + xor a +.done + ld [wTrainerSpriteOffset], a + ret diff --git a/engine/overworld/trainers.asm b/engine/overworld/trainers.asm deleted file mode 100755 index 655c6b2a..00000000 --- a/engine/overworld/trainers.asm +++ /dev/null @@ -1,349 +0,0 @@ -_GetSpritePosition1: - ld hl, wSpriteStateData1 - ld de, $4 - ld a, [wSpriteIndex] - ld [H_SPRITEINDEX], a - call GetSpriteDataPointer - ld a, [hli] ; c1x4 (screen Y pos) - ld [$ffeb], a - inc hl - ld a, [hl] ; c1x6 (screen X pos) - ld [$ffec], a - ld de, (wSpriteStateData2 + $4) - (wSpriteStateData1 + $6) - add hl, de - ld a, [hli] ; c2x4 (map Y pos) - ld [$ffed], a - ld a, [hl] ; c2x5 (map X pos) - ld [$ffee], a - ret - -_GetSpritePosition2: - ld hl, wSpriteStateData1 - ld de, $4 - ld a, [wSpriteIndex] - ld [H_SPRITEINDEX], a - call GetSpriteDataPointer - ld a, [hli] ; c1x4 (screen Y pos) - ld [wSavedSpriteScreenY], a - inc hl - ld a, [hl] ; c1x6 (screen X pos) - ld [wSavedSpriteScreenX], a - ld de, (wSpriteStateData2 + $4) - (wSpriteStateData1 + $6) - add hl, de - ld a, [hli] ; c2x4 (map Y pos) - ld [wSavedSpriteMapY], a - ld a, [hl] ; c2x5 (map X pos) - ld [wSavedSpriteMapX], a - ret - -_SetSpritePosition1: - ld hl, wSpriteStateData1 - ld de, $4 - ld a, [wSpriteIndex] - ld [H_SPRITEINDEX], a - call GetSpriteDataPointer - ld a, [$ffeb] ; c1x4 (screen Y pos) - ld [hli], a - inc hl - ld a, [$ffec] ; c1x6 (screen X pos) - ld [hl], a - ld de, (wSpriteStateData2 + $4) - (wSpriteStateData1 + $6) - add hl, de - ld a, [$ffed] ; c2x4 (map Y pos) - ld [hli], a - ld a, [$ffee] ; c2x5 (map X pos) - ld [hl], a - ret - -_SetSpritePosition2: - ld hl, wSpriteStateData1 - ld de, 4 - ld a, [wSpriteIndex] - ld [H_SPRITEINDEX], a - call GetSpriteDataPointer - ld a, [wSavedSpriteScreenY] - ld [hli], a ; c1x4 (screen Y pos) - inc hl - ld a, [wSavedSpriteScreenX] - ld [hl], a ; c1x6 (screen X pos) - ld de, (wSpriteStateData2 + $4) - (wSpriteStateData1 + $6) - add hl, de - ld a, [wSavedSpriteMapY] - ld [hli], a ; c2x4 (map Y pos) - ld a, [wSavedSpriteMapX] - ld [hl], a ; c2x5 (map X pos) - ret - -TrainerWalkUpToPlayer: - ld a, [wSpriteIndex] - swap a - ld [wTrainerSpriteOffset], a - call ReadTrainerScreenPosition - ld a, [wTrainerFacingDirection] - and a ; SPRITE_FACING_DOWN - jr z, .facingDown - cp SPRITE_FACING_UP - jr z, .facingUp - cp SPRITE_FACING_LEFT - jr z, .facingLeft - jr .facingRight -.facingDown - ld a, [wTrainerScreenY] - ld b, a - ld a, $3c ; (fixed) player screen Y pos - call CalcDifference - cp $10 ; trainer is right above player - ret z - swap a - dec a - ld c, a ; bc = steps yet to go to reach player - xor a - ld b, a ; a = direction to go to - jr .writeWalkScript -.facingUp - ld a, [wTrainerScreenY] - ld b, a - ld a, $3c ; (fixed) player screen Y pos - call CalcDifference - cp $10 ; trainer is right below player - ret z - swap a - dec a - ld c, a ; bc = steps yet to go to reach player - ld b, $0 - ld a, $40 ; a = direction to go to - jr .writeWalkScript -.facingRight - ld a, [wTrainerScreenX] - ld b, a - ld a, $40 ; (fixed) player screen X pos - call CalcDifference - cp $10 ; trainer is directly left of player - ret z - swap a - dec a - ld c, a ; bc = steps yet to go to reach player - ld b, $0 - ld a, $c0 ; a = direction to go to - jr .writeWalkScript -.facingLeft - ld a, [wTrainerScreenX] - ld b, a - ld a, $40 ; (fixed) player screen X pos - call CalcDifference - cp $10 ; trainer is directly right of player - ret z - swap a - dec a - ld c, a ; bc = steps yet to go to reach player - ld b, $0 - ld a, $80 ; a = direction to go to -.writeWalkScript - ld hl, wNPCMovementDirections2 - ld de, wNPCMovementDirections2 - call FillMemory ; write the necessary steps to reach player - ld [hl], $ff ; write end of list sentinel - ld a, [wSpriteIndex] - ld [H_SPRITEINDEX], a - jp MoveSprite_ - -; input: de = offset within sprite entry -; output: hl = pointer to sprite data -GetSpriteDataPointer: - push de - add hl, de - ld a, [H_SPRITEINDEX] - swap a - ld d, $0 - ld e, a - add hl, de - pop de - ret - -; tests if this trainer is in the right position to engage the player and do so if she is. -TrainerEngage: - push hl - push de - ld a, [wTrainerSpriteOffset] - add $2 - ld d, $0 - ld e, a - ld hl, wSpriteStateData1 - add hl, de - ld a, [hl] ; c1x2: sprite image index - sub $ff - jr nz, .spriteOnScreen ; test if sprite is on screen - jp .noEngage -.spriteOnScreen - ld a, [wTrainerSpriteOffset] - add $9 - ld d, $0 - ld e, a - ld hl, wSpriteStateData1 - add hl, de - ld a, [hl] ; c1x9: facing direction - ld [wTrainerFacingDirection], a - call ReadTrainerScreenPosition - ld a, [wTrainerScreenY] ; sprite screen Y pos - ld b, a - ld a, $3c - cp b - jr z, .linedUpY - ld a, [wTrainerScreenX] ; sprite screen X pos - ld b, a - ld a, $40 - cp b - jr z, .linedUpX - xor a - jp .noEngage -.linedUpY - ld a, [wTrainerScreenX] ; sprite screen X pos - ld b, a - ld a, $40 ; (fixed) player X position - call CalcDifference ; calc distance - jr z, .noEngage ; exact same position as player - call CheckSpriteCanSeePlayer - jr c, .engage - xor a - jr .noEngage -.linedUpX - ld a, [wTrainerScreenY] ; sprite screen Y pos - ld b, a - ld a, $3c ; (fixed) player Y position - call CalcDifference ; calc distance - jr z, .noEngage ; exact same position as player - call CheckSpriteCanSeePlayer - jr c, .engage - xor a - jp .noEngage -.engage - call CheckPlayerIsInFrontOfSprite - ld a, [wTrainerSpriteOffset] - and a - jr z, .noEngage - ld hl, wFlags_0xcd60 - set 0, [hl] - call EngageMapTrainer - ld a, $ff -.noEngage - ld [wTrainerSpriteOffset], a - pop de - pop hl - ret - -; reads trainer's Y position to wTrainerScreenY and X position to wTrainerScreenX -ReadTrainerScreenPosition: - ld a, [wTrainerSpriteOffset] - add $4 - ld d, $0 - ld e, a - ld hl, wSpriteStateData1 - add hl, de - ld a, [hl] ; c1x4 (sprite Y pos) - ld [wTrainerScreenY], a - ld a, [wTrainerSpriteOffset] - add $6 - ld d, $0 - ld e, a - ld hl, wSpriteStateData1 - add hl, de - ld a, [hl] ; c1x6 (sprite X pos) - ld [wTrainerScreenX], a - ret - -; checks if the sprite is properly lined up with the player with respect to the direction it's looking. Also checks the distance between player and sprite -; note that this does not necessarily mean the sprite is seeing the player, he could be behind it's back -; a: distance player to sprite -CheckSpriteCanSeePlayer: - ld b, a - ld a, [wTrainerEngageDistance] ; how far the trainer can see - cp b - jr nc, .checkIfLinedUp - jr .notInLine ; player too far away -.checkIfLinedUp - ld a, [wTrainerFacingDirection] ; sprite facing direction - cp SPRITE_FACING_DOWN - jr z, .checkXCoord - cp SPRITE_FACING_UP - jr z, .checkXCoord - cp SPRITE_FACING_LEFT - jr z, .checkYCoord - cp SPRITE_FACING_RIGHT - jr z, .checkYCoord - jr .notInLine -.checkXCoord - ld a, [wTrainerScreenX] ; sprite screen X position - ld b, a - cp $40 - jr z, .inLine - jr .notInLine -.checkYCoord - ld a, [wTrainerScreenY] ; sprite screen Y position - ld b, a - cp $3c - jr nz, .notInLine -.inLine - scf - ret -.notInLine - and a - ret - -; tests if the player is in front of the sprite (rather than behind it) -CheckPlayerIsInFrontOfSprite: - ld a, [wCurMap] - cp POWER_PLANT - jp z, .engage ; bypass this for power plant to get voltorb fake items to work - ld a, [wTrainerSpriteOffset] - add $4 - ld d, $0 - ld e, a - ld hl, wSpriteStateData1 - add hl, de - ld a, [hl] ; c1x4 (sprite screen Y pos) - cp $fc - jr nz, .notOnTopmostTile ; special case if sprite is on topmost tile (Y = $fc (-4)), make it come down a block - ld a, $c -.notOnTopmostTile - ld [wTrainerScreenY], a - ld a, [wTrainerSpriteOffset] - add $6 - ld d, $0 - ld e, a - ld hl, wSpriteStateData1 - add hl, de - ld a, [hl] ; c1x6 (sprite screen X pos) - ld [wTrainerScreenX], a - ld a, [wTrainerFacingDirection] ; facing direction - cp SPRITE_FACING_DOWN - jr nz, .notFacingDown - ld a, [wTrainerScreenY] ; sprite screen Y pos - cp $3c - jr c, .engage ; sprite above player - jr .noEngage ; sprite below player -.notFacingDown - cp SPRITE_FACING_UP - jr nz, .notFacingUp - ld a, [wTrainerScreenY] ; sprite screen Y pos - cp $3c - jr nc, .engage ; sprite below player - jr .noEngage ; sprite above player -.notFacingUp - cp SPRITE_FACING_LEFT - jr nz, .notFacingLeft - ld a, [wTrainerScreenX] ; sprite screen X pos - cp $40 - jr nc, .engage ; sprite right of player - jr .noEngage ; sprite left of player -.notFacingLeft - ld a, [wTrainerScreenX] ; sprite screen X pos - cp $40 - jr nc, .noEngage ; sprite right of player -.engage - ld a, $ff - jr .done -.noEngage - xor a -.done - ld [wTrainerSpriteOffset], a - ret diff --git a/engine/overworld/update_map.asm b/engine/overworld/update_map.asm index 8577b9e7..53a5592d 100644 --- a/engine/overworld/update_map.asm +++ b/engine/overworld/update_map.asm @@ -50,20 +50,20 @@ RedrawMapView: ld a, [wIsInBattle] inc a ret z - ld a, [H_AUTOBGTRANSFERENABLED] + ldh a, [hAutoBGTransferEnabled] push af - ld a, [hTilesetType] + ldh a, [hTilesetType] push af xor a - ld [H_AUTOBGTRANSFERENABLED], a - ld [hTilesetType], a ; no flower/water BG tile animations + ldh [hAutoBGTransferEnabled], a + ldh [hTilesetType], a ; no flower/water BG tile animations call LoadCurrentMapView call RunDefaultPaletteCommand ld hl, wMapViewVRAMPointer ld a, [hli] ld h, [hl] ld l, a - ld de, -2 * 32 + ld de, -2 * BG_MAP_WIDTH add hl, de ld a, h and $3 @@ -73,23 +73,23 @@ RedrawMapView: ld a, h ld [wBuffer + 1], a ; this copy of the address is not used ld a, 2 - ld [$ffbe], a - ld c, 9 ; number of rows of 2x2 tiles (this covers the whole screen) + ldh [hRedrawMapViewRowOffset], a + ld c, SCREEN_HEIGHT / 2 ; number of rows of 2x2 tiles (this covers the whole screen) .redrawRowLoop push bc push hl push hl ld hl, wTileMap - 2 * SCREEN_WIDTH ld de, SCREEN_WIDTH - ld a, [$ffbe] + ldh a, [hRedrawMapViewRowOffset] .calcWRAMAddrLoop add hl, de dec a jr nz, .calcWRAMAddrLoop call CopyToRedrawRowOrColumnSrcTiles pop hl - ld de, $20 - ld a, [$ffbe] + ld de, BG_MAP_WIDTH + ldh a, [hRedrawMapViewRowOffset] ld c, a .calcVRAMAddrLoop add hl, de @@ -98,13 +98,13 @@ RedrawMapView: or $98 dec c jr nz, .calcVRAMAddrLoop - ld [hRedrawRowOrColumnDest + 1], a + ldh [hRedrawRowOrColumnDest + 1], a ld a, l - ld [hRedrawRowOrColumnDest], a + ldh [hRedrawRowOrColumnDest], a ld a, REDRAW_ROW - ld [hRedrawRowOrColumnMode], a + ldh [hRedrawRowOrColumnMode], a call DelayFrame - ld hl, $ffbe + ld hl, hRedrawMapViewRowOffset inc [hl] inc [hl] pop hl @@ -112,9 +112,9 @@ RedrawMapView: dec c jr nz, .redrawRowLoop pop af - ld [hTilesetType], a + ldh [hTilesetType], a pop af - ld [H_AUTOBGTRANSFERENABLED], a + ldh [hAutoBGTransferEnabled], a ret CompareHLWithBC: diff --git a/engine/overworld/wild_mons.asm b/engine/overworld/wild_mons.asm index dae57f23..2593e0ec 100644 --- a/engine/overworld/wild_mons.asm +++ b/engine/overworld/wild_mons.asm @@ -1,4 +1,4 @@ -LoadWildData: +LoadWildData:: ld hl, WildDataPointers ld a, [wCurMap] @@ -16,10 +16,10 @@ LoadWildData: jr z, .NoGrassData ; if no grass data, skip to surfing data push hl ld de, wGrassMons ; otherwise, load grass data - ld bc, $0014 + ld bc, $14 call CopyData pop hl - ld bc, $0014 + ld bc, $14 add hl, bc .NoGrassData ld a, [hli] @@ -27,7 +27,7 @@ LoadWildData: and a ret z ; if no water data, we're done ld de, wWaterMons ; otherwise, load surfing data - ld bc, $0014 + ld bc, $14 jp CopyData -INCLUDE "data/wild_mons.asm" +INCLUDE "data/wild/grass_water.asm" diff --git a/engine/palettes.asm b/engine/palettes.asm deleted file mode 100755 index ec9816ab..00000000 --- a/engine/palettes.asm +++ /dev/null @@ -1,1116 +0,0 @@ -_RunPaletteCommand: - call GetPredefRegisters - ld a, b - cp $ff - jr nz, .next - ld a, [wDefaultPaletteCommand] ; use default command if command ID is $ff -.next - cp UPDATE_PARTY_MENU_BLK_PACKET - jp z, UpdatePartyMenuBlkPacket - ld l, a - ld h, 0 - add hl, hl - ld de, SetPalFunctions - add hl, de - ld a, [hli] - ld h, [hl] - ld l, a - ld de, SendSGBPackets - push de - jp hl - -SetPal_Black: - ld hl, PalPacket_Black - ld de, BlkPacket_Battle - ret - -; uses PalPacket_Empty to build a packet based on mon IDs and health color -SetPal_Battle: - ld hl, PalPacket_Empty - ld de, wPalPacket - ld bc, $10 - call CopyData - ;ld a, [wPlayerBattleStatus3] - ld hl, wBattleMonSpecies - ld a, [hl] - and a - jr z, .asm_71ef9 - ld hl, wPartyMon1 - ld a, [wPlayerMonNumber] - ld bc, wPartyMon2 - wPartyMon1 - call AddNTimes -.asm_71ef9 - call DeterminePaletteID - ld b, a - ;ld a, [wEnemyBattleStatus3] - ld hl, wEnemyMonSpecies2 - call DeterminePaletteID - ld c, a - ld hl, wPalPacket + 1 - ld a, [wPlayerHPBarColor] - add PAL_GREENBAR - ld [hli], a - inc hl - ld a, [wEnemyHPBarColor] - add PAL_GREENBAR - ld [hli], a - inc hl - ld a, b - ld [hli], a - inc hl - ld a, c - ld [hl], a - ld hl, wPalPacket - ld de, BlkPacket_Battle - ld a, SET_PAL_BATTLE - ld [wDefaultPaletteCommand], a - ret - -SetPal_TownMap: - ld hl, PalPacket_TownMap - ld de, BlkPacket_WholeScreen - ret - -; uses PalPacket_Empty to build a packet based the mon ID -SetPal_StatusScreen: - ld hl, PalPacket_Empty - ld de, wPalPacket - ld bc, $10 - call CopyData - ld a, [wcf91] - cp NUM_POKEMON_INDEXES + 1 - jr c, .pokemon - ld a, $1 ; not pokemon -.pokemon - call DeterminePaletteIDOutOfBattle - push af - ld hl, wPalPacket + 1 - ld a, [wStatusScreenHPBarColor] - add PAL_GREENBAR - ld [hli], a - inc hl - pop af - ld [hl], a - ld hl, wPalPacket - ld de, BlkPacket_StatusScreen - ret - -SetPal_PartyMenu: - ld hl, PalPacket_PartyMenu - ld de, wPartyMenuBlkPacket - ret - -SetPal_Pokedex: - ld hl, PalPacket_Pokedex - ld de, wPalPacket - ld bc, $10 - call CopyData - ld a, [wcf91] - call DeterminePaletteIDOutOfBattle - ld hl, wPalPacket + 3 - ld [hl], a - ld hl, wPalPacket - ld de, BlkPacket_Pokedex - ret - -SetPal_Slots: - ld hl, PalPacket_Slots - ld de, BlkPacket_Slots - ret - -SetPal_Titlescreen: - ld hl, PalPacket_Titlescreen - ld de, BlkPacket_Titlescreen - ret - -; used mostly for menus and the Oak intro -SetPal_Generic: - ld hl, PalPacket_Generic - ld de, BlkPacket_WholeScreen - ret - -SetPal_NidorinoIntro: - ld hl, PalPacket_NidorinoIntro - ld de, BlkPacket_NidorinoIntro - ret - -SetPal_GameFreakIntro: - ld hl, PalPacket_GameFreakIntro - ld de, BlkPacket_GameFreakIntro - ld a, SET_PAL_GENERIC - ld [wDefaultPaletteCommand], a - ret - -; uses PalPacket_Empty to build a packet based on the current map -SetPal_Overworld: - ld hl, PalPacket_Empty - ld de, wPalPacket - ld bc, $10 - call CopyData - ld a, [wCurMapTileset] - cp CEMETERY - jr z, .PokemonTowerOrAgatha - cp CAVERN - jr z, .caveOrBruno - ld a, [wCurMap] - cp REDS_HOUSE_1F - jr c, .townOrRoute - cp CERULEAN_CAVE_2F - jr c, .normalDungeonOrBuilding - cp NAME_RATERS_HOUSE - jr c, .caveOrBruno - cp LORELEIS_ROOM - jr z, .Lorelei - cp BRUNOS_ROOM - jr z, .caveOrBruno - cp TRADE_CENTER - jr z, .trade_center_colosseum - cp COLOSSEUM - jr z, .trade_center_colosseum -.normalDungeonOrBuilding - ld a, [wLastMap] ; town or route that current dungeon or building is located -.townOrRoute - cp SAFFRON_CITY + 1 - jr c, .town - ld a, PAL_ROUTE - 1 -.town - inc a ; a town's palette ID is its map ID + 1 - ld hl, wPalPacket + 1 - ld [hld], a - ld de, BlkPacket_WholeScreen - ld a, SET_PAL_OVERWORLD - ld [wDefaultPaletteCommand], a - ret -.PokemonTowerOrAgatha - ld a, PAL_GREYMON - 1 - jr .town -.caveOrBruno - ld a, PAL_CAVE - 1 - jr .town -.Lorelei - xor a - jr .town -.trade_center_colosseum - ld a, PAL_GREYMON - 1 - jr .town - -; used when a Pokemon is the only thing on the screen -; such as evolution, trading and the Hall of Fame -SetPal_PokemonWholeScreen: - push bc - ld hl, PalPacket_Empty - ld de, wPalPacket - ld bc, $10 - call CopyData - pop bc - ld a, c - and a - ld a, PAL_BLACK - jr nz, .next - ld a, [wWholeScreenPaletteMonSpecies] - call DeterminePaletteIDOutOfBattle -.next - ld [wPalPacket + 1], a - ld hl, wPalPacket - ld de, BlkPacket_WholeScreen - ret - -SetPal_TrainerCard: - ld hl, BlkPacket_TrainerCard - ld de, wTrainerCardBlkPacket - ld bc, $40 - call CopyData - ld de, BadgeBlkDataLengths - ld hl, wTrainerCardBlkPacket + 2 - ld a, [wObtainedBadges] - ld c, 8 -.badgeLoop - srl a - push af - jr c, .haveBadge -; The player doens't have the badge, so zero the badge's blk data. - push bc - ld a, [de] - ld c, a - xor a -.zeroBadgeDataLoop - ld [hli], a - dec c - jr nz, .zeroBadgeDataLoop - pop bc - jr .nextBadge -.haveBadge -; The player does have the badge, so skip past the badge's blk data. - ld a, [de] -.skipBadgeDataLoop - inc hl - dec a - jr nz, .skipBadgeDataLoop -.nextBadge - pop af - inc de - dec c - jr nz, .badgeLoop - ld hl, PalPacket_TrainerCard - ld de, wTrainerCardBlkPacket - ret - -SendUnknownPalPacket_7205d:: - ld hl, UnknownPalPacket_72811 - ld de, BlkPacket_WholeScreen - ret - -SendUnknownPalPacket_72064:: - ld hl, UnknownPalPacket_72821 - ld de, UnknownPacket_72751 - ret - -SetPalFunctions: - dw SetPal_Black - dw SetPal_Battle - dw SetPal_TownMap - dw SetPal_StatusScreen - dw SetPal_Pokedex - dw SetPal_Slots - dw SetPal_Titlescreen - dw SetPal_NidorinoIntro - dw SetPal_Generic - dw SetPal_Overworld - dw SetPal_PartyMenu - dw SetPal_PokemonWholeScreen - dw SetPal_GameFreakIntro - dw SetPal_TrainerCard - dw SendUnknownPalPacket_7205d - dw SendUnknownPalPacket_72064 - -; The length of the blk data of each badge on the Trainer Card. -; The Rainbow Badge has 3 entries because of its many colors. -BadgeBlkDataLengths: - db 6 ; Boulder Badge - db 6 ; Cascade Badge - db 6 ; Thunder Badge - db 6 * 3 ; Rainbow Badge - db 6 ; Soul Badge - db 6 ; Marsh Badge - db 6 ; Volcano Badge - db 6 ; Earth Badge - -DeterminePaletteID: - ld a, [hl] -DeterminePaletteIDOutOfBattle: - ld [wd11e], a - and a ; is the mon index 0? - jr z, .skipDexNumConversion - push bc - predef IndexToPokedex - pop bc - ld a, [wd11e] -.skipDexNumConversion - ld e, a - ld d, 0 - ld hl, MonsterPalettes ; not just for Pokemon, Trainers use it too - add hl, de - ld a, [hl] - ret - -YellowIntroPaletteAction:: - ld a, e - and a - jr nz, .asm_720bd - ld hl, PalPacket_Generic - ld a, [hGBC] - and a - jp z, SendSGBPacket - jp InitGBCPalettes - -.asm_720bd - ld hl, UnknownPalPacket_72811 - ld a, [hGBC] - and a - jp z, SendSGBPacket - call InitGBCPalettes - ld hl, PalPacket_Generic - inc hl - ld a, [hli] - call GetGBCBasePalAddress - ld a, e - ld [wGBCBasePalPointers + 2], a - ld a, d - ld [wGBCBasePalPointers + 2 + 1], a - xor a ; CONVERT_BGP - call DMGPalToGBCPal - ld a, 1 - call TransferCurBGPData - ret - -LoadOverworldPikachuFrontpicPalettes:: - ld hl, PalPacket_Empty - ld de, wPalPacket - ld bc, $10 - call CopyData - call GetPal_Pikachu - ld hl, wPartyMenuBlkPacket - ld [hl], a - ld hl, wPartyMenuBlkPacket + 2 - ld a, $26 - ld [hl], a - ld hl, wPalPacket - ld a, [hGBC] - and a - jr nz, .cgb_1 - call SendSGBPacket - jr .okay_1 - -.cgb_1 - call InitGBCPalettes -.okay_1 - ld hl, BlkPacket_WholeScreen - ld de, wPalPacket - ld bc, $10 - call CopyData - ld hl, wPartyMenuBlkPacket + 2 - ld a, $5 - ld [hli], a - ld a, $7 - ld [hli], a - ld a, $6 - ld [hli], a - ld a, $b - ld [hli], a - ld a, $a - ld [hl], a - ld hl, wPalPacket - ld a, [hGBC] - and a - jr nz, .cgb_2 - call SendSGBPacket - jr .okay_2 - -.cgb_2 - call InitGBCPalettes -.okay_2 - ret - -GetPal_Pikachu:: -; similar to SetPal_Overworld - ld a, [wCurMapTileset] - cp CEMETERY - jr z, .PokemonTowerOrAgatha - cp CAVERN - jr z, .caveOrBruno - ld a, [wCurMap] - cp REDS_HOUSE_1F - jr c, .townOrRoute - cp CERULEAN_CAVE_2F - jr c, .normalDungeonOrBuilding - cp NAME_RATERS_HOUSE - jr c, .caveOrBruno - cp LORELEIS_ROOM - jr z, .Lorelei - cp BRUNOS_ROOM - jr z, .caveOrBruno - cp TRADE_CENTER - jr z, .battleOrTradeCenter - cp COLOSSEUM - jr z, .battleOrTradeCenter -.normalDungeonOrBuilding - ld a, [wLastMap] ; town or route that current dungeon or building is located -.townOrRoute - cp SAFFRON_CITY + 1 - jr c, .town - ld a, PAL_ROUTE - 1 -.town - inc a ; a town's pallete ID is its map ID + 1 - ret - -.PokemonTowerOrAgatha - ld a, PAL_GREYMON - 1 - jr .town - -.caveOrBruno - ld a, PAL_CAVE - 1 - jr .town - -.Lorelei - xor a ; PAL_PALLET - 1 - jr .town - -.battleOrTradeCenter - ld a, PAL_GREYMON - 1 - jr .town - -InitPartyMenuBlkPacket: - ld hl, BlkPacket_PartyMenu - ld de, wPartyMenuBlkPacket - ld bc, $30 - jp CopyData - -UpdatePartyMenuBlkPacket: -; Update the blk packet with the palette of the HP bar that is -; specified in [wWhichPartyMenuHPBar]. - ld hl, wPartyMenuHPBarColors - ld a, [wWhichPartyMenuHPBar] - ld e, a - ld d, 0 - add hl, de - ld e, l - ld d, h - ld a, [de] - and a - ld e, (1 << 2) | 1 ; green - jr z, .next - dec a - ld e, (2 << 2) | 2 ; yellow - jr z, .next - ld e, (3 << 2) | 3 ; red -.next - push de - ld hl, wPartyMenuBlkPacket + 8 + 1 - ld bc, 6 - ld a, [wWhichPartyMenuHPBar] - call AddNTimes - pop de - ld [hl], e - ret - -SendSGBPacket: - ld a, 1 - ld [hDisableJoypadPolling], a ; don't poll joypad while sending packet - call _SendSGBPacket - xor a - ld [hDisableJoypadPolling], a - ret - -_SendSGBPacket: -;check number of packets - ld a, [hl] - and $07 - ret z -; store number of packets in B - ld b, a -.loop2 -; save B for later use - push bc -; send RESET signal (P14=LOW, P15=LOW) - xor a - ld [rJOYP], a -; set P14=HIGH, P15=HIGH - ld a, $30 - ld [rJOYP], a -;load length of packets (16 bytes) - ld b, $10 -.nextByte -;set bit counter (8 bits per byte) - ld e, $08 -; get next byte in the packet - ld a, [hli] - ld d, a -.nextBit0 - bit 0, d -; if 0th bit is not zero set P14=HIGH, P15=LOW (send bit 1) - ld a, $10 - jr nz, .next0 -; else (if 0th bit is zero) set P14=LOW, P15=HIGH (send bit 0) - ld a, $20 -.next0 - ld [rJOYP], a -; must set P14=HIGH, P15=HIGH between each "pulse" - ld a, $30 - ld [rJOYP], a -; rotation will put next bit in 0th position (so we can always use command -; "bit 0, d" to fetch the bit that has to be sent) - rr d -; decrease bit counter so we know when we have sent all 8 bits of current byte - dec e - jr nz, .nextBit0 - dec b - jr nz, .nextByte -; send bit 1 as a "stop bit" (end of parameter data) - ld a, $20 - ld [rJOYP], a -; set P14=HIGH, P15=HIGH - ld a, $30 - ld [rJOYP], a -; wait for about 70000 cycles - call Wait7000 -; restore (previously pushed) number of packets - pop bc - dec b -; return if there are no more packets - ret z -; else send 16 more bytes - jr .loop2 - -LoadSGB: - xor a - ld [wOnSGB], a - call CheckSGB - jr c, .onSGB - ld a, [hGBC] - and a - jr z, .onDMG - ld a, $1 - ld [wOnSGB], a -.onDMG - ret -.onSGB - ld a, $1 - ld [wOnSGB], a - di - call PrepareSuperNintendoVRAMTransfer - ei - ld a, 1 - ld [wCopyingSGBTileData], a - ld de, ChrTrnPacket - ld hl, SGBBorderGraphics - call CopyGfxToSuperNintendoVRAM - xor a - ld [wCopyingSGBTileData], a - ld de, PctTrnPacket - ld hl, BorderPalettes - call CopyGfxToSuperNintendoVRAM - xor a - ld [wCopyingSGBTileData], a - ld de, PalTrnPacket - ld hl, SuperPalettes - call CopyGfxToSuperNintendoVRAM - call ClearVram - ld hl, MaskEnCancelPacket - jp SendSGBPacket - -PrepareSuperNintendoVRAMTransfer: - ld hl, .packetPointers - ld c, 9 -.loop - push bc - ld a, [hli] - push hl - ld h, [hl] - ld l, a - call SendSGBPacket - pop hl - inc hl - pop bc - dec c - jr nz, .loop - ret - -.packetPointers -; Only the first packet is needed. - dw MaskEnFreezePacket - dw DataSnd_728a1 - dw DataSnd_728b1 - dw DataSnd_728c1 - dw DataSnd_728d1 - dw DataSnd_728e1 - dw DataSnd_728f1 - dw DataSnd_72901 - dw DataSnd_72911 - -CheckSGB: -; Returns whether the game is running on an SGB in carry. - ld hl, MltReq2Packet - call SendSGBPacket - call Wait7000 - ld a, [rJOYP] - and $3 - cp $3 - jr nz, .isSGB - ld a, $20 - ld [rJOYP], a - ld a, [rJOYP] - ld a, [rJOYP] - call Wait7000 - call Wait7000 - ld a, $30 - ld [rJOYP], a - call Wait7000 - call Wait7000 - ld a, $10 - ld [rJOYP], a - ld a, [rJOYP] - ld a, [rJOYP] - ld a, [rJOYP] - ld a, [rJOYP] - ld a, [rJOYP] - ld a, [rJOYP] - call Wait7000 - call Wait7000 - ld a, $30 - ld [rJOYP], a - ld a, [rJOYP] - ld a, [rJOYP] - ld a, [rJOYP] - call Wait7000 - call Wait7000 - ld a, [rJOYP] - and $3 - cp $3 - jr nz, .isSGB - call SendMltReq1Packet - and a - ret -.isSGB - call SendMltReq1Packet - scf - ret - -SendMltReq1Packet: - ld hl, MltReq1Packet - call SendSGBPacket - jp Wait7000 - -CopyGfxToSuperNintendoVRAM: - di - push de - call DisableLCD - ld a, $e4 - ld [rBGP], a - call _UpdateGBCPal_BGP_CheckDMG - ld de, vChars1 - ld a, [wCopyingSGBTileData] - and a - jr z, .notCopyingTileData - call CopySGBBorderTiles - jr .next -.notCopyingTileData - ld bc, $1000 - call CopyData -.next - ld hl, vBGMap0 - ld de, $c - ld a, $80 - ld c, $d -.loop - ld b, $14 -.innerLoop - ld [hli], a - inc a - dec b - jr nz, .innerLoop - add hl, de - dec c - jr nz, .loop - ld a, $e3 - ld [rLCDC], a - pop hl - call SendSGBPacket - xor a - ld [rBGP], a - call _UpdateGBCPal_BGP_CheckDMG - ei - ret - -Wait7000: -; Each loop takes 9 cycles so this routine actually waits 63000 cycles. - ld de, 7000 -.loop - nop - nop - nop - dec de - ld a, d - or e - jr nz, .loop - ret - -SendSGBPackets: - ld a, [hGBC] - and a - jr z, .notGBC - push de - call InitGBCPalettes - pop hl - call InitGBCPalettes - ld a, [rLCDC] - and rLCDC_ENABLE_MASK - ret z - call Delay3 - ret -.notGBC - push de - call SendSGBPacket - pop hl - jp SendSGBPacket - -InitGBCPalettes: - ld a, [hl] - and $f8 - cp $20 - jp z, TranslatePalPacketToBGMapAttributes - - inc hl - -index = 0 - - REPT NUM_ACTIVE_PALS - IF index > 0 - pop hl - ENDC - - ld a, [hli] - inc hl - - IF index < (NUM_ACTIVE_PALS + -1) - push hl - ENDC - - call GetGBCBasePalAddress - ld a, e - ld [wGBCBasePalPointers + index * 2], a - ld a, d - ld [wGBCBasePalPointers + index * 2 + 1], a - - xor a ; CONVERT_BGP - call DMGPalToGBCPal - ld a, index - call TransferCurBGPData - - ld a, CONVERT_OBP0 - call DMGPalToGBCPal - ld a, index - call TransferCurOBPData - - ld a, CONVERT_OBP1 - call DMGPalToGBCPal - ld a, index + 4 - call TransferCurOBPData - -index = index + 1 - ENDR - - ret - -GetGBCBasePalAddress:: -; Input: a = palette ID -; Output: de = palette address - push hl - ld l, a - xor a - ld h, a - add hl, hl - add hl, hl - add hl, hl - ld de, GBCBasePalettes - add hl, de - ld a, l - ld e, a - ld a, h - ld d, a - pop hl - ret - -DMGPalToGBCPal:: -; Populate wGBCPal with colors from a base palette, selected using one of the -; DMG palette registers. -; Input: -; a = which DMG palette register -; de = address of GBC base palette - and a - jr nz, .notBGP - ld a, [rBGP] - ld [wLastBGP], a - jr .convert -.notBGP - dec a - jr nz, .notOBP0 - ld a, [rOBP0] - ld [wLastOBP0], a - jr .convert -.notOBP0 - ld a, [rOBP1] - ld [wLastOBP1], a -.convert -color_index = 0 - REPT NUM_COLORS - ld b, a - and %11 - call .GetColorAddress - ld a, [hli] - ld [wGBCPal + color_index * 2], a - ld a, [hl] - ld [wGBCPal + color_index * 2 + 1], a - - IF color_index < (NUM_COLORS + -1) - ld a, b - rrca - rrca - ENDC - -color_index = color_index + 1 - ENDR - ret - -.GetColorAddress: - add a - ld l, a - xor a - ld h, a - add hl, de - ret - -TransferCurBGPData:: - push de - add a - add a - add a - or $80 ; auto-increment - ld [rBGPI], a - ld de, rBGPD - ld hl, wGBCPal - ld b, %10 ; mask for non-V-blank/non-H-blank STAT mode - ld a, [rLCDC] - and rLCDC_ENABLE_MASK - jr nz, .lcdEnabled - rept NUM_COLORS - call TransferPalColorLCDDisabled - endr - jr .done -.lcdEnabled - rept NUM_COLORS - call TransferPalColorLCDEnabled - endr -.done - pop de - ret - -BufferBGPPal:: -; Copy wGBCPal to palette a in wBGPPalsBuffer. - push de - add a - add a - add a - ld l, a - xor a - ld h, a - ld de, wBGPPalsBuffer - add hl, de - ld de, wGBCPal - ld c, PAL_SIZE -.loop - ld a, [de] - ld [hli], a - inc de - dec c - jr nz, .loop - pop de - ret - -TransferBGPPals:: -; Transfer the buffered BG palettes. - ld a, [rLCDC] - and rLCDC_ENABLE_MASK - jr z, .lcdDisabled - di -.waitLoop - ld a, [rLY] - cp 144 - jr c, .waitLoop -.lcdDisabled - call .DoTransfer - ei - ret - -.DoTransfer: - xor a - or $80 ; auto-increment - ld [rBGPI], a - ld de, rBGPD - ld hl, wBGPPalsBuffer - ld c, 4 * PAL_SIZE -.loop - ld a, [hli] - ld [de], a - dec c - jr nz, .loop - ret - -TransferCurOBPData: - push de - add a - add a - add a - or $80 ; auto-increment - ld [rOBPI], a - ld de, rOBPD - ld hl, wGBCPal - ld b, %10 ; mask for non-V-blank/non-H-blank STAT mode - ld a, [rLCDC] - and rLCDC_ENABLE_MASK - jr nz, .lcdEnabled - rept NUM_COLORS - call TransferPalColorLCDDisabled - endr - jr .done -.lcdEnabled - rept NUM_COLORS - call TransferPalColorLCDEnabled - endr -.done - pop de - ret - -TransferPalColorLCDEnabled: -; Transfer a palette color while the LCD is enabled. - -; In case we're already in H-blank or V-blank, wait for it to end. This is a -; precaution so that the transfer doesn't extend past the blanking period. - ld a, [rSTAT] - and b - jr z, TransferPalColorLCDEnabled - -; Wait for H-blank or V-blank to begin. -.notInBlankingPeriod - ld a, [rSTAT] - and b - jr nz, .notInBlankingPeriod -; fall through - -TransferPalColorLCDDisabled: -; Transfer a palette color while the LCD is disabled. - ld a, [hli] - ld [de], a - ld a, [hli] - ld [de], a - ret - -_UpdateGBCPal_BGP_CheckDMG:: - ld a, [hGBC] - and a - ret z -; fall through - -_UpdateGBCPal_BGP:: -index = 0 - - REPT NUM_ACTIVE_PALS - ld a, [wGBCBasePalPointers + index * 2] - ld e, a - ld a, [wGBCBasePalPointers + index * 2 + 1] - ld d, a - xor a ; CONVERT_BGP - call DMGPalToGBCPal - ld a, index - call BufferBGPPal - -index = index + 1 - ENDR - - call TransferBGPPals - ret - -_UpdateGBCPal_OBP:: -index = 0 - - REPT NUM_ACTIVE_PALS - ld a, [wGBCBasePalPointers + index * 2] - ld e, a - ld a, [wGBCBasePalPointers + index * 2 + 1] - ld d, a - ld a, c - call DMGPalToGBCPal - ld a, c - dec a - rlca - rlca - - IF index > 0 - IF index == 1 - inc a - ELSE - add index - ENDC - ENDC - - call TransferCurOBPData - -index = index + 1 - ENDR - - ret - -TranslatePalPacketToBGMapAttributes:: -; translate the SGB pal packets into something usable for the GBC - push hl - pop de - ld hl, PalPacketPointers - ld a, [hli] - ld c, a -.loop - ld a, e -.innerLoop - cp [hl] - jr z, .checkHighByte - inc hl - inc hl - dec c - jr nz, .innerLoop - ret -.checkHighByte -; the low byte of pointer matched, so check the high byte - inc hl - ld a, d - cp [hl] - jr z, .foundMatchingPointer - inc hl - dec c - jr nz, .loop - ret -.foundMatchingPointer - callba LoadBGMapAttributes - ret - -PalPacketPointers:: - db (palPacketPointersEnd - palPacketPointers) / 2 -palPacketPointers - dw BlkPacket_WholeScreen - dw BlkPacket_Battle - dw BlkPacket_StatusScreen - dw BlkPacket_Pokedex - dw BlkPacket_Slots - dw BlkPacket_Titlescreen - dw BlkPacket_NidorinoIntro - dw wPartyMenuBlkPacket - dw wTrainerCardBlkPacket - dw BlkPacket_GameFreakIntro - dw wPalPacket - dw UnknownPacket_72751 -palPacketPointersEnd - -CopySGBBorderTiles: -; SGB tile data is stored in a 4BPP planar format. -; Each tile is 32 bytes. The first 16 bytes contain bit planes 1 and 2, while -; the second 16 bytes contain bit planes 3 and 4. -; This function converts 2BPP planar data into this format by mapping -; 2BPP colors 0-3 to 4BPP colors 0-3. 4BPP colors 4-15 are not used. - ld b, 128 -.tileLoop -; Copy bit planes 1 and 2 of the tile data. - ld c, 16 -.copyLoop - ld a, [hli] - ld [de], a - inc de - dec c - jr nz, .copyLoop - -; Zero bit planes 3 and 4. - ld c, 16 - xor a -.zeroLoop - ld [de], a - inc de - dec c - jr nz, .zeroLoop - - dec b - jr nz, .tileLoop - ret - -INCLUDE "data/sgb_packets.asm" - -INCLUDE "data/mon_palettes.asm" - -INCLUDE "data/super_palettes.asm" - -INCLUDE "data/sgb_border.asm" diff --git a/engine/pathfinding.asm b/engine/pathfinding.asm deleted file mode 100644 index f3d23b7c..00000000 --- a/engine/pathfinding.asm +++ /dev/null @@ -1,201 +0,0 @@ -FindPathToPlayer: - xor a - ld hl, hFindPathNumSteps - ld [hli], a ; hFindPathNumSteps - ld [hli], a ; hFindPathFlags - ld [hli], a ; hFindPathYProgress - ld [hl], a ; hFindPathXProgress - ld hl, wNPCMovementDirections2 - ld de, $0 -.loop - ld a, [hFindPathYProgress] - ld b, a - ld a, [hNPCPlayerYDistance] ; Y distance in steps - call CalcDifference - ld d, a - and a - jr nz, .asm_f76a - ld a, [hFindPathFlags] - set 0, a ; current end of path matches the player's Y coordinate - ld [hFindPathFlags], a -.asm_f76a - ld a, [hFindPathXProgress] - ld b, a - ld a, [hNPCPlayerXDistance] ; X distance in steps - call CalcDifference - ld e, a - and a - jr nz, .asm_f77c - ld a, [hFindPathFlags] - set 1, a ; current end of path matches the player's X coordinate - ld [hFindPathFlags], a -.asm_f77c - ld a, [hFindPathFlags] - cp $3 ; has the end of the path reached the player's position? - jr z, .done -; Compare whether the X distance between the player and the current of the path -; is greater or if the Y distance is. Then, try to reduce whichever is greater. - ld a, e - cp d - jr c, .yDistanceGreater -; x distance is greater - ld a, [hNPCPlayerRelativePosFlags] - bit 1, a - jr nz, .playerIsLeftOfNPC - ld d, NPC_MOVEMENT_RIGHT - jr .next1 -.playerIsLeftOfNPC - ld d, NPC_MOVEMENT_LEFT -.next1 - ld a, [hFindPathXProgress] - add 1 - ld [hFindPathXProgress], a - jr .storeDirection -.yDistanceGreater - ld a, [hNPCPlayerRelativePosFlags] - bit 0, a - jr nz, .playerIsAboveNPC - ld d, NPC_MOVEMENT_DOWN - jr .next2 -.playerIsAboveNPC - ld d, NPC_MOVEMENT_UP -.next2 - ld a, [hFindPathYProgress] - add 1 - ld [hFindPathYProgress], a -.storeDirection - ld a, d - ld [hli], a - ld a, [hFindPathNumSteps] - inc a - ld [hFindPathNumSteps], a - jp .loop -.done - ld [hl], $ff - ret - -CalcPositionOfPlayerRelativeToNPC: - xor a - ld [hNPCPlayerRelativePosFlags], a - ld a, [wSpriteStateData1 + 4] ; player's sprite screen Y position in pixels - ld d, a - ld a, [wSpriteStateData1 + 6] ; player's sprite screen X position in pixels - ld e, a - ld hl, wSpriteStateData1 - ld a, [hNPCSpriteOffset] - add l - add $4 - ld l, a - jr nc, .noCarry - inc h -.noCarry - ld a, d - ld b, a - ld a, [hli] ; NPC sprite screen Y position in pixels - call CalcDifference - jr nc, .NPCSouthOfOrAlignedWithPlayer -.NPCNorthOfPlayer - push hl - ld hl, hNPCPlayerRelativePosFlags - bit 0, [hl] - set 0, [hl] - pop hl - jr .divideYDistance -.NPCSouthOfOrAlignedWithPlayer - push hl - ld hl, hNPCPlayerRelativePosFlags - bit 0, [hl] - res 0, [hl] - pop hl -.divideYDistance - push hl - ld hl, hDividend2 - ld [hli], a - ld a, 16 - ld [hli], a - call DivideBytes ; divide Y absolute distance by 16 - ld a, [hl] ; quotient - ld [hNPCPlayerYDistance], a - pop hl - inc hl - ld b, e - ld a, [hl] ; NPC sprite screen X position in pixels - call CalcDifference - jr nc, .NPCEastOfOrAlignedWithPlayer -.NPCWestOfPlayer - push hl - ld hl, hNPCPlayerRelativePosFlags - bit 1, [hl] - set 1, [hl] - pop hl - jr .divideXDistance -.NPCEastOfOrAlignedWithPlayer - push hl - ld hl, hNPCPlayerRelativePosFlags - bit 1, [hl] - res 1, [hl] - pop hl -.divideXDistance - ld [hDividend2], a - ld a, 16 - ld [hDivisor2], a - call DivideBytes ; divide X absolute distance by 16 - ld a, [hQuotient2] - ld [hNPCPlayerXDistance], a - ld a, [hNPCPlayerRelativePosPerspective] - and a - ret z - ld a, [hNPCPlayerRelativePosFlags] - cpl - and $3 - ld [hNPCPlayerRelativePosFlags], a - ret - -ConvertNPCMovementDirectionsToJoypadMasks: - ld a, [hNPCMovementDirections2Index] - ld [wNPCMovementDirections2Index], a - dec a - ld de, wSimulatedJoypadStatesEnd - ld hl, wNPCMovementDirections2 - add l - ld l, a - jr nc, .loop - inc h -.loop - ld a, [hld] - call ConvertNPCMovementDirectionToJoypadMask - ld [de], a - inc de - ld a, [hNPCMovementDirections2Index] - dec a - ld [hNPCMovementDirections2Index], a - jr nz, .loop - ret - -ConvertNPCMovementDirectionToJoypadMask: - push hl - ld b, a - ld hl, NPCMovementDirectionsToJoypadMasksTable -.loop - ld a, [hli] - cp $ff - jr z, .done - cp b - jr z, .loadJoypadMask - inc hl - jr .loop -.loadJoypadMask - ld a, [hl] -.done - pop hl - ret - -NPCMovementDirectionsToJoypadMasksTable: - db NPC_MOVEMENT_UP, D_UP - db NPC_MOVEMENT_DOWN, D_DOWN - db NPC_MOVEMENT_LEFT, D_LEFT - db NPC_MOVEMENT_RIGHT, D_RIGHT - db $ff - -; unreferenced - ret diff --git a/engine/pikachu_emotions.asm b/engine/pikachu_emotions.asm index 1518b28e..55262493 100755 --- a/engine/pikachu_emotions.asm +++ b/engine/pikachu_emotions.asm @@ -1,19 +1,19 @@ -IsPlayerTalkingToPikachu: +IsPlayerTalkingToPikachu:: ld a, [wd436] and a ret z - ld a, [hSpriteIndexOrTextID] + ldh a, [hSpriteIndexOrTextID] cp $f ret nz call InitializePikachuTextID xor a - ld [hSpriteIndexOrTextID], a + ldh [hSpriteIndexOrTextID], a ld [wd436], a ret -InitializePikachuTextID: - ld a, $d4 ; display - ld [hSpriteIndexOrTextID], a +InitializePikachuTextID:: + ld a, TEXT_PIKACHU_ANIM ; display + ldh [hSpriteIndexOrTextID], a xor a ld [wPlayerMovingDirection], a ld a, $1 @@ -92,7 +92,7 @@ StarterPikachuEmotionCommand_pcm: PlayPikachuSoundClip_: cp $ff ret z - callab PlayPikachuSoundClip + callfar PlayPikachuSoundClip ret StarterPikachuEmotionCommand_emote: @@ -190,7 +190,7 @@ PlaySpecificPikachuEmotion: ld a, e jr load_expression -TalkToPikachu: +TalkToPikachu:: call MapSpecificPikachuExpression jr c, load_expression call GetPikaPicAnimationScriptIndex @@ -267,7 +267,7 @@ MapSpecificPikachuExpression: jr .check_pikachu_status .notPewterPokecenter - callab Func_f24ae + callfar Func_f24ae ld a, e cp $ff jr nz, .play_emotion @@ -277,7 +277,7 @@ MapSpecificPikachuExpression: call IsPlayerPikachuAsleepInParty ldpikaemotion a, PikachuEmotion11 jr c, .play_emotion - callab CheckPikachuFaintedOrStatused ; same bank + callfar CheckPikachuFaintedOrStatused ; same bank ldpikaemotion a, PikachuEmotion28 jr c, .play_emotion ld a, [wCurMap] @@ -327,7 +327,7 @@ IsPlayerPikachuAsleepInParty: jr z, .done cp PIKACHU jr nz, .curMonNotStarterPikachu - callab IsThisPartymonStarterPikachu + callfar IsThisPartymonStarterPikachu jr nc, .curMonNotStarterPikachu ld a, [wWhichPokemon] ld hl, wPartyMon1Status @@ -358,7 +358,7 @@ INCLUDE "data/pikachu_emotions.asm" PikachuWalksToNurseJoy: ld a, $40 - ld [h_0xFFFC], a + ldh [hFFFC], a call LoadPikachuSpriteIntoVRAM call .GetMovementData and a @@ -366,7 +366,7 @@ PikachuWalksToNurseJoy: call ApplyPikachuMovementData .skip xor a - ld [h_0xFFFC], a + ldh [hFFFC], a ret .GetMovementData: diff --git a/engine/pikachu_follow.asm b/engine/pikachu_follow.asm index d9dc91df..fd2fbc47 100755 --- a/engine/pikachu_follow.asm +++ b/engine/pikachu_follow.asm @@ -457,7 +457,7 @@ Func_fc76a: call Func_fc82e jr c, .skip push bc - callab InitializeSpriteScreenPosition + callfar InitializeSpriteScreenPosition pop bc .skip ld hl, wSpritePikachuStateData1MovementStatus - wSpritePikachuStateData1 @@ -472,7 +472,7 @@ Func_fc76a: Func_fc793: call RefreshPikachuFollow push bc - callab InitializeSpriteScreenPosition + callfar InitializeSpriteScreenPosition pop bc ld hl, wSpritePikachuStateData1ImageIndex - wSpritePikachuStateData1 add hl, bc @@ -583,7 +583,7 @@ Func_fc842: ld hl, $0 push af call Random - ld a, [hRandomAdd] + ldh a, [hRandomAdd] and %11 ld e, a ld d, $0 @@ -1107,7 +1107,7 @@ IsPikachuRightNextToPlayer: xor a ret -GetPikachuFacingDirectionAndReturnToE: +GetPikachuFacingDirectionAndReturnToE:: call GetPikachuFacingDirection ld e, a ret @@ -1475,7 +1475,7 @@ AreThereAtLeastTwoStepsInPikachuFollowCommandBuffer: WillPikachuSpawnOnTheScreen: ld h, wSpriteStateData2 / $100 - ld a, [H_CURRENTSPRITEOFFSET] ; If we're here, this can only be $f0 + ldh a, [hCurrentSpriteOffset] ; If we're here, this can only be $f0 add wSpritePikachuStateData2MapY - wSpritePikachuStateData2 ld l, a ld b, [hl] @@ -1516,7 +1516,7 @@ WillPikachuSpawnOnTheScreen: jr c, .on_screen .not_on_screen ld h, wSpriteStateData1 / $100 - ld a, [H_CURRENTSPRITEOFFSET] + ldh a, [hCurrentSpriteOffset] add wSpritePikachuStateData1ImageIndex - wSpritePikachuStateData1 ld l, a ld [hl], $ff @@ -1525,7 +1525,7 @@ WillPikachuSpawnOnTheScreen: .on_screen ld h, wSpriteStateData2 / $100 - ld a, [H_CURRENTSPRITEOFFSET] + ldh a, [hCurrentSpriteOffset] add wSpritePikachuStateData2GrassPriority - wSpritePikachuStateData2 ld l, a ld a, [wGrassTile] @@ -1541,7 +1541,7 @@ WillPikachuSpawnOnTheScreen: .GetNPCCurrentTile: ld h, wSpriteStateData1 / $100 - ld a, [H_CURRENTSPRITEOFFSET] + ldh a, [hCurrentSpriteOffset] add wSpritePikachuStateData1YPixels - wSpritePikachuStateData1 ld l, a ld a, [hli] diff --git a/engine/pikachu_movement.asm b/engine/pikachu_movement.asm index 938715a4..2d87e947 100755 --- a/engine/pikachu_movement.asm +++ b/engine/pikachu_movement.asm @@ -914,14 +914,14 @@ LoadPikachuShadowOAMData: jr nz, .loop ret -LoadPikachuShadowIntoVRAM: +LoadPikachuShadowIntoVRAM:: ld hl, vNPCSprites2 + $7f * $10 ld de, LedgeHoppingShadowGFX_3F lb bc, BANK(LedgeHoppingShadowGFX_3F), (LedgeHoppingShadowGFX_3FEnd - LedgeHoppingShadowGFX_3F) / 8 jp CopyVideoDataDoubleAlternate LedgeHoppingShadowGFX_3F: -INCBIN "gfx/ledge_hopping_shadow.1bpp" +INCBIN "gfx/overworld/shadow.1bpp" LedgeHoppingShadowGFX_3FEnd: LoadPikachuBallIconIntoVRAM: @@ -958,7 +958,7 @@ LoadPikachuSpriteIntoVRAM: call CopyVideoDataAlternate ld de, PikachuSprite + $c * $10 ld hl, vNPCSprites2 + $c * $10 - ld a, [h_0xFFFC] + ldh a, [hFFFC] and a jr z, .load ld de, PikachuSprite + $c * $10 @@ -1006,7 +1006,7 @@ Cosine_e: ; cosine? Sine_e: ; sine? ld a, e -asm_fd908 +asm_fd908: and $3f cp $20 jr nc, .asm_fd913 diff --git a/engine/pikachu_pcm.asm b/engine/pikachu_pcm.asm index 1e6f8dc2..bf1aa57f 100755 --- a/engine/pikachu_pcm.asm +++ b/engine/pikachu_pcm.asm @@ -23,12 +23,12 @@ PlayPikachuSoundClip:: push bc push hl ld a, $80 - ld [rNR52], a + ldh [rNR52], a ld a, $77 - ld [rNR50], a + ldh [rNR50], a xor a - ld [rNR30], a - ld hl, $ff30 ; wave data + ldh [rNR30], a + ld hl, rWave_0 ; wave data ld de, wRedrawRowOrColumnSrcTiles .saveWaveDataLoop ld a, [hl] @@ -40,18 +40,18 @@ PlayPikachuSoundClip:: cp $40 ; end of wave data jr nz, .saveWaveDataLoop ld a, $80 - ld [rNR30], a - ld a, [rNR51] + ldh [rNR30], a + ldh a, [rNR51] or $44 - ld [rNR51], a + ldh [rNR51], a ld a, $ff - ld [rNR31], a + ldh [rNR31], a ld a, $20 - ld [rNR32], a + ldh [rNR32], a ld a, $ff - ld [rNR33], a + ldh [rNR33], a ld a, $87 - ld [rNR34], a + ldh [rNR34], a pop hl pop bc call PlayPikachuPCM @@ -59,10 +59,10 @@ PlayPikachuSoundClip:: ld [wc0f3], a ld [wc0f4], a ld a, $80 - ld [rNR52], a + ldh [rNR52], a xor a - ld [rNR30], a - ld hl, $ff30 + ldh [rNR30], a + ld hl, rWave_0 ld de, wRedrawRowOrColumnSrcTiles .reloadWaveDataLoop ld a, [de] @@ -72,20 +72,20 @@ PlayPikachuSoundClip:: cp $40 ; end of wave data jr nz, .reloadWaveDataLoop ld a, $80 - ld [rNR30], a - ld a, [rNR51] + ldh [rNR30], a + ldh a, [rNR51] and $bb - ld [rNR51], a + ldh [rNR51], a xor a ld [wChannelSoundIDs + Ch5], a ld [wChannelSoundIDs + Ch6], a ld [wChannelSoundIDs + Ch7], a ld [wChannelSoundIDs + Ch8], a - ld a, [H_LOADEDROMBANK] + ldh a, [hLoadedROMBank] ei ret -PikachuCriesPointerTable: +PikachuCriesPointerTable:: ; format: ; db bank ; dw pointer to cry diff --git a/engine/pikachu_pic_animation.asm b/engine/pikachu_pic_animation.asm index c79d9add..7829c048 100755 --- a/engine/pikachu_pic_animation.asm +++ b/engine/pikachu_pic_animation.asm @@ -88,10 +88,10 @@ PikaPicAnimationScriptPointerLookupTable: dpikapic PikaPicAnimScript20 StarterPikachuEmotionCommand_pikapic: - ld a, [H_AUTOBGTRANSFERENABLED] + ldh a, [hAutoBGTransferEnabled] push af xor a - ld [H_AUTOBGTRANSFERENABLED], a + ldh [hAutoBGTransferEnabled], a ld a, [de] ld [wPikaPicAnimNumber], a inc de @@ -99,12 +99,12 @@ StarterPikachuEmotionCommand_pikapic: call .RunPikapic pop de pop af - ld [H_AUTOBGTRANSFERENABLED], a + ldh [hAutoBGTransferEnabled], a ret .RunPikapic: call PlacePikapicTextBoxBorder - callab LoadOverworldPikachuFrontpicPalettes + callfar LoadOverworldPikachuFrontpicPalettes call ResetPikaPicAnimBuffer call LoadCurrentPikaPicAnimScriptPointer call ExecutePikaPicAnimScript @@ -135,14 +135,14 @@ ResetPikaPicAnimBuffer: PlacePikapicTextBoxBorder: xor a - ld [H_AUTOBGTRANSFERENABLED], a - coord hl, 6, 5 + ldh [hAutoBGTransferEnabled], a + hlcoord 6, 5 lb bc, 5, 5 call TextBoxBorder call Delay3 call UpdateSprites ld a, $1 - ld [H_AUTOBGTRANSFERENABLED], a + ldh [hAutoBGTransferEnabled], a call Delay3 ret @@ -202,13 +202,13 @@ endm ExecutePikaPicAnimScript: .loop xor a - ld [H_AUTOBGTRANSFERENABLED], a + ldh [hAutoBGTransferEnabled], a call RunPikaPicAnimSetupScript call DummyFunction_fdad5 call AnimateCurrentPikaPicAnimFrame call DummyFunction_fdad5 ld a, $1 - ld [H_AUTOBGTRANSFERENABLED], a + ldh [hAutoBGTransferEnabled], a call PikaPicAnimTimerAndJoypad and a jr z, .loop @@ -220,7 +220,7 @@ PikaPicAnimTimerAndJoypad: and a ret nz call JoypadLowSensitivity - ld a, [hJoyPressed] + ldh a, [hJoyPressed] and A_BUTTON | B_BUTTON ret @@ -460,7 +460,7 @@ LoadCurPikaPicObjectTilemap: ld b, a ld a, [wPikaPicPikaDrawStartY] add b - coord hl, 0, 0 + hlcoord 0, 0 ld bc, SCREEN_WIDTH call AddNTimes ld a, [wCurPikaPicAnimObjectXOffset] ; X offset @@ -611,14 +611,14 @@ PikaPicAnimCommand_loadgfx: push af ld a, $ff ld [wUpdateSpritesEnabled], a - ld a, [H_AUTOBGTRANSFERENABLED] + ldh a, [hAutoBGTransferEnabled] push af xor a - ld [H_AUTOBGTRANSFERENABLED], a - ld a, [hTilesetType] + ldh [hAutoBGTransferEnabled], a + ldh a, [hTilesetType] push af xor a - ld [hTilesetType], a + ldh [hTilesetType], a call GetPikaPicAnimByte ld [wPikaPicAnimCurGraphicID], a ld a, [wPikaPicAnimCurGraphicID] @@ -633,9 +633,9 @@ PikaPicAnimCommand_loadgfx: call DecompressRequestPikaPicAnimGFX .done pop af - ld [hTilesetType], a + ldh [hTilesetType], a pop af - ld [H_AUTOBGTRANSFERENABLED], a + ldh [hAutoBGTransferEnabled], a pop af ld [wUpdateSpritesEnabled], a ret @@ -783,7 +783,7 @@ PikaPicAnimCommand_cry: cp $ff ret z ld e, a - callab PlayPikachuSoundClip + callfar PlayPikachuSoundClip ret PikaPicAnimCommand_thunderbolt: @@ -843,7 +843,7 @@ PikaPicAnimCommand_thunderbolt: .UpdatePal: ld a, b - ld [rBGP], a + ldh [rBGP], a call UpdateGBCPal_BGP call DelayFrames ret diff --git a/engine/pokedex_rating.asm b/engine/pokedex_rating.asm deleted file mode 100755 index 4dfb6b39..00000000 --- a/engine/pokedex_rating.asm +++ /dev/null @@ -1,154 +0,0 @@ -DisplayDexRating: - ld hl, wPokedexSeen - ld b, wPokedexSeenEnd - wPokedexSeen - call CountSetBits - ld a, [wNumSetBits] - ld [hDexRatingNumMonsSeen], a - ld hl, wPokedexOwned - ld b, wPokedexOwnedEnd - wPokedexOwned - call CountSetBits - ld a, [wNumSetBits] - ld [hDexRatingNumMonsOwned], a - ld hl, DexRatingsTable -.findRating - ld a, [hli] - ld b, a - ld a, [hDexRatingNumMonsOwned] - cp b - jr c, .foundRating - inc hl - inc hl - jr .findRating -.foundRating - ld a, [hli] - ld h, [hl] - ld l, a ; load text pointer into hl - CheckAndResetEventA EVENT_HALL_OF_FAME_DEX_RATING - jr nz, .hallOfFame - push hl - ld hl, DexCompletionText - call PrintText - pop hl - call PrintText - callba PlayPokedexRatingSfx - jp WaitForTextScrollButtonPress -.hallOfFame - ld de, wDexRatingNumMonsSeen - ld a, [hDexRatingNumMonsSeen] - ld [de], a - inc de - ld a, [hDexRatingNumMonsOwned] - ld [de], a - inc de -.copyRatingTextLoop - ld a, [hli] - cp "@" - jr z, .doneCopying - ld [de], a - inc de - jr .copyRatingTextLoop -.doneCopying - ld [de], a - ret - -DexCompletionText: - TX_FAR _DexCompletionText - db "@" - -DexRatingsTable: - db 10 - dw DexRatingText_Own0To9 - db 20 - dw DexRatingText_Own10To19 - db 30 - dw DexRatingText_Own20To29 - db 40 - dw DexRatingText_Own30To39 - db 50 - dw DexRatingText_Own40To49 - db 60 - dw DexRatingText_Own50To59 - db 70 - dw DexRatingText_Own60To69 - db 80 - dw DexRatingText_Own70To79 - db 90 - dw DexRatingText_Own80To89 - db 100 - dw DexRatingText_Own90To99 - db 110 - dw DexRatingText_Own100To109 - db 120 - dw DexRatingText_Own110To119 - db 130 - dw DexRatingText_Own120To129 - db 140 - dw DexRatingText_Own130To139 - db 150 - dw DexRatingText_Own140To149 - db NUM_POKEMON + 1 - dw DexRatingText_Own150To151 - -DexRatingText_Own0To9: - TX_FAR _DexRatingText_Own0To9 - db "@" - -DexRatingText_Own10To19: - TX_FAR _DexRatingText_Own10To19 - db "@" - -DexRatingText_Own20To29: - TX_FAR _DexRatingText_Own20To29 - db "@" - -DexRatingText_Own30To39: - TX_FAR _DexRatingText_Own30To39 - db "@" - -DexRatingText_Own40To49: - TX_FAR _DexRatingText_Own40To49 - db "@" - -DexRatingText_Own50To59: - TX_FAR _DexRatingText_Own50To59 - db "@" - -DexRatingText_Own60To69: - TX_FAR _DexRatingText_Own60To69 - db "@" - -DexRatingText_Own70To79: - TX_FAR _DexRatingText_Own70To79 - db "@" - -DexRatingText_Own80To89: - TX_FAR _DexRatingText_Own80To89 - db "@" - -DexRatingText_Own90To99: - TX_FAR _DexRatingText_Own90To99 - db "@" - -DexRatingText_Own100To109: - TX_FAR _DexRatingText_Own100To109 - db "@" - -DexRatingText_Own110To119: - TX_FAR _DexRatingText_Own110To119 - db "@" - -DexRatingText_Own120To129: - TX_FAR _DexRatingText_Own120To129 - db "@" - -DexRatingText_Own130To139: - TX_FAR _DexRatingText_Own130To139 - db "@" - -DexRatingText_Own140To149: - TX_FAR _DexRatingText_Own140To149 - db "@" - -DexRatingText_Own150To151: - TX_FAR _DexRatingText_Own150To151 - db "@" diff --git a/engine/pokemon/add_mon.asm b/engine/pokemon/add_mon.asm new file mode 100644 index 00000000..d3d08e99 --- /dev/null +++ b/engine/pokemon/add_mon.asm @@ -0,0 +1,522 @@ +_AddPartyMon:: +; Adds a new mon to the player's or enemy's party. +; [wMonDataLocation] is used in an unusual way in this function. +; If the lower nybble is 0, the mon is added to the player's party, else the enemy's. +; If the entire value is 0, then the player is allowed to name the mon. + ld de, wPartyCount + ld a, [wMonDataLocation] + and $f + jr z, .next + ld de, wEnemyPartyCount +.next + ld a, [de] + inc a + cp PARTY_LENGTH + 1 + ret nc ; return if the party is already full + ld [de], a + ld a, [de] + ldh [hNewPartyLength], a + add e + ld e, a + jr nc, .noCarry + inc d +.noCarry + ld a, [wcf91] + ld [de], a ; write species of new mon in party list + inc de + ld a, $ff ; terminator + ld [de], a + ld hl, wPartyMonOT + ld a, [wMonDataLocation] + and $f + jr z, .next2 + ld hl, wEnemyMonOT +.next2 + ldh a, [hNewPartyLength] + dec a + call SkipFixedLengthTextEntries + ld d, h + ld e, l + ld hl, wPlayerName + ld bc, NAME_LENGTH + call CopyData + ld a, [wMonDataLocation] + and a + jr nz, .skipNaming + ld hl, wPartyMonNicks + ldh a, [hNewPartyLength] + dec a + call SkipFixedLengthTextEntries + ld a, NAME_MON_SCREEN + ld [wNamingScreenType], a + predef AskName +.skipNaming + ld hl, wPartyMons + ld a, [wMonDataLocation] + and $f + jr z, .next3 + ld hl, wEnemyMons +.next3 + ldh a, [hNewPartyLength] + dec a + ld bc, wPartyMon2 - wPartyMon1 + call AddNTimes + ld e, l + ld d, h + push hl + ld a, [wcf91] + ld [wd0b5], a + call GetMonHeader + ld hl, wMonHeader + ld a, [hli] + ld [de], a ; species + inc de + pop hl + push hl + ld a, [wMonDataLocation] + and $f + ld a, ATKDEFDV_TRAINER ; set enemy trainer mon IVs to fixed average values + ld b, SPDSPCDV_TRAINER + jr nz, .next4 + +; If the mon is being added to the player's party, update the pokedex. + ld a, [wcf91] + ld [wd11e], a + push de + predef IndexToPokedex + pop de + ld a, [wd11e] + dec a + ld c, a + ld b, FLAG_TEST + ld hl, wPokedexOwned + call FlagAction + ld a, c ; whether the mon was already flagged as owned + ld [wUnusedD153], a ; not read + ld a, [wd11e] + dec a + ld c, a + ld b, FLAG_SET + push bc + call FlagAction + pop bc + ld hl, wPokedexSeen + call FlagAction + + pop hl + push hl + + ld a, [wIsInBattle] + and a ; is this a wild mon caught in battle? + jr nz, .copyEnemyMonData + +; Not wild. + call Random ; generate random IVs + ld b, a + call Random + +.next4 + push bc + ld bc, wPartyMon1DVs - wPartyMon1 + add hl, bc + pop bc + ld [hli], a + ld [hl], b ; write IVs + ld bc, (wPartyMon1HPExp - 1) - (wPartyMon1DVs + 1) + add hl, bc + ld a, 1 + ld c, a + xor a + ld b, a + call CalcStat ; calc HP stat (set cur Hp to max HP) + ldh a, [hMultiplicand+1] + ld [de], a + inc de + ldh a, [hMultiplicand+2] + ld [de], a + inc de + xor a + ld [de], a ; box level + inc de + ld [de], a ; status ailments + inc de + jr .copyMonTypesAndMoves +.copyEnemyMonData + ld bc, wEnemyMon1DVs - wEnemyMon1 + add hl, bc + ld a, [wEnemyMonDVs] ; copy IVs from cur enemy mon + ld [hli], a + ld a, [wEnemyMonDVs + 1] + ld [hl], a + ld a, [wEnemyMonHP] ; copy HP from cur enemy mon + ld [de], a + inc de + ld a, [wEnemyMonHP+1] + ld [de], a + inc de + xor a + ld [de], a ; box level + inc de + ld a, [wEnemyMonStatus] ; copy status ailments from cur enemy mon + ld [de], a + inc de +.copyMonTypesAndMoves + ld hl, wMonHTypes + ld a, [hli] ; type 1 + ld [de], a + inc de + ld a, [hli] ; type 2 + ld [de], a + inc de + ld a, [hli] ; catch rate (held item in gen 2) + ld [de], a + ld a, [wcf91] + cp KADABRA + jr nz, .skipGivingTwistedSpoon + ld a, $60 ; twistedspoon in gen 2 + ld [de], a +.skipGivingTwistedSpoon + ld hl, wMonHMoves + ld a, [hli] + inc de + push de + ld [de], a + ld a, [hli] + inc de + ld [de], a + ld a, [hli] + inc de + ld [de], a + ld a, [hli] + inc de + ld [de], a + push de + dec de + dec de + dec de + xor a + ld [wLearningMovesFromDayCare], a + predef WriteMonMoves + pop de + ld a, [wPlayerID] ; set trainer ID to player ID + inc de + ld [de], a + ld a, [wPlayerID + 1] + inc de + ld [de], a + push de + ld a, [wCurEnemyLVL] + ld d, a + callfar CalcExperience + pop de + inc de + ldh a, [hExperience] ; write experience + ld [de], a + inc de + ldh a, [hExperience + 1] + ld [de], a + inc de + ldh a, [hExperience + 2] + ld [de], a + xor a + ld b, NUM_STATS * 2 +.writeEVsLoop ; set all EVs to 0 + inc de + ld [de], a + dec b + jr nz, .writeEVsLoop + inc de + inc de + pop hl + call AddPartyMon_WriteMovePP + inc de + ld a, [wCurEnemyLVL] + ld [de], a + inc de + ld a, [wIsInBattle] + dec a + jr nz, .calcFreshStats + ld hl, wEnemyMonMaxHP + ld bc, $a + call CopyData ; copy stats of cur enemy mon + pop hl + jr .done +.calcFreshStats + pop hl + ld bc, wPartyMon1HPExp - 1 - wPartyMon1 + add hl, bc + ld b, $0 + call CalcStats ; calculate fresh set of stats +.done + scf + ret + +LoadMovePPs: + call GetPredefRegisters + ; fallthrough +AddPartyMon_WriteMovePP: + ld b, NUM_MOVES +.pploop + ld a, [hli] ; read move ID + and a + jr z, .empty + dec a + push hl + push de + push bc + ld hl, Moves + ld bc, MoveEnd - Moves + call AddNTimes + ld de, wcd6d + ld a, BANK(Moves) + call FarCopyData + pop bc + pop de + pop hl + ld a, [wcd6d + 5] ; PP is byte 5 of move data +.empty + inc de + ld [de], a + dec b + jr nz, .pploop ; there are still moves to read + ret + +; adds enemy mon [wcf91] (at position [wWhichPokemon] in enemy list) to own party +; used in the cable club trade center +_AddEnemyMonToPlayerParty:: + ld hl, wPartyCount + ld a, [hl] + cp PARTY_LENGTH + scf + ret z ; party full, return failure + inc a + ld [hl], a ; add 1 to party members + ld c, a + ld b, $0 + add hl, bc + ld a, [wcf91] + ld [hli], a ; add mon as last list entry + ld [hl], $ff ; write new sentinel + ld hl, wPartyMons + ld a, [wPartyCount] + dec a + ld bc, wPartyMon2 - wPartyMon1 + call AddNTimes + ld e, l + ld d, h + ld hl, wLoadedMon + call CopyData ; write new mon's data (from wLoadedMon) + ld hl, wPartyMonOT + ld a, [wPartyCount] + dec a + call SkipFixedLengthTextEntries + ld d, h + ld e, l + ld hl, wEnemyMonOT + ld a, [wWhichPokemon] + call SkipFixedLengthTextEntries + ld bc, NAME_LENGTH + call CopyData ; write new mon's OT name (from an enemy mon) + ld hl, wPartyMonNicks + ld a, [wPartyCount] + dec a + call SkipFixedLengthTextEntries + ld d, h + ld e, l + ld hl, wEnemyMonNicks + ld a, [wWhichPokemon] + call SkipFixedLengthTextEntries + ld bc, NAME_LENGTH + call CopyData ; write new mon's nickname (from an enemy mon) + ld a, [wcf91] + ld [wd11e], a + predef IndexToPokedex + ld a, [wd11e] + dec a + ld c, a + ld b, FLAG_SET + ld hl, wPokedexOwned + push bc + call FlagAction ; add to owned pokemon + pop bc + ld hl, wPokedexSeen + call FlagAction ; add to seen pokemon + and a + ret ; return success + +_MoveMon:: + ld a, [wMoveMonType] + and a ; BOX_TO_PARTY + jr z, .checkPartyMonSlots + cp DAYCARE_TO_PARTY + jr z, .checkPartyMonSlots + cp PARTY_TO_DAYCARE + ld hl, wDayCareMon + jr z, .findMonDataSrc + ; else it's PARTY_TO_BOX + ld hl, wNumInBox + ld a, [hl] + cp MONS_PER_BOX + jr nz, .partyOrBoxNotFull + jr .boxFull +.checkPartyMonSlots + ld hl, wPartyCount + ld a, [hl] + cp PARTY_LENGTH + jr nz, .partyOrBoxNotFull +.boxFull + scf + ret +.partyOrBoxNotFull + inc a + ld [hl], a ; increment number of mons in party/box + ld c, a + ld b, 0 + add hl, bc + ld a, [wMoveMonType] + cp DAYCARE_TO_PARTY + ld a, [wDayCareMon] + jr z, .copySpecies + ld a, [wcf91] +.copySpecies + ld [hli], a ; write new mon ID + ld [hl], $ff ; write new sentinel +.findMonDataDest + ld a, [wMoveMonType] + dec a + ld hl, wPartyMons + ld bc, wPartyMon2 - wPartyMon1 ; $2c + ld a, [wPartyCount] + jr nz, .addMonOffset + ; if it's PARTY_TO_BOX + ld hl, wBoxMons + ld bc, wBoxMon2 - wBoxMon1 ; $21 + ld a, [wNumInBox] +.addMonOffset + dec a + call AddNTimes +.findMonDataSrc + push hl + ld e, l + ld d, h + ld a, [wMoveMonType] + and a + ld hl, wBoxMons + ld bc, wBoxMon2 - wBoxMon1 ; $21 + jr z, .addMonOffset2 + cp DAYCARE_TO_PARTY + ld hl, wDayCareMon + jr z, .copyMonData + ld hl, wPartyMons + ld bc, wPartyMon2 - wPartyMon1 ; $2c +.addMonOffset2 + ld a, [wWhichPokemon] + call AddNTimes +.copyMonData + push hl + push de + ld bc, wBoxMon2 - wBoxMon1 + call CopyData + pop de + pop hl + ld a, [wMoveMonType] + and a ; BOX_TO_PARTY + jr z, .findOTdest + cp DAYCARE_TO_PARTY + jr z, .findOTdest + ld bc, wBoxMon2 - wBoxMon1 + add hl, bc + ld a, [hl] ; hl = Level + inc de + inc de + inc de + ld [de], a ; de = BoxLevel +.findOTdest + ld a, [wMoveMonType] + cp PARTY_TO_DAYCARE + ld de, wDayCareMonOT + jr z, .findOTsrc + dec a + ld hl, wPartyMonOT + ld a, [wPartyCount] + jr nz, .addOToffset + ld hl, wBoxMonOT + ld a, [wNumInBox] +.addOToffset + dec a + call SkipFixedLengthTextEntries + ld d, h + ld e, l +.findOTsrc + ld hl, wBoxMonOT + ld a, [wMoveMonType] + and a + jr z, .addOToffset2 + ld hl, wDayCareMonOT + cp DAYCARE_TO_PARTY + jr z, .copyOT + ld hl, wPartyMonOT +.addOToffset2 + ld a, [wWhichPokemon] + call SkipFixedLengthTextEntries +.copyOT + ld bc, NAME_LENGTH + call CopyData + ld a, [wMoveMonType] +.findNickDest + cp PARTY_TO_DAYCARE + ld de, wDayCareMonName + jr z, .findNickSrc + dec a + ld hl, wPartyMonNicks + ld a, [wPartyCount] + jr nz, .addNickOffset + ld hl, wBoxMonNicks + ld a, [wNumInBox] +.addNickOffset + dec a + call SkipFixedLengthTextEntries + ld d, h + ld e, l +.findNickSrc + ld hl, wBoxMonNicks + ld a, [wMoveMonType] + and a + jr z, .addNickOffset2 + ld hl, wDayCareMonName + cp DAYCARE_TO_PARTY + jr z, .copyNick + ld hl, wPartyMonNicks +.addNickOffset2 + ld a, [wWhichPokemon] + call SkipFixedLengthTextEntries +.copyNick + ld bc, NAME_LENGTH + call CopyData + pop hl + ld a, [wMoveMonType] + cp PARTY_TO_BOX + jr z, .done + cp PARTY_TO_DAYCARE + jr z, .done + push hl + srl a + add $2 + ld [wMonDataLocation], a + call LoadMonData + farcall CalcLevelFromExperience + ld a, d + ld [wCurEnemyLVL], a + pop hl + ld bc, wBoxMon2 - wBoxMon1 + add hl, bc + ld [hli], a + ld d, h + ld e, l + ld bc, -18 + add hl, bc + ld b, $1 + call CalcStats +.done + and a + ret diff --git a/engine/pokemon/bills_pc.asm b/engine/pokemon/bills_pc.asm new file mode 100644 index 00000000..cc7864f2 --- /dev/null +++ b/engine/pokemon/bills_pc.asm @@ -0,0 +1,593 @@ +DisplayPCMainMenu:: + xor a + ldh [hAutoBGTransferEnabled], a + call SaveScreenTilesToBuffer2 + ld a, [wNumHoFTeams] + and a + jr nz, .leaguePCAvailable + CheckEvent EVENT_GOT_POKEDEX + jr z, .noOaksPC + ld a, [wNumHoFTeams] + and a + jr nz, .leaguePCAvailable + hlcoord 0, 0 + lb bc, 8, 14 + jr .next +.noOaksPC + hlcoord 0, 0 + lb bc, 6, 14 + jr .next +.leaguePCAvailable + hlcoord 0, 0 + lb bc, 10, 14 +.next + call TextBoxBorder + call UpdateSprites + ld a, 3 + ld [wMaxMenuItem], a + CheckEvent EVENT_MET_BILL + jr nz, .metBill + hlcoord 2, 2 + ld de, SomeonesPCText + jr .next2 +.metBill + hlcoord 2, 2 + ld de, BillsPCText +.next2 + call PlaceString + hlcoord 2, 4 + ld de, wPlayerName + call PlaceString + ld l, c + ld h, b + ld de, PlayersPCText + call PlaceString + CheckEvent EVENT_GOT_POKEDEX + jr z, .noOaksPC2 + hlcoord 2, 6 + ld de, OaksPCText + call PlaceString + ld a, [wNumHoFTeams] + and a + jr z, .noLeaguePC + ld a, 4 + ld [wMaxMenuItem], a + hlcoord 2, 8 + ld de, PKMNLeaguePCText + call PlaceString + hlcoord 2, 10 + ld de, LogOffPCText + jr .next3 +.noLeaguePC + hlcoord 2, 8 + ld de, LogOffPCText + jr .next3 +.noOaksPC2 + ld a, $2 + ld [wMaxMenuItem], a + hlcoord 2, 6 + ld de, LogOffPCText +.next3 + call PlaceString + ld a, A_BUTTON | B_BUTTON + ld [wMenuWatchedKeys], a + ld a, 2 + ld [wTopMenuItemY], a + ld a, 1 + ld [wTopMenuItemX], a + xor a + ld [wCurrentMenuItem], a + ld [wLastMenuItem], a + ld a, 1 + ldh [hAutoBGTransferEnabled], a + ret + +SomeonesPCText: db "SOMEONE's PC@" +BillsPCText: db "BILL's PC@" +PlayersPCText: db "'s PC@" +OaksPCText: db "PROF.OAK's PC@" +PKMNLeaguePCText: db "LEAGUE@" +LogOffPCText: db "LOG OFF@" + +BillsPC_:: + ld hl, wd730 + set 6, [hl] + xor a + ld [wParentMenuItem], a + inc a ; MONSTER_NAME + ld [wNameListType], a + call LoadHpBarAndStatusTilePatterns + ld a, [wListScrollOffset] + push af + ld a, [wFlags_0xcd60] + bit 3, a ; accessing Bill's PC through another PC? + jr nz, BillsPCMenu +; accessing it directly + ld a, SFX_TURN_ON_PC + call PlaySound + ld hl, SwitchOnText + call PrintText + +BillsPCMenu: + ld a, [wParentMenuItem] + ld [wCurrentMenuItem], a + ld hl, vChars2 tile $78 + ld de, PokeballTileGraphics + lb bc, BANK(PokeballTileGraphics), 1 + call CopyVideoData + call LoadScreenTilesFromBuffer2DisableBGTransfer + hlcoord 0, 12 + lb bc, 4, 18 + call TextBoxBorder + hlcoord 0, 0 + lb bc, 12, 12 + call TextBoxBorder + call UpdateSprites + hlcoord 2, 2 + ld de, BillsPCMenuText + call PlaceString + ld hl, wTopMenuItemY + ld a, 2 + ld [hli], a ; wTopMenuItemY + dec a + ld [hli], a ; wTopMenuItemX + inc hl + inc hl + ld a, 5 + ld [hli], a ; wMaxMenuItem + ld a, A_BUTTON | B_BUTTON + ld [hli], a ; wMenuWatchedKeys + xor a + ld [hli], a ; wLastMenuItem + ld [hli], a ; wPartyAndBillsPCSavedMenuItem + ld hl, wListScrollOffset + ld [hli], a ; wListScrollOffset + ld [hl], a ; wMenuWatchMovingOutOfBounds + ld [wPlayerMonNumber], a + hlcoord 9, 14 + lb bc, 2, 9 + call TextBoxBorder + ld a, [wCurrentBoxNum] + and $7f + cp 9 + jr c, .singleDigitBoxNum +; two digit box num + sub 9 + hlcoord 17, 16 + ld [hl], "1" + add "0" + jr .next +.singleDigitBoxNum + add "1" +.next + ldcoord_a 18, 16 + hlcoord 10, 16 + ld de, BoxNoPCText + call PlaceString + ld a, 1 + ldh [hAutoBGTransferEnabled], a + call Delay3 + call HandleMenuInput + bit 1, a + jp nz, ExitBillsPC ; b button + call PlaceUnfilledArrowMenuCursor + ld a, [wCurrentMenuItem] + ld [wParentMenuItem], a + and a + jp z, BillsPCWithdraw ; withdraw + cp $1 + jp z, BillsPCDeposit ; deposit + cp $2 + jp z, BillsPCRelease ; release + cp $3 + jp z, BillsPCChangeBox ; change box + cp $4 + jp z, BillsPCPrintBox + +ExitBillsPC: + ld a, [wFlags_0xcd60] + bit 3, a ; accessing Bill's PC through another PC? + jr nz, .next +; accessing it directly + call LoadTextBoxTilePatterns + ld a, SFX_TURN_OFF_PC + call PlaySound + call WaitForSoundToFinish +.next + ld hl, wFlags_0xcd60 + res 5, [hl] + call LoadScreenTilesFromBuffer2 + pop af + ld [wListScrollOffset], a + ld hl, wd730 + res 6, [hl] + ret + +BillsPCPrintBox: + callfar PrintPCBox + jp BillsPCMenu + +BillsPCDeposit: + ld a, [wPartyCount] + dec a + jr nz, .partyLargeEnough + ld hl, CantDepositLastMonText + call PrintText + jp BillsPCMenu +.partyLargeEnough + ld a, [wNumInBox] + cp MONS_PER_BOX + jr nz, .boxNotFull + ld hl, BoxFullText + call PrintText + jp BillsPCMenu +.boxNotFull + ld hl, wPartyCount + call DisplayMonListMenu + jp c, BillsPCMenu + callfar IsThisPartymonStarterPikachu_Party + jr nc, .asm_215ad + call CheckPikachuFollowingPlayer + jr z, .asm_215ad + ld hl, SleepingPikachuText2 + call PrintText + jp BillsPCMenu +.asm_215ad + call DisplayDepositWithdrawMenu + jp nc, BillsPCMenu + callfar IsThisPartymonStarterPikachu_Party + jr nc, .asm_215c9 + ld e, $1b + callfar PlayPikachuSoundClip + jr .asm_215cf +.asm_215c9 + ld a, [wcf91] + call PlayCry +.asm_215cf + callabd_ModifyPikachuHappiness PIKAHAPPY_DEPOSITED + ld a, PARTY_TO_BOX + ld [wMoveMonType], a + call MoveMon + xor a + ld [wRemoveMonFromBox], a + call RemovePokemon + call WaitForSoundToFinish + ld hl, wBoxNumString + ld a, [wCurrentBoxNum] + and $7f + cp 9 + jr c, .singleDigitBoxNum + sub 9 + ld [hl], "1" + inc hl + add "0" + jr .next +.singleDigitBoxNum + add "1" +.next + ld [hli], a + ld [hl], "@" + ld hl, MonWasStoredText + call PrintText + jp BillsPCMenu + +SleepingPikachuText2: + text_far _SleepingPikachuText2 + text_end + +BillsPCWithdraw: + ld a, [wNumInBox] + and a + jr nz, .boxNotEmpty + ld hl, NoMonText + call PrintText + jp BillsPCMenu +.boxNotEmpty + ld a, [wPartyCount] + cp PARTY_LENGTH + jr nz, .partyNotFull + ld hl, CantTakeMonText + call PrintText + jp BillsPCMenu +.partyNotFull + ld hl, wNumInBox + call DisplayMonListMenu + jp c, BillsPCMenu + call DisplayDepositWithdrawMenu + jp nc, BillsPCMenu + ld a, [wWhichPokemon] + ld hl, wBoxMonNicks + call GetPartyMonName + callfar IsThisPartymonStarterPikachu_Box + jr nc, .asm_21660 + ld e, $22 + callfar PlayPikachuSoundClip + jr .asm_21666 +.asm_21660 + ld a, [wcf91] + call PlayCry +.asm_21666 + xor a ; BOX_TO_PARTY + ld [wMoveMonType], a + call MoveMon + ld a, 1 + ld [wRemoveMonFromBox], a + call RemovePokemon + call WaitForSoundToFinish + ld hl, MonIsTakenOutText + call PrintText + jp BillsPCMenu + +BillsPCRelease: + ld a, [wNumInBox] + and a + jr nz, .loop + ld hl, NoMonText + call PrintText + jp BillsPCMenu +.loop + ld hl, wNumInBox + call DisplayMonListMenu + jp c, BillsPCMenu + callfar IsThisPartymonStarterPikachu_Box + jr c, .asm_216cb + ld hl, OnceReleasedText + call PrintText + call YesNoChoice + ld a, [wCurrentMenuItem] + and a + jr nz, .loop + inc a + ld [wRemoveMonFromBox], a + call RemovePokemon + call WaitForSoundToFinish + ld a, [wcf91] + call PlayCry + ld hl, MonWasReleasedText + call PrintText + jp BillsPCMenu + +.asm_216cb + ld a, [wWhichPokemon] + ld hl, wBoxMonNicks + call GetPartyMonName + ld e, $27 + callfar PlayPikachuSoundClip + ld hl, PikachuUnhappyText + call PrintText + jp BillsPCMenu + +BillsPCChangeBox: + farcall ChangeBox + jp BillsPCMenu + +DisplayMonListMenu: + ld a, l + ld [wListPointer], a + ld a, h + ld [wListPointer + 1], a + xor a + ld [wPrintItemPrices], a + ld [wListMenuID], a + inc a ; MONSTER_NAME + ld [wNameListType], a + ld a, [wPartyAndBillsPCSavedMenuItem] + ld [wCurrentMenuItem], a + call DisplayListMenuID + ld a, [wCurrentMenuItem] + ld [wPartyAndBillsPCSavedMenuItem], a + ret + +BillsPCMenuText: + db "WITHDRAW " + next "DEPOSIT " + next "RELEASE " + next "CHANGE BOX" + next "PRINT BOX" + next "SEE YA!" + db "@" + +BoxNoPCText: + db "BOX No.@" + +KnowsHMMove:: +; returns whether mon with party index [wWhichPokemon] knows an HM move + ld hl, wPartyMon1Moves + ld bc, wPartyMon2 - wPartyMon1 + jr .next +; unreachable + ld hl, wBoxMon1Moves + ld bc, wBoxMon2 - wBoxMon1 +.next + ld a, [wWhichPokemon] + call AddNTimes + ld b, NUM_MOVES +.loop + ld a, [hli] + push hl + push bc + ld hl, HMMoveArray + ld de, 1 + call IsInArray + pop bc + pop hl + ret c + dec b + jr nz, .loop + and a + ret + +HMMoveArray: +INCLUDE "data/moves/hm_moves.asm" + +DisplayDepositWithdrawMenu: + hlcoord 9, 10 + lb bc, 6, 9 + call TextBoxBorder + ld a, [wParentMenuItem] + and a ; was the Deposit or Withdraw item selected in the parent menu? + ld de, DepositPCText + jr nz, .next + ld de, WithdrawPCText +.next + hlcoord 11, 12 + call PlaceString + hlcoord 11, 14 + ld de, StatsCancelPCText + call PlaceString + ld hl, wTopMenuItemY + ld a, 12 + ld [hli], a ; wTopMenuItemY + ld a, 10 + ld [hli], a ; wTopMenuItemX + xor a + ld [hli], a ; wCurrentMenuItem + inc hl + ld a, 2 + ld [hli], a ; wMaxMenuItem + ld a, A_BUTTON | B_BUTTON + ld [hli], a ; wMenuWatchedKeys + xor a + ld [hl], a ; wLastMenuItem + ld hl, wListScrollOffset + ld [hli], a ; wListScrollOffset + ld [hl], a ; wMenuWatchMovingOutOfBounds + ld [wPlayerMonNumber], a + ld [wPartyAndBillsPCSavedMenuItem], a +.loop + call HandleMenuInput + bit 1, a ; pressed B? + jr nz, .exit + ld a, [wCurrentMenuItem] + and a + jr z, .choseDepositWithdraw + dec a + jr z, .viewStats +.exit + and a + ret +.choseDepositWithdraw + scf + ret +.viewStats + call SaveScreenTilesToBuffer1 + ld a, [wParentMenuItem] + and a + ld a, PLAYER_PARTY_DATA + jr nz, .next2 + ld a, BOX_DATA +.next2 + ld [wMonDataLocation], a + predef StatusScreen + predef StatusScreen2 + call LoadScreenTilesFromBuffer1 + call ReloadTilesetTilePatterns + call RunDefaultPaletteCommand + call LoadGBPal + jr .loop + +DepositPCText: db "DEPOSIT@" +WithdrawPCText: db "WITHDRAW@" +StatsCancelPCText: + db "STATS" + next "CANCEL@" + +SwitchOnText: + text_far _SwitchOnText + text_end + +WhatText: + text_far _WhatText + text_end + +DepositWhichMonText: + text_far _DepositWhichMonText + text_end + +MonWasStoredText: + text_far _MonWasStoredText + text_end + +CantDepositLastMonText: + text_far _CantDepositLastMonText + text_end + +BoxFullText: + text_far _BoxFullText + text_end + +MonIsTakenOutText: + text_far _MonIsTakenOutText + text_end + +NoMonText: + text_far _NoMonText + text_end + +CantTakeMonText: + text_far _CantTakeMonText + text_end + +PikachuUnhappyText: + text_far _PikachuUnhappyText + text_end + +ReleaseWhichMonText: + text_far _ReleaseWhichMonText + text_end + +OnceReleasedText: + text_far _OnceReleasedText + text_end + +MonWasReleasedText: + text_far _MonWasReleasedText + text_end + +CableClubLeftGameboy:: + ldh a, [hSerialConnectionStatus] + cp USING_EXTERNAL_CLOCK + ret z + ld a, [wSpritePlayerStateData1FacingDirection] + cp SPRITE_FACING_RIGHT + ret nz + ld a, [wCurMap] + cp TRADE_CENTER + ld a, LINK_STATE_START_TRADE + jr z, .next + inc a ; LINK_STATE_START_BATTLE +.next + ld [wLinkState], a + call EnableAutoTextBoxDrawing + tx_pre_jump JustAMomentText + +CableClubRightGameboy:: + ldh a, [hSerialConnectionStatus] + cp USING_INTERNAL_CLOCK + ret z + ld a, [wSpritePlayerStateData1FacingDirection] + cp SPRITE_FACING_LEFT + ret nz + ld a, [wCurMap] + cp TRADE_CENTER + ld a, LINK_STATE_START_TRADE + jr z, .next + inc a ; LINK_STATE_START_BATTLE +.next + ld [wLinkState], a + call EnableAutoTextBoxDrawing + tx_pre_jump JustAMomentText + +JustAMomentText:: + text_far _JustAMomentText + text_end + + ld a, [wSpritePlayerStateData1FacingDirection] + cp SPRITE_FACING_UP + ret nz + call EnableAutoTextBoxDrawing + tx_pre_jump OpenBillsPCText + +OpenBillsPCText:: + script_bills_pc + diff --git a/engine/pokemon/evos_moves.asm b/engine/pokemon/evos_moves.asm new file mode 100755 index 00000000..4e48fe30 --- /dev/null +++ b/engine/pokemon/evos_moves.asm @@ -0,0 +1,668 @@ +; try to evolve the mon in [wWhichPokemon] +TryEvolvingMon: +EvolveTradeMon: + ld hl, wCanEvolveFlags + xor a + ld [hl], a + ld a, [wWhichPokemon] + ld c, a + ld b, FLAG_SET + call Evolution_FlagAction + +; this is only called after battle +; it is supposed to do level up evolutions, though there is a bug that allows item evolutions to occur +EvolutionAfterBattle: + ldh a, [hTilesetType] + push af + xor a + ld [wEvolutionOccurred], a + dec a + ld [wWhichPokemon], a + push hl + push bc + push de + ld hl, wPartyCount + push hl + +Evolution_PartyMonLoop: ; loop over party mons + ld hl, wWhichPokemon + inc [hl] + pop hl + inc hl + ld a, [hl] + cp $ff ; have we reached the end of the party? + jp z, .done + ld [wEvoOldSpecies], a + push hl + ld a, [wWhichPokemon] + ld c, a + ld hl, wCanEvolveFlags + ld b, FLAG_TEST + call Evolution_FlagAction + ld a, c + and a ; is the mon's bit set? + jp z, Evolution_PartyMonLoop ; if not, go to the next mon + ld a, [wEvoOldSpecies] + dec a + ld b, 0 + ld hl, EvosMovesPointerTable + add a + rl b + ld c, a + add hl, bc + ld a, [hli] + ld h, [hl] + ld l, a + push hl + ld a, [wcf91] + push af + xor a ; PLAYER_PARTY_DATA + ld [wMonDataLocation], a + call LoadMonData + pop af + ld [wcf91], a + pop hl + +.evoEntryLoop ; loop over evolution entries + ld a, [hli] + and a ; have we reached the end of the evolution data? + jr z, Evolution_PartyMonLoop + ld b, a ; evolution type + cp EV_TRADE + jr z, .checkTradeEvo +; not trade evolution + ld a, [wLinkState] + cp LINK_STATE_TRADING + jr z, Evolution_PartyMonLoop ; if trading, go the next mon + ld a, b + cp EV_ITEM + jr z, .checkItemEvo + ld a, [wForceEvolution] + and a + jr nz, Evolution_PartyMonLoop + ld a, b + cp EV_LEVEL + jr z, .checkLevel +.checkTradeEvo + ld a, [wLinkState] + cp LINK_STATE_TRADING + jp nz, .nextEvoEntry1 ; if not trading, go to the next evolution entry + ld a, [hli] ; level requirement + ld b, a + ld a, [wLoadedMonLevel] + cp b ; is the mon's level greater than the evolution requirement? + jp c, Evolution_PartyMonLoop ; if so, go the next mon + jr .doEvolution +.checkItemEvo + ld a, [wIsInBattle] ; are we in battle? + and a + ld a, [hli] + jp nz, .nextEvoEntry1 ; don't evolve if we're in a battle as wcf91 could be holding the last mon sent out + + ld b, a ; evolution item + ld a, [wcf91] ; last item used + cp b ; was the evolution item in this entry used? + jp nz, .nextEvoEntry1 ; if not, go to the next evolution entry +.checkLevel + ld a, [hli] ; level requirement + ld b, a + ld a, [wLoadedMonLevel] + cp b ; is the mon's level greater than the evolution requirement? + jp c, .nextEvoEntry2 ; if so, go the next evolution entry +.doEvolution + ld [wCurEnemyLVL], a + ld a, 1 + ld [wEvolutionOccurred], a + push hl + ld a, [hl] + ld [wEvoNewSpecies], a + ld a, [wWhichPokemon] + ld hl, wPartyMonNicks + call GetPartyMonName + call CopyStringToCF4B + ld hl, IsEvolvingText + call PrintText + ld c, 50 + call DelayFrames + xor a + ldh [hAutoBGTransferEnabled], a + hlcoord 0, 0 + lb bc, 12, 20 + call ClearScreenArea + ld a, $1 + ldh [hAutoBGTransferEnabled], a + ld a, $ff + ld [wUpdateSpritesEnabled], a + call ClearSprites + callfar EvolveMon + jp c, CancelledEvolution + ld hl, EvolvedText + call PrintText + pop hl + ld a, [hl] + ld [wd0b5], a + ld [wLoadedMonSpecies], a + ld [wEvoNewSpecies], a + ld a, MONSTER_NAME + ld [wNameListType], a + ld a, BANK(MonsterNames) ; bank is not used for monster names + ld [wPredefBank], a + call GetName + push hl + ld hl, IntoText + call PrintText_NoCreatingTextBox + ld a, SFX_GET_ITEM_2 + call PlaySoundWaitForCurrent + call WaitForSoundToFinish + ld c, 40 + call DelayFrames + call ClearScreen + call RenameEvolvedMon + ld a, [wd11e] + push af + ld a, [wd0b5] + ld [wd11e], a + predef IndexToPokedex + ld a, [wd11e] + dec a + ld hl, BaseStats + ld bc, MonBaseStatsEnd - MonBaseStats + call AddNTimes + ld de, wMonHeader + call CopyData + ld a, [wd0b5] + ld [wMonHIndex], a + pop af + ld [wd11e], a + ld hl, wLoadedMonHPExp - 1 + ld de, wLoadedMonStats + ld b, $1 + call CalcStats + ld a, [wWhichPokemon] + ld hl, wPartyMon1 + ld bc, wPartyMon2 - wPartyMon1 + call AddNTimes + ld e, l + ld d, h + push hl + push bc + ld bc, wPartyMon1MaxHP - wPartyMon1 + add hl, bc + ld a, [hli] + ld b, a + ld c, [hl] + ld hl, wLoadedMonMaxHP + 1 + ld a, [hld] + sub c + ld c, a + ld a, [hl] + sbc b + ld b, a + ld hl, wLoadedMonHP + 1 + ld a, [hl] + add c + ld [hld], a + ld a, [hl] + adc b + ld [hl], a + dec hl + pop bc + call CopyData + ld a, [wd0b5] + ld [wd11e], a + xor a + ld [wMonDataLocation], a + call LearnMoveFromLevelUp + pop hl + predef SetPartyMonTypes + ld a, [wIsInBattle] + and a + call z, Evolution_ReloadTilesetTilePatterns + predef IndexToPokedex + ld a, [wd11e] + dec a + ld c, a + ld b, FLAG_SET + ld hl, wPokedexOwned + push bc + call Evolution_FlagAction + pop bc + ld hl, wPokedexSeen + call Evolution_FlagAction + pop de + pop hl + ld a, [wLoadedMonSpecies] + ld [hl], a + push hl + ld l, e + ld h, d + jr .nextEvoEntry2 + +.nextEvoEntry1 + inc hl + +.nextEvoEntry2 + inc hl + jp .evoEntryLoop + +.done + pop de + pop bc + pop hl + pop af + ldh [hTilesetType], a + ld a, [wLinkState] + cp LINK_STATE_TRADING + ret z + ld a, [wIsInBattle] + and a + ret nz + ld a, [wEvolutionOccurred] + and a + call nz, PlayDefaultMusic + ret + +RenameEvolvedMon: +; Renames the mon to its new, evolved form's standard name unless it had a +; nickname, in which case the nickname is kept. + ld a, [wd0b5] + push af + ld a, [wMonHIndex] + ld [wd0b5], a + call GetName + pop af + ld [wd0b5], a + ld hl, wcd6d + ld de, wcf4b +.compareNamesLoop + ld a, [de] + inc de + cp [hl] + inc hl + ret nz + cp "@" + jr nz, .compareNamesLoop + ld a, [wWhichPokemon] + ld bc, NAME_LENGTH + ld hl, wPartyMonNicks + call AddNTimes + push hl + call GetName + ld hl, wcd6d + pop de + jp CopyData + +CancelledEvolution: + ld hl, StoppedEvolvingText + call PrintText + call ClearScreen + pop hl + call Evolution_ReloadTilesetTilePatterns + jp Evolution_PartyMonLoop + +EvolvedText: + text_far _EvolvedText + text_end + +IntoText: + text_far _IntoText + text_end + +StoppedEvolvingText: + text_far _StoppedEvolvingText + text_end + +IsEvolvingText: + text_far _IsEvolvingText + text_end + +Evolution_ReloadTilesetTilePatterns: + ld a, [wLinkState] + cp LINK_STATE_TRADING + ret z + jp ReloadTilesetTilePatterns + +LearnMoveFromLevelUp: + ld a, [wd11e] ; species + ld [wcf91], a + call GetMonLearnset +.learnSetLoop ; loop over the learn set until we reach a move that is learnt at the current level or the end of the list + ld a, [hli] + and a ; have we reached the end of the learn set? + jr z, .done ; if we've reached the end of the learn set, jump + ld b, a ; level the move is learnt at + ld a, [wCurEnemyLVL] + cp b ; is the move learnt at the mon's current level? + ld a, [hli] ; move ID + jr nz, .learnSetLoop + ld d, a ; ID of move to learn + ld a, [wMonDataLocation] + and a + jr nz, .next +; If [wMonDataLocation] is 0 (PLAYER_PARTY_DATA), get the address of the mon's +; current moves in party data. Every call to this function sets +; [wMonDataLocation] to 0 because other data locations are not supported. +; If it is not 0, this function will not work properly. + ld hl, wPartyMon1Moves + ld a, [wWhichPokemon] + ld bc, wPartyMon2 - wPartyMon1 + call AddNTimes +.next + ld b, NUM_MOVES +.checkCurrentMovesLoop ; check if the move to learn is already known + ld a, [hli] + cp d + jr z, .done ; if already known, jump + dec b + jr nz, .checkCurrentMovesLoop + ld a, d + ld [wMoveNum], a + ld [wd11e], a + call GetMoveName + call CopyStringToCF4B + predef LearnMove + ld a, b + and a + jr z, .done + callfar IsThisPartymonStarterPikachu_Party + jr nc, .done + ld a, [wMoveNum] + cp THUNDERBOLT + jr z, .foundThunderOrThunderbolt + cp THUNDER + jr nz, .done +.foundThunderOrThunderbolt + ld a, $5 + ld [wd49c], a + ld a, $85 + ld [wPikachuMood], a +.done + ld a, [wcf91] + ld [wd11e], a + ret + +Func_3b079: + ld a, [wcf91] + push af + call Func_3b0a2 + jr c, .asm_3b09c + + call Func_3b10f + jr nc, .asm_3b096 + + call Func_3b0a2 + jr c, .asm_3b09c + + call Func_3b10f + jr nc, .asm_3b096 + + call Func_3b0a2 + jr c, .asm_3b09c +.asm_3b096 + pop af + ld [wcf91], a + and a + ret +.asm_3b09c + pop af + ld [wcf91], a + scf + ret + +Func_3b0a2: +; XXX what is wcf91 entering this function? + ld a, [wd11e] + ld [wMoveNum], a + predef CanLearnTM + ld a, c + and a + jr nz, .asm_3b0ec + ld hl, Pointer_3b0ee + ld a, [wcf91] + ld de, $1 + call IsInArray + jr c, .asm_3b0d2 + ld a, $ff + ld [wMonHGrowthRate], a + ld a, [wd11e] + ld hl, wMonHMoves + ld de, $1 + call IsInArray + jr c, .asm_3b0ec +.asm_3b0d2 + ld a, [wd11e] + ld d, a + call GetMonLearnset +.loop + ld a, [hli] + and a + jr z, .asm_3b0ea + ld b, a + ld a, [wCurEnemyLVL] + cp b + jr c, .asm_3b0ea + ld a, [hli] + cp d + jr z, .asm_3b0ec + jr .loop +.asm_3b0ea + and a + ret +.asm_3b0ec + scf + ret + +Pointer_3b0ee: + db NIDOKING + db IVYSAUR + db EXEGGUTOR + db GENGAR + db NIDOQUEEN + db ARCANINE + db GYARADOS + db BLASTOISE + db GOLEM + db DRAGONITE + db NINETALES + db DRAGONAIR + db KABUTOPS + db OMASTAR + db JIGGLYPUFF + db FLAREON + db JOLTEON + db VAPOREON + db BEEDRILL + db BUTTERFREE + db MACHAMP + db CLOYSTER + db CLEFABLE + db ALAKAZAM + db STARMIE + db VENUSAUR + db TENTACRUEL + db CHARMELEON + db WARTORTLE + db CHARIZARD + db VILEPLUME + db VICTREEBEL + db $ff + +Func_3b10f: + ld c, $0 +.asm_3b111 + ld hl, EvosMovesPointerTable + ld b, $0 + add hl, bc + add hl, bc + ld a, [hli] + ld h, [hl] + ld l, a +.asm_3b11b + ld a, [hli] + and a + jr z, .asm_3b130 + cp $2 + jr nz, .asm_3b124 + inc hl +.asm_3b124 + inc hl + ld a, [wcf91] + cp [hl] + jr z, .asm_3b138 + inc hl + ld a, [hl] + and a + jr nz, .asm_3b11b +.asm_3b130 + inc c + ld a, c + cp VICTREEBEL + jr c, .asm_3b111 + and a + ret +.asm_3b138 + inc c + ld a, c + ld [wcf91], a + scf + ret + +; writes the moves a mon has at level [wCurEnemyLVL] to [de] +; move slots are being filled up sequentially and shifted if all slots are full +WriteMonMoves: + call GetPredefRegisters + push hl + push de + push bc + call GetMonLearnset + jr .firstMove +.nextMove + pop de +.nextMove2 + inc hl +.firstMove + ld a, [hli] ; read level of next move in learnset + and a + jp z, .done ; end of list + ld b, a + ld a, [wCurEnemyLVL] + cp b + jp c, .done ; mon level < move level (assumption: learnset is sorted by level) + ld a, [wLearningMovesFromDayCare] + and a + jr z, .skipMinLevelCheck + ld a, [wDayCareStartLevel] + cp b + jr nc, .nextMove2 ; min level >= move level + +.skipMinLevelCheck + +; check if the move is already known + push de + ld c, NUM_MOVES +.alreadyKnowsCheckLoop + ld a, [de] + inc de + cp [hl] + jr z, .nextMove + dec c + jr nz, .alreadyKnowsCheckLoop + +; try to find an empty move slot + pop de + push de + ld c, NUM_MOVES +.findEmptySlotLoop + ld a, [de] + and a + jr z, .writeMoveToSlot2 + inc de + dec c + jr nz, .findEmptySlotLoop + +; no empty move slots found + pop de + push de + push hl + ld h, d + ld l, e + call WriteMonMoves_ShiftMoveData ; shift all moves one up (deleting move 1) + ld a, [wLearningMovesFromDayCare] + and a + jr z, .writeMoveToSlot + +; shift PP as well if learning moves from day care + push de + ld bc, wPartyMon1PP - (wPartyMon1Moves + 3) + add hl, bc + ld d, h + ld e, l + call WriteMonMoves_ShiftMoveData ; shift all move PP data one up + pop de + +.writeMoveToSlot + pop hl +.writeMoveToSlot2 + ld a, [hl] + ld [de], a + ld a, [wLearningMovesFromDayCare] + and a + jr z, .nextMove + +; write move PP value if learning moves from day care + push hl + ld a, [hl] + ld hl, wPartyMon1PP - wPartyMon1Moves + add hl, de + push hl + dec a + ld hl, Moves + ld bc, MoveEnd - Moves + call AddNTimes + ld de, wBuffer + ld a, BANK(Moves) + call FarCopyData + ld a, [wBuffer + 5] + pop hl + ld [hl], a + pop hl + jr .nextMove + +.done + pop bc + pop de + pop hl + ret + +; shifts all move data one up (freeing 4th move slot) +WriteMonMoves_ShiftMoveData: + ld c, NUM_MOVES - 1 +.loop + inc de + ld a, [de] + ld [hli], a + dec c + jr nz, .loop + ret + +Evolution_FlagAction: + predef_jump FlagActionPredef + +GetMonLearnset: + ld hl, EvosMovesPointerTable + ld b, 0 + ld a, [wcf91] + dec a + ld c, a + add hl, bc + add hl, bc + ld a, [hli] + ld h, [hl] + ld l, a +.skipEvolutionDataLoop ; loop to skip past the evolution data, which comes before the move data + ld a, [hli] + and a ; have we reached the end of the evolution data? + jr nz, .skipEvolutionDataLoop ; if not, jump back up + ret + +INCLUDE "data/pokemon/evos_moves.asm" diff --git a/engine/pokemon/experience.asm b/engine/pokemon/experience.asm new file mode 100755 index 00000000..427d2a7f --- /dev/null +++ b/engine/pokemon/experience.asm @@ -0,0 +1,149 @@ +; calculates the level a mon should be based on its current exp +CalcLevelFromExperience:: + ld a, [wLoadedMonSpecies] + ld [wd0b5], a + call GetMonHeader + ld d, $1 ; init level to 1 +.loop + inc d ; increment level + call CalcExperience + push hl + ld hl, wLoadedMonExp + 2 ; current exp +; compare exp needed for level d with current exp + ldh a, [hExperience + 2] + ld c, a + ld a, [hld] + sub c + ldh a, [hExperience + 1] + ld c, a + ld a, [hld] + sbc c + ldh a, [hExperience] + ld c, a + ld a, [hl] + sbc c + pop hl + jr nc, .loop ; if exp needed for level d is not greater than exp, try the next level + dec d ; since the exp was too high on the last loop iteration, go back to the previous value and return + ret + +; calculates the amount of experience needed for level d +CalcExperience:: + ld a, [wMonHGrowthRate] + add a + add a + ld c, a + ld b, 0 + ld hl, GrowthRateTable + add hl, bc + call CalcDSquared + ld a, d + ldh [hMultiplier], a + call Multiply + ld a, [hl] + and $f0 + swap a + ldh [hMultiplier], a + call Multiply + ld a, [hli] + and $f + ldh [hDivisor], a + ld b, $4 + call Divide + ldh a, [hQuotient + 1] + push af + ldh a, [hQuotient + 2] + push af + ldh a, [hQuotient + 3] + push af + call CalcDSquared + ld a, [hl] + and $7f + ldh [hMultiplier], a + call Multiply + ldh a, [hProduct + 1] + push af + ldh a, [hProduct + 2] + push af + ldh a, [hProduct + 3] + push af + ld a, [hli] + push af + xor a + ldh [hMultiplicand], a + ldh [hMultiplicand + 1], a + ld a, d + ldh [hMultiplicand + 2], a + ld a, [hli] + ldh [hMultiplier], a + call Multiply + ld b, [hl] + ldh a, [hProduct + 3] + sub b + ldh [hProduct + 3], a + ld b, $0 + ldh a, [hProduct + 2] + sbc b + ldh [hProduct + 2], a + ldh a, [hProduct + 1] + sbc b + ldh [hProduct + 1], a +; The difference of the linear term and the constant term consists of 3 bytes +; starting at hProduct + 1. Below, hExperience (an alias of that address) will +; be used instead for the further work of adding or subtracting the squared +; term and adding the cubed term. + pop af + and $80 + jr nz, .subtractSquaredTerm ; check sign + pop bc + ldh a, [hExperience + 2] + add b + ldh [hExperience + 2], a + pop bc + ldh a, [hExperience + 1] + adc b + ldh [hExperience + 1], a + pop bc + ldh a, [hExperience] + adc b + ldh [hExperience], a + jr .addCubedTerm +.subtractSquaredTerm + pop bc + ldh a, [hExperience + 2] + sub b + ldh [hExperience + 2], a + pop bc + ldh a, [hExperience + 1] + sbc b + ldh [hExperience + 1], a + pop bc + ldh a, [hExperience] + sbc b + ldh [hExperience], a +.addCubedTerm + pop bc + ldh a, [hExperience + 2] + add b + ldh [hExperience + 2], a + pop bc + ldh a, [hExperience + 1] + adc b + ldh [hExperience + 1], a + pop bc + ldh a, [hExperience] + adc b + ldh [hExperience], a + ret + +; calculates d*d +CalcDSquared: + xor a + ldh [hMultiplicand], a + ldh [hMultiplicand + 1], a + ld a, d + ldh [hMultiplicand + 2], a + ldh [hMultiplier], a + jp Multiply + +INCLUDE "data/growth_rates.asm" diff --git a/engine/pokemon/learn_move.asm b/engine/pokemon/learn_move.asm new file mode 100755 index 00000000..d365acd4 --- /dev/null +++ b/engine/pokemon/learn_move.asm @@ -0,0 +1,250 @@ +LearnMove: + call SaveScreenTilesToBuffer1 + ld a, [wWhichPokemon] + ld hl, wPartyMonNicks + call GetPartyMonName + ld hl, wcd6d + ld de, wLearnMoveMonName + ld bc, NAME_LENGTH + call CopyData + +DontAbandonLearning: + ld hl, wPartyMon1Moves + ld bc, wPartyMon2Moves - wPartyMon1Moves + ld a, [wWhichPokemon] + call AddNTimes + ld d, h + ld e, l + ld b, NUM_MOVES +.findEmptyMoveSlotLoop + ld a, [hl] + and a + jr z, .next + inc hl + dec b + jr nz, .findEmptyMoveSlotLoop + push de + call TryingToLearn + pop de + jp c, AbandonLearning + push hl + push de + ld [wd11e], a + call GetMoveName + ld hl, OneTwoAndText + call PrintText + pop de + pop hl +.next + ld a, [wMoveNum] + ld [hl], a + ld bc, wPartyMon1PP - wPartyMon1Moves + add hl, bc + push hl + push de + dec a + ld hl, Moves + ld bc, MoveEnd - Moves + call AddNTimes + ld de, wBuffer + ld a, BANK(Moves) + call FarCopyData + ld a, [wBuffer + 5] ; a = move's max PP + pop de + pop hl + ld [hl], a + ld a, [wIsInBattle] + and a + jp z, PrintLearnedMove + ld a, [wWhichPokemon] + ld b, a + ld a, [wPlayerMonNumber] + cp b + jp nz, PrintLearnedMove + ld h, d + ld l, e + ld de, wBattleMonMoves + ld bc, NUM_MOVES + call CopyData + ld bc, wPartyMon1PP - wPartyMon1OTID + add hl, bc + ld de, wBattleMonPP + ld bc, NUM_MOVES + call CopyData + jp PrintLearnedMove + +AbandonLearning: + ld hl, AbandonLearningText + call PrintText + hlcoord 14, 7 + lb bc, 8, 15 + ld a, TWO_OPTION_MENU + ld [wTextBoxID], a + call DisplayTextBoxID ; yes/no menu + ld a, [wCurrentMenuItem] + and a + jp nz, DontAbandonLearning + ld hl, DidNotLearnText + call PrintText + ld b, 0 + ret + +PrintLearnedMove: + ld hl, LearnedMove1Text + call PrintText + ld b, 1 + ret + +TryingToLearn: + push hl + ld hl, TryingToLearnText + call PrintText + hlcoord 14, 7 + lb bc, 8, 15 + ld a, TWO_OPTION_MENU + ld [wTextBoxID], a + call DisplayTextBoxID ; yes/no menu + pop hl + ld a, [wCurrentMenuItem] + rra + ret c + ld bc, -NUM_MOVES + add hl, bc + push hl + ld de, wMoves + ld bc, NUM_MOVES + call CopyData + callfar FormatMovesString + pop hl +.loop + push hl + ld hl, WhichMoveToForgetText + call PrintText + hlcoord 4, 7 + lb bc, 4, 14 + call TextBoxBorder + hlcoord 6, 8 + ld de, wMovesString + ldh a, [hFlagsFFFA] + set 2, a + ldh [hFlagsFFFA], a + call PlaceString + ldh a, [hFlagsFFFA] + res 2, a + ldh [hFlagsFFFA], a + ld hl, wTopMenuItemY + ld a, 8 + ld [hli], a ; wTopMenuItemY + ld a, 5 + ld [hli], a ; wTopMenuItemX + xor a + ld [hli], a ; wCurrentMenuItem + inc hl + ld a, [wNumMovesMinusOne] + ld [hli], a ; wMaxMenuItem + ld a, A_BUTTON | B_BUTTON + ld [hli], a ; wMenuWatchedKeys + ld [hl], 0 ; wLastMenuItem + ld hl, hFlagsFFFA + set 1, [hl] + call HandleMenuInput + ld hl, hFlagsFFFA + res 1, [hl] + push af + call LoadScreenTilesFromBuffer1 + pop af + pop hl + bit 1, a ; pressed b + jr nz, .cancel + push hl + ld a, [wCurrentMenuItem] + ld c, a + ld b, 0 + add hl, bc + ld a, [hl] + push af + push bc + call IsMoveHM + pop bc + pop de + ld a, d + jr c, .hm + pop hl + add hl, bc + and a + ret +.hm + ld hl, HMCantDeleteText + call PrintText + pop hl + jr .loop +.cancel + scf + ret + +LearnedMove1Text: + text_far _LearnedMove1Text + sound_get_item_1 ; plays SFX_GET_ITEM_1 in the party menu (rare candy) and plays SFX_LEVEL_UP in battle + text_promptbutton + text_end + +WhichMoveToForgetText: + text_far _WhichMoveToForgetText + text_end + +AbandonLearningText: + text_far _AbandonLearningText + text_end + +DidNotLearnText: + text_far _DidNotLearnText + text_end + +TryingToLearnText: + text_far _TryingToLearnText + text_end + +OneTwoAndText: +; bugfix: In Red/Blue, the SFX_SWAP sound was played in the wrong bank, which played an incorrect sound +; Yellow has fixed this by swapping to the correct bank + text_far _OneTwoAndText + text_pause + text_asm + push af + push bc + push de + push hl + ld a, $1 + ld [wMuteAudioAndPauseMusic], a + call DelayFrame + ld a, [wAudioROMBank] + push af + ld a, BANK(SFX_Swap_1) + ld [wAudioROMBank], a + ld [wAudioSavedROMBank], a + call WaitForSoundToFinish + ld a, SFX_SWAP + call PlaySound + call WaitForSoundToFinish + pop af + ld [wAudioROMBank], a + ld [wAudioSavedROMBank], a + xor a + ld [wMuteAudioAndPauseMusic], a + pop hl + pop de + pop bc + pop af + ld hl, PoofText + ret + +PoofText: + text_far _PoofText + text_pause +ForgotAndText: + text_far _ForgotAndText + text_end + +HMCantDeleteText: + text_far _HMCantDeleteText + text_end diff --git a/engine/pokemon/load_mon_data.asm b/engine/pokemon/load_mon_data.asm new file mode 100644 index 00000000..53840728 --- /dev/null +++ b/engine/pokemon/load_mon_data.asm @@ -0,0 +1,68 @@ +LoadMonData_:: +; Load monster [wWhichPokemon] from list [wMonDataLocation]: +; 0: partymon +; 1: enemymon +; 2: boxmon +; 3: daycaremon +; Return monster id at wcf91 and its data at wLoadedMon. +; Also load base stats at wMonHeader for convenience. + + ld a, [wDayCareMonSpecies] + ld [wcf91], a + ld a, [wMonDataLocation] + cp DAYCARE_DATA + jr z, .GetMonHeader + + ld a, [wWhichPokemon] + ld e, a + call GetMonSpecies + +.GetMonHeader + ld a, [wcf91] + ld [wd0b5], a ; input for GetMonHeader + call GetMonHeader + + ld hl, wPartyMons + ld bc, wPartyMon2 - wPartyMon1 + ld a, [wMonDataLocation] + cp ENEMY_PARTY_DATA + jr c, .getMonEntry + + ld hl, wEnemyMons + jr z, .getMonEntry + + cp 2 + ld hl, wBoxMons + ld bc, wBoxMon2 - wBoxMon1 + jr z, .getMonEntry + + ld hl, wDayCareMon + jr .copyMonData + +.getMonEntry + ld a, [wWhichPokemon] + call AddNTimes + +.copyMonData + ld de, wLoadedMon + ld bc, wPartyMon2 - wPartyMon1 + jp CopyData + +; get species of mon e in list [wMonDataLocation] for LoadMonData +GetMonSpecies: + ld hl, wPartySpecies + ld a, [wMonDataLocation] + and a + jr z, .getSpecies + dec a + jr z, .enemyParty + ld hl, wBoxSpecies + jr .getSpecies +.enemyParty + ld hl, wEnemyPartyMons +.getSpecies + ld d, 0 + add hl, de + ld a, [hl] + ld [wcf91], a + ret diff --git a/engine/pokemon/remove_mon.asm b/engine/pokemon/remove_mon.asm new file mode 100644 index 00000000..c85b96bf --- /dev/null +++ b/engine/pokemon/remove_mon.asm @@ -0,0 +1,95 @@ +_RemovePokemon:: + ld hl, wPartyCount + ld a, [wRemoveMonFromBox] + and a + jr z, .usePartyCount + ld hl, wNumInBox +.usePartyCount + ld a, [hl] + dec a + ld [hli], a + ld a, [wWhichPokemon] + ld c, a + ld b, $0 + add hl, bc + ld e, l + ld d, h + inc de +.shiftMonSpeciesLoop + ld a, [de] + inc de + ld [hli], a + inc a ; reached terminator? + jr nz, .shiftMonSpeciesLoop ; if not, continue shifting species + ld hl, wPartyMonOT + ld d, PARTY_LENGTH - 1 ; max number of pokemon to shift + ld a, [wRemoveMonFromBox] + and a + jr z, .usePartyMonOTs + ld hl, wBoxMonOT + ld d, MONS_PER_BOX - 1 +.usePartyMonOTs + ld a, [wWhichPokemon] + call SkipFixedLengthTextEntries + ld a, [wWhichPokemon] + cp d ; are we removing the last pokemon? + jr nz, .notRemovingLastMon ; if not, shift the pokemon below + ld [hl], $ff ; else, write the terminator and return + ret +.notRemovingLastMon + ld d, h + ld e, l + ld bc, NAME_LENGTH + add hl, bc + ld bc, wPartyMonNicks + ld a, [wRemoveMonFromBox] + and a + jr z, .usePartyMonNicks + ld bc, wBoxMonNicks +.usePartyMonNicks + call CopyDataUntil + ld hl, wPartyMons + ld bc, wPartyMon2 - wPartyMon1 + ld a, [wRemoveMonFromBox] + and a + jr z, .usePartyMonStructs + ld hl, wBoxMons + ld bc, wBoxMon2 - wBoxMon1 +.usePartyMonStructs + ld a, [wWhichPokemon] + call AddNTimes ; get address of the pokemon removed + ld d, h ; store in de for CopyDataUntil + ld e, l + ld a, [wRemoveMonFromBox] + and a + jr z, .copyUntilPartyMonOTs + ld bc, wBoxMon2 - wBoxMon1 + add hl, bc ; get address of pokemon after the pokemon removed + ld bc, wBoxMonOT ; address of when to stop copying + jr .continue +.copyUntilPartyMonOTs + ld bc, wPartyMon2 - wPartyMon1 + add hl, bc ; get address of pokemon after the pokemon removed + ld bc, wPartyMonOT ; address of when to stop copying +.continue + call CopyDataUntil ; shift all pokemon data after the removed mon to the removed mon's location + ld hl, wPartyMonNicks + ld a, [wRemoveMonFromBox] + and a + jr z, .usePartyMonNicks2 + ld hl, wBoxMonNicks +.usePartyMonNicks2 + ld bc, NAME_LENGTH + ld a, [wWhichPokemon] + call AddNTimes + ld d, h + ld e, l + ld bc, NAME_LENGTH + add hl, bc + ld bc, wPartyMonNicksEnd + ld a, [wRemoveMonFromBox] + and a + jr z, .copyUntilPartyMonNicksEnd + ld bc, wBoxMonNicksEnd +.copyUntilPartyMonNicksEnd + jp CopyDataUntil diff --git a/engine/pokemon/set_types.asm b/engine/pokemon/set_types.asm new file mode 100755 index 00000000..e9235f13 --- /dev/null +++ b/engine/pokemon/set_types.asm @@ -0,0 +1,15 @@ +; updates the types of a party mon (pointed to in hl) to the ones of the mon specified in wd11e +SetPartyMonTypes: + call GetPredefRegisters + ld bc, wPartyMon1Type - wPartyMon1 ; $5 + add hl, bc + ld a, [wd11e] + ld [wd0b5], a + push hl + call GetMonHeader + pop hl + ld a, [wMonHType1] + ld [hli], a + ld a, [wMonHType2] + ld [hl], a + ret diff --git a/engine/pokemon/status_ailments.asm b/engine/pokemon/status_ailments.asm new file mode 100755 index 00000000..3da1fc43 --- /dev/null +++ b/engine/pokemon/status_ailments.asm @@ -0,0 +1,46 @@ +PrintStatusAilment:: + ld a, [de] + bit PSN, a + jr nz, .psn + bit BRN, a + jr nz, .brn + bit FRZ, a + jr nz, .frz + bit PAR, a + jr nz, .par + and SLP + ret z + ld a, "S" + ld [hli], a + ld a, "L" + ld [hli], a + ld [hl], "P" + ret +.psn + ld a, "P" + ld [hli], a + ld a, "S" + ld [hli], a + ld [hl], "N" + ret +.brn + ld a, "B" + ld [hli], a + ld a, "R" + ld [hli], a + ld [hl], "N" + ret +.frz + ld a, "F" + ld [hli], a + ld a, "R" + ld [hli], a + ld [hl], "Z" + ret +.par + ld a, "P" + ld [hli], a + ld a, "A" + ld [hli], a + ld [hl], "R" + ret diff --git a/engine/pokemon/status_screen.asm b/engine/pokemon/status_screen.asm new file mode 100755 index 00000000..a2cfb595 --- /dev/null +++ b/engine/pokemon/status_screen.asm @@ -0,0 +1,496 @@ +DrawHP: +; Draws the HP bar in the stats screen + call GetPredefRegisters + ld a, $1 + jr DrawHP_ + +DrawHP2: +; Draws the HP bar in the party screen + call GetPredefRegisters + ld a, $2 + +DrawHP_: + ld [wHPBarType], a + push hl + ld a, [wLoadedMonHP] + ld b, a + ld a, [wLoadedMonHP + 1] + ld c, a + or b + jr nz, .nonzeroHP + xor a + ld c, a + ld e, a + ld a, $6 + ld d, a + jp .drawHPBarAndPrintFraction +.nonzeroHP + ld a, [wLoadedMonMaxHP] + ld d, a + ld a, [wLoadedMonMaxHP + 1] + ld e, a + predef HPBarLength + ld a, $6 + ld d, a + ld c, a +.drawHPBarAndPrintFraction + pop hl + push de + push hl + push hl + call DrawHPBar + pop hl + ldh a, [hFlagsFFFA] + bit 0, a + jr z, .printFractionBelowBar + ld bc, $9 ; right of bar + jr .printFraction +.printFractionBelowBar + ld bc, SCREEN_WIDTH + 1 ; below bar +.printFraction + add hl, bc + ld de, wLoadedMonHP + lb bc, 2, 3 + call PrintNumber + ld a, "/" + ld [hli], a + ld de, wLoadedMonMaxHP + lb bc, 2, 3 + call PrintNumber + pop hl + pop de + ret + + +; Predef 0x37 +StatusScreen: + call LoadMonData + ld a, [wMonDataLocation] + cp BOX_DATA + jr c, .DontRecalculate +; mon is in a box or daycare + ld a, [wLoadedMonBoxLevel] + ld [wLoadedMonLevel], a + ld [wCurEnemyLVL], a + ld hl, wLoadedMonHPExp - 1 + ld de, wLoadedMonStats + ld b, $1 + call CalcStats ; Recalculate stats +.DontRecalculate + ld hl, wd72c + set 1, [hl] + ld a, $33 + ldh [rNR50], a ; Reduce the volume + call GBPalWhiteOutWithDelay3 + call ClearScreen + call UpdateSprites + call LoadHpBarAndStatusTilePatterns + ld de, BattleHudTiles1 ; source + ld hl, vChars2 tile $6d ; dest + lb bc, BANK(BattleHudTiles1), 3 + call CopyVideoDataDouble ; ·│ :L and halfarrow line end + ld de, BattleHudTiles2 + ld hl, vChars2 tile $78 + lb bc, BANK(BattleHudTiles2), 1 + call CopyVideoDataDouble ; │ + ld de, BattleHudTiles3 + ld hl, vChars2 tile $76 + lb bc, BANK(BattleHudTiles3), 2 + call CopyVideoDataDouble ; ─ ┘ + ld de, PTile + ld hl, vChars2 tile $72 + lb bc, BANK(PTile), 1 + call CopyVideoDataDouble ; bold P (for PP) + ldh a, [hTilesetType] + push af + xor a + ldh [hTilesetType], a + hlcoord 19, 1 + lb bc, 6, 10 + call DrawLineBox ; Draws the box around name, HP and status + ld de, -6 + add hl, de + ld [hl], "" + dec hl + ld [hl], "№" + hlcoord 19, 9 + lb bc, 8, 6 + call DrawLineBox ; Draws the box around types, ID No. and OT + hlcoord 10, 9 + ld de, Type1Text + call PlaceString ; "TYPE1/" + hlcoord 11, 3 + predef DrawHP + ld hl, wStatusScreenHPBarColor + call GetHealthBarColor + ld b, SET_PAL_STATUS_SCREEN + call RunPaletteCommand + hlcoord 16, 6 + ld de, wLoadedMonStatus + call PrintStatusCondition + jr nz, .StatusWritten + hlcoord 16, 6 + ld de, OKText + call PlaceString ; "OK" +.StatusWritten + hlcoord 9, 6 + ld de, StatusText + call PlaceString ; "STATUS/" + hlcoord 14, 2 + call PrintLevel ; Pokémon level + ld a, [wMonHIndex] + ld [wd11e], a + ld [wd0b5], a + predef IndexToPokedex + hlcoord 3, 7 + ld de, wd11e + lb bc, LEADING_ZEROES | 1, 3 + call PrintNumber ; Pokémon no. + hlcoord 11, 10 + predef PrintMonType + ld hl, NamePointers2 + call .GetStringPointer + ld d, h + ld e, l + hlcoord 9, 1 + call PlaceString ; Pokémon name + ld hl, OTPointers + call .GetStringPointer + ld d, h + ld e, l + hlcoord 12, 16 + call PlaceString ; OT + hlcoord 12, 14 + ld de, wLoadedMonOTID + lb bc, LEADING_ZEROES | 2, 5 + call PrintNumber ; ID Number + ld d, $0 + call PrintStatsBox + call Delay3 + call GBPalNormal + hlcoord 1, 0 + call LoadFlippedFrontSpriteByMonIndex ; draw Pokémon picture + ld a, [wMonDataLocation] + cp ENEMY_PARTY_DATA + jr z, .playRegularCry + cp BOX_DATA + jr z, .checkBoxData + callfar IsThisPartymonStarterPikachu_Party + jr nc, .playRegularCry + jr .playPikachuSoundClip +.checkBoxData + callfar IsThisPartymonStarterPikachu_Box + jr nc, .playRegularCry +.playPikachuSoundClip + ld e, 16 + callfar PlayPikachuSoundClip + jr .continue +.playRegularCry + ld a, [wcf91] + call PlayCry ; play Pokémon cry +.continue + call WaitForTextScrollButtonPress ; wait for button + pop af + ldh [hTilesetType], a + ret + +.GetStringPointer + ld a, [wMonDataLocation] + add a + ld c, a + ld b, 0 + add hl, bc + ld a, [hli] + ld h, [hl] + ld l, a + ld a, [wMonDataLocation] + cp DAYCARE_DATA + ret z + ld a, [wWhichPokemon] + jp SkipFixedLengthTextEntries + +OTPointers: + dw wPartyMonOT + dw wEnemyMonOT + dw wBoxMonOT + dw wDayCareMonOT + +NamePointers2: + dw wPartyMonNicks + dw wEnemyMonNicks + dw wBoxMonNicks + dw wDayCareMonName + +Type1Text: + db "TYPE1/" + next "" + ; fallthrough +Type2Text: + db "TYPE2/" + next "" + ; fallthrough +IDNoText: + db "№/" + next "" + ; fallthrough +OTText: + db "OT/" + next "@" + +StatusText: + db "STATUS/@" + +OKText: + db "OK@" + +; Draws a line starting from hl high b and wide c +DrawLineBox: + ld de, SCREEN_WIDTH ; New line +.PrintVerticalLine + ld [hl], $78 ; │ + add hl, de + dec b + jr nz, .PrintVerticalLine + ld [hl], $77 ; ┘ + dec hl +.PrintHorizLine + ld [hl], $76 ; ─ + dec hl + dec c + jr nz, .PrintHorizLine + ld [hl], $6f ; ← (halfarrow ending) + ret + +PTile: INCBIN "gfx/font/P.1bpp" + +PrintStatsBox: + ld a, d + and a ; a is 0 from the status screen + jr nz, .DifferentBox + hlcoord 0, 8 + lb bc, 8, 8 + call TextBoxBorder ; Draws the box + hlcoord 1, 9 ; Start printing stats from here + ld bc, $19 ; Number offset + jr .PrintStats +.DifferentBox + hlcoord 9, 2 + lb bc, 8, 9 + call TextBoxBorder + hlcoord 11, 3 + ld bc, $18 +.PrintStats + push bc + push hl + ld de, StatsText + call PlaceString + pop hl + pop bc + add hl, bc + ld de, wLoadedMonAttack + lb bc, 2, 3 + call PrintStat + ld de, wLoadedMonDefense + call PrintStat + ld de, wLoadedMonSpeed + call PrintStat + ld de, wLoadedMonSpecial + jp PrintNumber +PrintStat: + push hl + call PrintNumber + pop hl + ld de, SCREEN_WIDTH * 2 + add hl, de + ret + +StatsText: + db "ATTACK" + next "DEFENSE" + next "SPEED" + next "SPECIAL@" + +StatusScreen2: + ldh a, [hTilesetType] + push af + xor a + ldh [hTilesetType], a + ldh [hAutoBGTransferEnabled], a + ld bc, NUM_MOVES + 1 + ld hl, wMoves + call FillMemory + ld hl, wLoadedMonMoves + ld de, wMoves + ld bc, NUM_MOVES + call CopyData + callfar FormatMovesString + hlcoord 9, 2 + lb bc, 5, 10 + call ClearScreenArea ; Clear under name + hlcoord 19, 3 + ld [hl], $78 + hlcoord 0, 8 + lb bc, 8, 18 + call TextBoxBorder ; Draw move container + hlcoord 2, 9 + ld de, wMovesString + call PlaceString ; Print moves + ld a, [wNumMovesMinusOne] + inc a + ld c, a + ld a, $4 + sub c + ld b, a ; Number of moves ? + hlcoord 11, 10 + ld de, SCREEN_WIDTH * 2 + ld a, "" + call StatusScreen_PrintPP ; Print "PP" + ld a, b + and a + jr z, .InitPP + ld c, a + ld a, "-" + call StatusScreen_PrintPP ; Fill the rest with -- +.InitPP + ld hl, wLoadedMonMoves + decoord 14, 10 + ld b, 0 +.PrintPP + ld a, [hli] + and a + jr z, .PPDone + push bc + push hl + push de + ld hl, wCurrentMenuItem + ld a, [hl] + push af + ld a, b + ld [hl], a + push hl + callfar GetMaxPP + pop hl + pop af + ld [hl], a + pop de + pop hl + push hl + ld bc, wPartyMon1PP - wPartyMon1Moves - 1 + add hl, bc + ld a, [hl] + and $3f + ld [wStatusScreenCurrentPP], a + ld h, d + ld l, e + push hl + ld de, wStatusScreenCurrentPP + lb bc, 1, 2 + call PrintNumber + ld a, "/" + ld [hli], a + ld de, wMaxPP + lb bc, 1, 2 + call PrintNumber + pop hl + ld de, SCREEN_WIDTH * 2 + add hl, de + ld d, h + ld e, l + pop hl + pop bc + inc b + ld a, b + cp $4 + jr nz, .PrintPP +.PPDone + hlcoord 9, 3 + ld de, StatusScreenExpText + call PlaceString + ld a, [wLoadedMonLevel] + push af + cp MAX_LEVEL + jr z, .Level100 + inc a + ld [wLoadedMonLevel], a ; Increase temporarily if not 100 +.Level100 + hlcoord 14, 6 + ld [hl], "" + inc hl + inc hl + call PrintLevel + pop af + ld [wLoadedMonLevel], a + ld de, wLoadedMonExp + hlcoord 12, 4 + lb bc, 3, 7 + call PrintNumber ; exp + call CalcExpToLevelUp + ld de, wLoadedMonExp + hlcoord 7, 6 + lb bc, 3, 7 + call PrintNumber ; exp needed to level up + hlcoord 9, 0 + call StatusScreen_ClearName + hlcoord 9, 1 + call StatusScreen_ClearName + ld a, [wMonHIndex] + ld [wd11e], a + call GetMonName + hlcoord 9, 1 + call PlaceString + ld a, $1 + ldh [hAutoBGTransferEnabled], a + call Delay3 + call WaitForTextScrollButtonPress ; wait for button + pop af + ldh [hTilesetType], a + ld hl, wd72c + res 1, [hl] + ld a, $77 + ldh [rNR50], a + call GBPalWhiteOut + jp ClearScreen + +CalcExpToLevelUp: + ld a, [wLoadedMonLevel] + cp MAX_LEVEL + jr z, .atMaxLevel + inc a + ld d, a + callfar CalcExperience + ld hl, wLoadedMonExp + 2 + ldh a, [hExperience + 2] + sub [hl] + ld [hld], a + ldh a, [hExperience + 1] + sbc [hl] + ld [hld], a + ldh a, [hExperience] + sbc [hl] + ld [hld], a + ret +.atMaxLevel + ld hl, wLoadedMonExp + xor a + ld [hli], a + ld [hli], a + ld [hl], a + ret + +StatusScreenExpText: + db "EXP POINTS" + next "LEVEL UP@" + +StatusScreen_ClearName: + ld bc, 10 + ld a, " " + jp FillMemory + +StatusScreen_PrintPP: +; print PP or -- c times, going down two rows each time + ld [hli], a + ld [hld], a + add hl, de + dec c + jr nz, StatusScreen_PrintPP + ret diff --git a/engine/predefs.asm b/engine/predefs.asm index cc6af5ac..73f69d03 100755 --- a/engine/predefs.asm +++ b/engine/predefs.asm @@ -1,4 +1,4 @@ -GetPredefPointer: +GetPredefPointer:: ; Store the contents of the register ; pairs (hl, de, bc) at wPredefRegisters. ; Then put the bank and address of predef @@ -49,113 +49,4 @@ GetPredefPointer: ret -PredefPointers:: - ; these are pointers to ASM routines. - ; they appear to be used in overworld map scripts. - const_def - add_predef DrawPlayerHUDAndHPBar - add_predef CopyUncompressedPicToTilemap - add_predef AnimateSendingOutMon - add_predef ScaleSpriteByTwo - add_predef LoadMonBackPic - add_predef CopyDownscaledMonTiles - add_predef Func_f0a7 - add_predef HealParty - add_predef MoveAnimation - add_predef DivideBCDPredef - add_predef DivideBCDPredef2 - add_predef AddBCDPredef - add_predef SubBCDPredef - add_predef DivideBCDPredef3 - add_predef DivideBCDPredef4 - add_predef InitPlayerData - add_predef FlagActionPredef - add_predef HideObject - add_predef IsObjectHidden - add_predef ApplyOutOfBattlePoisonDamage - add_predef AnyPartyAlive - add_predef ShowObject - add_predef ShowObject2 - add_predef ReplaceTileBlock - add_predef InitPlayerData2 - add_predef LoadTilesetHeader - add_predef LearnMoveFromLevelUp - add_predef LearnMove - add_predef GetQuantityOfItemInBag - - predef_const CheckForHiddenObjectOrBookshelfOrCardKeyDoor - predef_const GiveItem - dbw $03, CheckForHiddenObjectOrBookshelfOrCardKeyDoor ; home bank - dbw $03, GiveItem ; home bank - - add_predef ChangeBGPalColor0_4Frames - add_predef FindPathToPlayer - add_predef PredefShakeScreenVertically - add_predef CalcPositionOfPlayerRelativeToNPC - add_predef ConvertNPCMovementDirectionsToJoypadMasks - add_predef PredefShakeScreenHorizontally - add_predef UpdateHPBar - add_predef HPBarLength - add_predef Diploma_TextBoxBorder - add_predef DoubleOrHalveSelectedStats - add_predef ShowPokedexMenu - add_predef EvolutionAfterBattle - add_predef SaveSAVtoSRAM0 - add_predef InitOpponent - add_predef CableClub_Run - add_predef DrawBadges - add_predef ExternalClockTradeAnim - add_predef BattleTransition - add_predef CopyTileIDsFromList - add_predef PlayIntro - add_predef GetMoveSoundB - add_predef FlashScreen - add_predef GetTileAndCoordsInFrontOfPlayer - add_predef StatusScreen - add_predef StatusScreen2 - add_predef InternalClockTradeAnim - add_predef TrainerEngage - add_predef IndexToPokedex - add_predef DisplayPicCenteredOrUpperRight - add_predef UsedCut - add_predef ShowPokedexData - add_predef WriteMonMoves - add_predef SaveSAV - add_predef LoadSGB - add_predef MarkTownVisitedAndLoadMissableObjects - add_predef SetPartyMonTypes - add_predef CanLearnTM - add_predef TMToMove - add_predef _RunPaletteCommand - add_predef StarterDex - add_predef _AddPartyMon - add_predef UpdateHPBar2 - add_predef DrawEnemyHUDAndHPBar - add_predef LoadTownMap_Nest - add_predef PrintMonType - add_predef EmotionBubble - add_predef EmptyFunc3 ; return immediately - add_predef AskName - add_predef PewterGuys - add_predef SaveSAVtoSRAM2 - add_predef LoadSAV2 - add_predef LoadSAV - add_predef SaveSAVtoSRAM1 - add_predef DoInGameTradeDialogue - add_predef HallOfFamePC - add_predef DisplayDexRating - - predef_const _LeaveMapAnim - predef_const EnterMapAnim - dbw $1E, _LeaveMapAnim ; wrong bank - dbw $1E, EnterMapAnim ; wrong bank - add_predef GetTileTwoStepsInFrontOfPlayer - add_predef CheckForCollisionWhenPushingBoulder - add_predef PrintStrengthTxt - add_predef PickUpItem - add_predef PrintMoveType - add_predef LoadMovePPs - add_predef DrawHP - add_predef DrawHP2 - add_predef DisplayElevatorFloorMenu - add_predef OaksAideScript +INCLUDE "data/predef_pointers.asm" diff --git a/engine/predefs17.asm b/engine/predefs17.asm deleted file mode 100755 index 21289c6a..00000000 --- a/engine/predefs17.asm +++ /dev/null @@ -1,9 +0,0 @@ -; this function temporarily makes the starters (and Ivysaur) seen -; so that the full Pokedex information gets displayed in Oak's lab -StarterDex: - ld a, %01001011 ; set starter flags - ld [wPokedexOwned], a - predef ShowPokedexData - xor a ; unset starter flags - ld [wPokedexOwned], a - ret diff --git a/engine/predefs17_2.asm b/engine/predefs17_2.asm deleted file mode 100755 index e9235f13..00000000 --- a/engine/predefs17_2.asm +++ /dev/null @@ -1,15 +0,0 @@ -; updates the types of a party mon (pointed to in hl) to the ones of the mon specified in wd11e -SetPartyMonTypes: - call GetPredefRegisters - ld bc, wPartyMon1Type - wPartyMon1 ; $5 - add hl, bc - ld a, [wd11e] - ld [wd0b5], a - push hl - call GetMonHeader - pop hl - ld a, [wMonHType1] - ld [hli], a - ld a, [wMonHType2] - ld [hl], a - ret diff --git a/engine/predefs7.asm b/engine/predefs7.asm deleted file mode 100755 index bfa0ab57..00000000 --- a/engine/predefs7.asm +++ /dev/null @@ -1,54 +0,0 @@ -DisplayElevatorFloorMenu: - ld hl, wd730 - ld a, [hl] - push af - set 6, [hl] - ld hl, WhichFloorText - call PrintText - pop af - ld [wd730], a - ld hl, wItemList - ld a, l - ld [wListPointer], a - ld a, h - ld [wListPointer + 1], a - ld a, [wListScrollOffset] - push af - xor a - ld [wCurrentMenuItem], a - ld [wListScrollOffset], a - ld [wPrintItemPrices], a - ld a, SPECIALLISTMENU - ld [wListMenuID], a - call DisplayListMenuID - pop bc - ld a, b - ld [wListScrollOffset], a - ret c - ld hl, wCurrentMapScriptFlags - set 7, [hl] - ld hl, wElevatorWarpMaps - ld a, [wWhichPokemon] - add a - ld d, 0 - ld e, a - add hl, de - ld a, [hli] - ld b, a - ld a, [hl] - ld c, a - ld hl, wWarpEntries - call .UpdateWarp - -.UpdateWarp - inc hl - inc hl - ld a, b - ld [hli], a ; destination warp ID - ld a, c - ld [hli], a ; destination map ID - ret - -WhichFloorText: - TX_FAR _WhichFloorText - db "@" diff --git a/engine/predefsA.asm b/engine/predefsA.asm deleted file mode 100644 index e25735c5..00000000 --- a/engine/predefsA.asm +++ /dev/null @@ -1,73 +0,0 @@ -; inverts the BGP for 4 (6 on CGB due to lag) frames -ChangeBGPalColor0_4Frames: - call GetPredefRegisters ; leftover of red/blue, has no use here - ld a, [rBGP] - xor $ff - ld [rBGP], a - call UpdateGBCPal_BGP - ld c, 4 - call DelayFrames - ld a, [rBGP] - xor $ff - ld [rBGP], a - call UpdateGBCPal_BGP - ret - -PredefShakeScreenVertically: -; Moves the window down and then back in a sequence of progressively smaller -; numbers of pixels, starting at b. - call GetPredefRegisters - ld a, 1 - ld [wDisableVBlankWYUpdate], a - xor a -.loop - ld [$ff96], a - call .MutateWY - call .MutateWY - dec b - ld a, b - jr nz, .loop - xor a - ld [wDisableVBlankWYUpdate], a - ret - -.MutateWY - ld a, [$ff96] - xor b - ld [$ff96], a - ld [rWY], a - ld c, 3 - jp DelayFrames - -PredefShakeScreenHorizontally: -; Moves the window right and then back in a sequence of progressively smaller -; numbers of pixels, starting at b. - call GetPredefRegisters - xor a -.loop - ld [$ff97], a - call .MutateWX - ld c, 1 - call DelayFrames - call .MutateWX - dec b - ld a, b - jr nz, .loop - -; restore normal WX - ld a, 7 - ld [rWX], a - ret - -.MutateWX - ld a, [$ff97] - xor b - ld [$ff97], a - bit 7, a - jr z, .skipZeroing - xor a ; zero a if it's negative -.skipZeroing - add 7 - ld [rWX], a - ld c, 4 - jp DelayFrames diff --git a/engine/print_waiting_text.asm b/engine/print_waiting_text.asm deleted file mode 100644 index bd2180a1..00000000 --- a/engine/print_waiting_text.asm +++ /dev/null @@ -1,19 +0,0 @@ -PrintWaitingText: - coord hl, 3, 10 - lb bc, 1, 11 - ld a, [wIsInBattle] - and a - jr z, .asm_4b9a - call TextBoxBorder - jr .asm_4b9d -.asm_4b9a - call CableClub_TextBoxBorder -.asm_4b9d - coord hl, 4, 11 - ld de, WaitingText - call PlaceString - ld c, 50 - jp DelayFrames - -WaitingText: - db "Waiting...!@" diff --git a/engine/printer.asm b/engine/printer.asm index 5be5286c..f0b681af 100644 --- a/engine/printer.asm +++ b/engine/printer.asm @@ -16,16 +16,16 @@ PrintPokedexEntry: push af xor a ld [wUpdateSpritesEnabled], a - ld [hCanceledPrinting], a + ldh [hCanceledPrinting], a call Printer_PlayPrinterMusic - ld a, [rIE] + ldh a, [rIE] push af xor a - ld [rIF], a + ldh [rIF], a ld a, $9 - ld [rIE], a + ldh [rIE], a xor a - ld [H_AUTOBGTRANSFERENABLED], a + ldh [hAutoBGTransferEnabled], a call Printer_GetDexEntryRegisters call Printer_StartTransmission ld a, [wPrinterPokedexMonIsOwned] @@ -40,10 +40,10 @@ PrintPokedexEntry: ld [wcae2], a call Printer_CopyTileMapToPrinterTileBuffer call ClearScreen - callab Pokedex_DrawInterface - callab Pokedex_PlacePokemonList + callfar Pokedex_DrawInterface + callfar Pokedex_PlacePokemonList ld a, $1 - ld [H_AUTOBGTRANSFERENABLED], a + ldh [hAutoBGTransferEnabled], a call .TryPrintPage jr c, .finish_printing ld a, [wPrinterPokedexMonIsOwned] @@ -56,7 +56,7 @@ PrintPokedexEntry: call DelayFrames call SaveScreenTilesToBuffer1 xor a - ld [H_AUTOBGTRANSFERENABLED], a + ldh [hAutoBGTransferEnabled], a call Printer_PrepareDexEntryForPrinting ld a, $7 call Printer_StartTransmission @@ -65,16 +65,16 @@ PrintPokedexEntry: call Printer_CopyTileMapToPrinterTileBuffer call LoadScreenTilesFromBuffer1 ld a, $1 - ld [H_AUTOBGTRANSFERENABLED], a + ldh [hAutoBGTransferEnabled], a call .TryPrintPage .finish_printing xor a ld [wPrinterConnectionOpen], a ld [wPrinterOpcode], a xor a - ld [rIF], a + ldh [rIF], a pop af - ld [rIE], a + ldh [rIE], a call ReloadMapAfterPrinter call Printer_PlayMapMusic pop af @@ -105,7 +105,7 @@ PrintPokedexEntry: ret Printer_GetDexEntryRegisters: - callab DrawDexEntryOnScreen + callfar DrawDexEntryOnScreen ld a, l ld [wPrinterPokedexEntryTextPointer], a ld a, h @@ -125,20 +125,20 @@ Printer_GetDexEntryRegisters: Printer_PrepareDexEntryForPrinting: call ClearScreen - callab Pokedex_PrepareDexEntryForPrinting + callfar Pokedex_PrepareDexEntryForPrinting ret PrintSurfingMinigameHighScore: xor a - ld [hCanceledPrinting], a + ldh [hCanceledPrinting], a call Printer_PlayPrinterMusic call Printer_PrepareSurfingMinigameHighScoreTileMap - ld a, [rIE] + ldh a, [rIE] push af xor a - ld [rIF], a + ldh [rIF], a ld a, $9 - ld [rIE], a + ldh [rIE], a call StartTransmission_Send9Rows ld a, $13 ld [wcae2], a @@ -163,24 +163,24 @@ PrintSurfingMinigameHighScore: ld [wPrinterOpcode], a call Printer_CopyTileMapFromPrinterTileBuffer xor a - ld [rIF], a + ldh [rIF], a pop af - ld [rIE], a + ldh [rIE], a call ReloadMapAfterPrinter call Printer_PlayMapMusic ret -PrintDiploma: +PrintDiploma:: xor a - ld [hCanceledPrinting], a + ldh [hCanceledPrinting], a call Printer_PlayPrinterMusic call _DisplayDiploma - ld a, [rIE] + ldh a, [rIE] push af xor a - ld [rIF], a + ldh [rIF], a ld a, $9 - ld [rIE], a + ldh [rIE], a call StartTransmission_Send9Rows ld a, $10 ld [wcae2], a @@ -194,7 +194,7 @@ PrintDiploma: call DelayFrames call SaveScreenTilesToBuffer1 xor a - ld [H_AUTOBGTRANSFERENABLED], a + ldh [hAutoBGTransferEnabled], a call Func_e9ad3 call StartTransmission_Send9Rows ld a, $3 @@ -208,9 +208,9 @@ PrintDiploma: ld [wPrinterOpcode], a call Printer_CopyTileMapFromPrinterTileBuffer xor a - ld [rIF], a + ldh [rIF], a pop af - ld [rIE], a + ldh [rIE], a call ReloadMapAfterPrinter call Printer_PlayMapMusic ret @@ -246,17 +246,17 @@ PrintPCBox:: push af xor a ld [wUpdateSpritesEnabled], a - ld [hCanceledPrinting], a + ldh [hCanceledPrinting], a call Printer_PlayPrinterMusic - ld a, [rIE] + ldh a, [rIE] push af xor a - ld [rIF], a + ldh [rIF], a ld a, $9 - ld [rIE], a + ldh [rIE], a call SaveScreenTilesToBuffer1 xor a - ld [H_AUTOBGTRANSFERENABLED], a + ldh [hAutoBGTransferEnabled], a call PrintPCBox_DrawPage1 call StartTransmission_Send9Rows ld a, $10 @@ -271,7 +271,7 @@ PrintPCBox:: ld c, 12 call DelayFrames xor a - ld [H_AUTOBGTRANSFERENABLED], a + ldh [hAutoBGTransferEnabled], a call PrintPCBox_DrawPage2 call StartTransmission_Send9Rows ld a, $0 @@ -286,7 +286,7 @@ PrintPCBox:: ld c, 12 call DelayFrames xor a - ld [H_AUTOBGTRANSFERENABLED], a + ldh [hAutoBGTransferEnabled], a call PrintPCBox_DrawPage3 call StartTransmission_Send9Rows ld a, $0 @@ -301,7 +301,7 @@ PrintPCBox:: ld c, 12 call DelayFrames xor a - ld [H_AUTOBGTRANSFERENABLED], a + ldh [hAutoBGTransferEnabled], a call PrintPCBox_DrawPage4 call StartTransmission_Send9Rows ld a, $3 @@ -314,9 +314,9 @@ PrintPCBox:: ld [wPrinterConnectionOpen], a ld [wPrinterOpcode], a xor a - ld [rIF], a + ldh [rIF], a pop af - ld [rIE], a + ldh [rIE], a call ReloadMapAfterPrinter call Printer_PlayMapMusic pop af @@ -352,20 +352,20 @@ Func_e8dfb: ret String_e8e1f: - TX_FAR _NoPokemonText - db "@" + text_far _NoPokemonText + text_end -PrintFanClubPortrait: +PrintFanClubPortrait:: xor a - ld [hCanceledPrinting], a + ldh [hCanceledPrinting], a call Printer_PlayPrinterMusic call Printer_GetMonStats - ld a, [rIE] + ldh a, [rIE] push af xor a - ld [rIF], a + ldh [rIF], a ld a, $9 - ld [rIE], a + ldh [rIE], a call StartTransmission_Send9Rows ld a, $13 ld [wcae2], a @@ -390,9 +390,9 @@ PrintFanClubPortrait: ld [wPrinterOpcode], a call Printer_CopyTileMapFromPrinterTileBuffer xor a - ld [rIF], a + ldh [rIF], a pop af - ld [rIE], a + ldh [rIE], a call ReloadMapAfterPrinter call Printer_PlayMapMusic ret @@ -403,17 +403,17 @@ PrinterDebug: push de push hl call StopAllMusic - ld a, [rIE] + ldh a, [rIE] push af xor a - ld [rIF], a + ldh [rIF], a ld a, $9 - ld [rIE], a + ldh [rIE], a call StartTransmission_Send9Rows ld a, $13 ld [wcae2], a ld a, $1 - ld [H_AUTOBGTRANSFERENABLED], a + ldh [hAutoBGTransferEnabled], a call Printer_CopyTileMapToPrinterTileBuffer call PrinterDebug_LoadGFX .loop @@ -434,9 +434,9 @@ PrinterDebug: xor a call FillMemory xor a - ld [rIF], a + ldh [rIF], a pop af - ld [rIE], a + ldh [rIE], a pop hl pop de pop bc @@ -444,7 +444,7 @@ PrinterDebug: ret Printer_CheckPressingB: - ld a, [hJoyHeld] + ldh a, [hJoyHeld] and B_BUTTON jr nz, .quit and a @@ -461,43 +461,43 @@ Printer_CheckPressingB: ld a, $16 ld [wPrinterOpcode], a ld a, $88 - ld [rSB], a + ldh [rSB], a ld a, $1 - ld [rSC], a + ldh [rSC], a ld a, $81 - ld [rSC], a + ldh [rSC], a .wait_send_cancel ld a, [wPrinterOpcode] and a jr nz, .wait_send_cancel .already_done ld a, $1 - ld [hCanceledPrinting], a + ldh [hCanceledPrinting], a scf ret Printer_CopyTileMapToPrinterTileBuffer: - coord hl, 0, 0 - coord de, 0, 0, wPrinterTileBuffer + hlcoord 0, 0 + decoord 0, 0, wPrinterTileBuffer ld bc, SCREEN_HEIGHT * SCREEN_WIDTH call CopyData ret Printer_CopyTileMapFromPrinterTileBuffer: - coord hl, 0, 0, wPrinterTileBuffer - coord de, 0, 0 + hlcoord 0, 0, wPrinterTileBuffer + decoord 0, 0 ld bc, SCREEN_HEIGHT * SCREEN_WIDTH call CopyData ret Printer_ResetJoypadHRAM: xor a - ld [hJoyLast], a - ld [hJoyReleased], a - ld [hJoyPressed], a - ld [hJoyHeld], a - ld [hJoy5], a - ld [hJoy6], a + ldh [hJoyLast], a + ldh [hJoyReleased], a + ldh [hJoyPressed], a + ldh [hJoyHeld], a + ldh [hJoy5], a + ldh [hJoy6], a ret Printer_PlayPrinterMusic: @@ -568,8 +568,8 @@ GBPrinter_UpdateStatusMessage: ret z push af xor a - ld [H_AUTOBGTRANSFERENABLED], a - coord hl, 0, 5 + ldh [hAutoBGTransferEnabled], a + hlcoord 0, 5 lb bc, 10, 18 call TextBoxBorder pop af @@ -581,13 +581,13 @@ GBPrinter_UpdateStatusMessage: ld e, [hl] inc hl ld d, [hl] - coord hl, 1, 7 + hlcoord 1, 7 call PlaceString - coord hl, 2, 15 + hlcoord 2, 15 ld de, .PressBToCancel call PlaceString ld a, $1 - ld [H_AUTOBGTRANSFERENABLED], a + ldh [hAutoBGTransferEnabled], a xor a ld [wPrinterStatusIndicator], a ret @@ -648,39 +648,39 @@ Printer_PrepareSurfingMinigameHighScoreTileMap: ld hl, vChars2 lb bc, BANK(SurfingPikachu2Graphics), (SurfingPikachu2GraphicsEnd - SurfingPikachu2Graphics) / $10 call CopyVideoData - coord hl, 0, 0 + hlcoord 0, 0 call .PlaceRowAlternatingTiles - coord hl, 0, 17 + hlcoord 0, 17 call .PlaceRowAlternatingTiles - coord hl, 0, 0 + hlcoord 0, 0 call .PlaceColumnAlternatingTiles - coord hl, 19, 0 + hlcoord 19, 0 call .PlaceColumnAlternatingTiles ld a, $4 - coord hl, 0, 0 + hlcoord 0, 0 ld [hl], a - coord hl, 0, 17 + hlcoord 0, 17 ld [hl], a - coord hl, 19, 0 + hlcoord 19, 0 ld [hl], a - coord hl, 19, 17 + hlcoord 19, 17 ld [hl], a ld de, .Tilemap1 - coord hl, 10, 8 + hlcoord 10, 8 lb bc, 3, 8 call Diploma_Surfing_CopyBox ld de, .Tilemap2 - coord hl, 2, 11 + hlcoord 2, 11 lb bc, 6, 16 call Diploma_Surfing_CopyBox ld de, .PikachusBeachString - coord hl, 3, 2 + hlcoord 3, 2 call PlaceString ld de, .HiScoreString - coord hl, 9, 4 + hlcoord 9, 4 call PlaceString ld de, .PointsString - coord hl, 12, 6 + hlcoord 12, 6 call PlaceString ld de, wPlayerName ld hl, wPlayerName @@ -696,14 +696,14 @@ Printer_PrepareSurfingMinigameHighScoreTileMap: xor a .got_name_length ld c, a - coord hl, 2, 4 + hlcoord 2, 4 add hl, bc call PlaceString call CopySurfingMinigameScore ld b, 8 call RunPaletteCommand ld a, $1 - ld [H_AUTOBGTRANSFERENABLED], a + ldh [hAutoBGTransferEnabled], a call Delay3 call GBPalNormal ret @@ -771,7 +771,7 @@ Diploma_Surfing_CopyBox: CopySurfingMinigameScore: ld de, wSurfingMinigameHiScore + 1 - coord hl, 7, 6 + hlcoord 7, 6 ld a, [de] call .BCDConvertScore ld a, [de] @@ -796,19 +796,19 @@ PrintPCBox_DrawPage1: ld [wBoxNumString], a call ClearScreen call PrintPCBox_PlaceHorizontalLines - coord hl, 0, 0 + hlcoord 0, 0 ld bc, 11 * SCREEN_WIDTH ld a, " " call FillMemory call PrintPCBox_DrawLeftAndRightBorders call PrintPCBox_DrawTopBorder - coord hl, 4, 4 + hlcoord 4, 4 ld de, .PokemonListString call PlaceString - coord hl, 7, 6 + hlcoord 7, 6 ld de, .BoxString call PlaceString - coord hl, 11, 6 + hlcoord 11, 6 ld a, [wCurrentBoxNum] and $7f cp 9 @@ -823,7 +823,7 @@ PrintPCBox_DrawPage1: add "1" .placed_box_number ld [hl], a - coord hl, 4, 9 + hlcoord 4, 9 ld de, wBoxSpecies ld c, $3 call PrintPCBox_PlaceBoxMonInfo @@ -839,7 +839,7 @@ PrintPCBox_DrawPage2: ld a, [wBoxDataStart] cp 4 ret c - coord hl, 4, 0 + hlcoord 4, 0 ld de, wBoxSpecies + 3 ld c, 6 call PrintPCBox_PlaceBoxMonInfo @@ -852,7 +852,7 @@ PrintPCBox_DrawPage3: ld a, [wBoxDataStart] cp 10 ret c - coord hl, 4, 0 + hlcoord 4, 0 ld de, wBoxSpecies + 9 ld c, 6 call PrintPCBox_PlaceBoxMonInfo @@ -862,16 +862,16 @@ PrintPCBox_DrawPage4: call ClearScreen call PrintPCBox_PlaceHorizontalLines call PrintPCBox_DrawLeftAndRightBorders - coord hl, 0, 15 + hlcoord 0, 15 call PrintPCBox_DrawBottomBorderAtHL - coord hl, 0, 16 + hlcoord 0, 16 ld bc, 2 * SCREEN_WIDTH ld a, " " call FillMemory ld a, [wBoxDataStart] cp 16 ret c - coord hl, 4, 0 + hlcoord 4, 0 ld de, wBoxSpecies + 15 ld c, 5 call PrintPCBox_PlaceBoxMonInfo @@ -933,7 +933,7 @@ PrintPCBox_PlaceBoxMonInfo: ret PrintPCBox_DrawTopBorder: - coord hl, 0, 0 + hlcoord 0, 0 ld a, $79 ld [hli], a ld a, $7a @@ -947,7 +947,7 @@ PrintPCBox_DrawTopBorder: ret PrintPCBox_DrawLeftAndRightBorders: - coord hl, 0, 0 + hlcoord 0, 0 ld de, SCREEN_WIDTH - 1 ld c, SCREEN_HEIGHT .loop @@ -961,7 +961,7 @@ PrintPCBox_DrawLeftAndRightBorders: ret PrintPCBox_DrawBottomBorder: - coord hl, 0, 17 + hlcoord 0, 17 PrintPCBox_DrawBottomBorderAtHL: ld a, $7d ld [hli], a @@ -976,10 +976,10 @@ PrintPCBox_DrawBottomBorderAtHL: ret PrintPCBox_PlaceHorizontalLines: - coord hl, 4, 0 + hlcoord 4, 0 ld c, 6 call .PlaceHorizontalLine - coord hl, 6, 1 + hlcoord 6, 1 ld c, 6 .PlaceHorizontalLine: .loop diff --git a/engine/printer/serial.asm b/engine/printer/serial.asm index fa83eb9d..97f655bb 100755 --- a/engine/printer/serial.asm +++ b/engine/printer/serial.asm @@ -7,8 +7,8 @@ Printer_StartTransmission: xor a call Printer_FillMemory xor a - ld [rSB], a - ld [rSC], a + ldh [rSB], a + ldh [rSC], a ld [wPrinterOpcode], a ld hl, wPrinterConnectionOpen set 0, [hl] @@ -269,11 +269,11 @@ Printer_PrepareToSend: ld a, $1 ld [wPrinterOpcode], a ld a, $88 - ld [rSB], a + ldh [rSB], a ld a, $1 - ld [rSC], a + ldh [rSC], a ld a, $81 - ld [rSC], a + ldh [rSC], a ret CopyPrinterDataHeader: @@ -438,7 +438,7 @@ PrinterDataPacket6: ; unused db 15, 0, $00, 0 dw 15 -PrinterSerial_: +PrinterSerial_:: ld a, [wPrinterOpcode] ld e, a ld d, 0 @@ -573,7 +573,7 @@ PrinterSerial_: ret .Receive1: - ld a, [rSB] + ldh a, [rSB] ld [wPrinterHandshake], a ld a, $0 call .SendByte @@ -581,7 +581,7 @@ PrinterSerial_: ret .Receive2: - ld a, [rSB] + ldh a, [rSB] ld [wPrinterStatusFlags], a xor a ld [wPrinterOpcode], a @@ -606,15 +606,15 @@ PrinterSerial_: ret .SendByte: - ld [rSB], a + ldh [rSB], a ld a, $1 - ld [rSC], a + ldh [rSC], a ld a, $81 - ld [rSC], a + ldh [rSC], a ret .Receive2_: - ld a, [rSB] + ldh a, [rSB] ld [wPrinterStatusFlags], a xor a ld [wPrinterOpcode], a diff --git a/engine/random.asm b/engine/random.asm deleted file mode 100755 index 2fc83f6f..00000000 --- a/engine/random.asm +++ /dev/null @@ -1,13 +0,0 @@ -Random_:: -; Generate a random 16-bit value. - ld a, [rDIV] - ld b, a - ld a, [hRandomAdd] - adc b - ld [hRandomAdd], a - ld a, [rDIV] - ld b, a - ld a, [hRandomSub] - sbc b - ld [hRandomSub], a - ret diff --git a/engine/remove_pokemon.asm b/engine/remove_pokemon.asm deleted file mode 100644 index f29a428d..00000000 --- a/engine/remove_pokemon.asm +++ /dev/null @@ -1,95 +0,0 @@ -_RemovePokemon: - ld hl, wPartyCount - ld a, [wRemoveMonFromBox] - and a - jr z, .usePartyCount - ld hl, wNumInBox -.usePartyCount - ld a, [hl] - dec a - ld [hli], a - ld a, [wWhichPokemon] - ld c, a - ld b, $0 - add hl, bc - ld e, l - ld d, h - inc de -.shiftMonSpeciesLoop - ld a, [de] - inc de - ld [hli], a - inc a ; reached terminator? - jr nz, .shiftMonSpeciesLoop ; if not, continue shifting species - ld hl, wPartyMonOT - ld d, PARTY_LENGTH - 1 ; max number of pokemon to shift - ld a, [wRemoveMonFromBox] - and a - jr z, .usePartyMonOTs - ld hl, wBoxMonOT - ld d, MONS_PER_BOX - 1 -.usePartyMonOTs - ld a, [wWhichPokemon] - call SkipFixedLengthTextEntries - ld a, [wWhichPokemon] - cp d ; are we removing the last pokemon? - jr nz, .notRemovingLastMon ; if not, shift the pokemon below - ld [hl], $ff ; else, write the terminator and return - ret -.notRemovingLastMon - ld d, h - ld e, l - ld bc, NAME_LENGTH - add hl, bc - ld bc, wPartyMonNicks - ld a, [wRemoveMonFromBox] - and a - jr z, .usePartyMonNicks - ld bc, wBoxMonNicks -.usePartyMonNicks - call CopyDataUntil - ld hl, wPartyMons - ld bc, wPartyMon2 - wPartyMon1 - ld a, [wRemoveMonFromBox] - and a - jr z, .usePartyMonStructs - ld hl, wBoxMons - ld bc, wBoxMon2 - wBoxMon1 -.usePartyMonStructs - ld a, [wWhichPokemon] - call AddNTimes ; get address of the pokemon removed - ld d, h ; store in de for CopyDataUntil - ld e, l - ld a, [wRemoveMonFromBox] - and a - jr z, .copyUntilPartyMonOTs - ld bc, wBoxMon2 - wBoxMon1 - add hl, bc ; get address of pokemon after the pokemon removed - ld bc, wBoxMonOT ; address of when to stop copying - jr .continue -.copyUntilPartyMonOTs - ld bc, wPartyMon2 - wPartyMon1 - add hl, bc ; get address of pokemon after the pokemon removed - ld bc, wPartyMonOT ; address of when to stop copying -.continue - call CopyDataUntil ; shift all pokemon data after the removed mon to the removed mon's location - ld hl, wPartyMonNicks - ld a, [wRemoveMonFromBox] - and a - jr z, .usePartyMonNicks2 - ld hl, wBoxMonNicks -.usePartyMonNicks2 - ld bc, NAME_LENGTH - ld a, [wWhichPokemon] - call AddNTimes - ld d, h - ld e, l - ld bc, NAME_LENGTH - add hl, bc - ld bc, wPartyMonNicksEnd - ld a, [wRemoveMonFromBox] - and a - jr z, .copyUntilPartyMonNicksEnd - ld bc, wBoxMonNicksEnd -.copyUntilPartyMonNicksEnd - jp CopyDataUntil diff --git a/engine/save.asm b/engine/save.asm deleted file mode 100755 index 7f453bf0..00000000 --- a/engine/save.asm +++ /dev/null @@ -1,682 +0,0 @@ -LoadSAV: -;(if carry -> write -;"the file data is destroyed") - call ClearScreen - call LoadFontTilePatterns - call LoadTextBoxTilePatterns - call LoadSAV0 - jr c, .badsum - call LoadSAV1 - jr c, .badsum - call LoadSAV2 - jr c, .badsum - ld a, $2 ; good checksum - jr .goodsum -.badsum - ld hl, wd730 - push hl - set 6, [hl] - ld hl, FileDataDestroyedText - call PrintText - ld c, 100 - call DelayFrames - pop hl - res 6, [hl] - ld a, $1 ; bad checksum -.goodsum - ld [wSaveFileStatus], a - ret - -FileDataDestroyedText: - TX_FAR _FileDataDestroyedText - db "@" - -LoadSAV0: - call EnableSRAMAndLatchClockData - ld a, $1 - ld [MBC1SRamBank], a - ld hl, sPlayerName ; hero name located in SRAM - ld bc, sMainDataCheckSum - sPlayerName ; but here checks the full SAV - call SAVCheckSum - ld c, a - ld a, [sMainDataCheckSum] ; SAV's checksum - cp c - jp z, .checkSumsMatched - -; If the computed checksum didn't match the saved on, try again. - ld hl, sPlayerName - ld bc, sMainDataCheckSum - sPlayerName - call SAVCheckSum - ld c, a - ld a, [sMainDataCheckSum] ; SAV's checksum - cp c - jp nz, SAVBadCheckSum - -.checkSumsMatched - ld hl, sPlayerName - ld de, wPlayerName - ld bc, NAME_LENGTH - call CopyData - ld hl, sMainData - ld de, wMainDataStart - ld bc, wMainDataEnd - wMainDataStart - call CopyData - ld hl, wCurMapTileset - set 7, [hl] - ld hl, sSpriteData - ld de, wSpriteDataStart - ld bc, wSpriteDataEnd - wSpriteDataStart - call CopyData - ld a, [sTilesetType] - ld [hTilesetType], a - ld hl, sCurBoxData - ld de, wBoxDataStart - ld bc, wBoxDataEnd - wBoxDataStart - call CopyData - and a - jp SAVGoodChecksum - -LoadSAV1: - call EnableSRAMAndLatchClockData - ld a, $1 - ld [MBC1SRamBank], a - ld hl, sPlayerName ; hero name located in SRAM - ld bc, sMainDataCheckSum - sPlayerName ; but here checks the full SAV - call SAVCheckSum - ld c, a - ld a, [sMainDataCheckSum] ; SAV's checksum - cp c - jr nz, SAVBadCheckSum - ld hl, sCurBoxData - ld de, wBoxDataStart - ld bc, wBoxDataEnd - wBoxDataStart - call CopyData - and a - jp SAVGoodChecksum - -LoadSAV2: - call EnableSRAMAndLatchClockData - ld a, $1 - ld [MBC1SRamBank], a - ld hl, sPlayerName ; hero name located in SRAM - ld bc, sMainDataCheckSum - sPlayerName ; but here checks the full SAV - call SAVCheckSum - ld c, a - ld a, [sMainDataCheckSum] ; SAV's checksum - cp c - jp nz, SAVBadCheckSum - ld hl, sPartyData - ld de, wPartyDataStart - ld bc, wPartyDataEnd - wPartyDataStart - call CopyData - ld hl, sMainData - ld de, wPokedexOwned - ld bc, wPokedexSeenEnd - wPokedexOwned - call CopyData - and a - jp SAVGoodChecksum - -SAVBadCheckSum: - scf - -SAVGoodChecksum: - call DisableSRAMAndPrepareClockData - ret - -LoadSAVIgnoreBadCheckSum: -; unused function that loads save data and ignores bad checksums - call LoadSAV0 - call LoadSAV1 - jp LoadSAV2 - -SaveSAV: - callba PrintSaveScreenText - ld c, 10 - call DelayFrames - ld hl, WouldYouLikeToSaveText - call SaveSAVConfirm - and a ;|0 = Yes|1 = No| - ret nz - ld c, 10 - call DelayFrames - ld a, [wSaveFileStatus] - cp $1 - jr z, .save - call SAVCheckRandomID - jr z, .save - ld hl, OlderFileWillBeErasedText - call SaveSAVConfirm - and a - ret nz -.save - call SaveSAVtoSRAM - ld hl, SavingText - call PrintText - ld c, 128 - call DelayFrames - ld hl, GameSavedText - call PrintText - ld c,10 - call DelayFrames - ld a, SFX_SAVE - call PlaySoundWaitForCurrent - call WaitForSoundToFinish - ld c, 30 - call DelayFrames - ret - -SaveSAVConfirm: - call PrintText - coord hl, 0, 7 - lb bc, 8, 1 - ld a, TWO_OPTION_MENU - ld [wTextBoxID], a - call DisplayTextBoxID ; yes/no menu - ld a, [wCurrentMenuItem] - ret - -WouldYouLikeToSaveText: - TX_FAR _WouldYouLikeToSaveText - db "@" - -SavingText: - TX_FAR _SavingText - db "@" - -GameSavedText: - TX_FAR _GameSavedText - db "@" - -OlderFileWillBeErasedText: - TX_FAR _OlderFileWillBeErasedText - db "@" - -SaveSAVtoSRAM0: - call EnableSRAMAndLatchClockData - ld a, $1 - ld [MBC1SRamBank], a - ld hl, wPlayerName - ld de, sPlayerName - ld bc, NAME_LENGTH - call CopyData - ld hl, wMainDataStart - ld de, sMainData - ld bc, wMainDataEnd - wMainDataStart - call CopyData - ld hl, wSpriteDataStart - ld de, sSpriteData - ld bc, wSpriteDataEnd - wSpriteDataStart - call CopyData - ld hl, wBoxDataStart - ld de, sCurBoxData - ld bc, wBoxDataEnd - wBoxDataStart - call CopyData - ld a, [hTilesetType] - ld [sTilesetType], a - ld hl, sPlayerName - ld bc, sMainDataCheckSum - sPlayerName - call SAVCheckSum - ld [sMainDataCheckSum], a - call DisableSRAMAndPrepareClockData - ret - -SaveSAVtoSRAM1: -; stored pokémon - call EnableSRAMAndLatchClockData - ld a, $1 - ld [MBC1SRamBank], a - ld hl, wBoxDataStart - ld de, sCurBoxData - ld bc, wBoxDataEnd - wBoxDataStart - call CopyData - ld hl, sPlayerName - ld bc, sMainDataCheckSum - sPlayerName - call SAVCheckSum - ld [sMainDataCheckSum], a - call DisableSRAMAndPrepareClockData - ret - -SaveSAVtoSRAM2: - call EnableSRAMAndLatchClockData - ld a, $1 - ld [MBC1SRamBank], a - ld hl, wPartyDataStart - ld de, sPartyData - ld bc, wPartyDataEnd - wPartyDataStart - call CopyData - ld hl, wPokedexOwned ; pokédex only - ld de, sMainData - ld bc, wPokedexSeenEnd - wPokedexOwned - call CopyData - ld hl, wPikachuHappiness - ld de, sMainData + $179 - ld a, [hli] - ld [de], a - inc de - ld a, [hl] - ld [de], a - ld hl, sPlayerName - ld bc, sMainDataCheckSum - sPlayerName - call SAVCheckSum - ld [sMainDataCheckSum], a - call DisableSRAMAndPrepareClockData - ret - -SaveSAVtoSRAM: - ld a, $2 - ld [wSaveFileStatus], a - call SaveSAVtoSRAM0 - call SaveSAVtoSRAM1 - jp SaveSAVtoSRAM2 - -SAVCheckSum: -;Check Sum (result[1 byte] is complemented) - ld d, 0 -.loop - ld a, [hli] - add d - ld d, a - dec bc - ld a, b - or c - jr nz, .loop - ld a, d - cpl - ret - -CalcIndividualBoxCheckSums: - ld hl, sBox1 ; sBox7 - ld de, sBank2IndividualBoxChecksums ; sBank3IndividualBoxChecksums - ld b, NUM_BOXES / 2 -.loop - push bc - push de - ld bc, wBoxDataEnd - wBoxDataStart - call SAVCheckSum - pop de - ld [de], a - inc de - pop bc - dec b - jr nz, .loop - ret - -GetBoxSRAMLocation: -; in: a = box num -; out: b = box SRAM bank, hl = pointer to start of box - ld hl, BoxSRAMPointerTable - ld a, [wCurrentBoxNum] - and $7f - cp NUM_BOXES / 2 - ld b, 2 - jr c, .next - inc b - sub NUM_BOXES / 2 -.next - ld e, a - ld d, 0 - add hl, de - add hl, de - ld a, [hli] - ld h, [hl] - ld l, a - ret - -BoxSRAMPointerTable: - dw sBox1 ; sBox7 - dw sBox2 ; sBox8 - dw sBox3 ; sBox9 - dw sBox4 ; sBox10 - dw sBox5 ; sBox11 - dw sBox6 ; sBox12 - -ChangeBox:: - ld hl, WhenYouChangeBoxText - call PrintText - call YesNoChoice - ld a, [wCurrentMenuItem] - and a - ret nz ; return if No was chosen - ld hl, wCurrentBoxNum - bit 7, [hl] ; is it the first time player is changing the box? - call z, EmptyAllSRAMBoxes ; if so, empty all boxes in SRAM - call DisplayChangeBoxMenu - call UpdateSprites - ld hl, hFlags_0xFFFA - set 1, [hl] - call HandleMenuInput - ld hl, hFlags_0xFFFA - res 1, [hl] - bit 1, a ; pressed b - ret nz - ld a, $b6 - call PlaySoundWaitForCurrent - call WaitForSoundToFinish - call GetBoxSRAMLocation - ld e, l - ld d, h - ld hl, wBoxDataStart - call CopyBoxToOrFromSRAM ; copy old box from WRAM to SRAM - ld a, [wCurrentMenuItem] - set 7, a - ld [wCurrentBoxNum], a - call GetBoxSRAMLocation - ld de, wBoxDataStart - call CopyBoxToOrFromSRAM ; copy new box from SRAM to WRAM - ld hl, wMapTextPtr - ld de, wChangeBoxSavedMapTextPointer - ld a, [hli] - ld [de], a - inc de - ld a, [hl] - ld [de], a - call RestoreMapTextPointer - call SaveSAVtoSRAM - ld hl, wChangeBoxSavedMapTextPointer - call SetMapTextPointer - ret - -WhenYouChangeBoxText: - TX_FAR _WhenYouChangeBoxText - db "@" - -CopyBoxToOrFromSRAM: -; copy an entire box from hl to de with b as the SRAM bank - push hl - call EnableSRAMAndLatchClockData - ld a, b - ld [MBC1SRamBank], a - ld bc, wBoxDataEnd - wBoxDataStart - call CopyData - pop hl - -; mark the memory that the box was copied from as am empty box - xor a - ld [hli], a - dec a - ld [hl], a - - ld hl, sBox1 ; sBox7 - ld bc, sBank2AllBoxesChecksum - sBox1 - call SAVCheckSum - ld [sBank2AllBoxesChecksum], a ; sBank3AllBoxesChecksum - call CalcIndividualBoxCheckSums - call DisableSRAMAndPrepareClockData - ret - -DisplayChangeBoxMenu: - xor a - ld [H_AUTOBGTRANSFERENABLED], a - ld a, A_BUTTON | B_BUTTON - ld [wMenuWatchedKeys], a - ld a, 11 - ld [wMaxMenuItem], a - ld a, 1 - ld [wTopMenuItemY], a - ld a, 12 - ld [wTopMenuItemX], a - xor a - ld [wMenuWatchMovingOutOfBounds], a - ld a, [wCurrentBoxNum] - and $7f - ld [wCurrentMenuItem], a - ld [wLastMenuItem], a - coord hl, 0, 0 - lb bc, 2, 9 - call TextBoxBorder - ld hl, ChooseABoxText - call PrintText - coord hl, 11, 0 - lb bc, 12, 7 - call TextBoxBorder - ld hl, hFlags_0xFFFA - set 2, [hl] - ld de, BoxNames - coord hl, 13, 1 - call PlaceString - ld hl, hFlags_0xFFFA - res 2, [hl] - ld a, [wCurrentBoxNum] - and $7f - cp 9 - jr c, .singleDigitBoxNum - sub 9 - coord hl, 8, 2 - ld [hl], "1" - add "0" - jr .next -.singleDigitBoxNum - add "1" -.next - Coorda 9, 2 - coord hl, 1, 2 - ld de, BoxNoText - call PlaceString - call GetMonCountsForAllBoxes - coord hl, 18, 1 - ld de, wBoxMonCounts - ld bc, SCREEN_WIDTH - ld a, $c -.loop - push af - ld a, [de] - and a ; is the box empty? - jr z, .skipPlacingPokeball - ld [hl], $78 ; place pokeball tile next to box name if box not empty -.skipPlacingPokeball - add hl, bc - inc de - pop af - dec a - jr nz, .loop - ld a, 1 - ld [H_AUTOBGTRANSFERENABLED], a - ret - -ChooseABoxText: - TX_FAR _ChooseABoxText - db "@" - -BoxNames: - db "BOX 1" - next "BOX 2" - next "BOX 3" - next "BOX 4" - next "BOX 5" - next "BOX 6" - next "BOX 7" - next "BOX 8" - next "BOX 9" - next "BOX10" - next "BOX11" - next "BOX12@" - -BoxNoText: - db "BOX No.@" - -EmptyAllSRAMBoxes: -; marks all boxes in SRAM as empty (initialisation for the first time the -; player changes the box) - call EnableSRAMAndLatchClockData - ld a, 2 - ld [MBC1SRamBank], a - call EmptySRAMBoxesInBank - ld a, 3 - ld [MBC1SRamBank], a - call EmptySRAMBoxesInBank - call DisableSRAMAndPrepareClockData - ret - -EmptySRAMBoxesInBank: -; marks every box in the current SRAM bank as empty - ld hl, sBox1 ; sBox7 - call EmptySRAMBox - ld hl, sBox2 ; sBox8 - call EmptySRAMBox - ld hl, sBox3 ; sBox9 - call EmptySRAMBox - ld hl, sBox4 ; sBox10 - call EmptySRAMBox - ld hl, sBox5 ; sBox11 - call EmptySRAMBox - ld hl, sBox6 ; sBox12 - call EmptySRAMBox - ld hl, sBox1 ; sBox7 - ld bc, sBank2AllBoxesChecksum - sBox1 - call SAVCheckSum - ld [sBank2AllBoxesChecksum], a ; sBank3AllBoxesChecksum - call CalcIndividualBoxCheckSums - ret - -EmptySRAMBox: - xor a - ld [hli], a - dec a - ld [hl], a - ret - -GetMonCountsForAllBoxes: - ld hl, wBoxMonCounts - push hl - call EnableSRAMAndLatchClockData - ld a, $2 - ld [MBC1SRamBank], a - call GetMonCountsForBoxesInBank - ld a, $3 - ld [MBC1SRamBank], a - call GetMonCountsForBoxesInBank - call DisableSRAMAndPrepareClockData - pop hl - -; copy the count for the current box from WRAM - ld a, [wCurrentBoxNum] - and $7f - ld c, a - ld b, 0 - add hl, bc - ld a, [wNumInBox] - ld [hl], a - - ret - -GetMonCountsForBoxesInBank: - ld a, [sBox1] ; sBox7 - ld [hli], a - ld a, [sBox2] ; sBox8 - ld [hli], a - ld a, [sBox3] ; sBox9 - ld [hli], a - ld a, [sBox4] ; sBox10 - ld [hli], a - ld a, [sBox5] ; sBox11 - ld [hli], a - ld a, [sBox6] ; sBox12 - ld [hli], a - ret - -SAVCheckRandomID: -;checks if Sav file is the same by checking player's name 1st letter ($a598) -; and the two random numbers generated at game beginning -;(which are stored at wPlayerID)s - call EnableSRAMAndLatchClockData - ld a, $1 - ld [MBC1SRamBank], a - ld a, [sPlayerName] - and a - jr z, .next - ld hl, sPlayerName - ld bc, sMainDataCheckSum - sPlayerName - call SAVCheckSum - ld c, a - ld a, [sMainDataCheckSum] - cp c - jr nz, .next - ld hl, sMainData + (wPlayerID - wMainDataStart) ; player ID - ld a, [hli] - ld h, [hl] - ld l, a - ld a, [wPlayerID] - cp l - jr nz, .next - ld a, [wPlayerID + 1] - cp h -.next - ld a, $00 - ld [MBC1SRamBankingMode], a - ld [MBC1SRamEnable], a - ret - -SaveHallOfFameTeams: - ld a, [wNumHoFTeams] - dec a - cp HOF_TEAM_CAPACITY - jr nc, .shiftHOFTeams - ld hl, sHallOfFame - ld bc, HOF_TEAM - call AddNTimes - ld e, l - ld d, h - ld hl, wHallOfFame - ld bc, HOF_TEAM - jr HallOfFame_Copy - -.shiftHOFTeams -; if the space designated for HOF teams is full, then shift all HOF teams to the next slot, making space for the new HOF team -; this deletes the last HOF team though - ld hl, sHallOfFame + HOF_TEAM - ld de, sHallOfFame - ld bc, HOF_TEAM * (HOF_TEAM_CAPACITY - 1) - call HallOfFame_Copy - ld hl, wHallOfFame - ld de, sHallOfFame + HOF_TEAM * (HOF_TEAM_CAPACITY - 1) - ld bc, HOF_TEAM - jr HallOfFame_Copy - -LoadHallOfFameTeams: - ld hl, sHallOfFame - ld bc, HOF_TEAM - ld a, [wHoFTeamIndex] - call AddNTimes - ld de, wHallOfFame - ld bc, HOF_TEAM - ; fallthrough - -HallOfFame_Copy: - call EnableSRAMAndLatchClockData - xor a - ld [MBC1SRamBank], a - call CopyData - call DisableSRAMAndPrepareClockData - ret - -ClearSAV: - call EnableSRAMAndLatchClockData - ld a, $4 -.loop - dec a - push af - call PadSRAM_FF - pop af - jr nz, .loop - call DisableSRAMAndPrepareClockData - ret - -PadSRAM_FF: - ld [MBC1SRamBank], a - ld hl, $a000 - ld bc, $2000 - ld a, $ff - jp FillMemory - -EnableSRAMAndLatchClockData: - ld a, $1 - ld [MBC1SRamBankingMode], a - ld a, SRAM_ENABLE - ld [MBC1SRamEnable], a - ret - -DisableSRAMAndPrepareClockData: - ld a, SRAM_DISABLE - ld [MBC1SRamBankingMode], a - ld [MBC1SRamEnable], a - ret diff --git a/engine/slot_machine.asm b/engine/slot_machine.asm deleted file mode 100755 index b4514618..00000000 --- a/engine/slot_machine.asm +++ /dev/null @@ -1,891 +0,0 @@ -PromptUserToPlaySlots: - call SaveScreenTilesToBuffer2 - ld a, BANK(DisplayTextIDInit) - ld [wAutoTextBoxDrawingControl], a - ld b, a - ld hl, DisplayTextIDInit - call Bankswitch - ld hl, PlaySlotMachineText - call PrintText - call YesNoChoice - ld a, [wCurrentMenuItem] - and a - jr nz, .done ; if player chose No - dec a - ld [wUpdateSpritesEnabled], a - ld hl, wSlotMachineRerollCounter - xor a - ld [hli], a - ld [hl], SMILE_BUBBLE - predef EmotionBubble - call GBPalWhiteOutWithDelay3 - call LoadSlotMachineTiles - call LoadFontTilePatterns - ld b, SET_PAL_SLOTS - call RunPaletteCommand - call Delay3 - call GBPalNormal - ld a, $e4 - ld [rOBP0], a - call UpdateGBCPal_OBP0 - ld hl, wd730 - set 6, [hl] - xor a - ld [wSlotMachineAllowMatchesCounter], a - ld hl, wStoppingWhichSlotMachineWheel - ld bc, $0014 - call FillMemory - call MainSlotMachineLoop - ld hl, wd730 - res 6, [hl] - xor a - ld [wSlotMachineAllowMatchesCounter], a - call GBPalWhiteOutWithDelay3 - ld a, $1 - ld [wUpdateSpritesEnabled], a - call RunDefaultPaletteCommand - call ReloadMapSpriteTilePatterns - call ReloadTilesetTilePatterns -.done - call LoadScreenTilesFromBuffer2 - call Delay3 - call GBPalNormal - ld a, [wSlotMachineSavedROMBank] - push af - jp CloseTextDisplay - -PlaySlotMachineText: - TX_FAR _PlaySlotMachineText - db "@" - -MainSlotMachineLoop: - call SlotMachine_PrintCreditCoins - xor a - ld hl, wPayoutCoins - ld [hli], a - ld [hl], a - call SlotMachine_PrintPayoutCoins - ld hl, BetHowManySlotMachineText - call PrintText - call SaveScreenTilesToBuffer1 -.loop - ld a, A_BUTTON | B_BUTTON - ld [wMenuWatchedKeys], a - ld a, 2 - ld [wMaxMenuItem], a - ld a, 12 - ld [wTopMenuItemY], a - ld a, 15 - ld [wTopMenuItemX], a - xor a - ld [wCurrentMenuItem], a - ld [wLastMenuItem], a - ld [wMenuWatchMovingOutOfBounds], a - coord hl, 14, 11 - lb bc, 5, 4 - call TextBoxBorder - coord hl, 16, 12 - ld de, CoinMultiplierSlotMachineText - call PlaceString - call HandleMenuInput - and B_BUTTON - jp nz, LoadScreenTilesFromBuffer1 - ld a, [wCurrentMenuItem] - ld b, a - ld a, 3 - sub b - ld [wSlotMachineBet], a - ld hl, wPlayerCoins - ld c, a - ld a, [hli] - and a - jr nz, .skip1 - ld a, [hl] - cp c - jr nc, .skip1 - ld hl, NotEnoughCoinsSlotMachineText - call PrintText - jr .loop -.skip1 - call LoadScreenTilesFromBuffer1 - call SlotMachine_SubtractBetFromPlayerCoins - call SlotMachine_LightBalls - call SlotMachine_SetFlags - ld a, 4 - ld hl, wSlotMachineWheel1SlipCounter - ld [hli], a - ld [hli], a - ld [hl], a - call WaitForSoundToFinish - ld a, SFX_SLOTS_NEW_SPIN - call PlaySound - ld hl, StartSlotMachineText - call PrintText - call SlotMachine_SpinWheels - call SlotMachine_CheckForMatches - ld hl, wPlayerCoins - ld a, [hli] - or [hl] - jr nz, .skip2 - ld hl, OutOfCoinsSlotMachineText - call PrintText - ld c, 60 - jp DelayFrames -.skip2 - ld hl, OneMoreGoSlotMachineText - call PrintText - coord hl, 14, 12 - lb bc, 13, 15 - xor a ; YES_NO_MENU - ld [wTwoOptionMenuID], a - ld a, TWO_OPTION_MENU - ld [wTextBoxID], a - call DisplayTextBoxID - ld a, [wCurrentMenuItem] - and a - ret nz - call SlotMachine_PutOutLitBalls - jp MainSlotMachineLoop - -CoinMultiplierSlotMachineText: - db "×3" - next "×2" - next "×1@" - -OutOfCoinsSlotMachineText: - TX_FAR _OutOfCoinsSlotMachineText - db "@" - -BetHowManySlotMachineText: - TX_FAR _BetHowManySlotMachineText - db "@" - -StartSlotMachineText: - TX_FAR _StartSlotMachineText - db "@" - -NotEnoughCoinsSlotMachineText: - TX_FAR _NotEnoughCoinsSlotMachineText - db "@" - -OneMoreGoSlotMachineText: - TX_FAR _OneMoreGoSlotMachineText - db "@" - -SlotMachine_SetFlags: - ld hl, wSlotMachineFlags - bit 7, [hl] - ret nz - ld a, [wSlotMachineAllowMatchesCounter] - and a - jr nz, .allowMatches - call Random - and a - jr z, .setAllowMatchesCounter ; 1/256 (~0.4%) chance - ld b, a - ld a, [wSlotMachineSevenAndBarModeChance] - cp b - jr c, .allowSevenAndBarMatches - ld a, 210 - cp b - jr c, .allowMatches ; 55/256 (~21.5%) chance - ld [hl], 0 - ret -.allowMatches - set 6, [hl] - ret -.setAllowMatchesCounter - ld a, 60 - ld [wSlotMachineAllowMatchesCounter], a - ret -.allowSevenAndBarMatches - set 7, [hl] - ret - -SlotMachine_SpinWheels: - ld c, 20 -.loop1 - push bc - call SlotMachine_AnimWheel1 - call SlotMachine_AnimWheel2 - call SlotMachine_AnimWheel3 - ld c, 2 - call DelayFrames - pop bc - dec c - jr nz, .loop1 - xor a - ld [wStoppingWhichSlotMachineWheel], a -.loop2 - call SlotMachine_HandleInputWhileWheelsSpin - call SlotMachine_StopOrAnimWheel1 - call SlotMachine_StopOrAnimWheel2 - call SlotMachine_StopOrAnimWheel3 - ret c - ld a, [wOnSGB] - xor $1 - inc a - ld c, a - call DelayFrames - jr .loop2 - -; Note that the wheels can only stop when a symbol is centred in the wheel -; and thus 3 full symbols rather than 2 full symbols and 2 half symbols are -; visible. The 3 functions below ensure this by checking if the wheel offset -; is even before stopping the wheel. - -SlotMachine_StopOrAnimWheel1: - ld a, [wStoppingWhichSlotMachineWheel] - cp 1 - jr c, .animWheel - ld de, wSlotMachineWheel1Offset - ld a, [de] - rra - jr nc, .animWheel ; check that a symbol is centred in the wheel - ld hl, wSlotMachineWheel1SlipCounter - ld a, [hl] - and a - ret z - dec [hl] - call SlotMachine_StopWheel1Early - ret nz -.animWheel - jp SlotMachine_AnimWheel1 - -SlotMachine_StopOrAnimWheel2: - ld a, [wStoppingWhichSlotMachineWheel] - cp 2 - jr c, .animWheel - ld de, wSlotMachineWheel2Offset - ld a, [de] - rra - jr nc, .animWheel ; check that a symbol is centred in the wheel - ld hl, wSlotMachineWheel2SlipCounter - ld a, [hl] - and a - ret z - dec [hl] - call SlotMachine_StopWheel2Early - ret z -.animWheel - jp SlotMachine_AnimWheel2 - -SlotMachine_StopOrAnimWheel3: - ld a, [wStoppingWhichSlotMachineWheel] - cp 3 - jr c, .animWheel - ld de, wSlotMachineWheel3Offset - ld a, [de] - rra - jr nc, .animWheel ; check that a symbol is centred in the wheel -; wheel 3 stops as soon as possible - scf - ret -.animWheel - call SlotMachine_AnimWheel3 - and a - ret - -SlotMachine_StopWheel1Early: - call SlotMachine_GetWheel1Tiles - ld hl, wSlotMachineWheel1BottomTile - ld a, [wSlotMachineFlags] - and $80 - jr nz, .sevenAndBarMode -; Stop early if the middle symbol is not a cherry. - inc hl - ld a, [hl] - cp SLOTSCHERRY >> 8 - jr nz, .stopWheel - ret -; It looks like this was intended to make the wheel stop when a 7 symbol was -; visible, but it has a bug and so the wheel stops randomly. -.sevenAndBarMode - ld c, $3 -.loop - ld a, [hli] - cp SLOTS7 >> 8 - jr c, .stopWheel ; condition never true - dec c - jr nz, .loop - ret -.stopWheel - inc a - ld hl, wSlotMachineWheel1SlipCounter - ld [hl], 0 - ret - -SlotMachine_StopWheel2Early: - call SlotMachine_GetWheel2Tiles - ld a, [wSlotMachineFlags] - and $80 - jr nz, .sevenAndBarMode -; Stop early if any symbols are lined up in the first two wheels. - call SlotMachine_FindWheel1Wheel2Matches - ret nz - jr .stopWheel -; Stop early if two 7 symbols or two bar symbols are lined up in the first two -; wheels OR if no symbols are lined up and the bottom symbol in wheel 2 is a -; 7 symbol or bar symbol. The second part could be a bug or a way to reduce the -; player's odds. -.sevenAndBarMode - call SlotMachine_FindWheel1Wheel2Matches - ld a, [de] - cp (SLOTSBAR >> 8) + 1 - ret nc -.stopWheel - xor a - ld [wSlotMachineWheel2SlipCounter], a - ret - -SlotMachine_FindWheel1Wheel2Matches: -; return whether wheel 1 and wheel 2's current positions allow a match (given -; that wheel 3 stops in a good position) in Z - ld hl, wSlotMachineWheel1BottomTile - ld de, wSlotMachineWheel2BottomTile - ld a, [de] - cp [hl] ; wheel 1 bottom, wheel 2 bottom - ret z - inc de - ld a, [de] - cp [hl] ; wheel 1 bottom, wheel 2 middle - ret z - inc hl - cp [hl] ; wheel 1 middle, wheel 2 middle - ret z - inc hl - cp [hl] ; wheel 1 top, wheel 2 middle - ret z - inc de - ld a, [de] - cp [hl] ; wheel 1 top, wheel 2 top - ret z - dec de - dec de - ret - -SlotMachine_CheckForMatches: - call SlotMachine_GetWheel3Tiles - ld a, [wSlotMachineBet] - cp 2 - jr z, .checkMatchesFor2CoinBet - cp 1 - jr z, .checkMatchFor1CoinBet -; 3 coin bet allows diagonal matches (plus the matches for 1/2 coin bets) - ld hl, wSlotMachineWheel1BottomTile - ld de, wSlotMachineWheel2MiddleTile - ld bc, wSlotMachineWheel3TopTile - call SlotMachine_CheckForMatch - jp z, .foundMatch - ld hl, wSlotMachineWheel1TopTile - ld de, wSlotMachineWheel2MiddleTile - ld bc, wSlotMachineWheel3BottomTile - call SlotMachine_CheckForMatch - jr z, .foundMatch -; 2 coin bet allows top/bottom horizontal matches (plus the match for a 1 coin bet) -.checkMatchesFor2CoinBet - ld hl, wSlotMachineWheel1TopTile - ld de, wSlotMachineWheel2TopTile - ld bc, wSlotMachineWheel3TopTile - call SlotMachine_CheckForMatch - jr z, .foundMatch - ld hl, wSlotMachineWheel1BottomTile - ld de, wSlotMachineWheel2BottomTile - ld bc, wSlotMachineWheel3BottomTile - call SlotMachine_CheckForMatch - jr z, .foundMatch -; 1 coin bet only allows a middle horizontal match -.checkMatchFor1CoinBet - ld hl, wSlotMachineWheel1MiddleTile - ld de, wSlotMachineWheel2MiddleTile - ld bc, wSlotMachineWheel3MiddleTile - call SlotMachine_CheckForMatch - jr z, .foundMatch - ld a, [wSlotMachineFlags] - and $c0 - jr z, .noMatch - ld hl, wSlotMachineRerollCounter - dec [hl] - jr nz, .rollWheel3DownByOneSymbol -.noMatch - ld hl, NotThisTimeText - call PrintText -.done - xor a - ld [wMuteAudioAndPauseMusic], a - ret -.rollWheel3DownByOneSymbol - call SlotMachine_AnimWheel3 - call DelayFrame - call SlotMachine_AnimWheel3 - call DelayFrame - jp SlotMachine_CheckForMatches -.foundMatch - ld a, [wSlotMachineFlags] - and $c0 - jr z, .rollWheel3DownByOneSymbol ; roll wheel if player isn't allowed to win - and $80 - jr nz, .acceptMatch -; if 7/bar matches aren't enabled and the match was a 7/bar symbol, roll wheel - ld a, [hl] - cp (SLOTSBAR >> 8) + 1 - jr c, .rollWheel3DownByOneSymbol -.acceptMatch - ld a, [hl] - sub $2 - ld [wSlotMachineWinningSymbol], a - ld hl, SlotRewardPointers - ld c, a - ld b, 0 - add hl, bc - ld a, [hli] - ld e, a - ld a, [hli] - ld d, a - push de - ld a, [hli] - ld h, [hl] - ld l, a - ld de, wcf4b - ld bc, 4 - call CopyData - pop hl - ld de, .flashScreenLoop - push de - jp hl - -.flashScreenLoop - ld a, [rBGP] - xor $40 - ld [rBGP], a - call UpdateGBCPal_BGP - ld c, 5 - call DelayFrames - dec b - jr nz, .flashScreenLoop - ld hl, wPayoutCoins - ld [hl], d - inc hl - ld [hl], e - call SlotMachine_PrintPayoutCoins - ld hl, SymbolLinedUpSlotMachineText - call PrintText - call WaitForTextScrollButtonPress - call SlotMachine_PayCoinsToPlayer - call SlotMachine_PrintPayoutCoins - ld a, $e4 - ld [rOBP0], a - call UpdateGBCPal_OBP0 - jp .done - -SymbolLinedUpSlotMachineText: - TX_ASM - push bc - call SlotMachine_PrintWinningSymbol - ld hl, LinedUpText - pop bc - inc bc - inc bc - inc bc - inc bc - ret - -LinedUpText: - TX_FAR _LinedUpText - db "@" - -SlotRewardPointers: - dw SlotReward300Func - dw SlotReward300Text - dw SlotReward100Func - dw SlotReward100Text - dw SlotReward8Func - dw SlotReward8Text - dw SlotReward15Func - dw SlotReward15Text - dw SlotReward15Func - dw SlotReward15Text - dw SlotReward15Func - dw SlotReward15Text - -SlotReward300Text: - db "300@" - -SlotReward100Text: - db "100@" - -SlotReward8Text: - db "8@" - -SlotReward15Text: - db "15@" - -NotThisTimeText: - TX_FAR _NotThisTimeText - db "@" - -; compares the slot machine tiles at bc, de, and hl -SlotMachine_CheckForMatch: - ld a, [de] - cp [hl] - ret nz - ld a, [bc] - cp [hl] - ret - -SlotMachine_GetWheel3Tiles: - ld de, wSlotMachineWheel3BottomTile - ld hl, SlotMachineWheel3 - ld a, [wSlotMachineWheel3Offset] - call SlotMachine_GetWheelTiles - -SlotMachine_GetWheel2Tiles: - ld de, wSlotMachineWheel2BottomTile - ld hl, SlotMachineWheel2 - ld a, [wSlotMachineWheel2Offset] - call SlotMachine_GetWheelTiles - -SlotMachine_GetWheel1Tiles: - ld de, wSlotMachineWheel1BottomTile - ld hl, SlotMachineWheel1 - ld a, [wSlotMachineWheel1Offset] - -SlotMachine_GetWheelTiles: - ld c, a - ld b, 0 - add hl, bc - ld c, 3 -.loop - ld a, [hli] - ld [de], a - inc de - inc hl - dec c - jr nz, .loop - ret - -SlotReward8Func: - ld hl, wSlotMachineAllowMatchesCounter - ld a, [hl] - and a - jr z, .skip - dec [hl] -.skip - ld b, $2 - ld de, 8 - ret - -SlotReward15Func: - ld hl, wSlotMachineAllowMatchesCounter - ld a, [hl] - and a - jr z, .skip - dec [hl] -.skip - ld b, $4 - ld de, 15 - ret - -SlotReward100Func: - ld a, SFX_GET_KEY_ITEM - call PlaySound - xor a - ld [wSlotMachineFlags], a - ld b, $8 - ld de, 100 - ret - -SlotReward300Func: - ld hl, YeahText - call PrintText - ld a, SFX_GET_ITEM_2 - call PlaySound - call Random - cp $80 - ld a, $0 - jr c, .skip - ld [wSlotMachineFlags], a -.skip - ld [wSlotMachineAllowMatchesCounter], a - ld b, $14 - ld de, 300 - ret - -YeahText: - TX_FAR _YeahText - TX_DELAY - db "@" - -SlotMachine_PrintWinningSymbol: -; prints winning symbol and down arrow in text box - coord hl, 2, 14 - ld a, [wSlotMachineWinningSymbol] - add $25 - ld [hli], a - inc a - ld [hld], a - inc a - ld de, -SCREEN_WIDTH - add hl, de - ld [hli], a - inc a - ld [hl], a - coord hl, 18, 16 - ld [hl], "▼" - ret - -SlotMachine_SubtractBetFromPlayerCoins: - ld hl, wTempCoins2 + 1 - ld a, [wSlotMachineBet] - ld [hld], a - xor a - ld [hli], a - ld de, wPlayerCoins + 1 - ld c, $2 - predef SubBCDPredef - -SlotMachine_PrintCreditCoins: - coord hl, 5, 1 - ld de, wPlayerCoins - ld c, $2 - jp PrintBCDNumber - -SlotMachine_PrintPayoutCoins: - coord hl, 11, 1 - ld de, wPayoutCoins - lb bc, LEADING_ZEROES | 2, 4 ; 2 bytes, 4 digits - jp PrintNumber - -SlotMachine_PayCoinsToPlayer: - ld a, $1 - ld [wMuteAudioAndPauseMusic], a - call WaitForSoundToFinish - -; Put 1 in the temp coins variable. This value is added to the player's coins -; repeatedly so the player can watch the value go up 1 coin at a time. - ld hl, wTempCoins1 - xor a - ld [hli], a - inc a - ld [hl], a - - ld a, 5 - ld [wAnimCounter], a - -; Subtract 1 from the payout amount and add 1 to the player's coins each -; iteration until the payout amount reaches 0. -.loop - ld a, [wPayoutCoins + 1] - ld l, a - ld a, [wPayoutCoins] - ld h, a - or l - ret z - ld de, -1 - add hl, de - ld a, l - ld [wPayoutCoins + 1], a - ld a, h - ld [wPayoutCoins], a - ld hl, wTempCoins1 + 1 - ld de, wPlayerCoins + 1 - ld c, $2 - predef AddBCDPredef - call SlotMachine_PrintCreditCoins - call SlotMachine_PrintPayoutCoins - ld a, SFX_SLOTS_REWARD - call PlaySound - ld a, [wAnimCounter] - dec a - jr nz, .skip1 - ld a, [rOBP0] - xor $40 ; make the slot wheel symbols flash - ld [rOBP0], a - call UpdateGBCPal_OBP0 - ld a, 5 -.skip1 - ld [wAnimCounter], a - ld a, [wSlotMachineWinningSymbol] - cp (SLOTSBAR >> 8) + 1 - ld c, 8 - jr nc, .skip2 - srl c ; c = 4 (make the the coins transfer faster if the symbol was 7 or bar) -.skip2 - call DelayFrames - jr .loop - -SlotMachine_PutOutLitBalls: - ld a, $23 - ld [wNewSlotMachineBallTile], a - jr SlotMachine_UpdateThreeCoinBallTiles - -SlotMachine_LightBalls: - ld a, $14 - ld [wNewSlotMachineBallTile], a - ld a, [wSlotMachineBet] - dec a - jr z, SlotMachine_UpdateOneCoinBallTiles - dec a - jr z, SlotMachine_UpdateTwoCoinBallTiles - -SlotMachine_UpdateThreeCoinBallTiles: - coord hl, 3, 2 - call SlotMachine_UpdateBallTiles - coord hl, 3, 10 - call SlotMachine_UpdateBallTiles - -SlotMachine_UpdateTwoCoinBallTiles: - coord hl, 3, 4 - call SlotMachine_UpdateBallTiles - coord hl, 3, 8 - call SlotMachine_UpdateBallTiles - -SlotMachine_UpdateOneCoinBallTiles: - coord hl, 3, 6 - -SlotMachine_UpdateBallTiles: - ld a, [wNewSlotMachineBallTile] - ld [hl], a - ld bc, 13 - add hl, bc - ld [hl], a - ld bc, 7 - add hl, bc - inc a - ld [hl], a - ld bc, 13 - add hl, bc - ld [hl], a - ret - -SlotMachine_AnimWheel1: - ld bc, SlotMachineWheel1 - ld de, wSlotMachineWheel1Offset - ld hl, wOAMBuffer - ld a, $30 - ld [wBaseCoordX], a - jr SlotMachine_AnimWheel - -SlotMachine_AnimWheel2: - ld bc, SlotMachineWheel2 - ld de, wSlotMachineWheel2Offset - ld hl, wOAMBuffer + $30 - ld a, $50 - ld [wBaseCoordX], a - jr SlotMachine_AnimWheel - -SlotMachine_AnimWheel3: - ld bc, SlotMachineWheel3 - ld de, wSlotMachineWheel3Offset - ld hl, wOAMBuffer + $60 - ld a, $70 - ld [wBaseCoordX], a - -SlotMachine_AnimWheel: - ld a, $58 - ld [wBaseCoordY], a - push de - ld a, [de] - ld d, b - add c - ld e, a - jr nc, .loop - inc d -.loop - ld a, [wBaseCoordY] - ld [hli], a - ld a, [wBaseCoordX] - ld [hli], a - ld a, [de] - ld [hli], a - ld a, $80 - ld [hli], a - ld a, [wBaseCoordY] - ld [hli], a - ld a, [wBaseCoordX] - add $8 - ld [hli], a - ld a, [de] - inc a - ld [hli], a - ld a, $80 - ld [hli], a - inc de - ld a, [wBaseCoordY] - sub $8 - ld [wBaseCoordY], a - cp $28 - jr nz, .loop - pop de - ld a, [de] - inc a ; advance the offset so that the wheel animates - cp 30 - jr nz, .skip - xor a ; wrap around to 0 when the offset reaches 30 -.skip - ld [de], a - ret - -SlotMachine_HandleInputWhileWheelsSpin: - call DelayFrame - call JoypadLowSensitivity - ld a, [hJoy5] - and A_BUTTON - ret z - ld hl, wStoppingWhichSlotMachineWheel - ld a, [hl] - dec a - ld de, wSlotMachineWheel1SlipCounter - jr z, .skip - dec a - ld de, wSlotMachineWheel2SlipCounter - jr z, .skip -.loop - inc [hl] - ld a, SFX_SLOTS_STOP_WHEEL - jp PlaySound -.skip - ld a, [de] - and a - ret nz - jr .loop - -LoadSlotMachineTiles: - call DisableLCD - ld hl, SlotMachineTiles2 - ld de, vChars0 - ld bc, $1c0 - ld a, BANK(SlotMachineTiles2) - call FarCopyData - ld hl, SlotMachineTiles1 - ld de, vChars2 - ld bc, $250 - ld a, BANK(SlotMachineTiles1) - call FarCopyData - ld hl, SlotMachineTiles2 - ld de, vChars2 + $250 - ld bc, $1c0 - ld a, BANK(SlotMachineTiles2) - call FarCopyData - ld hl, SlotMachineMap - coord de, 0, 0 - ld bc, SlotMachineMapEnd - SlotMachineMap - call CopyData - call EnableLCD - ld hl, wSlotMachineWheel1Offset - ld a, $1c - ld [hli], a - ld [hli], a - ld [hl], a - call SlotMachine_AnimWheel1 - call SlotMachine_AnimWheel2 - jp SlotMachine_AnimWheel3 - -SlotMachineMap: - INCBIN "gfx/tilemaps/slotmachine.map" -SlotMachineMapEnd: - -INCLUDE "data/slot_machine_wheels.asm" - -SlotMachineTiles1: - INCBIN "gfx/slotmachine1.2bpp" diff --git a/engine/slots/game_corner_slots.asm b/engine/slots/game_corner_slots.asm new file mode 100755 index 00000000..48321974 --- /dev/null +++ b/engine/slots/game_corner_slots.asm @@ -0,0 +1,54 @@ +StartSlotMachine: + ld a, [wHiddenObjectFunctionArgument] + cp SLOTS_OUTOFORDER + jr z, .printOutOfOrder + cp SLOTS_OUTTOLUNCH + jr z, .printOutToLunch + cp SLOTS_SOMEONESKEYS + jr z, .printSomeonesKeys + farcall AbleToPlaySlotsCheck + ld a, [wCanPlaySlots] + and a + ret z + ld a, [wLuckySlotHiddenObjectIndex] + ld b, a + ld a, [wHiddenObjectIndex] + inc a + cp b + jr z, .match + ld a, 253 + jr .next +.match + ld a, 250 +.next + ld [wSlotMachineSevenAndBarModeChance], a + ldh a, [hLoadedROMBank] + ld [wSlotMachineSavedROMBank], a + call PromptUserToPlaySlots + ret +.printOutOfOrder + tx_pre_id GameCornerOutOfOrderText + jr .printText +.printOutToLunch + tx_pre_id GameCornerOutToLunchText + jr .printText +.printSomeonesKeys + tx_pre_id GameCornerSomeonesKeysText +.printText + push af + call EnableAutoTextBoxDrawing + pop af + call PrintPredefTextID + ret + +GameCornerOutOfOrderText:: + text_far _GameCornerOutOfOrderText + text_end + +GameCornerOutToLunchText:: + text_far _GameCornerOutToLunchText + text_end + +GameCornerSomeonesKeysText:: + text_far _GameCornerSomeonesKeysText + text_end diff --git a/engine/slots/game_corner_slots2.asm b/engine/slots/game_corner_slots2.asm new file mode 100755 index 00000000..a4ba4ec1 --- /dev/null +++ b/engine/slots/game_corner_slots2.asm @@ -0,0 +1,31 @@ +AbleToPlaySlotsCheck: + ld a, [wSpritePlayerStateData1ImageIndex] + and $8 + jr z, .done ; not able + ld b, COIN_CASE + predef GetQuantityOfItemInBag + ld a, b + and a + ld b, (GameCornerCoinCaseText_id - TextPredefs) / 2 + 1 + jr z, .printCoinCaseRequired + ld hl, wPlayerCoins + ld a, [hli] + or [hl] + jr nz, .done ; able to play + ld b, (GameCornerNoCoinsText_id - TextPredefs) / 2 + 1 +.printCoinCaseRequired + call EnableAutoTextBoxDrawing + ld a, b + call PrintPredefTextID + xor a +.done + ld [wCanPlaySlots], a + ret + +GameCornerCoinCaseText:: + text_far _GameCornerCoinCaseText + text_end + +GameCornerNoCoinsText:: + text_far _GameCornerNoCoinsText + text_end diff --git a/engine/slots/slot_machine.asm b/engine/slots/slot_machine.asm new file mode 100755 index 00000000..ba007d9d --- /dev/null +++ b/engine/slots/slot_machine.asm @@ -0,0 +1,892 @@ +PromptUserToPlaySlots: + call SaveScreenTilesToBuffer2 + ld a, BANK(DisplayTextIDInit) ; TRUE + ld [wAutoTextBoxDrawingControl], a + ld b, a + ld hl, DisplayTextIDInit + call Bankswitch + ld hl, PlaySlotMachineText + call PrintText + call YesNoChoice + ld a, [wCurrentMenuItem] + and a + jr nz, .done ; if player chose No + dec a + ld [wUpdateSpritesEnabled], a + ld hl, wSlotMachineRerollCounter + xor a + ld [hli], a + ld [hl], SMILE_BUBBLE + predef EmotionBubble + call GBPalWhiteOutWithDelay3 + call LoadSlotMachineTiles + call LoadFontTilePatterns + ld b, SET_PAL_SLOTS + call RunPaletteCommand + call Delay3 + call GBPalNormal + ld a, $e4 + ldh [rOBP0], a + call UpdateGBCPal_OBP0 + ld hl, wd730 + set 6, [hl] + xor a + ld [wSlotMachineAllowMatchesCounter], a + ld hl, wStoppingWhichSlotMachineWheel + ld bc, $14 + call FillMemory + call MainSlotMachineLoop + ld hl, wd730 + res 6, [hl] + xor a + ld [wSlotMachineAllowMatchesCounter], a + call GBPalWhiteOutWithDelay3 + ld a, $1 + ld [wUpdateSpritesEnabled], a + call RunDefaultPaletteCommand + call ReloadMapSpriteTilePatterns + call ReloadTilesetTilePatterns +.done + call LoadScreenTilesFromBuffer2 + call Delay3 + call GBPalNormal + ld a, [wSlotMachineSavedROMBank] + push af + jp CloseTextDisplay + +PlaySlotMachineText: + text_far _PlaySlotMachineText + text_end + +MainSlotMachineLoop: + call SlotMachine_PrintCreditCoins + xor a + ld hl, wPayoutCoins + ld [hli], a + ld [hl], a + call SlotMachine_PrintPayoutCoins + ld hl, BetHowManySlotMachineText + call PrintText + call SaveScreenTilesToBuffer1 +.loop + ld a, A_BUTTON | B_BUTTON + ld [wMenuWatchedKeys], a + ld a, 2 + ld [wMaxMenuItem], a + ld a, 12 + ld [wTopMenuItemY], a + ld a, 15 + ld [wTopMenuItemX], a + xor a + ld [wCurrentMenuItem], a + ld [wLastMenuItem], a + ld [wMenuWatchMovingOutOfBounds], a + hlcoord 14, 11 + lb bc, 5, 4 + call TextBoxBorder + hlcoord 16, 12 + ld de, CoinMultiplierSlotMachineText + call PlaceString + call HandleMenuInput + and B_BUTTON + jp nz, LoadScreenTilesFromBuffer1 + ld a, [wCurrentMenuItem] + ld b, a + ld a, 3 + sub b + ld [wSlotMachineBet], a + ld hl, wPlayerCoins + ld c, a + ld a, [hli] + and a + jr nz, .skip1 + ld a, [hl] + cp c + jr nc, .skip1 + ld hl, NotEnoughCoinsSlotMachineText + call PrintText + jr .loop +.skip1 + call LoadScreenTilesFromBuffer1 + call SlotMachine_SubtractBetFromPlayerCoins + call SlotMachine_LightBalls + call SlotMachine_SetFlags + ld a, 4 + ld hl, wSlotMachineWheel1SlipCounter + ld [hli], a + ld [hli], a + ld [hl], a + call WaitForSoundToFinish + ld a, SFX_SLOTS_NEW_SPIN + call PlaySound + ld hl, StartSlotMachineText + call PrintText + call SlotMachine_SpinWheels + call SlotMachine_CheckForMatches + ld hl, wPlayerCoins + ld a, [hli] + or [hl] + jr nz, .skip2 + ld hl, OutOfCoinsSlotMachineText + call PrintText + ld c, 60 + jp DelayFrames +.skip2 + ld hl, OneMoreGoSlotMachineText + call PrintText + hlcoord 14, 12 + lb bc, 13, 15 + xor a ; YES_NO_MENU + ld [wTwoOptionMenuID], a + ld a, TWO_OPTION_MENU + ld [wTextBoxID], a + call DisplayTextBoxID + ld a, [wCurrentMenuItem] + and a + ret nz + call SlotMachine_PutOutLitBalls + jp MainSlotMachineLoop + +CoinMultiplierSlotMachineText: + db "×3" + next "×2" + next "×1@" + +OutOfCoinsSlotMachineText: + text_far _OutOfCoinsSlotMachineText + text_end + +BetHowManySlotMachineText: + text_far _BetHowManySlotMachineText + text_end + +StartSlotMachineText: + text_far _StartSlotMachineText + text_end + +NotEnoughCoinsSlotMachineText: + text_far _NotEnoughCoinsSlotMachineText + text_end + +OneMoreGoSlotMachineText: + text_far _OneMoreGoSlotMachineText + text_end + +SlotMachine_SetFlags: + ld hl, wSlotMachineFlags + bit 7, [hl] + ret nz + ld a, [wSlotMachineAllowMatchesCounter] + and a + jr nz, .allowMatches + call Random + and a + jr z, .setAllowMatchesCounter ; 1/256 (~0.4%) chance + ld b, a + ld a, [wSlotMachineSevenAndBarModeChance] + cp b + jr c, .allowSevenAndBarMatches + ld a, 210 + cp b + jr c, .allowMatches ; 55/256 (~21.5%) chance + ld [hl], 0 + ret +.allowMatches + set 6, [hl] + ret +.setAllowMatchesCounter + ld a, 60 + ld [wSlotMachineAllowMatchesCounter], a + ret +.allowSevenAndBarMatches + set 7, [hl] + ret + +SlotMachine_SpinWheels: + ld c, 20 +.loop1 + push bc + call SlotMachine_AnimWheel1 + call SlotMachine_AnimWheel2 + call SlotMachine_AnimWheel3 + ld c, 2 + call DelayFrames + pop bc + dec c + jr nz, .loop1 + xor a + ld [wStoppingWhichSlotMachineWheel], a +.loop2 + call SlotMachine_HandleInputWhileWheelsSpin + call SlotMachine_StopOrAnimWheel1 + call SlotMachine_StopOrAnimWheel2 + call SlotMachine_StopOrAnimWheel3 + ret c + ld a, [wOnSGB] + xor $1 + inc a + ld c, a + call DelayFrames + jr .loop2 + +; Note that the wheels can only stop when a symbol is centred in the wheel +; and thus 3 full symbols rather than 2 full symbols and 2 half symbols are +; visible. The 3 functions below ensure this by checking if the wheel offset +; is even before stopping the wheel. + +SlotMachine_StopOrAnimWheel1: + ld a, [wStoppingWhichSlotMachineWheel] + cp 1 + jr c, .animWheel + ld de, wSlotMachineWheel1Offset + ld a, [de] + rra + jr nc, .animWheel ; check that a symbol is centred in the wheel + ld hl, wSlotMachineWheel1SlipCounter + ld a, [hl] + and a + ret z + dec [hl] + call SlotMachine_StopWheel1Early + ret nz +.animWheel + jp SlotMachine_AnimWheel1 + +SlotMachine_StopOrAnimWheel2: + ld a, [wStoppingWhichSlotMachineWheel] + cp 2 + jr c, .animWheel + ld de, wSlotMachineWheel2Offset + ld a, [de] + rra + jr nc, .animWheel ; check that a symbol is centred in the wheel + ld hl, wSlotMachineWheel2SlipCounter + ld a, [hl] + and a + ret z + dec [hl] + call SlotMachine_StopWheel2Early + ret z +.animWheel + jp SlotMachine_AnimWheel2 + +SlotMachine_StopOrAnimWheel3: + ld a, [wStoppingWhichSlotMachineWheel] + cp 3 + jr c, .animWheel + ld de, wSlotMachineWheel3Offset + ld a, [de] + rra + jr nc, .animWheel ; check that a symbol is centred in the wheel +; wheel 3 stops as soon as possible + scf + ret +.animWheel + call SlotMachine_AnimWheel3 + and a + ret + +SlotMachine_StopWheel1Early: + call SlotMachine_GetWheel1Tiles + ld hl, wSlotMachineWheel1BottomTile + ld a, [wSlotMachineFlags] + and $80 + jr nz, .sevenAndBarMode +; Stop early if the middle symbol is not a cherry. + inc hl + ld a, [hl] + cp HIGH(SLOTSCHERRY) + jr nz, .stopWheel + ret +; It looks like this was intended to make the wheel stop when a 7 symbol was +; visible, but it has a bug and so the wheel stops randomly. +.sevenAndBarMode + ld c, $3 +.loop + ld a, [hli] + cp HIGH(SLOTS7) + jr c, .stopWheel ; condition never true + dec c + jr nz, .loop + ret +.stopWheel + inc a + ld hl, wSlotMachineWheel1SlipCounter + ld [hl], 0 + ret + +SlotMachine_StopWheel2Early: + call SlotMachine_GetWheel2Tiles + ld a, [wSlotMachineFlags] + and $80 + jr nz, .sevenAndBarMode +; Stop early if any symbols are lined up in the first two wheels. + call SlotMachine_FindWheel1Wheel2Matches + ret nz + jr .stopWheel +; Stop early if two 7 symbols or two bar symbols are lined up in the first two +; wheels OR if no symbols are lined up and the bottom symbol in wheel 2 is a +; 7 symbol or bar symbol. The second part could be a bug or a way to reduce the +; player's odds. +.sevenAndBarMode + call SlotMachine_FindWheel1Wheel2Matches + ld a, [de] + cp HIGH(SLOTSBAR) + 1 + ret nc +.stopWheel + xor a + ld [wSlotMachineWheel2SlipCounter], a + ret + +SlotMachine_FindWheel1Wheel2Matches: +; return whether wheel 1 and wheel 2's current positions allow a match (given +; that wheel 3 stops in a good position) in Z + ld hl, wSlotMachineWheel1BottomTile + ld de, wSlotMachineWheel2BottomTile + ld a, [de] + cp [hl] ; wheel 1 bottom, wheel 2 bottom + ret z + inc de + ld a, [de] + cp [hl] ; wheel 1 bottom, wheel 2 middle + ret z + inc hl + cp [hl] ; wheel 1 middle, wheel 2 middle + ret z + inc hl + cp [hl] ; wheel 1 top, wheel 2 middle + ret z + inc de + ld a, [de] + cp [hl] ; wheel 1 top, wheel 2 top + ret z + dec de + dec de + ret + +SlotMachine_CheckForMatches: + call SlotMachine_GetWheel3Tiles + ld a, [wSlotMachineBet] + cp 2 + jr z, .checkMatchesFor2CoinBet + cp 1 + jr z, .checkMatchFor1CoinBet +; 3 coin bet allows diagonal matches (plus the matches for 1/2 coin bets) + ld hl, wSlotMachineWheel1BottomTile + ld de, wSlotMachineWheel2MiddleTile + ld bc, wSlotMachineWheel3TopTile + call SlotMachine_CheckForMatch + jp z, .foundMatch + ld hl, wSlotMachineWheel1TopTile + ld de, wSlotMachineWheel2MiddleTile + ld bc, wSlotMachineWheel3BottomTile + call SlotMachine_CheckForMatch + jr z, .foundMatch +; 2 coin bet allows top/bottom horizontal matches (plus the match for a 1 coin bet) +.checkMatchesFor2CoinBet + ld hl, wSlotMachineWheel1TopTile + ld de, wSlotMachineWheel2TopTile + ld bc, wSlotMachineWheel3TopTile + call SlotMachine_CheckForMatch + jr z, .foundMatch + ld hl, wSlotMachineWheel1BottomTile + ld de, wSlotMachineWheel2BottomTile + ld bc, wSlotMachineWheel3BottomTile + call SlotMachine_CheckForMatch + jr z, .foundMatch +; 1 coin bet only allows a middle horizontal match +.checkMatchFor1CoinBet + ld hl, wSlotMachineWheel1MiddleTile + ld de, wSlotMachineWheel2MiddleTile + ld bc, wSlotMachineWheel3MiddleTile + call SlotMachine_CheckForMatch + jr z, .foundMatch + ld a, [wSlotMachineFlags] + and $c0 + jr z, .noMatch + ld hl, wSlotMachineRerollCounter + dec [hl] + jr nz, .rollWheel3DownByOneSymbol +.noMatch + ld hl, NotThisTimeText + call PrintText +.done + xor a + ld [wMuteAudioAndPauseMusic], a + ret +.rollWheel3DownByOneSymbol + call SlotMachine_AnimWheel3 + call DelayFrame + call SlotMachine_AnimWheel3 + call DelayFrame + jp SlotMachine_CheckForMatches +.foundMatch + ld a, [wSlotMachineFlags] + and $c0 + jr z, .rollWheel3DownByOneSymbol ; roll wheel if player isn't allowed to win + and $80 + jr nz, .acceptMatch +; if 7/bar matches aren't enabled and the match was a 7/bar symbol, roll wheel + ld a, [hl] + cp HIGH(SLOTSBAR) + 1 + jr c, .rollWheel3DownByOneSymbol +.acceptMatch + ld a, [hl] + sub $2 + ld [wSlotMachineWinningSymbol], a + ld hl, SlotRewardPointers + ld c, a + ld b, 0 + add hl, bc + ld a, [hli] + ld e, a + ld a, [hli] + ld d, a + push de + ld a, [hli] + ld h, [hl] + ld l, a + ld de, wcf4b + ld bc, 4 + call CopyData + pop hl + ld de, .flashScreenLoop + push de + jp hl + +.flashScreenLoop + ldh a, [rBGP] + xor $40 + ldh [rBGP], a + call UpdateGBCPal_BGP + ld c, 5 + call DelayFrames + dec b + jr nz, .flashScreenLoop + ld hl, wPayoutCoins + ld [hl], d + inc hl + ld [hl], e + call SlotMachine_PrintPayoutCoins + ld hl, SymbolLinedUpSlotMachineText + call PrintText + call WaitForTextScrollButtonPress + call SlotMachine_PayCoinsToPlayer + call SlotMachine_PrintPayoutCoins + ld a, $e4 + ldh [rOBP0], a + call UpdateGBCPal_OBP0 + jp .done + +SymbolLinedUpSlotMachineText: + text_asm + push bc + call SlotMachine_PrintWinningSymbol + ld hl, LinedUpText + pop bc + inc bc + inc bc + inc bc + inc bc + ret + +LinedUpText: + text_far _LinedUpText + text_end + +SlotRewardPointers: + dw SlotReward300Func + dw SlotReward300Text + dw SlotReward100Func + dw SlotReward100Text + dw SlotReward8Func + dw SlotReward8Text + dw SlotReward15Func + dw SlotReward15Text + dw SlotReward15Func + dw SlotReward15Text + dw SlotReward15Func + dw SlotReward15Text + +SlotReward300Text: + db "300@" + +SlotReward100Text: + db "100@" + +SlotReward8Text: + db "8@" + +SlotReward15Text: + db "15@" + +NotThisTimeText: + text_far _NotThisTimeText + text_end + +; compares the slot machine tiles at bc, de, and hl +SlotMachine_CheckForMatch: + ld a, [de] + cp [hl] + ret nz + ld a, [bc] + cp [hl] + ret + +SlotMachine_GetWheel3Tiles: + ld de, wSlotMachineWheel3BottomTile + ld hl, SlotMachineWheel3 + ld a, [wSlotMachineWheel3Offset] + call SlotMachine_GetWheelTiles + +SlotMachine_GetWheel2Tiles: + ld de, wSlotMachineWheel2BottomTile + ld hl, SlotMachineWheel2 + ld a, [wSlotMachineWheel2Offset] + call SlotMachine_GetWheelTiles + +SlotMachine_GetWheel1Tiles: + ld de, wSlotMachineWheel1BottomTile + ld hl, SlotMachineWheel1 + ld a, [wSlotMachineWheel1Offset] + +SlotMachine_GetWheelTiles: + ld c, a + ld b, 0 + add hl, bc + ld c, 3 +.loop + ld a, [hli] + ld [de], a + inc de + inc hl + dec c + jr nz, .loop + ret + +SlotReward8Func: + ld hl, wSlotMachineAllowMatchesCounter + ld a, [hl] + and a + jr z, .skip + dec [hl] +.skip + ld b, $2 + ld de, 8 + ret + +SlotReward15Func: + ld hl, wSlotMachineAllowMatchesCounter + ld a, [hl] + and a + jr z, .skip + dec [hl] +.skip + ld b, $4 + ld de, 15 + ret + +SlotReward100Func: + ld a, SFX_GET_KEY_ITEM + call PlaySound + xor a + ld [wSlotMachineFlags], a + ld b, $8 + ld de, 100 + ret + +SlotReward300Func: + ld hl, YeahText + call PrintText + ld a, SFX_GET_ITEM_2 + call PlaySound + call Random + cp $80 + ld a, $0 + jr c, .skip + ld [wSlotMachineFlags], a +.skip + ld [wSlotMachineAllowMatchesCounter], a + ld b, $14 + ld de, 300 + ret + +YeahText: + text_far _YeahText + text_pause + text_end + +SlotMachine_PrintWinningSymbol: +; prints winning symbol and down arrow in text box + hlcoord 2, 14 + ld a, [wSlotMachineWinningSymbol] + add $25 + ld [hli], a + inc a + ld [hld], a + inc a + ld de, -SCREEN_WIDTH + add hl, de + ld [hli], a + inc a + ld [hl], a + hlcoord 18, 16 + ld [hl], "▼" + ret + +SlotMachine_SubtractBetFromPlayerCoins: + ld hl, wTempCoins2 + 1 + ld a, [wSlotMachineBet] + ld [hld], a + xor a + ld [hli], a + ld de, wPlayerCoins + 1 + ld c, $2 + predef SubBCDPredef + +SlotMachine_PrintCreditCoins: + hlcoord 5, 1 + ld de, wPlayerCoins + ld c, $2 + jp PrintBCDNumber + +SlotMachine_PrintPayoutCoins: + hlcoord 11, 1 + ld de, wPayoutCoins + lb bc, LEADING_ZEROES | 2, 4 ; 2 bytes, 4 digits + jp PrintNumber + +SlotMachine_PayCoinsToPlayer: + ld a, $1 + ld [wMuteAudioAndPauseMusic], a + call WaitForSoundToFinish + +; Put 1 in the temp coins variable. This value is added to the player's coins +; repeatedly so the player can watch the value go up 1 coin at a time. + ld hl, wTempCoins1 + xor a + ld [hli], a + inc a + ld [hl], a + + ld a, 5 + ld [wAnimCounter], a + +; Subtract 1 from the payout amount and add 1 to the player's coins each +; iteration until the payout amount reaches 0. +.loop + ld a, [wPayoutCoins + 1] + ld l, a + ld a, [wPayoutCoins] + ld h, a + or l + ret z + ld de, -1 + add hl, de + ld a, l + ld [wPayoutCoins + 1], a + ld a, h + ld [wPayoutCoins], a + ld hl, wTempCoins1 + 1 + ld de, wPlayerCoins + 1 + ld c, $2 + predef AddBCDPredef + call SlotMachine_PrintCreditCoins + call SlotMachine_PrintPayoutCoins + ld a, SFX_SLOTS_REWARD + call PlaySound + ld a, [wAnimCounter] + dec a + jr nz, .skip1 + ldh a, [rOBP0] + xor $40 ; make the slot wheel symbols flash + ldh [rOBP0], a + call UpdateGBCPal_OBP0 + ld a, 5 +.skip1 + ld [wAnimCounter], a + ld a, [wSlotMachineWinningSymbol] + cp HIGH(SLOTSBAR) + 1 + ld c, 8 + jr nc, .skip2 + srl c ; c = 4 (make the the coins transfer faster if the symbol was 7 or bar) +.skip2 + call DelayFrames + jr .loop + +SlotMachine_PutOutLitBalls: + ld a, $23 + ld [wNewSlotMachineBallTile], a + jr SlotMachine_UpdateThreeCoinBallTiles + +SlotMachine_LightBalls: + ld a, $14 + ld [wNewSlotMachineBallTile], a + ld a, [wSlotMachineBet] + dec a + jr z, SlotMachine_UpdateOneCoinBallTiles + dec a + jr z, SlotMachine_UpdateTwoCoinBallTiles + +SlotMachine_UpdateThreeCoinBallTiles: + hlcoord 3, 2 + call SlotMachine_UpdateBallTiles + hlcoord 3, 10 + call SlotMachine_UpdateBallTiles + +SlotMachine_UpdateTwoCoinBallTiles: + hlcoord 3, 4 + call SlotMachine_UpdateBallTiles + hlcoord 3, 8 + call SlotMachine_UpdateBallTiles + +SlotMachine_UpdateOneCoinBallTiles: + hlcoord 3, 6 + +SlotMachine_UpdateBallTiles: + ld a, [wNewSlotMachineBallTile] + ld [hl], a + ld bc, 13 + add hl, bc + ld [hl], a + ld bc, 7 + add hl, bc + inc a + ld [hl], a + ld bc, 13 + add hl, bc + ld [hl], a + ret + +SlotMachine_AnimWheel1: + ld bc, SlotMachineWheel1 + ld de, wSlotMachineWheel1Offset + ld hl, wOAMBuffer + ld a, $30 + ld [wBaseCoordX], a + jr SlotMachine_AnimWheel + +SlotMachine_AnimWheel2: + ld bc, SlotMachineWheel2 + ld de, wSlotMachineWheel2Offset + ld hl, wOAMBuffer + $30 + ld a, $50 + ld [wBaseCoordX], a + jr SlotMachine_AnimWheel + +SlotMachine_AnimWheel3: + ld bc, SlotMachineWheel3 + ld de, wSlotMachineWheel3Offset + ld hl, wOAMBuffer + $60 + ld a, $70 + ld [wBaseCoordX], a + +SlotMachine_AnimWheel: + ld a, $58 + ld [wBaseCoordY], a + push de + ld a, [de] + ld d, b + add c + ld e, a + jr nc, .loop + inc d +.loop + ld a, [wBaseCoordY] + ld [hli], a + ld a, [wBaseCoordX] + ld [hli], a + ld a, [de] + ld [hli], a + ld a, $80 + ld [hli], a + ld a, [wBaseCoordY] + ld [hli], a + ld a, [wBaseCoordX] + add $8 + ld [hli], a + ld a, [de] + inc a + ld [hli], a + ld a, $80 + ld [hli], a + inc de + ld a, [wBaseCoordY] + sub $8 + ld [wBaseCoordY], a + cp $28 + jr nz, .loop + pop de + ld a, [de] + inc a ; advance the offset so that the wheel animates + cp 30 + jr nz, .skip + xor a ; wrap around to 0 when the offset reaches 30 +.skip + ld [de], a + ret + +SlotMachine_HandleInputWhileWheelsSpin: + call DelayFrame + call JoypadLowSensitivity + ldh a, [hJoy5] + and A_BUTTON + ret z + ld hl, wStoppingWhichSlotMachineWheel + ld a, [hl] + dec a + ld de, wSlotMachineWheel1SlipCounter + jr z, .skip + dec a + ld de, wSlotMachineWheel2SlipCounter + jr z, .skip +.loop + inc [hl] + ld a, SFX_SLOTS_STOP_WHEEL + jp PlaySound +.skip + ld a, [de] + and a + ret nz + jr .loop + +LoadSlotMachineTiles: + call DisableLCD + ld hl, SlotMachineTiles2 + ld de, vChars0 + ld bc, $1c tiles ; should be SlotMachineTiles2End - SlotMachineTiles2, or $18 tiles + ld a, BANK(SlotMachineTiles2) + call FarCopyData + ld hl, SlotMachineTiles1 + ld de, vChars2 + ld bc, SlotMachineTiles1End - SlotMachineTiles1 + ld a, BANK(SlotMachineTiles1) + call FarCopyData + ld hl, SlotMachineTiles2 + ld de, vChars2 tile $25 + ld bc, $1c tiles ; should be SlotMachineTiles2End - SlotMachineTiles2, or $18 tiles + ld a, BANK(SlotMachineTiles2) + call FarCopyData + ld hl, SlotMachineMap + decoord 0, 0 + ld bc, SlotMachineMapEnd - SlotMachineMap + call CopyData + call EnableLCD + ld hl, wSlotMachineWheel1Offset + ld a, $1c + ld [hli], a + ld [hli], a + ld [hl], a + call SlotMachine_AnimWheel1 + call SlotMachine_AnimWheel2 + jp SlotMachine_AnimWheel3 + +SlotMachineMap: + INCBIN "gfx/slots/slots.tilemap" +SlotMachineMapEnd: + +INCLUDE "data/events/slot_machine_wheels.asm" + +SlotMachineTiles1: + INCBIN "gfx/slots/slots_1.2bpp" +SlotMachineTiles1End: diff --git a/engine/special_warps.asm b/engine/special_warps.asm deleted file mode 100644 index 3a8b8b86..00000000 --- a/engine/special_warps.asm +++ /dev/null @@ -1,149 +0,0 @@ -SpecialWarpIn: - call LoadSpecialWarpData - predef LoadTilesetHeader - ld hl, wd732 - bit 2, [hl] ; dungeon warp or fly warp? - res 2, [hl] - jr z, .next -; if dungeon warp or fly warp - ld a, [wDestinationMap] - jr .next2 -.next - bit 1, [hl] - jr z, .next3 - call EmptyFunc -.next3 - ld a, 0 -.next2 - ld b, a - ld a, [wd72d] - and a - jr nz, .next4 - ld a, b -.next4 - ld hl, wd732 - bit 4, [hl] ; dungeon warp? - ret nz -; if not dungeon warp - ld [wLastMap], a - ret - -; gets the map ID, tile block map view pointer, tileset, and coordinates -LoadSpecialWarpData: - ld a, [wd72d] - cp TRADE_CENTER - jr nz, .notTradeCenter - ld hl, TradeCenterSpec1 - ld a, [hSerialConnectionStatus] - cp USING_INTERNAL_CLOCK ; which gameboy is clocking determines who is on the left and who is on the right - jr z, .copyWarpData - ld hl, TradeCenterSpec2 - jr .copyWarpData -.notTradeCenter - cp COLOSSEUM - jr nz, .notColosseum - ld hl, ColosseumSpec1 - ld a, [hSerialConnectionStatus] - cp USING_INTERNAL_CLOCK - jr z, .copyWarpData - ld hl, ColosseumSpec2 - jr .copyWarpData -.notColosseum - ld a, [wd732] - bit 1, a - jr nz, .notFirstMap - bit 2, a - jr nz, .notFirstMap - ld hl, FirstMapSpec -.copyWarpData - ld de, wCurMap - ld c, $7 -.copyWarpDataLoop - ld a, [hli] - ld [de], a - inc de - dec c - jr nz, .copyWarpDataLoop - ld a, [hli] - ld [wCurMapTileset], a - xor a - jr .done -.notFirstMap - ld a, [wLastMap] ; this value is overwritten before it's ever read - ld hl, wd732 - bit 4, [hl] ; used dungeon warp (jumped down hole/waterfall)? - jr nz, .usedDunegonWarp - bit 6, [hl] ; return to last pokemon center (or player's house)? - res 6, [hl] - jr z, .otherDestination -; return to last pokemon center or player's house - ld a, [wLastBlackoutMap] - jr .usedFlyWarp -.usedDunegonWarp - ld hl, wd72d - res 4, [hl] - ld a, [wDungeonWarpDestinationMap] - ld b, a - ld [wCurMap], a - ld a, [wWhichDungeonWarp] - ld c, a - ld hl, DungeonWarpList - ld de, 0 - ld a, 6 - ld [wDungeonWarpDataEntrySize], a -.dungeonWarpListLoop - ld a, [hli] - cp b - jr z, .matchedDungeonWarpDestinationMap - inc hl - jr .nextDungeonWarp -.matchedDungeonWarpDestinationMap - ld a, [hli] - cp c - jr z, .matchedDungeonWarpID -.nextDungeonWarp - ld a, [wDungeonWarpDataEntrySize] - add e - ld e, a - jr .dungeonWarpListLoop -.matchedDungeonWarpID - ld hl, DungeonWarpData - add hl, de - jr .copyWarpData2 -.otherDestination - ld a, [wDestinationMap] -.usedFlyWarp - ld b, a - ld [wCurMap], a - ld hl, FlyWarpDataPtr -.flyWarpDataPtrLoop - ld a, [hli] - inc hl - cp b - jr z, .foundFlyWarpMatch - inc hl - inc hl - jr .flyWarpDataPtrLoop -.foundFlyWarpMatch - ld a, [hli] - ld h, [hl] - ld l, a -.copyWarpData2 - ld de, wCurrentTileBlockMapViewPointer - ld c, $6 -.copyWarpDataLoop2 - ld a, [hli] - ld [de], a - inc de - dec c - jr nz, .copyWarpDataLoop2 - xor a ; OVERWORLD - ld [wCurMapTileset], a -.done - ld [wYOffsetSinceLastSpecialWarp], a - ld [wXOffsetSinceLastSpecialWarp], a - ld a, $ff ; the player's coordinates have already been updated using a special warp, so don't use any of the normal warps - ld [wDestinationWarpID], a - ret - -INCLUDE "data/special_warps.asm" diff --git a/engine/status_ailments.asm b/engine/status_ailments.asm deleted file mode 100755 index 787533c4..00000000 --- a/engine/status_ailments.asm +++ /dev/null @@ -1,46 +0,0 @@ -PrintStatusAilment: - ld a, [de] - bit PSN, a - jr nz, .psn - bit BRN, a - jr nz, .brn - bit FRZ, a - jr nz, .frz - bit PAR, a - jr nz, .par - and SLP - ret z - ld a, "S" - ld [hli], a - ld a, "L" - ld [hli], a - ld [hl], "P" - ret -.psn - ld a, "P" - ld [hli], a - ld a, "S" - ld [hli], a - ld [hl], "N" - ret -.brn - ld a, "B" - ld [hli], a - ld a, "R" - ld [hli], a - ld [hl], "N" - ret -.frz - ld a, "F" - ld [hli], a - ld a, "R" - ld [hli], a - ld [hl], "Z" - ret -.par - ld a, "P" - ld [hli], a - ld a, "A" - ld [hli], a - ld [hl], "R" - ret diff --git a/engine/subtract_paid_money.asm b/engine/subtract_paid_money.asm deleted file mode 100644 index a6a6ec2e..00000000 --- a/engine/subtract_paid_money.asm +++ /dev/null @@ -1,17 +0,0 @@ -; subtracts the amount the player paid from their money -; sets carry flag if there is enough money and unsets carry flag if not -SubtractAmountPaidFromMoney_: - ld de, wPlayerMoney - ld hl, hMoney ; total price of items - ld c, 3 ; length of money in bytes - call StringCmp - ret c - ld de, wPlayerMoney + 2 - ld hl, hMoney + 2 ; total price of items - ld c, 3 ; length of money in bytes - predef SubBCDPredef ; subtract total price from money - ld a, MONEY_BOX - ld [wTextBoxID], a - call DisplayTextBoxID ; redraw money text box - and a - ret diff --git a/engine/surfing_minigame.asm b/engine/surfing_minigame.asm index b89d22dc..578e6b1e 100755 --- a/engine/surfing_minigame.asm +++ b/engine/surfing_minigame.asm @@ -3,52 +3,52 @@ SurfingPikachuMinigame: call DelayFrame call DelayFrame call DelayFrame - ld a, [hTilesetType] + ldh a, [hTilesetType] push af xor a - ld [hTilesetType], a + ldh [hTilesetType], a ld a, [wUpdateSpritesEnabled] push af ld a, $ff ld [wUpdateSpritesEnabled], a - ld a, [rIE] + ldh a, [rIE] push af xor a - ld [rIF], a + ldh [rIF], a ld a, $f - ld [rIE], a + ldh [rIE], a ld a, $8 - ld [rSTAT], a - ld a, [H_AUTOBGTRANSFERDEST + 1] + ldh [rSTAT], a + ldh a, [hAutoBGTransferDest + 1] push af ld a, $98 - ld [H_AUTOBGTRANSFERDEST + 1], a + ldh [hAutoBGTransferDest + 1], a call SurfingPikachuMinigameIntro call SurfingPikachuLoop xor a - ld [rBGP], a - ld [rOBP0], a - ld [rOBP1], a + ldh [rBGP], a + ldh [rOBP0], a + ldh [rOBP1], a call UpdateGBCPal_BGP call UpdateGBCPal_OBP0 call UpdateGBCPal_OBP1 call ClearObjectAnimationBuffers call ClearSprites xor a - ld [hLCDCPointer], a - ld [hSCX], a - ld [hSCY], a + ldh [hLCDCPointer], a + ldh [hSCX], a + ldh [hSCY], a ld a, $90 - ld [hWY], a + ldh [hWY], a call DelayFrame pop af - ld [H_AUTOBGTRANSFERDEST + 1], a + ldh [hAutoBGTransferDest + 1], a xor a - ld [rIF], a + ldh [rIF], a pop af - ld [rIE], a + ldh [rIE], a xor a - ld [rSTAT], a + ldh [rSTAT], a call RunDefaultPaletteCommand call ReloadMapAfterSurfingMinigame call PlayDefaultMusic @@ -56,7 +56,7 @@ SurfingPikachuMinigame: pop af ld [wUpdateSpritesEnabled], a pop af - ld [hTilesetType], a + ldh [hTilesetType], a ret SurfingPikachuLoop: @@ -88,12 +88,12 @@ SurfingPikachu_CheckPressedSelect: ld hl, wd492 bit 1, [hl] ret z - ld a, [hJoyPressed] + ldh a, [hJoyPressed] and SELECT ret Func_f80b7: - ld a, [hJoyPressed] + ldh a, [hJoyPressed] and START ret z ld hl, wc5e2 @@ -175,7 +175,7 @@ SurfingPikachuMinigame_LoadGFXAndLayout: xor a call FillMemory xor a - ld [H_AUTOBGTRANSFERENABLED], a + ldh [hAutoBGTransferEnabled], a call ClearObjectAnimationBuffers ld hl, SurfingPikachu1Graphics1 @@ -230,12 +230,12 @@ SurfingPikachuMinigame_LoadGFXAndLayout: call SurfingMinigame_InitScanlineOverrides xor a - ld [hSCX], a - ld [hSCY], a + ldh [hSCX], a + ldh [hSCY], a ld a, $7e - ld [hWY], a + ldh [hWY], a ld a, rSCY - $ff00 - ld [hLCDCPointer], a + ldh [hLCDCPointer], a ld a, $40 ld [wSurfingMinigamePikachuSpeed], a xor a @@ -251,12 +251,12 @@ SurfingPikachuMinigame_LoadGFXAndLayout: call Func_f81ff call Func_f8256 ld a, $e3 - ld [rLCDC], a + ldh [rLCDC], a call SurfingPikachuMinigame_SetBGPals ld a, $e4 - ld [rOBP0], a + ldh [rOBP0], a ld a, $e0 - ld [rOBP1], a + ldh [rOBP1], a call UpdateGBCPal_OBP0 call UpdateGBCPal_OBP1 ret @@ -266,13 +266,13 @@ SurfingPikachuMinigame_SetBGPals: and a jr nz, .sgb ld a, $d0 - ld [rBGP], a + ldh [rBGP], a call UpdateGBCPal_BGP ret .sgb ld a, $e4 - ld [rBGP], a + ldh [rBGP], a call UpdateGBCPal_BGP ret @@ -479,31 +479,31 @@ Func_f8324: ld hl, wSurfingMinigameRoutineNumber inc [hl] ld a, $90 - ld [hSCX], a + ldh [hSCX], a ld a, $72 ld [wSurfingMinigameWaveFunctionNumber], a ld a, $4 ld [wc5d2], a xor a - ld [hLCDCPointer], a + ldh [hLCDCPointer], a ld [wSurfingMinigameSCX], a ld [wSurfingMinigameSCX + 1], a ld [wSurfingMinigameSCX + 2], a ret Func_f835c: - ld a, [hSCX] + ldh a, [hSCX] and a jr z, .asm_f837b call SurfingMinigame_UpdateLYOverrides call SurfingMinigame_SetPikachuHeight call SurfingMinigame_ReadBGMapBuffer - ld a, [hSCX] + ldh a, [hSCX] dec a dec a dec a dec a - ld [hSCX], a + ldh [hSCX], a ld a, $e0 ld [wSurfingMinigameXOffset], a call SurfingMinigame_GenerateBGMap @@ -599,7 +599,7 @@ SurfingMinigame_WaitLast: SurfingMinigame_ExitOnPressA: call SurfingMinigame_UpdateLYOverrides - ld a, [hJoyPressed] + ldh a, [hJoyPressed] and A_BUTTON ret z ld hl, wSurfingMinigameRoutineNumber @@ -620,7 +620,7 @@ SurfingMinigame_GameOver: ret .wait_press_a - ld a, [hJoyPressed] + ldh a, [hJoyPressed] and A_BUTTON ret z ld hl, wSurfingMinigameRoutineNumber @@ -662,7 +662,7 @@ SurfingMinigame_UpdatePikachuDistance: dec [hl] ret -SurfingMinigameAnimatedObjectFn_Pikachu +SurfingMinigameAnimatedObjectFn_Pikachu: ld a, [wc5d2] ld e, a ld d, $0 @@ -1088,7 +1088,7 @@ SufingMinigame_ReduceSpeedBy128: ret Func_f871e: - ld a, [hSCX] + ldh a, [hSCX] and $7 cp $3 jr c, .asm_f8740 @@ -1110,7 +1110,7 @@ Func_f871e: ret Func_f8742: - ld a, [hSCX] + ldh a, [hSCX] and $7 cp $3 ret c @@ -1209,7 +1209,7 @@ Func_f87b5: ret .GetYCoord: - ld a, [hSCX] + ldh a, [hSCX] and $8 jr nz, .get_height_plus_9 ld hl, wSurfingMinigameWaveHeight + 8 @@ -1229,7 +1229,7 @@ Func_f87b5: ret .six_or_twenty - ld a, [hSCX] + ldh a, [hSCX] and $7 ld e, a ld a, [hl] @@ -1237,7 +1237,7 @@ Func_f87b5: ret .seven - ld a, [hSCX] + ldh a, [hSCX] and $7 add [hl] ret @@ -1328,7 +1328,7 @@ SurfingMinigame_MoveClouds: SurfingMinigame_ReadBGMapBuffer: ld a, [wSurfingMinigameBGMapReadBuffer] ; ??? - ld a, [hSCX] + ldh a, [hSCX] add $48 ld e, a srl e @@ -1358,19 +1358,19 @@ SurfingMinigame_ReadBGMapBuffer: .copy ld de, wSurfingMinigameBGMapReadBuffer ld a, e - ld [H_VBCOPYDEST], a + ldh [hVBlankCopyDest], a ld a, d - ld [H_VBCOPYDEST + 1], a + ldh [hVBlankCopyDest + 1], a ld a, l - ld [H_VBCOPYSRC], a + ldh [hVBlankCopySource], a ld a, h - ld [H_VBCOPYSRC + 1], a + ldh [hVBlankCopySource + 1], a ld a, 16 / $10 - ld [H_VBCOPYSIZE], a + ldh [hVBlankCopySize], a ret SurfingMinigame_SetPikachuHeight: - ld a, [hSCX] + ldh a, [hSCX] and $8 jr nz, .asm_f88b9 ld hl, wSurfingMinigameWaveHeight + 7 @@ -1391,7 +1391,7 @@ SurfingMinigame_SetPikachuHeight: ret .asm_f88d0 - ld a, [hSCX] + ldh a, [hSCX] and $7 ld e, a ld a, [hl] @@ -1400,7 +1400,7 @@ SurfingMinigame_SetPikachuHeight: ret .asm_f88db - ld a, [hSCX] + ldh a, [hSCX] and $7 add [hl] ld [wSurfingMinigamePikachuObjectHeight], a @@ -1457,7 +1457,7 @@ SurfingMinigame_DrawResultsScreen: xor a call FillMemory ld hl, .BeachTilemap - coord de, 0, 6 + decoord 0, 6 ld bc, .BeachTilemapEnd - .BeachTilemap call CopyData call .PlaceTextbox @@ -1466,7 +1466,7 @@ SurfingMinigame_DrawResultsScreen: xor a call FillMemory ld a, $1 - ld [H_AUTOBGTRANSFERENABLED], a + ldh [hAutoBGTransferEnabled], a ret .BeachTilemap: @@ -1474,39 +1474,39 @@ INCBIN "gfx/unknown_f8946.map" .BeachTilemapEnd: .PlaceTextbox: - coord hl, 1, 1 + hlcoord 1, 1 lb de, $3b, $3c ld a, $40 call .place_row - coord hl, 1, 2 + hlcoord 1, 2 lb de, $3f, $3f ld a, $ff call .place_row - coord hl, 1, 3 + hlcoord 1, 3 lb de, $3f, $3f ld a, $ff call .place_row - coord hl, 1, 4 + hlcoord 1, 4 lb de, $3f, $3f ld a, $ff call .place_row - coord hl, 1, 5 + hlcoord 1, 5 lb de, $3f, $3f ld a, $ff call .place_row - coord hl, 1, 6 + hlcoord 1, 6 lb de, $3f, $3f ld a, $ff call .place_row - coord hl, 1, 7 + hlcoord 1, 7 lb de, $3f, $3f ld a, $ff call .place_row - coord hl, 1, 8 + hlcoord 1, 8 lb de, $3f, $3f ld a, $ff call .place_row - coord hl, 1, 9 + hlcoord 1, 9 lb de, $3d, $3e ld a, $40 call .place_row @@ -1525,7 +1525,7 @@ INCBIN "gfx/unknown_f8946.map" SurfingMinigame_PrintTextHiScore: ld hl, .Hi_Score - coord de, 6, 8 + decoord 6, 8 ld bc, $9 call CopyData ret @@ -1535,7 +1535,7 @@ SurfingMinigame_PrintTextHiScore: SurfingMinigame_WriteHPLeft: ld hl, .HP_Left - coord de, 2, 2 + decoord 2, 2 ld bc, $7 call CopyData call SurfingMinigame_BCDPrintHPLeft @@ -1570,7 +1570,7 @@ SurfingMinigame_AddRemainingHPToTotal: ret SurfingMinigame_BCDPrintHPLeft: - coord hl, 10, 2 + hlcoord 10, 2 ld de, wSurfingMinigamePikachuHP + 1 ld a, [de] call SurfingPikachu_PlaceBCDNumber @@ -1588,7 +1588,7 @@ SurfingMinigame_BCDPrintHPLeft: SurfingMinigame_WriteRadness: ld hl, .Radness - coord de, 2, 4 + decoord 2, 4 ld bc, $7 call CopyData call SurfingMinigame_BCDPrintRadness @@ -1633,10 +1633,10 @@ SurfingMinigame_AddRadnessToTotal: SurfingMinigame_BCDPrintRadness: ld a, [wSurfingMinigameRadnessScore + 1] - coord hl, 10, 4 + hlcoord 10, 4 call SurfingPikachu_PlaceBCDNumber ld a, [wSurfingMinigameRadnessScore] - coord hl, 12, 4 + hlcoord 12, 4 call SurfingPikachu_PlaceBCDNumber inc hl inc hl @@ -1664,10 +1664,10 @@ SurfingMinigame_AddPointsToTotal: SurfingMinigame_BCDPrintTotalScore: ld a, [wSurfingMinigameTotalScore + 1] - coord hl, 10, 6 + hlcoord 10, 6 call SurfingPikachu_PlaceBCDNumber ld a, [wSurfingMinigameTotalScore] - coord hl, 12, 6 + hlcoord 12, 6 call SurfingPikachu_PlaceBCDNumber inc hl inc hl @@ -1680,7 +1680,7 @@ SurfingMinigame_BCDPrintTotalScore: SurfingMinigame_WriteTotal: ld hl, .Total - coord de, 2, 6 + decoord 2, 6 ld bc, $5 call CopyData call SurfingMinigame_BCDPrintRadness @@ -1723,10 +1723,10 @@ DidPlayerGetAHighScore: SurfingMinigame_PlayPikaCryIfSurfingPikaInParty: push de - callab IsSurfingPikachuInThePlayersParty + callfar IsSurfingPikachuInThePlayersParty pop de ret nc - callab PlayPikachuSoundClip + callfar PlayPikachuSoundClip ret SurfingMinigame_IncreaseRadnessMeter: @@ -1853,7 +1853,7 @@ SurfingMinigame_AddRadness: Func_f8c97: ld a, $a0 ld [wSurfingMinigameXOffset], a - ld a, [hSCX] + ldh a, [hSCX] ld h, a ld a, [wSurfingMinigameSCX] ld l, a @@ -1862,13 +1862,13 @@ Func_f8c97: ld a, l ld [wSurfingMinigameSCX], a ld a, h - ld [hSCX], a + ldh [hSCX], a jr SurfingMinigame_GenerateBGMap SurfingMinigame_ScrollAndGenerateBGMap: ld a, $a0 ld [wSurfingMinigameXOffset], a - ld a, [hSCX] + ldh a, [hSCX] ld h, a ld a, [wSurfingMinigameSCX] ld l, a @@ -1877,10 +1877,10 @@ SurfingMinigame_ScrollAndGenerateBGMap: ld a, l ld [wSurfingMinigameSCX], a ld a, h - ld [hSCX], a + ldh [hSCX], a SurfingMinigame_GenerateBGMap: ld hl, wSurfingMinigameSCX + 1 - ld a, [hSCX] + ldh a, [hSCX] cp [hl] ret z ld [hl], a @@ -1921,7 +1921,7 @@ SurfingMinigame_GenerateBGMap: jr nz, .loop ld a, [wSurfingMinigameXOffset] ld e, a - ld a, [hSCX] + ldh a, [hSCX] add e and $f0 srl a @@ -1932,11 +1932,11 @@ SurfingMinigame_GenerateBGMap: ld hl, vBGMap0 add hl, de ld a, l - ld [hRedrawRowOrColumnDest], a + ldh [hRedrawRowOrColumnDest], a ld a, h - ld [hRedrawRowOrColumnDest + 1], a + ldh [hRedrawRowOrColumnDest + 1], a ld a, $1 - ld [hRedrawRowOrColumnMode], a + ldh [hRedrawRowOrColumnMode], a ret .CopyRedrawSrcTiles: @@ -2330,7 +2330,7 @@ SurfingPikachuMinigameIntro: call ClearSprites call DisableLCD xor a - ld [H_AUTOBGTRANSFERENABLED], a + ldh [hAutoBGTransferEnabled], a call ClearObjectAnimationBuffers ld hl, SurfingPikachu1Graphics3 ld de, $8800 @@ -2358,24 +2358,24 @@ SurfingPikachuMinigameIntro: call SpawnAnimatedObject call DrawSurfingPikachuMinigameIntroBackground xor a - ld [hSCX], a - ld [hSCY], a + ldh [hSCX], a + ldh [hSCY], a ld a, $90 - ld [hWY], a + ldh [hWY], a ld b, $f call RunPaletteCommand ld a, $e3 - ld [rLCDC], a + ldh [rLCDC], a ld a, $1 - ld [H_AUTOBGTRANSFERENABLED], a + ldh [hAutoBGTransferEnabled], a call DelayFrame call DelayFrame call DelayFrame call SurfingPikachuMinigame_SetBGPals ld a, $e4 - ld [rOBP0], a + ldh [rOBP0], a ld a, $e0 - ld [rOBP1], a + ldh [rOBP1], a call UpdateGBCPal_OBP0 call UpdateGBCPal_OBP1 call DelayFrame @@ -2400,22 +2400,22 @@ DrawSurfingPikachuMinigameIntroBackground: ld a, $ff call FillMemory ld hl, Tilemap_f90bc - coord de, 0, 6 + decoord 0, 6 ld bc, 12 * SCREEN_WIDTH call CopyData ld de, Tilemap_f91c8 - coord hl, 4, 0 + hlcoord 4, 0 lb bc, 6, 12 call .CopyBox - coord hl, 3, 7 + hlcoord 3, 7 lb bc, 3, 15 call .FillBoxWithFF ld hl, Tilemap_f91ac - coord de, 3, 7 + decoord 3, 7 ld bc, 15 call CopyData ld hl, Tilemap_f91bb - coord de, 4, 9 + decoord 4, 9 ld bc, 13 call CopyData ret @@ -2499,25 +2499,25 @@ SurfingMinigame_InitScanlineOverrides: SurfingPikachu_GetJoypad_3FrameBuffer: call Joypad - ld a, [H_FRAMECOUNTER] + ldh a, [hFrameCounter] and a jr nz, .delayed - ld a, [hJoyHeld] - ld [hJoy5], a + ldh a, [hJoyHeld] + ldh [hJoy5], a ld a, $2 - ld [H_FRAMECOUNTER], a + ldh [hFrameCounter], a ret .delayed xor a - ld [hJoy5], a + ldh [hJoy5], a ret SurfingPikachuMinigame_BlankPals: xor a - ld [rBGP], a - ld [rOBP0], a - ld [rOBP1], a + ldh [rBGP], a + ldh [rOBP0], a + ldh [rOBP1], a call UpdateGBCPal_BGP call UpdateGBCPal_OBP0 call UpdateGBCPal_OBP1 @@ -2525,10 +2525,10 @@ SurfingPikachuMinigame_BlankPals: SurfingPikachuMinigame_NormalPals: ld a, $e4 - ld [rBGP], a - ld [rOBP0], a + ldh [rBGP], a + ldh [rOBP0], a ld a, $e0 - ld [rOBP1], a + ldh [rOBP1], a call UpdateGBCPal_BGP call UpdateGBCPal_OBP0 call UpdateGBCPal_OBP1 diff --git a/engine/test_battle.asm b/engine/test_battle.asm deleted file mode 100644 index d9dcf1fa..00000000 --- a/engine/test_battle.asm +++ /dev/null @@ -1,45 +0,0 @@ -TestBattle: - ret - -.loop - call GBPalNormal - - ; Don't mess around - ; with obedience. - ld a, %10000000 ; EARTHBADGE - ld [wObtainedBadges], a - - ld hl, wFlags_D733 - set BIT_TEST_BATTLE, [hl] - - ; Reset the party. - ld hl, wPartyCount - xor a - ld [hli], a - dec a - ld [hl], a - - ; Give the player a - ; level 20 Rhydon. - ld a, RHYDON - ld [wcf91], a - ld a, 20 - ld [wCurEnemyLVL], a - xor a - ld [wMonDataLocation], a - ld [wCurMap], a - call AddPartyMon - - ; Fight against a - ; level 20 Rhydon. - ld a, RHYDON - ld [wCurOpponent], a - - predef InitOpponent - - ; When the battle ends, - ; do it all again. - ld a, 1 - ld [wUpdateSpritesEnabled], a - ld [H_AUTOBGTRANSFERENABLED], a - jr .loop diff --git a/engine/titlescreen.asm b/engine/titlescreen.asm deleted file mode 100755 index d4dd0fd3..00000000 --- a/engine/titlescreen.asm +++ /dev/null @@ -1,370 +0,0 @@ -SetDefaultNamesBeforeTitlescreen: - ld hl, NintenText - ld de, wPlayerName - call CopyFixedLengthText - ld hl, SonyText - ld de, wRivalName - call CopyFixedLengthText - xor a - ld [hWY], a - ld [wLetterPrintingDelayFlags], a - ld hl, wd732 - ld [hli], a - ld [hli], a - ld [hl], a - ld a, BANK(Music_TitleScreen) - ld [wAudioROMBank], a - ld [wAudioSavedROMBank], a - -DisplayTitleScreen: - call GBPalWhiteOut - ld a, $1 - ld [H_AUTOBGTRANSFERENABLED], a - xor a - ld [hTilesetType], a - ld [hSCX], a - ld a, $40 - ld [hSCY], a - ld a, $90 - ld [hWY], a - call ClearScreen - call DisableLCD - call LoadFontTilePatterns -; todo: fix hl pointers - ld hl, NintendoCopyrightLogoGraphics - ld de, vTitleLogo + $600 - ld bc, $50 - ld a, BANK(NintendoCopyrightLogoGraphics) - call FarCopyData - ld hl, NineTile - ld de, vTitleLogo + $6e0 - ld bc, $10 - ld a, BANK(NineTile) - call FarCopyData - ld hl, GamefreakLogoGraphics - ld de, vTitleLogo + 101 * $10 - ld bc, 9 * $10 - ld a, BANK(GamefreakLogoGraphics) - call FarCopyData - callab LoadYellowTitleScreenGFX - ld hl, vBGMap0 - ld bc, (vBGMap1 + $400) - vBGMap0 - ld a, " " - call FillMemory - callab TitleScreen_PlacePokemonLogo - call FillSpriteBuffer0WithAA - call .WriteCopyrightTiles - call SaveScreenTilesToBuffer2 - call LoadScreenTilesFromBuffer2 - call EnableLCD - callab TitleScreen_PlacePikachu - ld a, $9b - call TitleScreenCopyTileMapToVRAM - call SaveScreenTilesToBuffer1 - ld a, $40 - ld [hWY], a - call LoadScreenTilesFromBuffer2 - ld a, vBGMap0 / $100 - call TitleScreenCopyTileMapToVRAM - ld b, SET_PAL_TITLE_SCREEN - call RunPaletteCommand - call GBPalNormal - ld a, %11100000 - ld [rOBP0], a - call UpdateGBCPal_OBP0 - -; make pokemon logo bounce up and down - ld bc, hSCY ; background scroll Y - ld hl, .TitleScreenPokemonLogoYScrolls -.bouncePokemonLogoLoop - ld a, [hli] - and a - jr z, .finishedBouncingPokemonLogo - ld d, a - cp -3 - jr nz, .skipPlayingSound - ld a, SFX_INTRO_CRASH - call PlaySound -.skipPlayingSound - ld a, [hli] - ld e, a - call .ScrollTitleScreenPokemonLogo - jr .bouncePokemonLogoLoop - -.TitleScreenPokemonLogoYScrolls: -; Controls the bouncing effect of the Pokemon logo on the title screen - db -4,16 ; y scroll amount, number of times to scroll - db 3,4 - db -3,4 - db 2,2 - db -2,2 - db 1,2 - db -1,2 - db 0 ; terminate list with 0 - -.ScrollTitleScreenPokemonLogo: -; Scrolls the Pokemon logo on the title screen to create the bouncing effect -; Scrolls d pixels e times - call DelayFrame - ld a, [bc] ; background scroll Y - add d - ld [bc], a - dec e - jr nz, .ScrollTitleScreenPokemonLogo - ret - -; place tiles for title screen copyright -.WriteCopyrightTiles - coord hl, 2, 17 - ld de, .tileScreenCopyrightTiles -.titleScreenCopyrightTilesLoop - ld a, [de] - inc de - cp $ff - ret z - ld [hli], a - jr .titleScreenCopyrightTilesLoop - -.tileScreenCopyrightTiles - db $e0,$e1,$e2,$e3,$e1,$e2,$ee,$e5,$e6,$e7,$e8,$e9,$ea,$eb,$ec,$ed,$ff ; ©1995-1999 GAME FREAK inc. - -.finishedBouncingPokemonLogo - call LoadScreenTilesFromBuffer1 - ld c, 36 - call DelayFrames - ld a, SFX_INTRO_WHOOSH - call PlaySound - -; scroll game version in from the right - callab TitleScreen_PlacePikaSpeechBubble - ld a, SCREEN_HEIGHT_PIXELS - ld [hWY], a - call Delay3 - ld e, 0 - call TitleScreen_PlayPikachuPCM - call WaitForSoundToFinish - call StopAllMusic - ld a, MUSIC_TITLE_SCREEN - ld [wNewSoundID], a - call PlaySound -.loop - xor a - ld [wUnusedCC5B], a - ld [wTitleScreenScene], a - ld [wTitleScreenScene + 1], a - ld [wTitleScreenScene + 2], a - ld [wTitleScreenScene + 3], a - ld a, $f - ld [wTitleScreenScene + 4], a -.titleScreenLoop - call IncrementResetCounter - jp c, .doTitlescreenReset - call DelayFrame - call JoypadLowSensitivity - ld a, [hJoyHeld] - cp D_UP | SELECT | B_BUTTON - jr z, .go_to_main_menu - and A_BUTTON | START - jr nz, .go_to_main_menu - call DoTitleScreenFunction - jr .titleScreenLoop - -.go_to_main_menu - ld e, $a - call TitleScreen_PlayPikachuPCM - call GBPalWhiteOutWithDelay3 - call ClearSprites - xor a - ld [hWY], a - inc a - ld [H_AUTOBGTRANSFERENABLED], a - call ClearScreen - ld a, vBGMap0 / $100 - call TitleScreenCopyTileMapToVRAM - ld a, vBGMap1 / $100 - call TitleScreenCopyTileMapToVRAM - call Delay3 - call LoadGBPal - ld a, [hJoyHeld] - ld b, a - and D_UP | SELECT | B_BUTTON - cp D_UP | SELECT | B_BUTTON - jp z, .doClearSaveDialogue - jp MainMenu - -.asm_42f0 -; unreferenced - callab PrinterDebug - jp .loop - -.asm_42fb -; unreferenced - ld a, [wTitleScreenScene + 4] - inc a - cp $2a - jr c, .asm_4305 - ld a, $f -.asm_4305 - ld [wTitleScreenScene + 4], a - ld e, a - callab PlayPikachuSoundClip - xor a - ld [wTitleScreenScene + 2], a - ld [wTitleScreenScene + 3], a - jp .titleScreenLoop - -.doTitlescreenReset - ld [wAudioFadeOutControl], a - call StopAllMusic -.audioFadeLoop - ld a, [wAudioFadeOutControl] - and a - jr nz, .audioFadeLoop - jp Init - -.doClearSaveDialogue - jpba DoClearSaveDialogue - - -TitleScreenCopyTileMapToVRAM: - ld [H_AUTOBGTRANSFERDEST + 1], a - jp Delay3 - -LoadCopyrightAndTextBoxTiles: - xor a - ld [hWY], a - call ClearScreen - call LoadTextBoxTilePatterns - -LoadCopyrightTiles: - ld de, NintendoCopyrightLogoGraphics - ld hl, vChars2 + $600 - lb bc, BANK(NintendoCopyrightLogoGraphics), (TextBoxGraphics + $10 - NintendoCopyrightLogoGraphics) / $10 ; bug: overflows into text box graphics and copies the "A" tile - call CopyVideoData - coord hl, 2, 7 - ld de, CopyrightTextString - jp PlaceString - -CopyrightTextString: - db $60,$61,$62,$63,$61,$62,$7c,$7f,$65,$66,$67,$68,$69,$6a ; ©1995-1999 Nintendo - next $60,$61,$62,$63,$61,$62,$7c,$7f,$6b,$6c,$6d,$6e,$6f,$70,$71,$72 ; ©1995-1999 Creatures inc. - next $60,$61,$62,$63,$61,$62,$7c,$7f,$73,$74,$75,$76,$77,$78,$79,$7a,$7b ; ©1995-1999 GAME FREAK inc. - db "@" - -TitleScreen_PlayPikachuPCM: - callab PlayPikachuSoundClip - ret - -DoTitleScreenFunction: - call .CheckTimer - ld a, [wTitleScreenScene] - ld e, a - ld d, 0 - ld hl, .Jumptable - add hl, de - add hl, de - ld a, [hli] - ld h, [hl] - ld l, a - jp hl - - -.Jumptable: - dw .Nop - dw .BlinkHalf - dw .BlinkWait - dw .BlinkWait - dw .BlinkClosed - dw .BlinkWait - dw .BlinkWait - dw .BlinkHalf - dw .BlinkWait - dw .BlinkWait - dw .BlinkOpen - dw .GoBackToStart - -.GoBackToStart: - xor a - ld [wTitleScreenScene], a -.Nop - ret - -.BlinkOpen: - ld e, 0 - jr .LoadBlinkFrame - -.BlinkHalf: - ld e, 4 - jr .LoadBlinkFrame - -.BlinkClosed: - ld e, 8 -.LoadBlinkFrame: - ld hl, wOAMBuffer + 2 - ld c, 8 -.loop - ld a, [hl] - and $f3 - or e - ld [hli], a - inc hl - inc hl - inc hl - dec c - jr nz, .loop -.BlinkWait: - ld hl, wTitleScreenScene - inc [hl] - ret - -.CheckTimer: - ld hl, wTitleScreenTimer - ld a, [hl] - inc [hl] - and a - jr z, .restart - cp $80 - jr z, .restart - cp $90 - ret nz -.restart - ld a, $1 - ld [wTitleScreenScene], a - ret - -; copy text of fixed length NAME_LENGTH (like player name, rival name, mon names, ...) -CopyFixedLengthText: - ld bc, NAME_LENGTH - jp CopyData - -NintenText: db "NINTEN@" -SonyText: db "SONY@" - -IncrementResetCounter: - ld hl, wTitleScreenScene + 2 - ld e, [hl] - inc hl - ld d, [hl] - inc de - ld a, d - cp $c - jr z, .doReset - ld [hl], d - dec hl - ld [hl], e - and a - ret - -.doReset - scf - ret - -FillSpriteBuffer0WithAA: - xor a - call SwitchSRAMBankAndLatchClockData - ld hl, sSpriteBuffer0 - ld bc, $20 - ld a, $aa - call FillMemory - call PrepareRTCDataAndDisableSRAM - ret diff --git a/engine/titlescreen2.asm b/engine/titlescreen2.asm deleted file mode 100755 index 8b4bc4de..00000000 --- a/engine/titlescreen2.asm +++ /dev/null @@ -1,122 +0,0 @@ -; Leftover of Red/Blue. Seemingly unused - -TitleScroll_WaitBall: -; Wait around for the TitleBall animation to play out. -; hi: speed -; lo: duration - db $05, $05, 0 - -TitleScroll_In: -; Scroll a TitleMon in from the right. -; hi: speed -; lo: duration - db $a2, $94, $84, $63, $52, $31, $11, 0 - -TitleScroll_Out: -; Scroll a TitleMon out to the left. -; hi: speed -; lo: duration - db $12, $22, $32, $42, $52, $62, $83, $93, 0 - -TitleScroll: - ld a, d - - ld bc, TitleScroll_In - ld d, $88 - ld e, 0 ; don't animate titleball - - and a - jr nz, .ok - - ld bc, TitleScroll_Out - ld d, $00 - ld e, 0 ; don't animate titleball -.ok - -_TitleScroll: - ld a, [bc] - and a - ret z - - inc bc - push bc - - ld b, a - and $f - ld c, a - ld a, b - and $f0 - swap a - ld b, a - -.loop - ld h, d - ld l, $48 - call .ScrollBetween - - ld h, $00 - ld l, $88 - call .ScrollBetween - - ld a, d - add b - ld d, a - - call GetTitleBallY - dec c - jr nz, .loop - - pop bc - jr _TitleScroll - -.ScrollBetween: -.wait - ld a, [rLY] ; rLY - cp l - jr nz, .wait - - ld a, h - ld [rSCX], a - -.wait2 - ld a, [rLY] ; rLY - cp h - jr z, .wait2 - ret - -TitleBallYTable: -; OBJ y-positions for the Poke Ball held by Red in the title screen. -; This is really two 0-terminated lists. Initiated with an index of 1. - db 0, $71, $6f, $6e, $6d, $6c, $6d, $6e, $6f, $71, $74, 0 - -TitleScreenAnimateBallIfStarterOut: -; Animate the TitleBall if a starter just got scrolled out. - ld a, [wTitleScreenScene] - cp STARTER1 - jr z, .ok - cp STARTER2 - jr z, .ok - cp STARTER3 - ret nz -.ok - ld e, 1 ; animate titleball - ld bc, TitleScroll_WaitBall - ld d, 0 - jp _TitleScroll - -GetTitleBallY: -; Get position e from TitleBallYTable - push de - push hl - xor a - ld d, a - ld hl, TitleBallYTable - add hl, de - ld a, [hl] - pop hl - pop de - and a - ret z - ld [wOAMBuffer + $28], a - inc e - ret diff --git a/engine/town_map.asm b/engine/town_map.asm deleted file mode 100755 index 7d32b5fe..00000000 --- a/engine/town_map.asm +++ /dev/null @@ -1,628 +0,0 @@ -DisplayTownMap: - call LoadTownMap - ld hl, wUpdateSpritesEnabled - ld a, [hl] - push af - ld [hl], $ff - push hl - ld a, $1 - ld [hJoy7], a - ld a, [wCurMap] - push af - ld b, $0 - call DrawPlayerOrBirdSprite ; player sprite - coord hl, 1, 0 - ld de, wcd6d - call PlaceString - ld hl, wOAMBuffer - ld de, wTileMapBackup - ld bc, $10 - call CopyData - ld hl, vSprites + $40 - ld de, TownMapCursor - lb bc, BANK(TownMapCursor), (TownMapCursorEnd - TownMapCursor) / $8 - call CopyVideoDataDouble - xor a - ld [wWhichTownMapLocation], a - pop af - jr .enterLoop - -.townMapLoop - coord hl, 0, 0 - lb bc, 1, 20 - call ClearScreenArea - ld hl, TownMapOrder - ld a, [wWhichTownMapLocation] - ld c, a - ld b, 0 - add hl, bc - ld a, [hl] -.enterLoop - ld de, wTownMapCoords - call LoadTownMapEntry - ld a, [de] - push hl - call TownMapCoordsToOAMCoords - ld a, $4 - ld [wOAMBaseTile], a - ld hl, wOAMBuffer + $10 - call WriteTownMapSpriteOAM ; town map cursor sprite - pop hl - ld de, wcd6d -.copyMapName - ld a, [hli] - ld [de], a - inc de - cp $50 - jr nz, .copyMapName - coord hl, 1, 0 - ld de, wcd6d - call PlaceString - ld hl, wOAMBuffer + $10 - ld de, wTileMapBackup + 16 - ld bc, $10 - call CopyData -.inputLoop - call TownMapSpriteBlinkingAnimation - call JoypadLowSensitivity - ld a, [hJoy5] - ld b, a - and A_BUTTON | B_BUTTON | D_UP | D_DOWN - jr z, .inputLoop - ld a, SFX_TINK - call PlaySound - bit 6, b - jr nz, .pressedUp - bit 7, b - jr nz, .pressedDown - xor a - ld [wTownMapSpriteBlinkingEnabled], a - ld [hJoy7], a - ld [wAnimCounter], a - call ExitTownMap - pop hl - pop af - ld [hl], a - ret -.pressedUp - ld a, [wWhichTownMapLocation] - inc a - cp TownMapOrderEnd - TownMapOrder ; number of list items + 1 - jr nz, .noOverflow - xor a -.noOverflow - ld [wWhichTownMapLocation], a - jp .townMapLoop -.pressedDown - ld a, [wWhichTownMapLocation] - dec a - cp -1 - jr nz, .noUnderflow - ld a, TownMapOrderEnd - TownMapOrder - 1 ; number of list items -.noUnderflow - ld [wWhichTownMapLocation], a - jp .townMapLoop - -.asm_70f87 - ld a,[hJoy5] - and D_DOWN | D_UP - ret z - callab PlayPikachuSoundClip - ret - -INCLUDE "data/town_map_order.asm" - -TownMapCursor: - INCBIN "gfx/town_map_cursor.1bpp" -TownMapCursorEnd: - -LoadTownMap_Nest: - call LoadTownMap - ld hl, wUpdateSpritesEnabled - ld a, [hl] - push af - ld [hl], $ff - push hl - call DisplayWildLocations - call GetMonName - coord hl, 1, 0 - call PlaceString - ld h, b - ld l, c - ld de, MonsNestText - call PlaceString - call WaitForTextScrollButtonPress - call ExitTownMap - pop hl - pop af - ld [hl], a - ret - -MonsNestText: - db "'s NEST@" - -LoadTownMap_Fly: - call ClearSprites - call LoadTownMap - ld a, $1 - ld [hJoy7], a - call LoadPlayerSpriteGraphics - call LoadFontTilePatterns - ld de, BirdSprite - ld b, BANK(BirdSprite) - ld c, $c - ld hl, vSprites + $40 - call CopyVideoData - ld de, TownMapUpArrow - ld hl, vChars1 + $6d0 - lb bc, BANK(TownMapUpArrow), (TownMapUpArrowEnd - TownMapUpArrow) / $8 - call CopyVideoDataDouble - call BuildFlyLocationsList - ld hl, wUpdateSpritesEnabled - ld a, [hl] - push af - ld [hl], $ff - push hl - coord hl, 0, 0 - ld de, ToText - call PlaceString - ld a, [wCurMap] - ld b, $0 - call DrawPlayerOrBirdSprite - ld hl, wFlyLocationsList - coord de, 18, 0 -.townMapFlyLoop - ld a, " " - ld [de], a - push hl - push hl - coord hl, 3, 0 - lb bc, 1, 15 - call ClearScreenArea - pop hl - ld a, [hl] - ld b, $4 - call DrawPlayerOrBirdSprite ; draw bird sprite - coord hl, 3, 0 - ld de, wcd6d - call PlaceString - ld c, 15 - call DelayFrames - coord hl, 18, 0 - ld [hl], "▶" - coord hl, 19, 0 - ld [hl], "▼" - pop hl -.inputLoop - push hl - call DelayFrame - call JoypadLowSensitivity - ld a, [hJoy5] - ld b, a - pop hl - and A_BUTTON | B_BUTTON | D_UP | D_DOWN - jr z, .inputLoop - bit 0, b - jr nz, .pressedA - ld a, SFX_TINK - call PlaySound - bit 6, b - jr nz, .pressedUp - bit 7, b - jr nz, .pressedDown - jr .pressedB -.pressedA - ld a, SFX_HEAL_AILMENT - call PlaySound - ld a, [hl] - ld [wDestinationMap], a - ld hl, wd732 - set 3, [hl] - inc hl - set 7, [hl] -.pressedB - xor a - ld [wTownMapSpriteBlinkingEnabled], a - ld [hJoy7], a - call GBPalWhiteOutWithDelay3 - pop hl - pop af - ld [hl], a - ret -.pressedUp - coord de, 18, 0 - inc hl - ld a, [hl] - cp $ff - jr z, .wrapToStartOfList - cp $fe - jr z, .pressedUp ; skip past unvisited towns - jp .townMapFlyLoop -.wrapToStartOfList - ld hl, wFlyLocationsList - jp .townMapFlyLoop -.pressedDown - coord de, 19, 0 - dec hl - ld a, [hl] - cp $ff - jr z, .wrapToEndOfList - cp $fe - jr z, .pressedDown ; skip past unvisited towns - jp .townMapFlyLoop -.wrapToEndOfList - ld hl, wFlyLocationsList + 11 - jr .pressedDown - -ToText: - db "To@" - -BuildFlyLocationsList: - ld hl, wFlyLocationsList - 1 - ld [hl], $ff - inc hl - ld a, [wTownVisitedFlag] - ld e, a - ld a, [wTownVisitedFlag + 1] - ld d, a - ld bc, SAFFRON_CITY + 1 -.loop - srl d - rr e - ld a, $fe ; store $fe if the town hasn't been visited - jr nc, .notVisited - ld a, b ; store the map number of the town if it has been visited -.notVisited - ld [hl], a - inc hl - inc b - dec c - jr nz, .loop - ld [hl], $ff - ret - -TownMapUpArrow: - INCBIN "gfx/up_arrow.1bpp" -TownMapUpArrowEnd: - -LoadTownMap: - call GBPalWhiteOutWithDelay3 - call ClearScreen - call UpdateSprites - coord hl, 0, 0 - lb bc, $12, $12 - call TextBoxBorder - call DisableLCD - ld hl, WorldMapTileGraphics - ld de, vChars2 + $600 - ld bc, WorldMapTileGraphicsEnd - WorldMapTileGraphics - ld a, BANK(WorldMapTileGraphics) - call FarCopyData - ld hl, MonNestIcon - ld de, vSprites + $40 - ld bc, MonNestIconEnd - MonNestIcon - ld a, BANK(MonNestIcon) - call FarCopyDataDouble - coord hl, 0, 0 - ld de, CompressedMap -.nextTile - ld a, [de] - and a - jr z, .done - ld b, a - and $f - ld c, a - ld a, b - swap a - and $f - add $60 -.writeRunLoop - ld [hli], a - dec c - jr nz, .writeRunLoop - inc de - jr .nextTile -.done - call EnableLCD - ld b, SET_PAL_TOWN_MAP - call RunPaletteCommand - call Delay3 - call GBPalNormal - xor a - ld [wAnimCounter], a - inc a - ld [wTownMapSpriteBlinkingEnabled], a - ret - -CompressedMap: -; you can decompress this file with the redrle program in the extras/ dir - INCBIN "gfx/town_map.rle" - -ExitTownMap: -; clear town map graphics data and load usual graphics data - xor a - ld [wTownMapSpriteBlinkingEnabled], a - call GBPalWhiteOut - call ClearScreen - call ClearSprites - call LoadPlayerSpriteGraphics - call LoadFontTilePatterns - call UpdateSprites - jp RunDefaultPaletteCommand - -DrawPlayerOrBirdSprite: -; a = map number -; b = OAM base tile - push af - ld a, b - ld [wOAMBaseTile], a - pop af - ld de, wTownMapCoords - call LoadTownMapEntry - ld a, [de] - push hl - call TownMapCoordsToOAMCoords - call WritePlayerOrBirdSpriteOAM - pop hl - ld de, wcd6d -.loop - ld a, [hli] - ld [de], a - inc de - cp "@" - jr nz, .loop - ld hl, wOAMBuffer - ld de, wTileMapBackup - ld bc, $a0 - jp CopyData - -DisplayWildLocations: - callba FindWildLocationsOfMon - call ZeroOutDuplicatesInList - ld hl, wOAMBuffer - ld de, wTownMapCoords -.loop - ld a, [de] - cp $ff - jr z, .exitLoop - and a - jr z, .nextEntry - push hl - call LoadTownMapEntry - pop hl - ld a, [de] - cp $19 ; Cerulean Cave's coordinates - jr z, .nextEntry ; skip Cerulean Cave - call TownMapCoordsToOAMCoords - ld a, $4 ; nest icon tile no. - ld [hli], a - xor a - ld [hli], a -.nextEntry - inc de - jr .loop -.exitLoop - ld a, l - and a ; were any OAM entries written? - jr nz, .drawPlayerSprite -; if no OAM entries were written, print area unknown text - coord hl, 1, 7 - lb bc, 2, 15 - call TextBoxBorder - coord hl, 2, 9 - ld de, AreaUnknownText - call PlaceString - jr .done -.drawPlayerSprite - ld a, [wCurMap] - ld b, $0 - call DrawPlayerOrBirdSprite -.done - ld hl, wOAMBuffer - ld de, wTileMapBackup - ld bc, $a0 - jp CopyData - -AreaUnknownText: - db " AREA UNKNOWN@" - -TownMapCoordsToOAMCoords: -; in: lower nybble of a = x, upper nybble of a = y -; out: b and [hl] = (y * 8) + 24, c and [hl+1] = (x * 8) + 24 - push af - and $f0 - srl a - add 24 - ld b, a - ld [hli], a - pop af - and $f - swap a - srl a - add 24 - ld c, a - ld [hli], a - ret - -WritePlayerOrBirdSpriteOAM: - ld a, [wOAMBaseTile] - and a - ld hl, wOAMBuffer + $90 ; for player sprite - jr z, WriteTownMapSpriteOAM - ld hl, wOAMBuffer + $80 ; for bird sprite - -WriteTownMapSpriteOAM: - push hl - -; Subtract 4 from c (X coord) and 4 from b (Y coord). However, the carry from c -; is added to b, so the net result is that only 3 is subtracted from b. - lb hl, -4, -4 - add hl, bc - - ld b, h - ld c, l - pop hl - -WriteAsymmetricMonPartySpriteOAM: -; Writes 4 OAM blocks for a helix mon party sprite, since it does not have -; a vertical line of symmetry. - lb de, 2, 2 -.loop - push de - push bc -.innerLoop - ld a, b - ld [hli], a - ld a, c - ld [hli], a - ld a, [wOAMBaseTile] - ld [hli], a - inc a - ld [wOAMBaseTile], a - xor a - ld [hli], a - inc d - ld a, 8 - add c - ld c, a - dec e - jr nz, .innerLoop - pop bc - pop de - ld a, 8 - add b - ld b, a - dec d - jr nz, .loop - ret - -WriteSymmetricMonPartySpriteOAM: -; Writes 4 OAM blocks for a mon party sprite other than a helix. All the -; sprites other than the helix one have a vertical line of symmetry which allows -; the X-flip OAM bit to be used so that only 2 rather than 4 tile patterns are -; needed. - xor a - ld [wSymmetricSpriteOAMAttributes], a - lb de, 2, 2 -.loop - push de - push bc -.innerLoop - ld a, b - ld [hli], a ; Y - ld a, c - ld [hli], a ; X - ld a, [wOAMBaseTile] - ld [hli], a ; tile - ld a, [wSymmetricSpriteOAMAttributes] - ld [hli], a ; attributes - xor (1 << OAM_X_FLIP) - ld [wSymmetricSpriteOAMAttributes], a - inc d - ld a, 8 - add c - ld c, a - dec e - jr nz, .innerLoop - pop bc - pop de - push hl - ld hl, wOAMBaseTile - inc [hl] - inc [hl] - pop hl - ld a, 8 - add b - ld b, a - dec d - jr nz, .loop - ret - -ZeroOutDuplicatesInList: -; replace duplicate bytes in the list of wild pokemon locations with 0 - ld de, wBuffer -.loop - ld a, [de] - inc de - cp $ff - ret z - ld c, a - ld l, e - ld h, d -.zeroDuplicatesLoop - ld a, [hl] - cp $ff - jr z, .loop - cp c - jr nz, .skipZeroing - xor a - ld [hl], a -.skipZeroing - inc hl - jr .zeroDuplicatesLoop - -LoadTownMapEntry: -; in: a = map number -; out: lower nybble of [de] = x, upper nybble of [de] = y, hl = address of name - cp REDS_HOUSE_1F - jr c, .external - ld bc, 4 - ld hl, InternalMapEntries -.loop - cp [hl] - jr c, .foundEntry - add hl, bc - jr .loop -.foundEntry - inc hl - jr .readEntry -.external - ld hl, ExternalMapEntries - ld c, a - ld b, 0 - add hl, bc - add hl, bc - add hl, bc -.readEntry - ld a, [hli] - ld [de], a - ld a, [hli] - ld h, [hl] - ld l, a - ret - -INCLUDE "data/town_map_entries.asm" - -INCLUDE "text/map_names.asm" - -MonNestIcon: - INCBIN "gfx/mon_nest_icon.1bpp" -MonNestIconEnd: - -TownMapSpriteBlinkingAnimation: - ld a, [wAnimCounter] - inc a - cp 25 - jr z, .hideSprites - cp 50 - jr nz, .done -; show sprites when the counter reaches 50 - ld hl, wTileMapBackup - ld de, wOAMBuffer - ld bc, $90 - call CopyData - xor a - jr .done -.hideSprites - ld hl, wOAMBuffer - ld b, $24 - ld de, $4 -.hideSpritesLoop - ld [hl], $a0 - add hl, de - dec b - jr nz, .hideSpritesLoop - ld a, 25 -.done - ld [wAnimCounter], a - jp DelayFrame diff --git a/engine/trade.asm b/engine/trade.asm deleted file mode 100755 index e4bc0768..00000000 --- a/engine/trade.asm +++ /dev/null @@ -1,857 +0,0 @@ -InternalClockTradeAnim: -; Do the trading animation with the player's gameboy on the left. -; In-game trades and internally clocked link cable trades use this. - ld a, [wTradedPlayerMonSpecies] - ld [wLeftGBMonSpecies], a - ld a, [wTradedEnemyMonSpecies] - ld [wRightGBMonSpecies], a - ld de, InternalClockTradeFuncSequence - jr TradeAnimCommon - -ExternalClockTradeAnim: -; Do the trading animation with the player's gameboy on the right. -; Externally clocked link cable trades use this. - ld a, [wTradedEnemyMonSpecies] - ld [wLeftGBMonSpecies], a - ld a, [wTradedPlayerMonSpecies] - ld [wRightGBMonSpecies], a - ld de, ExternalClockTradeFuncSequence - -TradeAnimCommon: - ld a, [wOptions] - push af - and %110000 ; preserve speaker options - ld [wOptions], a - ld a, [hSCY] - push af - ld a, [hSCX] - push af - xor a - ld [hSCY], a - ld [hSCX], a - push de -.loop - pop de - ld a, [de] - cp $ff - jr z, .done - inc de - push de - ld hl, TradeFuncPointerTable - add a - ld c, a - ld b, $0 - add hl, bc - ld a, [hli] - ld h, [hl] - ld l, a - ld de, .loop - push de - jp hl ; call trade func, which will return to the top of the loop -.done - pop af - ld [hSCX], a - pop af - ld [hSCY], a - pop af - ld [wOptions], a - ret - -addtradefunc: MACRO -\1TradeFunc:: - dw \1 - ENDM - -tradefunc: MACRO - db (\1TradeFunc - TradeFuncPointerTable) / 2 - ENDM - -; The functions in the sequences below are executed in order by TradeFuncCommon. -; They are from opposite perspectives. The external clock one makes use of -; Trade_SwapNames to swap the player and enemy names for some functions. - -InternalClockTradeFuncSequence: - tradefunc LoadTradingGFXAndMonNames - tradefunc Trade_ShowPlayerMon - tradefunc Trade_DrawOpenEndOfLinkCable - tradefunc Trade_AnimateBallEnteringLinkCable - tradefunc Trade_AnimLeftToRight - tradefunc Trade_Delay100 - tradefunc Trade_ShowClearedWindow - tradefunc PrintTradeWentToText - tradefunc PrintTradeForSendsText - tradefunc PrintTradeFarewellText - tradefunc Trade_AnimRightToLeft - tradefunc Trade_ShowClearedWindow - tradefunc Trade_DrawOpenEndOfLinkCable - tradefunc Trade_ShowEnemyMon - tradefunc Trade_Delay100 - tradefunc Trade_Cleanup - db $FF - -ExternalClockTradeFuncSequence: - tradefunc LoadTradingGFXAndMonNames - tradefunc Trade_ShowClearedWindow - tradefunc PrintTradeWillTradeText - tradefunc PrintTradeFarewellText - tradefunc Trade_SwapNames - tradefunc Trade_AnimLeftToRight - tradefunc Trade_SwapNames - tradefunc Trade_ShowClearedWindow - tradefunc Trade_DrawOpenEndOfLinkCable - tradefunc Trade_ShowEnemyMon - tradefunc Trade_SlideTextBoxOffScreen - tradefunc Trade_ShowPlayerMon - tradefunc Trade_DrawOpenEndOfLinkCable - tradefunc Trade_AnimateBallEnteringLinkCable - tradefunc Trade_SwapNames - tradefunc Trade_AnimRightToLeft - tradefunc Trade_SwapNames - tradefunc Trade_Delay100 - tradefunc Trade_ShowClearedWindow - tradefunc PrintTradeWentToText - tradefunc Trade_Cleanup - db $FF - -TradeFuncPointerTable: - addtradefunc LoadTradingGFXAndMonNames - addtradefunc Trade_ShowPlayerMon - addtradefunc Trade_DrawOpenEndOfLinkCable - addtradefunc Trade_AnimateBallEnteringLinkCable - addtradefunc Trade_ShowEnemyMon - addtradefunc Trade_AnimLeftToRight - addtradefunc Trade_AnimRightToLeft - addtradefunc Trade_Delay100 - addtradefunc Trade_ShowClearedWindow - addtradefunc PrintTradeWentToText - addtradefunc PrintTradeForSendsText - addtradefunc PrintTradeFarewellText - addtradefunc PrintTradeTakeCareText - addtradefunc PrintTradeWillTradeText - addtradefunc Trade_Cleanup - addtradefunc Trade_SlideTextBoxOffScreen - addtradefunc Trade_SwapNames - -Trade_Delay100: - ld c, 100 - jp DelayFrames - -Trade_CopyTileMapToVRAM: - ld a, $1 - ld [H_AUTOBGTRANSFERENABLED], a - call Delay3 - xor a - ld [H_AUTOBGTRANSFERENABLED], a - ret - -Trade_Delay80: - ld c, 80 - jp DelayFrames - -Trade_ClearTileMap: - coord hl, 0, 0 - ld bc, SCREEN_WIDTH * SCREEN_HEIGHT - ld a, " " - jp FillMemory - -LoadTradingGFXAndMonNames: - call Trade_ClearTileMap - call DisableLCD - ld hl, TradingAnimationGraphics - ld de, vChars2 + $310 - ld bc, TradingAnimationGraphicsEnd - TradingAnimationGraphics - ld a, BANK(TradingAnimationGraphics) - call FarCopyData - ld hl, TradingAnimationGraphics2 - ld de, vSprites + $7c0 - ld bc, TradingAnimationGraphics2End - TradingAnimationGraphics2 - ld a, BANK(TradingAnimationGraphics2) - call FarCopyData - ld hl, vBGMap0 - ld bc, $800 - ld a, " " - call FillMemory - call ClearSprites - ld a, $ff - ld [wUpdateSpritesEnabled], a - ld hl, wd730 - set 6, [hl] ; turn on instant text printing - ld a, [wOnSGB] - and a - ld a, $e4 ; non-SGB OBP0 - jr z, .next - ld a, $f0 ; SGB OBP0 -.next - ld [rOBP0], a - call UpdateGBCPal_OBP0 - call EnableLCD - xor a - ld [H_AUTOBGTRANSFERENABLED], a - ld a, [wTradedPlayerMonSpecies] - ld [wd11e], a - call GetMonName - ld hl, wcd6d - ld de, wcf4b - ld bc, NAME_LENGTH - call CopyData - ld a, [wTradedEnemyMonSpecies] - ld [wd11e], a - jp GetMonName - -Trade_LoadMonPartySpriteGfx: - ld a, %11010000 - ld [rOBP1], a - call UpdateGBCPal_OBP1 - jpba LoadMonPartySpriteGfx - -Trade_SwapNames: - ld hl, wPlayerName - ld de, wBuffer - ld bc, NAME_LENGTH - call CopyData - ld hl, wLinkEnemyTrainerName - ld de, wPlayerName - ld bc, NAME_LENGTH - call CopyData - ld hl, wBuffer - ld de, wLinkEnemyTrainerName - ld bc, NAME_LENGTH - jp CopyData - -Trade_Cleanup: - xor a - call LoadGBPal - ld hl, wd730 - res 6, [hl] ; turn off instant text printing - ret - -Trade_ShowPlayerMon: - ld a, %10101011 - ld [rLCDC], a - ld a, $50 - ld [hWY], a - ld a, $86 - ld [rWX], a - ld [hSCX], a - xor a - ld [H_AUTOBGTRANSFERENABLED], a - coord hl, 4, 0 - lb bc, 6, 10 - call TextBoxBorder - call Trade_PrintPlayerMonInfoText - ld b, vBGMap0 / $100 - call CopyScreenTileBufferToVRAM - call ClearScreen - ld a, [wTradedPlayerMonSpecies] - call Trade_LoadMonSprite - ld a, $7e -.slideScreenLoop - push af - call DelayFrame - pop af - ld [rWX], a - ld [hSCX], a - dec a - dec a - and a - jr nz, .slideScreenLoop - call Trade_Delay80 - ld a, TRADE_BALL_POOF_ANIM - call Trade_ShowAnimation - ld a, TRADE_BALL_DROP_ANIM - call Trade_ShowAnimation ; clears mon pic - ld a, [wTradedPlayerMonSpecies] - call PlayCry - xor a - ld [H_AUTOBGTRANSFERENABLED], a - ret - -Trade_DrawOpenEndOfLinkCable: - call Trade_ClearTileMap - ld b, vBGMap0 / $100 - call CopyScreenTileBufferToVRAM - ld b, SET_PAL_GENERIC - call RunPaletteCommand - -; This function call is pointless. It just copies blank tiles to VRAM that was -; already filled with blank tiles. - ld hl, vBGMap1 + $8c - call Trade_CopyCableTilesOffScreen - - ld a, $a0 - ld [hSCX], a - call DelayFrame - ld a, %10001011 - ld [rLCDC], a - coord hl, 6, 2 - ld b, $7 ; open end of link cable tile ID list index - call CopyTileIDsFromList_ZeroBaseTileID - call Trade_CopyTileMapToVRAM - ld a, SFX_HEAL_HP - call PlaySound - ld c, 20 -.loop - ld a, [hSCX] - add 4 - ld [hSCX], a - dec c - jr nz, .loop - ret - -Trade_AnimateBallEnteringLinkCable: - ld a, TRADE_BALL_SHAKE_ANIM - call Trade_ShowAnimation - ld c, 10 - call DelayFrames - ld a, %11100100 - ld [rOBP0], a - call UpdateGBCPal_OBP0 - xor a - ld [wLinkCableAnimBulgeToggle], a - lb bc, $20, $60 -.moveBallInsideLinkCableLoop - push bc - xor a - ld de, Trade_BallInsideLinkCableOAM - call WriteOAMBlock - ld a, [wLinkCableAnimBulgeToggle] - xor $1 - ld [wLinkCableAnimBulgeToggle], a - add $7e - ld hl, wOAMBuffer + $02 - ld de, 4 - ld c, e -.cycleLinkCableBulgeTile - ld [hl], a - add hl, de - dec c - jr nz, .cycleLinkCableBulgeTile - call Delay3 - pop bc - ld a, c - add $4 - ld c, a - cp $a0 - jr nc, .ballSpriteReachedEdgeOfScreen - ld a, SFX_TINK - call PlaySound - jr .moveBallInsideLinkCableLoop -.ballSpriteReachedEdgeOfScreen - call ClearSprites - ld a, $1 - ld [H_AUTOBGTRANSFERENABLED], a - call ClearScreen - ld b, $98 - call CopyScreenTileBufferToVRAM - call Delay3 - xor a - ld [H_AUTOBGTRANSFERENABLED], a - ret - -Trade_BallInsideLinkCableOAM: - db $7E,$00,$7E,$20 - db $7E,$40,$7E,$60 - -Trade_ShowEnemyMon: - ld a, TRADE_BALL_TILT_ANIM - call Trade_ShowAnimation - call Trade_ShowClearedWindow - coord hl, 4, 10 - lb bc, 6, 10 - call TextBoxBorder - call Trade_PrintEnemyMonInfoText - call Trade_CopyTileMapToVRAM - ld a, $1 - ld [H_AUTOBGTRANSFERENABLED], a - ld a, [wTradedEnemyMonSpecies] - call Trade_LoadMonSprite - ld a, TRADE_BALL_POOF_ANIM - call Trade_ShowAnimation - ld a, $1 - ld [H_AUTOBGTRANSFERENABLED], a - ld a, [wTradedEnemyMonSpecies] - call PlayCry - call Trade_Delay100 - coord hl, 4, 10 - lb bc, 8, 12 - call ClearScreenArea - jp PrintTradeTakeCareText - -Trade_AnimLeftToRight: -; Animates the mon moving from the left GB to the right one. - call Trade_InitGameboyTransferGfx - ld a, $1 - ld [wTradedMonMovingRight], a - ld a, %11100100 - ld [rOBP0], a - call UpdateGBCPal_OBP0 - ld a, $54 - ld [wBaseCoordX], a - ld a, $1c - ld [wBaseCoordY], a - ld a, [wLeftGBMonSpecies] - ld [wMonPartySpriteSpecies], a - call Trade_WriteCircledMonOAM - call Trade_DrawLeftGameboy - call Trade_CopyTileMapToVRAM - call Trade_DrawCableAcrossScreen - ld hl, vBGMap1 + $8c - call Trade_CopyCableTilesOffScreen - ld b, $6 - call Trade_AnimMonMoveHorizontal - ld a, $1 - ld [H_AUTOBGTRANSFERENABLED], a - call Trade_DrawCableAcrossScreen - ld b, $4 - call Trade_AnimMonMoveHorizontal - call Trade_DrawRightGameboy - ld b, $6 - call Trade_AnimMonMoveHorizontal - xor a - ld [H_AUTOBGTRANSFERENABLED], a - call Trade_AnimMonMoveVertical - jp ClearSprites - -Trade_AnimRightToLeft: -; Animates the mon moving from the right GB to the left one. - call Trade_InitGameboyTransferGfx - xor a - ld [wTradedMonMovingRight], a - ld a, $64 - ld [wBaseCoordX], a - ld a, $44 - ld [wBaseCoordY], a - ld a, [wRightGBMonSpecies] - ld [wMonPartySpriteSpecies], a - call Trade_WriteCircledMonOAM - call Trade_DrawRightGameboy - call Trade_CopyTileMapToVRAM - call Trade_DrawCableAcrossScreen - ld hl, vBGMap1 + $94 - call Trade_CopyCableTilesOffScreen - call Trade_AnimMonMoveVertical - ld b, $6 - call Trade_AnimMonMoveHorizontal - ld a, $1 - ld [H_AUTOBGTRANSFERENABLED], a - call Trade_DrawCableAcrossScreen - ld b, $4 - call Trade_AnimMonMoveHorizontal - call Trade_DrawLeftGameboy - ld b, $6 - call Trade_AnimMonMoveHorizontal - xor a - ld [H_AUTOBGTRANSFERENABLED], a - jp ClearSprites - -Trade_InitGameboyTransferGfx: -; Initialises the graphics for showing a mon moving between gameboys. - ld a, $1 - ld [H_AUTOBGTRANSFERENABLED], a - call ClearScreen - ld b, SET_PAL_GENERIC - call RunPaletteCommand - xor a - ld [H_AUTOBGTRANSFERENABLED], a - call Trade_LoadMonPartySpriteGfx - call DelayFrame - ld a, %10101011 - ld [rLCDC], a - xor a - ld [hSCX], a - ld a, $90 - ld [hWY], a - ret - -Trade_DrawLeftGameboy: - call Trade_ClearTileMap - -; draw link cable - coord hl, 11, 4 - ld a, $5d - ld [hli], a - ld a, $5e - ld c, 8 -.loop - ld [hli], a - dec c - jr nz, .loop - -; draw gameboy pic - coord hl, 5, 3 - ld b, $6 - call CopyTileIDsFromList_ZeroBaseTileID - -; draw text box with player name below gameboy pic - coord hl, 4, 12 - lb bc, 2, 7 - call TextBoxBorder - coord hl, 5, 14 - ld de, wPlayerName - call PlaceString - - jp DelayFrame - -Trade_DrawRightGameboy: - call Trade_ClearTileMap - -; draw horizontal segment of link cable - coord hl, 0, 4 - ld a, $5e - ld c, $e -.loop - ld [hli], a - dec c - jr nz, .loop - -; draw vertical segment of link cable - ld a, $5f - ld [hl], a - ld de, SCREEN_WIDTH - add hl, de - ld a, $61 - ld [hl], a - add hl, de - ld [hl], a - add hl, de - ld [hl], a - add hl, de - ld [hl], a - add hl, de - ld a, $60 - ld [hld], a - ld a, $5d - ld [hl], a - -; draw gameboy pic - coord hl, 7, 8 - ld b, $6 - call CopyTileIDsFromList_ZeroBaseTileID - -; draw text box with enemy name above link cable - coord hl, 6, 0 - lb bc, 2, 7 - call TextBoxBorder - coord hl, 7, 2 - ld de, wLinkEnemyTrainerName - call PlaceString - - jp DelayFrame - -Trade_DrawCableAcrossScreen: -; Draws the link cable across the screen. - call Trade_ClearTileMap - coord hl, 0, 4 - ld a, $5e - ld c, SCREEN_WIDTH -.loop - ld [hli], a - dec c - jr nz, .loop - ret - -Trade_CopyCableTilesOffScreen: -; This is used to copy the link cable tiles off screen so that the cable -; continues when the screen is scrolled. - push hl - coord hl, 0, 4 - call CopyToRedrawRowOrColumnSrcTiles - pop hl - ld a, h - ld [hRedrawRowOrColumnDest + 1], a - ld a, l - ld [hRedrawRowOrColumnDest], a - ld a, REDRAW_ROW - ld [hRedrawRowOrColumnMode], a - ld c, 10 - jp DelayFrames - -Trade_AnimMonMoveHorizontal: -; Animates the mon going through the link cable horizontally over a distance of -; b 16-pixel units. - ld a, [wTradedMonMovingRight] - ld e, a - ld d, $8 -.scrollLoop - ld a, e - dec a - jr z, .movingRight -; moving left - ld a, [hSCX] - sub $2 - jr .next -.movingRight - ld a, [hSCX] - add $2 -.next - ld [hSCX], a - call DelayFrame - dec d - jr nz, .scrollLoop - call Trade_AnimCircledMon - dec b - jr nz, Trade_AnimMonMoveHorizontal - ret - -Trade_AnimCircledMon: -; Cycles between the two animation frames of the mon party sprite, cycles -; between a circle and an oval around the mon sprite, and makes the cable flash. - push de - push bc - push hl - ld a, [rBGP] - xor $3c ; make link cable flash - ld [rBGP], a - call UpdateGBCPal_BGP - ld hl, wOAMBuffer + $02 - ld de, $4 - ld c, $14 -.loop - ld a, [hl] - xor $40 - ld [hl], a - add hl, de - dec c - jr nz, .loop - pop hl - pop bc - pop de - ret - -Trade_WriteCircledMonOAM: - callba WriteMonPartySpriteOAMBySpecies - call Trade_WriteCircleOAM - -Trade_AddOffsetsToOAMCoords: - ld hl, wOAMBuffer - ld c, $14 ; SCREEN_WIDTH? -.loop - ld a, [wBaseCoordY] - add [hl] - ld [hli], a - ld a, [wBaseCoordX] - add [hl] - ld [hli], a - inc hl - inc hl - dec c - jr nz, .loop - ret - -Trade_AnimMonMoveVertical: -; Animates the mon going through the link cable vertically as well as -; horizontally for a bit. The last bit of horizontal movement (when moving -; right) or the first bit of horizontal movement (when moving left) are done -; here instead of Trade_AnimMonMoveHorizontal because this function moves the -; sprite itself rather than scrolling the screen around the sprite. Moving the -; sprite itself is necessary because the vertical segment of the link cable is -; to the right of the screen position that the mon sprite has when -; Trade_AnimMonMoveHorizontal is executing. - ld a, [wTradedMonMovingRight] - and a - jr z, .movingLeft -; moving right - lb bc, 4, 0 ; move right - call .doAnim - lb bc, 0, 10 ; move down - jr .doAnim -.movingLeft - lb bc, 0, -10 ; move up - call .doAnim - lb bc, -4, 0 ; move left -.doAnim - ld a, b - ld [wBaseCoordX], a - ld a, c - ld [wBaseCoordY], a - ld d, $4 -.loop - call Trade_AddOffsetsToOAMCoords - call Trade_AnimCircledMon - ld c, 8 - call DelayFrames - dec d - jr nz, .loop - ret - -Trade_WriteCircleOAM: -; Writes the OAM blocks for the circle around the traded mon as it passes -; the link cable. - ld hl, Trade_CircleOAMPointers - ld c, $4 - xor a -.loop - push bc - ld e, [hl] - inc hl - ld d, [hl] - inc hl - ld c, [hl] - inc hl - ld b, [hl] - inc hl - push hl - inc a - push af - call WriteOAMBlock - pop af - pop hl - pop bc - dec c - jr nz, .loop - ret - -Trade_CircleOAMPointers: - dw Trade_CircleOAM0 - db $08,$08 - dw Trade_CircleOAM1 - db $18,$08 - dw Trade_CircleOAM2 - db $08,$18 - dw Trade_CircleOAM3 - db $18,$18 - -Trade_CircleOAM0: - db $38,$10,$39,$10 - db $3A,$10,$3B,$10 - -Trade_CircleOAM1: - db $39,$30,$38,$30 - db $3B,$30,$3A,$30 - -Trade_CircleOAM2: - db $3A,$50,$3B,$50 - db $38,$50,$39,$50 - -Trade_CircleOAM3: - db $3B,$70,$3A,$70 - db $39,$70,$38,$70 - -; a = species -Trade_LoadMonSprite: - ld [wcf91], a - ld [wd0b5], a - ld [wWholeScreenPaletteMonSpecies], a - ld b, SET_PAL_POKEMON_WHOLE_SCREEN - ld c, 0 - call RunPaletteCommand - ld a, [H_AUTOBGTRANSFERENABLED] - xor $1 - ld [H_AUTOBGTRANSFERENABLED], a - call GetMonHeader - coord hl, 7, 2 - call LoadFlippedFrontSpriteByMonIndex - ld c, 10 - jp DelayFrames - -Trade_ShowClearedWindow: -; clears the window and covers the BG entirely with the window - ld a, $1 - ld [H_AUTOBGTRANSFERENABLED], a - call ClearScreen - ld a, %11100011 - ld [rLCDC], a - ld a, $7 - ld [rWX], a - xor a - ld [hWY], a - ld a, $90 - ld [hSCX], a - ret - -Trade_SlideTextBoxOffScreen: -; Slides the window right until it's off screen. The window usually just has -; a text box at the bottom when this is called. However, when this is called -; after Trade_ShowEnemyMon in the external clock sequence, there is a mon pic -; above the text box and it is also scrolled off the screen. - ld c, 50 - call DelayFrames -.loop - call DelayFrame - ld a, [rWX] - inc a - inc a - ld [rWX], a - cp $a1 - jr nz, .loop - call Trade_ClearTileMap - ld c, 10 - call DelayFrames - ld a, $7 - ld [rWX], a - ret - -PrintTradeWentToText: - ld hl, TradeWentToText - call PrintText - ld c, 200 - call DelayFrames - jp Trade_SlideTextBoxOffScreen - -TradeWentToText: - TX_FAR _TradeWentToText - db "@" - -PrintTradeForSendsText: - ld hl, TradeForText - call PrintText - call Trade_Delay80 - ld hl, TradeSendsText - call PrintText - jp Trade_Delay80 - -TradeForText: - TX_FAR _TradeForText - db "@" - -TradeSendsText: - TX_FAR _TradeSendsText - db "@" - -PrintTradeFarewellText: - ld hl, TradeWavesFarewellText - call PrintText - call Trade_Delay80 - ld hl, TradeTransferredText - call PrintText - call Trade_Delay80 - jp Trade_SlideTextBoxOffScreen - -TradeWavesFarewellText: - TX_FAR _TradeWavesFarewellText - db "@" - -TradeTransferredText: - TX_FAR _TradeTransferredText - db "@" - -PrintTradeTakeCareText: - ld hl, TradeTakeCareText - call PrintText - jp Trade_Delay80 - -TradeTakeCareText: - TX_FAR _TradeTakeCareText - db "@" - -PrintTradeWillTradeText: - ld hl, TradeWillTradeText - call PrintText - call Trade_Delay80 - ld hl, TradeforText - call PrintText - jp Trade_Delay80 - -TradeWillTradeText: - TX_FAR _TradeWillTradeText - db "@" - -TradeforText: - TX_FAR _TradeforText - db "@" - -Trade_ShowAnimation: - ld [wAnimationID], a - xor a - ld [wAnimationType], a - predef_jump MoveAnimation diff --git a/engine/trade2.asm b/engine/trade2.asm deleted file mode 100755 index 2c79e077..00000000 --- a/engine/trade2.asm +++ /dev/null @@ -1,48 +0,0 @@ -Trade_PrintPlayerMonInfoText: - coord hl, 5, 0 - ld de, Trade_MonInfoText - call PlaceString - ld a, [wTradedPlayerMonSpecies] - ld [wd11e], a - predef IndexToPokedex - coord hl, 9, 0 - ld de, wd11e - lb bc, LEADING_ZEROES | 1, 3 - call PrintNumber - coord hl, 5, 2 - ld de, wcf4b - call PlaceString - coord hl, 8, 4 - ld de, wTradedPlayerMonOT - call PlaceString - coord hl, 8, 6 - ld de, wTradedPlayerMonOTID - lb bc, LEADING_ZEROES | 2, 5 - jp PrintNumber - -Trade_PrintEnemyMonInfoText: - coord hl, 5, 10 - ld de, Trade_MonInfoText - call PlaceString - ld a, [wTradedEnemyMonSpecies] - ld [wd11e], a - predef IndexToPokedex - coord hl, 9, 10 - ld de, wd11e - lb bc, LEADING_ZEROES | 1, 3 - call PrintNumber - coord hl, 5, 12 - ld de, wcd6d - call PlaceString - coord hl, 8, 14 - ld de, wTradedEnemyMonOT - call PlaceString - coord hl, 8, 16 - ld de, wTradedEnemyMonOTID - lb bc, LEADING_ZEROES | 2, 5 - jp PrintNumber - -Trade_MonInfoText: - db "──№⠄",$4E - next "OT/" - next $73,"№⠄","@" diff --git a/engine/unknown_ea3ea.asm b/engine/unknown_ea3ea.asm index 1908809b..c10f1555 100755 --- a/engine/unknown_ea3ea.asm +++ b/engine/unknown_ea3ea.asm @@ -13,7 +13,7 @@ Printer_GetMonStats: call CopyVideoDataDouble xor a - ld [H_AUTOBGTRANSFERENABLED], a + ldh [hAutoBGTransferEnabled], a xor a ld [wWhichTradeMonSelectionMenu], a call LoadMonData @@ -22,22 +22,22 @@ Printer_GetMonStats: lb bc, 16, 18 call TextBoxBorder - coord hl, 0, 12 + hlcoord 0, 12 lb bc, 4, 18 call TextBoxBorder - coord hl, 3, 10 + hlcoord 3, 10 call PrintLevelFull - coord hl, 2, 10 + hlcoord 2, 10 ld a, $6e ld [hli], a ld [hl], " " - coord hl, 2, 11 - ld [hl], "′" + hlcoord 2, 11 + ld [hl], "’" - coord hl, 4, 11 + hlcoord 4, 11 ld de, wLoadedMonMaxHP lb bc, 2, 3 call PrintNumber @@ -47,15 +47,15 @@ Printer_GetMonStats: ld [wd0b5], a ld hl, wPartyMonNicks call .GetNamePointer - coord hl, 8, 2 + hlcoord 8, 2 call PlaceString call GetMonName - coord hl, 9, 3 + hlcoord 9, 3 call PlaceString predef IndexToPokedex - coord hl, 2, 8 + hlcoord 2, 8 ld [hl], "№" inc hl ld [hl], $f2 @@ -64,35 +64,35 @@ Printer_GetMonStats: lb bc, $80 | 1, 3 call PrintNumber - coord hl, 8, 4 + hlcoord 8, 4 ld de, .OT call PlaceString ld hl, wPartyMonOT call .GetNamePointer - coord hl, 9, 5 + hlcoord 9, 5 call PlaceString - coord hl, 9, 6 + hlcoord 9, 6 ld de, .IDNo call PlaceString - coord hl, 13, 6 + hlcoord 13, 6 ld de, wLoadedMonOTID lb bc, $80 | 2, 5 call PrintNumber - coord hl, 9, 8 + hlcoord 9, 8 ld de, .Stats - ld a, [hFlags_0xFFFA] + ldh a, [hFlagsFFFA] set 2, a - ld [hFlags_0xFFFA], a + ldh [hFlagsFFFA], a call PlaceString - ld a, [hFlags_0xFFFA] + ldh a, [hFlagsFFFA] res 2, a - ld [hFlags_0xFFFA], a + ldh [hFlagsFFFA], a - coord hl, 16, 8 + hlcoord 16, 8 ld de, wLoadedMonAttack ld a, 4 .loop @@ -113,19 +113,19 @@ Printer_GetMonStats: dec a jr nz, .loop - coord hl, 1, 13 + hlcoord 1, 13 ld a, [wLoadedMonMoves] call .PlaceMoveName - coord hl, 1, 14 + hlcoord 1, 14 ld a, [wLoadedMonMoves + 1] call .PlaceMoveName - coord hl, 1, 15 + hlcoord 1, 15 ld a, [wLoadedMonMoves + 2] call .PlaceMoveName - coord hl, 1, 16 + hlcoord 1, 16 ld a, [wLoadedMonMoves + 3] call .PlaceMoveName @@ -133,10 +133,10 @@ Printer_GetMonStats: call RunPaletteCommand ld a, $1 - ld [H_AUTOBGTRANSFERENABLED], a + ldh [hAutoBGTransferEnabled], a call Delay3 call GBPalNormal - coord hl, 1, 1 + hlcoord 1, 1 call LoadFlippedFrontSpriteByMonIndex ret @@ -468,11 +468,11 @@ Func_ea74c: ld [wPrinterSendByteOffset], a ld [wPrinterSendByteOffset + 1], a ld a, $88 - ld [rSB], a + ldh [rSB], a ld a, $1 - ld [rSC], a + ldh [rSC], a ld a, $81 - ld [rSC], a + ldh [rSC], a ret Func_ea76b: @@ -832,25 +832,25 @@ PrinterDebug_PrepOAMForPrinting: dw .Pal3 .Pal0: - ld a, [rOBP0] + ldh a, [rOBP0] and $3 ret .Pal2: - ld a, [rOBP0] + ldh a, [rOBP0] and $c srl a srl a ret .Pal1: - ld a, [rOBP0] + ldh a, [rOBP0] and $30 swap a ret .Pal3: - ld a, [rOBP0] + ldh a, [rOBP0] and $c0 rlca rlca diff --git a/engine/vermilion_gym_trash_cans.asm b/engine/vermilion_gym_trash_cans.asm index 49dee50c..1bc0590b 100755 --- a/engine/vermilion_gym_trash_cans.asm +++ b/engine/vermilion_gym_trash_cans.asm @@ -54,7 +54,7 @@ Yellow_SampleSecondTrashCan: call AddNTimes call AddNTimes ; ???? ld a, [hli] - ld [hGymTrashCanRandNumMask], a + ldh [hGymTrashCanRandNumMask], a ld e, a push hl call TrashCanRandom diff --git a/engine/yellow_intro.asm b/engine/yellow_intro.asm index 9c9e26b3..324ba86d 100755 --- a/engine/yellow_intro.asm +++ b/engine/yellow_intro.asm @@ -1,12 +1,12 @@ PlayIntroScene: - ld a, [rIE] + ldh a, [rIE] push af xor a - ld [rIF], a + ldh [rIF], a ld a, $f - ld [rIE], a + ldh [rIE], a ld a, $8 - ld [rSTAT], a + ldh [rSTAT], a call InitYellowIntroGFXAndMusic call DelayFrame .loop @@ -14,7 +14,7 @@ PlayIntroScene: bit 7, a jr nz, .go_to_title_screen call JoypadLowSensitivity - ld a, [hJoyPressed] + ldh a, [hJoyPressed] and A_BUTTON | B_BUTTON | START jr nz, .go_to_title_screen call Func_f98fc @@ -32,14 +32,14 @@ PlayIntroScene: .go_to_title_screen call YellowIntro_BlankPalettes xor a - ld [hLCDCPointer], a + ldh [hLCDCPointer], a call DelayFrame xor a - ld [rIF], a + ldh [rIF], a pop af - ld [rIE], a + ldh [rIE], a ld a, $90 - ld [hWY], a + ldh [hWY], a call ClearObjectAnimationBuffers ld hl, wTileMap ld bc, SCREEN_WIDTH * SCREEN_HEIGHT @@ -47,12 +47,12 @@ PlayIntroScene: call Bank3E_FillMemory call YellowIntro_BlankOAMBuffer ld a, $1 - ld [H_AUTOBGTRANSFERENABLED], a + ldh [hAutoBGTransferEnabled], a call DelayFrame call DelayFrame call DelayFrame xor a - ld [H_AUTOBGTRANSFERENABLED], a + ldh [hAutoBGTransferEnabled], a ret Func_f98a2: @@ -127,20 +127,20 @@ YellowIntro_NextScene: YellowIntroScene0: xor a - ld [hLCDCPointer], a + ldh [hLCDCPointer], a lb de, $58, $58 ld a, $1 call YellowIntro_SpawnAnimatedObjectAndSavePointer xor a - ld [hSCX], a - ld [hSCY], a + ldh [hSCX], a + ldh [hSCY], a ld a, $90 - ld [hWY], a + ldh [hWY], a ld a, $e4 - ld [rBGP], a - ld [rOBP0], a + ldh [rBGP], a + ldh [rOBP0], a ld a, $c4 - ld [rOBP1], a + ldh [rOBP1], a call UpdateGBCPal_BGP call UpdateGBCPal_OBP0 call UpdateGBCPal_OBP1 @@ -161,7 +161,7 @@ YellowIntroScene2: ld c, $8 call UpdateMusicCTimes xor a - ld [hLCDCPointer], a + ldh [hLCDCPointer], a ld hl, vBGMap0 ld bc, $400 xor a @@ -196,7 +196,7 @@ YellowIntroScene2_PlaceGraphic: add $10 dec b jr nz, .row - ld a, [hGBC] + ldh a, [hGBC] and a jr z, .dmg_sgb ; We can actually set palettes! @@ -204,7 +204,7 @@ YellowIntroScene2_PlaceGraphic: ld de, $20 ld b, $6 ld a, $1 - ld [rVBK], a + ldh [rVBK], a .attr_row ld c, $6 push hl @@ -217,7 +217,7 @@ YellowIntroScene2_PlaceGraphic: dec b jr nz, .attr_row xor a - ld [rVBK], a + ldh [rVBK], a .dmg_sgb ret @@ -260,11 +260,11 @@ YellowIntroFlyingSpeedBarData: YellowIntroScene3: call YellowIntro_CheckFrameTimerDecrement jr c, .expired - ld a, [hSCX] + ldh a, [hSCX] cp $68 ret z add $4 - ld [hSCX], a + ldh [hSCX], a ret .expired @@ -276,7 +276,7 @@ YellowIntroScene4: call YellowIntro_BlankPalsDelay2AndDisableLCD ld c, $5 call UpdateMusicCTimes - ld a, [hGBC] + ldh a, [hGBC] and a jr z, .dmg_sgb ; We can actually set palettes! @@ -284,7 +284,7 @@ YellowIntroScene4: ld de, $20 ld b, $6 ld a, $1 - ld [rVBK], a + ldh [rVBK], a xor a .attr_row ld c, $6 @@ -298,10 +298,10 @@ YellowIntroScene4: dec b jr nz, .attr_row xor a - ld [rVBK], a + ldh [rVBK], a .dmg_sgb xor a - ld [hLCDCPointer], a + ldh [hLCDCPointer], a call Func_f9e5f lb de, $58, $58 ld a, $2 @@ -324,7 +324,7 @@ YellowIntroScene6: ld c, $5 call UpdateMusicCTimes ld a, rSCY - $ff00 - ld [hLCDCPointer], a + ldh [hLCDCPointer], a call YellowIntro_Copy8BitSineWave ld hl, vBGMap0 ld bc, $60 @@ -385,7 +385,7 @@ YellowIntroScene8: ld c, $5 call UpdateMusicCTimes xor a - ld [hLCDCPointer], a + ldh [hLCDCPointer], a call Func_f9e5f lb de, $58, $58 ld a, $3 @@ -408,7 +408,7 @@ YellowIntroScene10: ld c, $5 call UpdateMusicCTimes xor a - ld [hLCDCPointer], a + ldh [hLCDCPointer], a ld hl, vBGMap0 ld bc, $400 xor a @@ -476,15 +476,15 @@ YellowIntroScene11: ld hl, YellowIntroCloudGFX1 add hl, de ld a, l - ld [H_VBCOPYSRC], a + ldh [hVBlankCopySource], a ld a, h - ld [H_VBCOPYSRC + 1], a + ldh [hVBlankCopySource + 1], a xor a - ld [H_VBCOPYDEST], a + ldh [hVBlankCopyDest], a ld a, $96 - ld [H_VBCOPYDEST + 1], a + ldh [hVBlankCopyDest + 1], a ld a, $4 - ld [H_VBCOPYSIZE], a + ldh [hVBlankCopySize], a ret .expired @@ -500,7 +500,7 @@ YellowIntroScene12: ld c, $5 call UpdateMusicCTimes xor a - ld [hLCDCPointer], a + ldh [hLCDCPointer], a ld hl, vBGMap0 ld bc, $80 ld a, $1 @@ -561,10 +561,10 @@ YellowIntroScene14: ld de, YellowIntroPalSequence_f9dd6 call YellowIntro_LoadDMGPalAndIncrementCounter jr c, .expired - ld [rBGP], a - ld [rOBP0], a + ldh [rBGP], a + ldh [rOBP0], a and $f0 - ld [rOBP1], a + ldh [rOBP1], a call UpdateGBCPal_BGP call UpdateGBCPal_OBP0 call UpdateGBCPal_OBP1 @@ -577,24 +577,24 @@ YellowIntroScene14: ld bc, $50 ld a, $1 call Bank3E_FillMemory - coord hl, 0, 4 + hlcoord 0, 4 ld bc, CopyVideoDataAlternate xor a call Bank3E_FillMemory - coord hl, 0, 14 + hlcoord 0, 14 ld bc, $50 ld a, $1 call Bank3E_FillMemory ld a, $1 - ld [H_AUTOBGTRANSFERENABLED], a + ldh [hAutoBGTransferEnabled], a call DelayFrame call DelayFrame call DelayFrame xor a - ld [H_AUTOBGTRANSFERENABLED], a + ldh [hAutoBGTransferEnabled], a ld a, $e4 - ld [rOBP0], a - ld [rBGP], a + ldh [rOBP0], a + ldh [rBGP], a call UpdateGBCPal_BGP call UpdateGBCPal_OBP0 lb de, $58, $58 @@ -611,22 +611,22 @@ YellowIntroScene15: ld a, [wYellowIntroSceneTimer] and $3 ret nz - ld a, [rOBP0] + ldh a, [rOBP0] xor $ff - ld [rOBP0], a - ld a, [rBGP] + ldh [rOBP0], a + ldh a, [rBGP] xor $3 - ld [rBGP], a + ldh [rBGP], a call UpdateGBCPal_BGP call UpdateGBCPal_OBP0 ret .expired xor a - ld [hLCDCPointer], a + ldh [hLCDCPointer], a ld a, $e4 - ld [rBGP], a - ld [rOBP0], a + ldh [rBGP], a + ldh [rOBP0], a call UpdateGBCPal_BGP call UpdateGBCPal_OBP0 call YellowIntro_NextScene @@ -634,8 +634,8 @@ YellowIntroScene16: ld de, YellowIntroPalSequence_f9e0a call YellowIntro_LoadDMGPalAndIncrementCounter jr c, .expired - ld [rOBP0], a - ld [rBGP], a + ldh [rOBP0], a + ldh [rBGP], a call UpdateGBCPal_BGP call UpdateGBCPal_OBP0 ret @@ -743,9 +743,9 @@ Func_f9e5f: YellowIntro_BlankPalsDelay2AndDisableLCD: xor a - ld [rBGP], a - ld [rOBP0], a - ld [rOBP1], a + ldh [rBGP], a + ldh [rOBP0], a + ldh [rOBP1], a call UpdateGBCPal_BGP call UpdateGBCPal_OBP0 call UpdateGBCPal_OBP1 @@ -756,19 +756,19 @@ YellowIntro_BlankPalsDelay2AndDisableLCD: Func_f9e9a: ld e, a - callab YellowIntroPaletteAction + callfar YellowIntroPaletteAction xor a - ld [hSCX], a - ld [hSCY], a + ldh [hSCX], a + ldh [hSCY], a ld a, $90 - ld [hWY], a + ldh [hWY], a ld a, $e3 - ld [rLCDC], a + ldh [rLCDC], a ld a, $e4 - ld [rBGP], a - ld [rOBP0], a + ldh [rBGP], a + ldh [rOBP0], a ld a, $e0 - ld [rOBP1], a + ldh [rOBP1], a call UpdateGBCPal_BGP call UpdateGBCPal_OBP0 call UpdateGBCPal_OBP1 @@ -798,41 +798,41 @@ YellowIntro_Copy8BitSineWave: Request7TileTransferFromC810ToC710: ld a, $10 - ld [H_VBCOPYSRC], a + ldh [hVBlankCopySource], a ld a, wLYOverridesBuffer / $100 - ld [H_VBCOPYSRC + 1], a + ldh [hVBlankCopySource + 1], a ld a, $10 - ld [H_VBCOPYDEST], a + ldh [hVBlankCopyDest], a ld a, wLYOverrides / $100 - ld [H_VBCOPYDEST + 1], a + ldh [hVBlankCopyDest + 1], a ld a, $7 - ld [H_VBCOPYSIZE], a + ldh [hVBlankCopySize], a ret InitYellowIntroGFXAndMusic: xor a - ld [H_AUTOBGTRANSFERENABLED], a - ld [hSCX], a - ld [hSCY], a - ld [H_AUTOBGTRANSFERDEST], a + ldh [hAutoBGTransferEnabled], a + ldh [hSCX], a + ldh [hSCY], a + ldh [hAutoBGTransferDest], a ld a, $98 - ld [H_AUTOBGTRANSFERDEST + 1], a + ldh [hAutoBGTransferDest + 1], a call YellowIntro_BlankTileMap ld hl, wTileMap ld bc, SCREEN_WIDTH * SCREEN_HEIGHT ld a, $1 call Bank3E_FillMemory - coord hl, 0, 4 + hlcoord 0, 4 ld bc, CopyVideoDataAlternate xor a call Bank3E_FillMemory ld a, $1 - ld [H_AUTOBGTRANSFERENABLED], a + ldh [hAutoBGTransferEnabled], a call DelayFrame call DelayFrame call DelayFrame xor a - ld [H_AUTOBGTRANSFERENABLED], a + ldh [hAutoBGTransferEnabled], a ld de, $6b5a ld hl, $8000 ld bc, $3eff @@ -915,9 +915,9 @@ YellowIntro_BlankOAMBuffer: YellowIntro_BlankPalettes: xor a - ld [rBGP], a - ld [rOBP0], a - ld [rOBP1], a + ldh [rBGP], a + ldh [rOBP0], a + ldh [rOBP1], a call UpdateGBCPal_BGP call UpdateGBCPal_OBP0 call UpdateGBCPal_OBP1 -- cgit v1.3.1-sl0p