diff --git a/constants/audio_constants.asm b/constants/audio_constants.asm index 36c3500618..f3333ec9f4 100644 --- a/constants/audio_constants.asm +++ b/constants/audio_constants.asm @@ -55,7 +55,7 @@ DEF HW_CH4_DISABLE_MASK EQU (~HW_CH4_ENABLE_MASK & $ff) const REG_FREQUENCY_LO ; 3 ; wChannelFlags1 constants - const_def + bit_const_def const BIT_PERFECT_PITCH ; 0 ; controlled by toggle_perfect_pitch command const BIT_SOUND_CALL ; 1 ; if in sound call const BIT_NOISE_OR_SFX ; 2 ; if channel is the music noise channel or an SFX channel diff --git a/constants/event_constants.asm b/constants/event_constants.asm index 7bcef25cdf..a5dd43c15f 100644 --- a/constants/event_constants.asm +++ b/constants/event_constants.asm @@ -1,7 +1,7 @@ ; wEventFlags bit flags ; Pallet Town events - const_def + word_const_def const EVENT_FOLLOWED_OAK_INTO_LAB const_skip 2 const EVENT_HALL_OF_FAME_DEX_RATING diff --git a/constants/item_constants.asm b/constants/item_constants.asm index 8f623d557b..7e27e7db78 100644 --- a/constants/item_constants.asm +++ b/constants/item_constants.asm @@ -5,7 +5,7 @@ ; - TechnicalMachinePrices (see data/items/tm_prices.asm) ; - KeyItemFlags (see data/items/key_items.asm) ; - ItemUsePtrTable (see engine/items/item_effects.asm) - const_def + listable_const_def const NO_ITEM ; $00 const MASTER_BALL ; $01 const ULTRA_BALL ; $02 diff --git a/constants/map_constants.asm b/constants/map_constants.asm index fe0bd9f53e..6238ee7045 100644 --- a/constants/map_constants.asm +++ b/constants/map_constants.asm @@ -22,7 +22,7 @@ ENDM ; - WildDataPointers (see data/wild/grass_water.asm) ; Each map also has associated data in maps.asm. ; Order: towns/cities, then routes, then indoor/dungeon maps - const_def + listable_const_def map_const PALLET_TOWN, 10, 9 ; $00 map_const VIRIDIAN_CITY, 20, 18 ; $01 map_const PEWTER_CITY, 20, 18 ; $02 @@ -401,5 +401,3 @@ DEF NUM_MAPS EQU const_value ; Indoor maps, such as houses, use this as the Map ID in their exit warps ; This map ID takes the player back to the last outdoor map they were on, stored in wLastMap DEF LAST_MAP EQU $ff - -ASSERT NUM_MAPS <= LAST_MAP, "map IDs overlap LAST_MAP" diff --git a/constants/map_data_constants.asm b/constants/map_data_constants.asm index 32a56518cc..ac00e4260b 100644 --- a/constants/map_data_constants.asm +++ b/constants/map_data_constants.asm @@ -2,19 +2,14 @@ ; height of north/south connections DEF MAP_BORDER EQU 3 -; connection directions - const_def - const EAST_F - const WEST_F - const SOUTH_F - const NORTH_F +; wCurMapConnections : \1 +; connection directions : BIT_\1 + bit_const_def + shift_const EAST ; $01 (BIT_EAST ; 0) + shift_const WEST ; $02 (BIT_WEST ; 1) + shift_const SOUTH ; $04 (BIT_SOUTH ; 2) + shift_const NORTH ; $08 (BIT_NORTH ; 4) -; wCurMapConnections - const_def - shift_const EAST ; 1 - shift_const WEST ; 2 - shift_const SOUTH ; 4 - shift_const NORTH ; 8 ; wWarpEntries DEF MAX_WARP_EVENTS EQU 32 diff --git a/constants/menu_constants.asm b/constants/menu_constants.asm index c4476e032d..605b6bdafd 100644 --- a/constants/menu_constants.asm +++ b/constants/menu_constants.asm @@ -2,7 +2,7 @@ DEF BAG_ITEM_CAPACITY EQU 20 DEF PC_ITEM_CAPACITY EQU 50 ; text box IDs - const_def 1 + listable_const_def 1 const MESSAGE_BOX ; $01 const_skip ; $02 const MENU_TEMPLATE_03 ; $03 unused diff --git a/constants/move_animation_constants.asm b/constants/move_animation_constants.asm index 2057541b0e..682dd1f63b 100644 --- a/constants/move_animation_constants.asm +++ b/constants/move_animation_constants.asm @@ -1,6 +1,7 @@ ; special effects that are part of move animations ; SpecialEffectPointers associates them with effect routines (see data/battle_anims/special_effect_pointers.asm) - const_def $C0 + listable_const_def $C0 +DEF SUBANIM_CONST_LIMIT EQU const_value - 1 DEF FIRST_SE_ID EQU const_value const_skip $18 const SE_WAVY_SCREEN ; $D8 used in Psywave/Night Shade/Psychic etc. @@ -48,7 +49,7 @@ DEF FIRST_SE_ID EQU const_value ; The 0 or 1 in the name of a subanim indicates whether to use tileset 0 or 1 data/moves/animations.asm. ; "Both" indicates either can be used for different images using the same animation. - const_def + max_const_def SUBANIM_CONST_LIMIT const SUBANIM_0_STAR const SUBANIM_0_STAR_TWICE const SUBANIM_0_STAR_THRICE diff --git a/constants/move_constants.asm b/constants/move_constants.asm index 1dccabfd7c..21263db5a2 100644 --- a/constants/move_constants.asm +++ b/constants/move_constants.asm @@ -4,7 +4,7 @@ ; - MoveNames (see data/moves/names.asm) ; - AttackAnimationPointers (see data/moves/animations.asm) ; - MoveSoundTable (see data/moves/sfx.asm) - const_def + listable_const_def const NO_MOVE ; 00 const POUND ; 01 const KARATE_CHOP ; 02 diff --git a/constants/move_effect_constants.asm b/constants/move_effect_constants.asm index 6914fafdf1..9ed13f6ba4 100644 --- a/constants/move_effect_constants.asm +++ b/constants/move_effect_constants.asm @@ -3,7 +3,7 @@ ; {status condition}_EFFECT means that the move causes the status condition every time it hits the target ; MoveEffectPointerTable indexes (see data/moves/effects_pointers.asm) - const_def + listable_const_def const NO_ADDITIONAL_EFFECT ; $00 const EFFECT_01 ; $01 unused const POISON_SIDE_EFFECT1 ; $02 diff --git a/constants/pokemon_constants.asm b/constants/pokemon_constants.asm index ea206bb83a..6c003a8fb8 100644 --- a/constants/pokemon_constants.asm +++ b/constants/pokemon_constants.asm @@ -5,7 +5,9 @@ ; - CryData (see data/pokemon/cries.asm) ; - PokedexOrder (see data/pokemon/dex_order.asm) ; - PokedexEntryPointers (see data/pokemon/dex_entries.asm) - const_def + max_const_def OPP_ID_OFFSET - 1 + ; Pokemons and trainers share ID values. + ; Note : even without this limitation, they would be limited to $FD. const NO_MON ; $00 const RHYDON ; $01 const KANGASKHAN ; $02 diff --git a/constants/sprite_data_constants.asm b/constants/sprite_data_constants.asm index 44dc0fa94e..95f97b7715 100644 --- a/constants/sprite_data_constants.asm +++ b/constants/sprite_data_constants.asm @@ -1,26 +1,20 @@ -; sprite facing directions - const_def 0, $04 - const SPRITE_FACING_DOWN ; $00 - const SPRITE_FACING_UP ; $04 - const SPRITE_FACING_LEFT ; $08 - const SPRITE_FACING_RIGHT ; $0C +MACRO sprite_facing_const + const \1 + DEF \2 EQU \1 << 4 +ENDM - const_def 0, $40 - const NPC_MOVEMENT_DOWN ; $00 - const NPC_MOVEMENT_UP ; $40 - const NPC_MOVEMENT_LEFT ; $80 - const NPC_MOVEMENT_RIGHT ; $C0 +; sprite facing directions + nybble_const_def 0, $4 + sprite_facing_const SPRITE_FACING_DOWN, NPC_MOVEMENT_DOWN ; $00, $00 + sprite_facing_const SPRITE_FACING_UP, NPC_MOVEMENT_UP ; $04, $40 + sprite_facing_const SPRITE_FACING_LEFT, NPC_MOVEMENT_LEFT ; $08, $80 + sprite_facing_const SPRITE_FACING_RIGHT, NPC_MOVEMENT_RIGHT ; $0C, $C0 DEF NPC_CHANGE_FACING EQU $E0 ; player direction constants - const_def - const PLAYER_DIR_BIT_RIGHT ; 0 - const PLAYER_DIR_BIT_LEFT ; 1 - const PLAYER_DIR_BIT_DOWN ; 2 - const PLAYER_DIR_BIT_UP ; 3 - -DEF PLAYER_DIR_RIGHT EQU 1 << PLAYER_DIR_BIT_RIGHT -DEF PLAYER_DIR_LEFT EQU 1 << PLAYER_DIR_BIT_LEFT -DEF PLAYER_DIR_DOWN EQU 1 << PLAYER_DIR_BIT_DOWN -DEF PLAYER_DIR_UP EQU 1 << PLAYER_DIR_BIT_UP + bit_const_def + shift_const PLAYER_DIR_RIGHT ; $01 (BIT_PLAYER_DIR_RIGHT ; 0) + shift_const PLAYER_DIR_LEFT ; $02 (BIT_PLAYER_DIR_LEFT ; 1) + shift_const PLAYER_DIR_DOWN ; $04 (BIT_PLAYER_DIR_DOWN ; 2) + shift_const PLAYER_DIR_UP ; $08 (BIT_PLAYER_DIR_UP ; 3) diff --git a/constants/tileset_constants.asm b/constants/tileset_constants.asm index e7fe88f530..1650166be9 100644 --- a/constants/tileset_constants.asm +++ b/constants/tileset_constants.asm @@ -1,6 +1,12 @@ +; Tileset IDs values are limited by the fact that the function LoadTilesetHeader (engine/overworld/tilesets.asm) +; multiply the ID by 8 before taking carry into account. +; Hence any value bigger than 31 would overflow. +; Note : even without this limitation, would be listable_const_def +DEF TILESET_CONST_LIMIT EQU $FF / 8 + ; tileset ids ; Tilesets indexes (see data/tilesets/tileset_headers.asm) - const_def + max_const_def TILESET_CONST_LIMIT const OVERWORLD ; 0 const REDS_HOUSE_1 ; 1 const MART ; 2 diff --git a/constants/trainer_constants.asm b/constants/trainer_constants.asm index 4daf8a960f..fce2e14724 100644 --- a/constants/trainer_constants.asm +++ b/constants/trainer_constants.asm @@ -1,8 +1,8 @@ DEF OPP_ID_OFFSET EQU 200 MACRO trainer_const - const \1 - DEF OPP_\1 EQU OPP_ID_OFFSET + \1 + const OPP_\1 + DEF \1 EQU OPP_\1 - OPP_ID_OFFSET ENDM ; trainer class ids @@ -13,7 +13,7 @@ ENDM ; - TrainerPicAndMoneyPointers (see data/trainers/pic_pointers_money.asm) ; - TrainerAIPointers (see data/trainers/ai_pointers.asm) ; - TrainerClassMoveChoiceModifications (see data/trainers/move_choices.asm) - const_def + listable_const_def OPP_ID_OFFSET trainer_const NOBODY ; $00 trainer_const YOUNGSTER ; $01 trainer_const BUG_CATCHER ; $02 @@ -62,4 +62,4 @@ ENDM trainer_const CHANNELER ; $2D trainer_const AGATHA ; $2E trainer_const LANCE ; $2F -DEF NUM_TRAINERS EQU const_value - 1 +DEF NUM_TRAINERS EQU const_value - OPP_ID_OFFSET - 1 diff --git a/constants/type_constants.asm b/constants/type_constants.asm index 8226af1abb..804832f186 100644 --- a/constants/type_constants.asm +++ b/constants/type_constants.asm @@ -1,5 +1,5 @@ ; TypeNames indexes (see data/types/names.asm) - const_def + listable_const_def DEF PHYSICAL EQU const_value const NORMAL ; $00 diff --git a/engine/items/item_effects.asm b/engine/items/item_effects.asm index c4ce13de6f..539f878ac0 100644 --- a/engine/items/item_effects.asm +++ b/engine/items/item_effects.asm @@ -726,13 +726,13 @@ ItemUseSurfboard: ; 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 + bit BIT_PLAYER_DIR_UP, a ld b, PAD_UP jr nz, .storeSimulatedButtonPress - bit PLAYER_DIR_BIT_DOWN, a + bit BIT_PLAYER_DIR_DOWN, a ld b, PAD_DOWN jr nz, .storeSimulatedButtonPress - bit PLAYER_DIR_BIT_LEFT, a + bit BIT_PLAYER_DIR_LEFT, a ld b, PAD_LEFT jr nz, .storeSimulatedButtonPress ld b, PAD_RIGHT diff --git a/engine/overworld/movement.asm b/engine/overworld/movement.asm index be8d6f62fb..46b1c44e33 100644 --- a/engine/overworld/movement.asm +++ b/engine/overworld/movement.asm @@ -29,22 +29,22 @@ UpdatePlayerSprite: jr nz, .moving ld a, [wPlayerMovingDirection] ; check if down - bit PLAYER_DIR_BIT_DOWN, a + bit BIT_PLAYER_DIR_DOWN, a jr z, .checkIfUp xor a ; ld a, SPRITE_FACING_DOWN jr .next .checkIfUp - bit PLAYER_DIR_BIT_UP, a + bit BIT_PLAYER_DIR_UP, a jr z, .checkIfLeft ld a, SPRITE_FACING_UP jr .next .checkIfLeft - bit PLAYER_DIR_BIT_LEFT, a + bit BIT_PLAYER_DIR_LEFT, a jr z, .checkIfRight ld a, SPRITE_FACING_LEFT jr .next .checkIfRight - bit PLAYER_DIR_BIT_RIGHT, a + bit BIT_PLAYER_DIR_RIGHT, a jr z, .notMoving ld a, SPRITE_FACING_RIGHT jr .next @@ -415,17 +415,17 @@ MakeNPCFacePlayer: jr nz, NotYetMoving res BIT_FACE_PLAYER, [hl] ld a, [wPlayerDirection] - bit PLAYER_DIR_BIT_UP, a + bit BIT_PLAYER_DIR_UP, a jr z, .notFacingDown ld c, SPRITE_FACING_DOWN jr .facingDirectionDetermined .notFacingDown - bit PLAYER_DIR_BIT_DOWN, a + bit BIT_PLAYER_DIR_DOWN, a jr z, .notFacingUp ld c, SPRITE_FACING_UP jr .facingDirectionDetermined .notFacingUp - bit PLAYER_DIR_BIT_LEFT, a + bit BIT_PLAYER_DIR_LEFT, a jr z, .notFacingRight ld c, SPRITE_FACING_RIGHT jr .facingDirectionDetermined diff --git a/home/overworld.asm b/home/overworld.asm index a06a32da3c..c7b1f8642a 100644 --- a/home/overworld.asm +++ b/home/overworld.asm @@ -2047,22 +2047,22 @@ LoadMapHeader:: ld a, [wCurMapConnections] ld b, a ; check north - bit NORTH_F, b + bit BIT_NORTH, b jr z, .checkSouth ld de, wNorthConnectionHeader call CopyMapConnectionHeader .checkSouth - bit SOUTH_F, b + bit BIT_SOUTH, b jr z, .checkWest ld de, wSouthConnectionHeader call CopyMapConnectionHeader .checkWest - bit WEST_F, b + bit BIT_WEST, b jr z, .checkEast ld de, wWestConnectionHeader call CopyMapConnectionHeader .checkEast - bit EAST_F, b + bit BIT_EAST, b jr z, .getObjectDataPointer ld de, wEastConnectionHeader call CopyMapConnectionHeader diff --git a/includes.asm b/includes.asm index ea6f1a8e49..8464fa8171 100644 --- a/includes.asm +++ b/includes.asm @@ -28,11 +28,11 @@ INCLUDE "constants/move_constants.asm" INCLUDE "constants/move_animation_constants.asm" INCLUDE "constants/move_effect_constants.asm" INCLUDE "constants/item_constants.asm" +INCLUDE "constants/trainer_constants.asm" INCLUDE "constants/pokemon_constants.asm" INCLUDE "constants/pokedex_constants.asm" INCLUDE "constants/pokemon_data_constants.asm" INCLUDE "constants/player_constants.asm" -INCLUDE "constants/trainer_constants.asm" INCLUDE "constants/icon_constants.asm" INCLUDE "constants/sprite_constants.asm" INCLUDE "constants/sprite_data_constants.asm" diff --git a/macros/const.asm b/macros/const.asm index d6a34672a1..e418b2a29d 100644 --- a/macros/const.asm +++ b/macros/const.asm @@ -1,21 +1,74 @@ ; Enumerate constants +; Arguments : +; \1 starting constant value +; \2 incrementation value +; \3 constant value limit MACRO? const_def - IF _NARG >= 1 - DEF const_value = \1 - ELSE - DEF const_value = 0 - ENDC - IF _NARG >= 2 - DEF const_inc = \2 - ELSE - DEF const_inc = 1 - ENDC + DEF const_format = $FF + const_def_common \# +ENDM + +MACRO? bit_const_def + DEF const_format = $7 + REDEF const_format_string EQUS "bit" + const_def_common \# +ENDM + +MACRO? nybble_const_def + DEF const_format = $F + REDEF const_format_string EQUS "nybble" + const_def_common \# +ENDM + +MACRO? word_const_def + DEF const_format = $FFFF + const_def_common \# +ENDM + +; Disable constant limit verification. +MACRO? unlimited_const_def + ASSERT WARN, _NARG <= 2, "Third argument found, unlimited_const_def disable constant value limitations." + DEF const_format = $FFFFFFFF + const_def_common \# +ENDM + +; Some functions like IsInArray use value $FF as a list terminator. Predefine constant limit as $FE +MACRO? listable_const_def + ASSERT WARN, _NARG <= 2, "Third argument found, listable_const_def already define constant value limit as $FE." + max_const_def $FE, \# +ENDM + +; max_* variations of the macros define the constant limit with the first argument +MACRO? max_const_def + DEF const_format = $FF + max_const_def_common \# +ENDM + +MACRO? max_bit_const_def + DEF const_format = $7 + REDEF const_format_string EQUS "bit" + max_const_def_common \# +ENDM + +MACRO? max_nybble_const_def + DEF const_format = $F + REDEF const_format_string EQUS "nybble" + max_const_def_common \# +ENDM + +MACRO? max_word_const_def + DEF const_format = $FFFF + max_const_def_common \# ENDM MACRO? const - DEF \1 EQU const_value - DEF const_value += const_inc + IF (const_format != $FFFFFFFF) && ((const_inc > 0 && const_value > const_limit) || (const_inc < 0 && const_value < const_limit)) + fail "Constant value cannot be {const_size_compare} than {const_limit}.\n Attempted to define constant \1 for value {const_value}." + ELSE + DEF \1 EQU const_value + DEF const_value += const_inc + ENDC ENDM MACRO? const_export @@ -24,8 +77,14 @@ MACRO? const_export ENDM MACRO? shift_const - DEF \1 EQU 1 << const_value - DEF const_value += const_inc + IF (const_format != $FFFFFFFF) && ((const_inc > 0 && const_value > const_limit) || (const_inc < 0 && const_value < const_limit)) + DEF failed_const_value = 1 << const_value + fail "Constant value cannot be {const_size_compare} than {const_limit}.\n Attempted to use constant value {const_value} to define constant \1 for shifted value {failed_const_value}." + ELSE + DEF BIT_\1 EQU const_value + DEF \1 EQU 1 << const_value + DEF const_value += const_inc + ENDC ENDM MACRO? const_skip @@ -37,8 +96,9 @@ MACRO? const_skip ENDM MACRO? const_next - if (const_value > 0 && \1 < const_value) || (const_value < 0 && \1 > const_value) - fail "const_next cannot go backwards from {const_value} to \1" + if (const_inc > 0 && \1 < const_value) || (const_inc < 0 && \1 > const_value) + DEF failed_const_value = \1 + fail "const_next cannot go backwards from {const_value} to {failed_const_value} with a {const_inc} increment." else DEF const_value = \1 endc @@ -56,3 +116,99 @@ MACRO? rb_skip rsset _RS + 1 ENDC ENDM + +; Macros past this comment arent meant to be used by themselves + +MACRO? max_const_def_common + IF _NARG >= 3 + const_def_common \2, \3, \1 + ELIF _NARG >= 2 + const_def_common \2, 1, \1 + ELIF _NARG >= 1 + const_def_common 0, 1, \1 + ELSE + const_def_common 0, 1 + ENDC +ENDM + +MACRO? const_def_common + IF _NARG >= 1 + DEF const_value = \1 + ELSE + DEF const_value = 0 + ENDC + IF _NARG >= 2 + DEF const_inc = \2 + ELSE + DEF const_inc = 1 + ENDC + ; pass all constant limit related operations if unlimited_const_def + IF const_format != $FFFFFFFF + IF const_inc > 0 + REDEF const_size_compare EQUS "bigger" + ELSE ; const_inc < 0 + REDEF const_size_compare EQUS "smaller" + ENDC + + const_def_common_{const_format} \# + + ; check the coherance of the starting value and constant limit. + IF (const_format == $7 || const_format == $F) && (const_limit < 0 || const_limit > const_format) + fail "Constant limit {const_limit} for {const_format_string}_const_def outside of range [$0 , {const_format}]" + ELIF (const_format == $7 || const_format == $F) && (const_value < 0 || const_value > const_format) + fail "Starting constant value {const_value} for {const_format_string}_const_def outside of range [$0 , {const_format}]." + ELIF (const_inc > 0 && const_value > const_limit) || (const_inc < 0 && const_value < const_limit) + fail "Starting constant value {const_value} cannot be {const_size_compare} than constant limit value {const_limit} while using a {d:const_inc} increment." + ELIF ((const_limit > 0 && const_value < 0) && (const_value & const_format) < const_limit) + DEF failed_const_value = const_value & const_format + fail "Starting constant value and constant limit allow an overlap in constant value range [{failed_const_value} , {const_limit}]." + ELIF ((const_limit < 0 && const_value > 0) && const_value > (const_limit & const_format)) + DEF failed_const_value = const_limit & const_format + fail "Starting constant value and constant limit allow an overlap in constant value range [{failed_const_value} , {const_value}]." + ELIF (const_limit & const_format) == (const_value & const_format) && \ + ((const_limit & const_format) != const_limit) != ((const_value & const_format) != const_value) + DEF failed_const_value = const_value & const_format + fail "Starting constant value and constant limit allow an overlap on constant value {failed_const_value}." + ENDC + ENDC +ENDM + +MACRO? const_def_common_$FFFF + const_def_common_$FF \# +ENDM +MACRO? const_def_common_$FF + ; change default $FF const_format to $FFFF if starting constant value is outside of [-$100 ; $FF] range + IF const_format == $FF && (const_value < -$100 || const_value > $FF) + DEF const_format = $FFFF + ENDC + + IF _NARG >= 3 + DEF const_limit = \3 + ; change default $FF const_format to $FFFF if constant limit is outside of [-$100 ; $FF] range + IF const_format == $FF && (const_limit < -$100 || const_limit > $FF) + DEF const_format = $FFFF + ENDC + ELIF const_value >= 0 && const_inc > 0 + DEF const_limit = const_format + ELIF const_value < 0 && const_inc < 0 + DEF const_limit = -1 - const_format + ELIF const_inc < 0 + DEF const_limit = const_value - const_format + ELSE + DEF const_limit = const_value + const_format + ENDC +ENDM + +MACRO? const_def_common_$F + const_def_common_$7 \# +ENDM +MACRO? const_def_common_$7 + IF _NARG >= 3 + DEF const_limit = \3 + ; set constant limit to 0 for negative increment and to const_format for positive + ELIF const_inc < 0 + DEF const_limit = 0 + ELSE + DEF const_limit = const_format + ENDC +ENDM diff --git a/macros/scripts/text.asm b/macros/scripts/text.asm index a848f587f6..aa7546a71b 100644 --- a/macros/scripts/text.asm +++ b/macros/scripts/text.asm @@ -181,9 +181,11 @@ MACRO text_end db TX_END ENDM +DEF TEXT_SCRIPT_CONST_LIMIT EQU const_value + ; Text script IDs (see home/text_script.asm) - const_def -1, -1 + const_def $ff, -1, TEXT_SCRIPT_CONST_LIMIT const TX_SCRIPT_POKECENTER_NURSE ; $ff MACRO script_pokecenter_nurse