From c5675927feefc60a286de1725515d1475a30ca2c Mon Sep 17 00:00:00 2001 From: Remy Oukaour Date: Tue, 12 Dec 2017 12:18:11 -0500 Subject: Identify more sprite-related constants --- docs/map_scripts.md | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) (limited to 'docs') diff --git a/docs/map_scripts.md b/docs/map_scripts.md index edd3657ec..e259638dd 100644 --- a/docs/map_scripts.md +++ b/docs/map_scripts.md @@ -3,7 +3,7 @@ ## `const_value set 2` -### `const` *`MAPNAME_PERSONNAME`* +- **`const` *`MAPNAME_PERSONNAME`*** ## `MapName_MapScriptHeader:` @@ -11,16 +11,18 @@ ## `.MapTriggers: db` *N* -### `maptrigger` *script* +- **`maptrigger` *script*** ## `.MapCallbacks: db` *N* -### `dbw` *type*, *script* +- **`dbw` *type*, *script*** ## Scripts +[Scripting commands](docs/scripting_commands.md) + ## Text @@ -39,19 +41,19 @@ ## `.Warps: db` *N* -### `warp_def` *y*, *x*, *warp_id*, *map* +- **`warp_def` *y*, *x*, *warp_id*, *map*** ## `.XYTriggers: db` *N* -### `xy_trigger` *id*, *y*, *x*, `$0`, *script*, `$0`, `$0` +- **`xy_trigger` *id*, *y*, *x*, `$0`, *script*, `$0`, `$0`** ## `.Signposts: db` *N* -### `signpost` *y*, *x*, *type*, *script* +- `signpost` *y*, *x*, *type*, *script*** -#### Signpost types: +Signpost types: - **`SIGNPOST_READ`** @@ -69,9 +71,9 @@ ## `.PersonEvents: db` *N* -### `person_event` *sprite*, *y*, *x*, *movement*, *ry*, *rx*, *hour*, *daytime*, *palette*, *type*, *range*, *script*, *event_flag* +- **`person_event` *sprite*, *y*, *x*, *movement*, *ry*, *rx*, *hour*, *daytime*, *palette*, *type*, *range*, *script*, *event_flag*** -#### Movement types: +Movement types: - **`SPRITEMOVEDATA_ITEM_TREE`** @@ -105,7 +107,7 @@ - **`SPRITEMOVEDATA_LAPRAS`** -#### Person types: +Person types: - **`PERSONTYPE_SCRIPT`** -- cgit v1.2.3 From 5b13a7a13b9ebbb26a75b9ef19221e8e140c221b Mon Sep 17 00:00:00 2001 From: Remy Oukaour Date: Tue, 12 Dec 2017 13:22:19 -0500 Subject: Identify more sprite-related constants Start more documentation --- docs/move_anim_commands.md | 99 ++++++++++++++++++++++++++++++++++++++++++++++ docs/movement_commands.md | 81 +++++++++++++++++++++++++++++++++++++ 2 files changed, 180 insertions(+) create mode 100644 docs/move_anim_commands.md create mode 100644 docs/movement_commands.md (limited to 'docs') diff --git a/docs/move_anim_commands.md b/docs/move_anim_commands.md new file mode 100644 index 000000000..5669187f7 --- /dev/null +++ b/docs/move_anim_commands.md @@ -0,0 +1,99 @@ +# Move Animation Commands + +## `$00`−`$EF`: `anim_wait` *length* + +## `$D0`: `anim_obj` *object*, *x*, *y*, *param* + +## `$D1`: `anim_1gfx` *gfx* + +## `$D2`: `anim_2gfx` *gfx1*, *gfx2* + +## `$D3`: `anim_3gfx` *gfx1*, *gfx2*, *gfx3* + +## `$D4`: `anim_4gfx` *gfx1*, *gfx2*, *gfx3*, *gfx4* + +## `$D5`: `anim_5gfx` *gfx1*, *gfx2*, *gfx3*, *gfx4*, *gfx5* + +## `$D6`: `anim_incobj` *id* + +## `$D7`: `anim_setobj` *id*, *object* + +## `$D8`: `anim_incbgeffect` *effect* + +## `$D9`: `anim_enemyfeetobj` + +## `$DA`: `anim_playerheadobj` + +## `$DB`: `anim_checkpokeball` + +## `$DC`: `anim_transform` + +## `$DD`: `anim_raisesub` + +## `$DE`: `anim_dropsub` + +## `$DF`: `anim_resetobp0` + +## `$E0`: `anim_sound` *duration*, *tracks*, *id* + +## `$E1`: `anim_cry` *pitch* + +## `$E2`: `anim_minimizeopp` + +## `$E3`: `anim_oamon` + +## `$E4`: `anim_oamoff` + +## `$E5`: `anim_clearobjs` + +## `$E6`: `anim_beatup` + +## `$E7`: `anim_0xe7` + +## `$E8`: `anim_updateactorpic` + +## `$E9`: `anim_minimize` + +## `$EA`: `anim_0xea` + +## `$EB`: `anim_0xeb` + +## `$EC`: `anim_0xec` + +## `$ED`: `anim_0xed` + +## `$EE`: `anim_if_param_and` *value*, *address* + +## `$EF`: `anim_jumpuntil` *address* + +## `$F0`: `anim_bgeffect` *effect*, *unknown1*, *unknown2*, *unknown3* + +## `$F1`: `anim_bgp` *colors* + +## `$F2`: `anim_obp0` *colors* + +## `$F3`: `anim_obp1` *colors* + +## `$F4`: `anim_clearsprites` + +## `$F5`: `anim_0xf5` + +## `$F6`: `anim_0xf6` + +## `$F7`: `anim_0xf7` + +## `$F8`: `anim_if_param_equal` *value*, *address* + +## `$F9`: `anim_setvar` *value* + +## `$FA`: `anim_incvar` + +## `$FB`: `anim_if_var_equal` *value*, *address* + +## `$FC`: `anim_jump` *address* + +## `$FD`: `anim_loop` *count*, *address* + +## `$FE`: `anim_call` *address* + +## `$FF`: `anim_ret` diff --git a/docs/movement_commands.md b/docs/movement_commands.md new file mode 100644 index 000000000..702bd1f6c --- /dev/null +++ b/docs/movement_commands.md @@ -0,0 +1,81 @@ +# Movement Commands + +## `$00`−`$03`: `turn_head` *direction* + +## `$04`−`$07`: `turn_step` *direction* + +## `$08`−`$0B`: `slow_step` *direction* + +## `$0C`−`$0F`: `step` *direction* + +## `$10`−`$13`: `big_step` *direction* + +## `$14`−`$17`: `slow_slide_step` *direction* + +## `$18`−`$1B`: `slide_step` *direction* + +## `$1C`−`$1F`: `fast_slide_step` *direction* + +## `$20`−`$23`: `turn_away` *direction* + +## `$24`−`$27`: `turn_in` *direction* + +## `$28`−`$2B`: `turn_waterfall` *direction* + +## `$2C`−`$2F`: `slow_jump_step` *direction* + +## `$30`−`$33`: `jump_step` *direction* + +## `$34`−`$37`: `fast_jump_step` *direction* + +## `$38`: `remove_sliding` + +## `$39`: `set_sliding` + +## `$3A`: `remove_fixed_facing` + +## `$3B`: `fix_facing` + +## `$3C`: `show_person` + +## `$3D`: `hide_person` + +## `$3E`−`$46`: `step_sleep` *length* + +## `$47`: `step_end` + +## `$48`: `step_48` *param* + +## `$49`: `remove_person` + +## `$4A`: `step_loop` + +## `$4B`: `step_4b` + +## `$4C`: `teleport_from` + +## `$4D`: `teleport_to` + +## `$4E`: `skyfall` + +## `$4F`: `step_dig` *length* + +## `$50`: `step_bump` + +## `$51`: `fish_got_bite` + +## `$52`: `fish_cast_rod` + +## `$53`: `hide_emote` + +## `$54`: `show_emote` + +## `$55`: `step_shake` *displacement* + +## `$56`: `tree_shake` + +## `$57`: `rock_smash` *length* + +## `$58`: `return_dig` *length* + +## `$59`: `skyfall_top` -- cgit v1.2.3 From 0b34c997d6b24ff3b229396c2b8351f08a132410 Mon Sep 17 00:00:00 2001 From: Remy Oukaour Date: Tue, 12 Dec 2017 13:51:07 -0500 Subject: Add basic documentation for text commands. --- docs/event_commands.md | 345 +++++++++++++++++++++++++++++++++++++++++++++ docs/map_scripts.md | 15 +- docs/scripting_commands.md | 345 --------------------------------------------- docs/text_commands.md | 131 +++++++++++++++++ 4 files changed, 484 insertions(+), 352 deletions(-) create mode 100644 docs/event_commands.md delete mode 100644 docs/scripting_commands.md create mode 100644 docs/text_commands.md (limited to 'docs') diff --git a/docs/event_commands.md b/docs/event_commands.md new file mode 100644 index 000000000..662159481 --- /dev/null +++ b/docs/event_commands.md @@ -0,0 +1,345 @@ +# Event Commands + +## `$00`: `scall` *script* + +## `$01`: `farscall` *script* + +## `$02`: `ptcall` *script* + +## `$03`: `jump` *script* + +## `$04`: `farjump` *script* + +## `$05`: `ptjump` *script* + +## `$06`: `if_equal` *byte*, *script* + +## `$07`: `if_not_equal` *byte*, *script* + +## `$08`: `iffalse` *script* + +## `$09`: `iftrue` *script* + +## `$0A`: `if_greater_than` *byte*, *script* + +## `$0B`: `if_less_than` *byte*, *script* + +## `$0C`: `jumpstd` *std_script* + +## `$0D`: `callstd` *std_script* + +## `$0E`: `callasm` *asm* + +## `$0F`: `special` *special_pointer* + +## `$10`: `ptcallasm` *asm* + +## `$11`: `checkmaptriggers` *map* + +## `$12`: `domaptrigger` *map*, *trigger_id* + +## `$13`: `checktriggers` + +## `$14`: `dotrigger` *trigger_id* + +## `$15`: `writebyte` *value* + +## `$16`: `addvar` *value* + +## `$17`: `random` *value* + +## `$18`: `checkver` + +## `$19`: `copybytetovar` *address* + +## `$1A`: `copyvartobyte` *address* + +## `$1B`: `loadvar` *address*, *value* + +## `$1C`: `checkcode` *variable* + +## `$1D`: `writevarcode` *variable* + +## `$1E`: `writecode` *variable*, *value* + +## `$1F`: `giveitem` *item_id*[, *quantity*=1] + +## `$20`: `takeitem` *item_id*[, *quantity*=1] + +## `$21`: `checkitem` *item_id* + +## `$22`: `givemoney` *account*, *value* + +## `$23`: `takemoney` *account*, *value* + +## `$24`: `checkmoney` *account*, *value* + +## `$25`: `givecoins` *value* + +## `$26`: `takecoins` *value* + +## `$27`: `checkcoins` *value* + +## `$28`: `addcellnum` *contact_id* + +## `$29`: `delcellnum` *contact_id* + +## `$2A`: `checkcellnum` *contact_id* + +## `$2B`: `checktime` *time* + +- **`checkmorn`:** `checktime MORN` +- **`checkday`:** `checktime DAY` +- **`checknite`:** `checktime NITE` + +## `$2C`: `checkpoke` *mon_id* + +## `$2D`: `givepoke` *mon_id*, *level*[, *item*=0[, *trainer*=0, *ot_name*, *nickname*]] + +## `$2E`: `giveegg` *mon_id*, *level* + +## `$2F`: `givepokeitem` *pointer* + +## `$30`: `checkpokeitem` *pointer* + +## `$31`: `checkevent` *event_flag* + +## `$32`: `clearevent` *event_flag* + +## `$33`: `setevent` *event_flag* + +## `$34`: `checkflag` *engine_flag* + +## `$35`: `clearflag` *engine_flag* + +## `$36`: `setflag` *engine_flag* + +## `$37`: `wildon` + +## `$38`: `wildoff` + +## `$39`: `xycompare` *pointer* + +## `$3A`: `warpmod` *warp_id*, *map* + +## `$3B`: `blackoutmod` *map* + +## `$3C`: `warp` *map*, *x*, *y* + +## `$3D`: `readmoney` *account*, *memory* + +## `$3E`: `readcoins` *memory* + +## `$3F`: `RAM2MEM` *memory* + +## `$40`: `pokenamemem` *mon_id*, *memory* + +## `$41`: `itemtotext` *item_id*, *memory* + +## `$42`: `mapnametotext` *memory* + +## `$43`: `trainertotext` *trainer_id*, *trainer_group*, *memory* + +## `$44`: `stringtotext` *text_pointer*, *memory* + +## `$45`: `itemnotify` + +## `$46`: `pocketisfull` + +## `$47`: `opentext` + +## `$48`: `refreshscreen` *dummy* + +## `$49`: `closetext` + +## `$4A`: `loadbytec2cf` *byte* + +## `$4B`: `farwritetext` *text_pointer* + +## `$4C`: `writetext` *text_pointer* + +## `$4D`: `repeattext` *byte1*, *byte2* + +## `$4E`: `yesorno` + +## `$4F`: `loadmenudata` *data_pointer* + +## `$50`: `closewindow` + +## `$51`: `jumptextfaceplayer` *text_pointer* + +## `$52`: `farjumptext` *text_pointer* + +## `$53`: `jumptext` *text_pointer* + +## `$54`: `waitbutton` + +## `$55`: `buttonsound` + +## `$56`: `pokepic` *mon_id* + +## `$57`: `closepokepic` + +## `$58`: `_2dmenu` + +## `$59`: `verticalmenu` + +## `$5A`: `loadpikachudata` + +## `$5B`: `randomwildmon` + +## `$5C`: `loadmemtrainer` + +## `$5D`: `loadwildmon` *mon_id*, *level* + +## `$5E`: `loadtrainer` *trainer_group*, *trainer_id* + +## `$5F`: `startbattle` + +## `$60`: `reloadmapafterbattle` + +## `$61`: `catchtutorial` *byte* + +## `$62`: `trainertext` *which_text* + +## `$63`: `trainerflagaction` *action* + +## `$64`: `winlosstext` *win_text_pointer*, *loss_text_pointer* + +## `$65`: `scripttalkafter` + +## `$66`: `end_if_just_battled` + +## `$67`: `check_just_battled` + +## `$68`: `setlasttalked` *person* + +## `$69`: `applymovement` *person*, *data_pointer* + +## `$6A`: `applymovement2` *data_pointer* + +## `$6B`: `faceplayer` + +## `$6C`: `faceperson` *person1*, *person2* + +## `$6D`: `variablesprite` *variable_sprite_id*, *sprite_id* + +## `$6E`: `disappear` *person* + +## `$6F`: `appear` *person* + +## `$70`: `follow` *person2*, *person1* + +## `$71`: `stopfollow` + +## `$72`: `moveperson` *person*, *x*, *y* + +## `$73`: `writepersonxy` *person* + +## `$74`: `loademote` *emote_id* + +## `$75`: `showemote` *emote_id*, *person*, *length* + +## `$76`: `spriteface` *person*, *facing* + +## `$77`: `follownotexact` *person2*, *person1* + +## `$78`: `earthquake` *param* + +## `$79`: `changemap` *bank*, *blockdata_pointer* + +## `$7A`: `changeblock` *x*, *y*, *block* + +## `$7B`: `reloadmap` + +## `$7C`: `reloadmappart` + +## `$7D`: `writecmdqueue` *queue_pointer* + +## `$7E`: `delcmdqueue` *byte* + +## `$7F`: `playmusic` *music_id* + +## `$80`: `encountermusic` + +## `$81`: `musicfadeout` *music_id*, *length* + +## `$82`: `playmapmusic` + +## `$83`: `dontrestartmapmusic` + +## `$84`: `cry` *mon_id* + +## `$85`: `playsound` *sfx_id* + +## `$86`: `waitsfx` + +## `$87`: `warpsound` + +## `$88`: `specialsound` + +## `$89`: `passtoengine` *data_pointer* + +## `$8A`: `newloadmap` *which_method* + +## `$8B`: `pause` *length* + +## `$8C`: `deactivatefacing` *length* + +## `$8D`: `priorityjump` *script* + +## `$8E`: `warpcheck` + +## `$8F`: `ptpriorityjump` *script* + +## `$90`: `return` + +## `$91`: `end` + +## `$92`: `reloadandreturn` *which_method* + +## `$93`: `end_all` + +## `$94`: `pokemart` *dialog_id*, *mart_id* + +## `$95`: `elevator` *floor_list* + +## `$96`: `trade` *trade_id* + +## `$97`: `askforphonenumber` *contact_id* + +## `$98`: `phonecall` *call_id* + +## `$99`: `hangup` + +## `$9A`: `describedecoration` *byte* + +## `$9B`: `fruittree` *tree_id* + +## `$9C`: `specialphonecall` *call_id* + +## `$9D`: `checkphonecall` + +## `$9E`: `verbosegiveitem` *item_id*[, *quantity*=1] + +## `$9F`: `verbosegiveitem2` *item_id*, *variable* + +## `$A0`: `swarm` *swarm_id*, *map* + +## `$A1`: `halloffame` + +## `$A2`: `credits` + +## `$A3`: `warpfacing` *facing*, *map*, *x*, *y* + +## `$A4`: `battletowertext` *memory* + +## `$A5`: `landmarktotext` *landmark_id*, *memory* + +## `$A6`: `trainerclassname` *trainer_group*, *memory* + +## `$A7`: `name` *type*, *id*, *memory* + +## `$A8`: `wait` *duration* + +## `$A9`: `check_save` diff --git a/docs/map_scripts.md b/docs/map_scripts.md index e259638dd..e7138c4c8 100644 --- a/docs/map_scripts.md +++ b/docs/map_scripts.md @@ -19,18 +19,19 @@ - **`dbw` *type*, *script*** -## Scripts +## Event scripts -[Scripting commands](docs/scripting_commands.md) +[Event commands](docs/event_commands.md) ## Text -- **`text`** -- **`line`** -- **`cont`** -- **`para`** -- **`done`** +[Text commands](docs/text_commands.md) + + +## Movement data + +[Movement commands](docs/movement_commands.md) ## `MapName_MapEventHeader:` diff --git a/docs/scripting_commands.md b/docs/scripting_commands.md deleted file mode 100644 index 32ba7d338..000000000 --- a/docs/scripting_commands.md +++ /dev/null @@ -1,345 +0,0 @@ -# Scripting Commands - -## `$00`: `scall` *script* - -## `$01`: `farscall` *script* - -## `$02`: `ptcall` *script* - -## `$03`: `jump` *script* - -## `$04`: `farjump` *script* - -## `$05`: `ptjump` *script* - -## `$06`: `if_equal` *byte*, *script* - -## `$07`: `if_not_equal` *byte*, *script* - -## `$08`: `iffalse` *script* - -## `$09`: `iftrue` *script* - -## `$0A`: `if_greater_than` *byte*, *script* - -## `$0B`: `if_less_than` *byte*, *script* - -## `$0C`: `jumpstd` *std_script* - -## `$0D`: `callstd` *std_script* - -## `$0E`: `callasm` *asm* - -## `$0F`: `special` *special_pointer* - -## `$10`: `ptcallasm` *asm* - -## `$11`: `checkmaptriggers` *map* - -## `$12`: `domaptrigger` *map*, *trigger_id* - -## `$13`: `checktriggers` - -## `$14`: `dotrigger` *trigger_id* - -## `$15`: `writebyte` *value* - -## `$16`: `addvar` *value* - -## `$17`: `random` *value* - -## `$18`: `checkver` - -## `$19`: `copybytetovar` *address* - -## `$1A`: `copyvartobyte` *address* - -## `$1B`: `loadvar` *address*, *value* - -## `$1C`: `checkcode` *variable* - -## `$1D`: `writevarcode` *variable* - -## `$1E`: `writecode` *variable*, *value* - -## `$1F`: `giveitem` *item_id*[, *quantity*=1] - -## `$20`: `takeitem` *item_id*[, *quantity*=1] - -## `$21`: `checkitem` *item_id* - -## `$22`: `givemoney` *account*, *value* - -## `$23`: `takemoney` *account*, *value* - -## `$24`: `checkmoney` *account*, *value* - -## `$25`: `givecoins` *value* - -## `$26`: `takecoins` *value* - -## `$27`: `checkcoins` *value* - -## `$28`: `addcellnum` *contact_id* - -## `$29`: `delcellnum` *contact_id* - -## `$2A`: `checkcellnum` *contact_id* - -## `$2B`: `checktime` *time* - -- **`checkmorn`:** `checktime MORN` -- **`checkday`:** `checktime DAY` -- **`checknite`:** `checktime NITE` - -## `$2C`: `checkpoke` *mon_id* - -## `$2D`: `givepoke` *mon_id*, *level*[, *item*=0[, *trainer*=0, *ot_name*, *nickname*]] - -## `$2E`: `giveegg` *mon_id*, *level* - -## `$2F`: `givepokeitem` *pointer* - -## `$30`: `checkpokeitem` *pointer* - -## `$31`: `checkevent` *event_flag* - -## `$32`: `clearevent` *event_flag* - -## `$33`: `setevent` *event_flag* - -## `$34`: `checkflag` *engine_flag* - -## `$35`: `clearflag` *engine_flag* - -## `$36`: `setflag` *engine_flag* - -## `$37`: `wildon` - -## `$38`: `wildoff` - -## `$39`: `xycompare` *pointer* - -## `$3A`: `warpmod` *warp_id*, *map* - -## `$3B`: `blackoutmod` *map* - -## `$3C`: `warp` *map*, *x*, *y* - -## `$3D`: `readmoney` *account*, *memory* - -## `$3E`: `readcoins` *memory* - -## `$3F`: `RAM2MEM` *memory* - -## `$40`: `pokenamemem` *mon_id*, *memory* - -## `$41`: `itemtotext` *item_id*, *memory* - -## `$42`: `mapnametotext` *memory* - -## `$43`: `trainertotext` *trainer_id*, *trainer_group*, *memory* - -## `$44`: `stringtotext` *text_pointer*, *memory* - -## `$45`: `itemnotify` - -## `$46`: `pocketisfull` - -## `$47`: `opentext` - -## `$48`: `refreshscreen` *dummy* - -## `$49`: `closetext` - -## `$4A`: `loadbytec2cf` *byte* - -## `$4B`: `farwritetext` *text_pointer* - -## `$4C`: `writetext` *text_pointer* - -## `$4D`: `repeattext` *byte1*, *byte2* - -## `$4E`: `yesorno` - -## `$4F`: `loadmenudata` *data_pointer* - -## `$50`: `closewindow` - -## `$51`: `jumptextfaceplayer` *text_pointer* - -## `$52`: `farjumptext` *text_pointer* - -## `$53`: `jumptext` *text_pointer* - -## `$54`: `waitbutton` - -## `$55`: `buttonsound` - -## `$56`: `pokepic` *mon_id* - -## `$57`: `closepokepic` - -## `$58`: `_2dmenu` - -## `$59`: `verticalmenu` - -## `$5A`: `loadpikachudata` - -## `$5B`: `randomwildmon` - -## `$5C`: `loadmemtrainer` - -## `$5D`: `loadwildmon` *mon_id*, *level* - -## `$5E`: `loadtrainer` *trainer_group*, *trainer_id* - -## `$5F`: `startbattle` - -## `$60`: `reloadmapafterbattle` - -## `$61`: `catchtutorial` *byte* - -## `$62`: `trainertext` *which_text* - -## `$63`: `trainerflagaction` *action* - -## `$64`: `winlosstext` *win_text_pointer*, *loss_text_pointer* - -## `$65`: `scripttalkafter` - -## `$66`: `end_if_just_battled` - -## `$67`: `check_just_battled` - -## `$68`: `setlasttalked` *person* - -## `$69`: `applymovement` *person*, *data_pointer* - -## `$6A`: `applymovement2` *data_pointer* - -## `$6B`: `faceplayer` - -## `$6C`: `faceperson` *person1*, *person2* - -## `$6D`: `variablesprite` *variable_sprite_id*, *sprite_id* - -## `$6E`: `disappear` *person* - -## `$6F`: `appear` *person* - -## `$70`: `follow` *person2*, *person1* - -## `$71`: `stopfollow` - -## `$72`: `moveperson` *person*, *x*, *y* - -## `$73`: `writepersonxy` *person* - -## `$74`: `loademote` *emote_id* - -## `$75`: `showemote` *emote_id*, *person*, *length* - -## `$76`: `spriteface` *person*, *facing* - -## `$77`: `follownotexact` *person2*, *person1* - -## `$78`: `earthquake` *param* - -## `$79`: `changemap` *bank*, *blockdata_pointer* - -## `$7A`: `changeblock` *x*, *y*, *block* - -## `$7B`: `reloadmap` - -## `$7C`: `reloadmappart` - -## `$7D`: `writecmdqueue` *queue_pointer* - -## `$7E`: `delcmdqueue` *byte* - -## `$7F`: `playmusic` *music_id* - -## `$80`: `encountermusic` - -## `$81`: `musicfadeout` *music_id*, *length* - -## `$82`: `playmapmusic` - -## `$83`: `dontrestartmapmusic` - -## `$84`: `cry` *mon_id* - -## `$85`: `playsound` *sfx_id* - -## `$86`: `waitsfx` - -## `$87`: `warpsound` - -## `$88`: `specialsound` - -## `$89`: `passtoengine` *data_pointer* - -## `$8A`: `newloadmap` *which_method* - -## `$8B`: `pause` *length* - -## `$8C`: `deactivatefacing` *length* - -## `$8D`: `priorityjump` *script* - -## `$8E`: `warpcheck` - -## `$8F`: `ptpriorityjump` *script* - -## `$90`: `return` - -## `$91`: `end` - -## `$92`: `reloadandreturn` *which_method* - -## `$93`: `end_all` - -## `$94`: `pokemart` *dialog_id*, *mart_id* - -## `$95`: `elevator` *floor_list* - -## `$96`: `trade` *trade_id* - -## `$97`: `askforphonenumber` *contact_id* - -## `$98`: `phonecall` *call_id* - -## `$99`: `hangup` - -## `$9A`: `describedecoration` *byte* - -## `$9B`: `fruittree` *tree_id* - -## `$9C`: `specialphonecall` *call_id* - -## `$9D`: `checkphonecall` - -## `$9E`: `verbosegiveitem` *item_id*[, *quantity*=1] - -## `$9F`: `verbosegiveitem2` *item_id*, *variable* - -## `$A0`: `swarm` *swarm_id*, *map* - -## `$A1`: `halloffame` - -## `$A2`: `credits` - -## `$A3`: `warpfacing` *facing*, *map*, *x*, *y* - -## `$A4`: `battletowertext` *memory* - -## `$A5`: `landmarktotext` *landmark_id*, *memory* - -## `$A6`: `trainerclassname` *trainer_group*, *memory* - -## `$A7`: `name` *type*, *id*, *memory* - -## `$A8`: `wait` *duration* - -## `$A9`: `check_save` diff --git a/docs/text_commands.md b/docs/text_commands.md new file mode 100644 index 000000000..3d502f399 --- /dev/null +++ b/docs/text_commands.md @@ -0,0 +1,131 @@ +# Text Commands + +## `$00`: `text` *text* + +Start writing text until `"@"`. + +## `$4E`: `next` *text* + +Move a line down. + +## `$4F`: `line` *text* + +Start writing at the bottom line. + +## `$50`: `page` *text* + +Start a new Pokédex page. + +## `$51`: `para` *text* + +Start a new paragraph. + +## `$55`: `cont` *text* + +Scroll to the next line. + +## `$57`: `done` + +End a text box. + +## `$58`: `prompt` + +Prompt the player to end a text box (initiating some other event). + +## `$01`: `text_from_ram` *address* + +Write text from a RAM address. + +## `$02`: `text_bcd` *address*, *flags* + +Write [BCD](https://en.wikipedia.org/wiki/Binary-coded_decimal) from an address, +typically RAM. + +## `$03`: `text_move` *address* + +Move to a new tile. + +## `$04`: `text_box` *address*, *height*, *width* + +Draw a box. + +## `$05`: `text_low` + +Write text at (1, 16). + +## `$06`: `text_waitbutton` + +Wait for button press; show arrow. + +## `$07`: `text_scroll` + +Pushes text up two lines and sets the `bc` cursor to the border tile below the +first character column of the text box. + +## `$08`: `start_asm` + +Start interpreting assembly code. + +## `$09`: `deciram` *address*, *bytes*, *digits* + +Read *bytes* bytes from *address* and print them as a *digits*-digit number. + +## `$0A`: `interpret_data` + +Exit. + +## `$0B`: `sound_dex_fanfare_50_79` + +Play `SFX_DEX_FANFARE_50_79`. + +## `$0C`: `limited_interpret_data` *number* + +Print *number* `"…"`s. + +## `$0D`: `link_wait_button` + +Wait for button press; show arrow. + +## `$0E`: `sound_dex_fanfare_20_49` + +Play `SFX_DEX_FANFARE_20_49`. + +## `$0F`: `sound_item` + +Play `SFX_ITEM`. + +## `$10`: `sound_caught_mon` + +Play `SFX_CAUGHT_MON`. + +## `$11`: `sound_dex_fanfare_80_109` + +Play `SFX_DEX_FANFARE_80_109`. + +## `$12`: `sound_fanfare` + +Play `SFX_FANFARE`. + +## `$13`: `sound_slot_machine_start` + +Play `SFX_SLOT_MACHINE_START`. + +## `$14`: `text_buffer` *id* + +Write text from one of the following addresses (listed in `StringBufferPointers`): + +0. `StringBuffer3` +1. `StringBuffer4` +2. `StringBuffer5` +3. `StringBuffer2` +4. `StringBuffer1` +5. `EnemyMonNick` +6. `BattleMonNick` + +## `$15`: `current_day` + +Print the weekday. + +## `$16`: `text_jump` *address* + +Write text from a different bank. -- cgit v1.2.3 From 906d356e09fd8bf59d97d151aec0ffc3e25ca7f5 Mon Sep 17 00:00:00 2001 From: Remy Oukaour Date: Tue, 12 Dec 2017 13:51:58 -0500 Subject: Fix relative links --- docs/map_scripts.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'docs') diff --git a/docs/map_scripts.md b/docs/map_scripts.md index e7138c4c8..47c6f4f67 100644 --- a/docs/map_scripts.md +++ b/docs/map_scripts.md @@ -21,17 +21,17 @@ ## Event scripts -[Event commands](docs/event_commands.md) +[Event commands](event_commands.md) ## Text -[Text commands](docs/text_commands.md) +[Text commands](text_commands.md) ## Movement data -[Movement commands](docs/movement_commands.md) +[Movement commands](movement_commands.md) ## `MapName_MapEventHeader:` -- cgit v1.2.3 From 33eb3c6af263773674d18fcc18457a71ee976ffc Mon Sep 17 00:00:00 2001 From: Remy Oukaour Date: Tue, 12 Dec 2017 13:56:17 -0500 Subject: Start documentation for map callbacks. --- docs/map_scripts.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'docs') diff --git a/docs/map_scripts.md b/docs/map_scripts.md index 47c6f4f67..7546a5ad7 100644 --- a/docs/map_scripts.md +++ b/docs/map_scripts.md @@ -18,6 +18,24 @@ - **`dbw` *type*, *script*** +Callback types: + +- **`MAPCALLBACK_NEWMAP`** + +- **`MAPCALLBACK_TILES`** + +- **`MAPCALLBACK_OBJECTS`** + +- **`MAPCALLBACK_SPRITES`** + +- **`MAPCALLBACK_CMDQUEUE`** + + **`dbw CMDQUEUE_STONETABLE,` *table_pointer*** + + **`stonetable` *warp_id*, *person*, *script*** + + **`db -1 ; end`** + ## Event scripts -- cgit v1.2.3 From 8b501c19a6a70f8911159b510760eb3dbcb5a3a6 Mon Sep 17 00:00:00 2001 From: Remy Oukaour Date: Tue, 12 Dec 2017 13:57:14 -0500 Subject: Fix Markdown syntax --- docs/map_scripts.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs') diff --git a/docs/map_scripts.md b/docs/map_scripts.md index 7546a5ad7..f26de1949 100644 --- a/docs/map_scripts.md +++ b/docs/map_scripts.md @@ -70,7 +70,7 @@ Callback types: ## `.Signposts: db` *N* -- `signpost` *y*, *x*, *type*, *script*** +- **`signpost` *y*, *x*, *type*, *script*** Signpost types: -- cgit v1.2.3 From f0ab09125493f91d66af836e0abb977459a0d801 Mon Sep 17 00:00:00 2001 From: Remy Oukaour Date: Tue, 12 Dec 2017 18:50:39 -0500 Subject: Add an FAQ, and ive a bit more detail in Windows install instructions --- docs/text_commands.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'docs') diff --git a/docs/text_commands.md b/docs/text_commands.md index 3d502f399..865ea69b5 100644 --- a/docs/text_commands.md +++ b/docs/text_commands.md @@ -38,8 +38,9 @@ Write text from a RAM address. ## `$02`: `text_bcd` *address*, *flags* -Write [BCD](https://en.wikipedia.org/wiki/Binary-coded_decimal) from an address, -typically RAM. +Write [BCD](bcd) from an address, typically RAM. + +[bcd]: https://en.wikipedia.org/wiki/Binary-coded_decimal ## `$03`: `text_move` *address* -- cgit v1.2.3 From 93c32e35806af6c0a8b731c5322ee5df58c797f9 Mon Sep 17 00:00:00 2001 From: Remy Oukaour Date: Tue, 12 Dec 2017 20:15:07 -0500 Subject: Document bugs and glitches --- docs/bugs.md | 689 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 689 insertions(+) create mode 100644 docs/bugs.md (limited to 'docs') diff --git a/docs/bugs.md b/docs/bugs.md new file mode 100644 index 000000000..bbf23d249 --- /dev/null +++ b/docs/bugs.md @@ -0,0 +1,689 @@ +# Bugs + + +## Belly Drum sharply boosts Attack even with under 50% HP + +([Video](https://www.youtube.com/watch?v=zuCLMikWo4Y)) + +This is a bug with `BattleCommand_BellyDrum` in [battle/effect_commands.asm](battle/effect_commands.asm): + +``` +BattleCommand_BellyDrum: ; 37c1a +; bellydrum +; This command is buggy because it raises the user's attack +; before checking that it has enough HP to use the move. +; Swap the order of these two blocks to fix. + call BattleCommand_AttackUp2 + ld a, [AttackMissed] + and a + jr nz, .failed + + callab GetHalfMaxHP + callab CheckUserHasEnoughHP + jr nc, .failed +``` + +**Fix:** + +``` +BattleCommand_BellyDrum: ; 37c1a +; bellydrum + callab GetHalfMaxHP + callab CheckUserHasEnoughHP + jr nc, .failed + + call BattleCommand_AttackUp2 + ld a, [AttackMissed] + and a + jr nz, .failed +``` + + +## HP bar animation is slower with more HP + +([Video](https://www.youtube.com/watch?v=SE-BfsFgZVM)) + +This is a bug with `LongAnim_UpdateVariables` in [engine/anim_hp_bar.asm](engine/anim_hp_bar.asm): + +``` + ; This routine is buggy. The result from ComputeHPBarPixels is stored + ; in e. However, the pop de opcode deletes this result before it is even + ; used. The game then proceeds as though it never deleted that output. + ; To fix, uncomment the line below. + call ComputeHPBarPixels + ; ld a, e + pop bc + pop de + pop hl + ld a, e ; Comment or delete this line to fix the above bug. + ld hl, wCurHPBarPixels + cp [hl] + jr z, .loop + ld [hl], a + and a + ret +``` + +**Fix:** Move `ld a, e` to right after `call ComputeHPBarPixels`. + + +## Experience underflow for level 1 Pokémon with Medium-Slow growth rate + +([Video](https://www.youtube.com/watch?v=SXH8u0plHrE)) + +This can bring Pokémon straight from level 1 to 100 by gaining just a few experience points. + +This is a bug with `CalcExpAtLevel` in [main.asm](main.asm): + +``` +CalcExpAtLevel: ; 50e47 +; (a/b)*n**3 + c*n**2 + d*n - e + ld a, [BaseGrowthRate] + add a + add a + ld c, a + ld b, 0 + ld hl, GrowthRates + add hl, bc +``` + +**Fix:** + +``` +CalcExpAtLevel: ; 50e47 +; (a/b)*n**3 + c*n**2 + d*n - e + ld a, d + cp 1 + jr nz, .UseExpFormula +; Pokémon have 0 experience at level 1 + xor a + ld hl, hProduct + ld [hli], a + ld [hli], a + ld [hli], a + ld [hl], a + ret + +.UseExpFormula + ld a, [BaseGrowthRate] + add a + add a + ld c, a + ld b, 0 + ld hl, GrowthRates + add hl, bc +``` + + +## Five-digit experience gain is printed incorrectly + +([Video](https://www.youtube.com/watch?v=o54VjpAEoO8)) + +This is a bug with `Text_ABoostedStringBuffer2ExpPoints` and `Text_StringBuffer2ExpPoints` in [text/common_2.asm](text/common_2.asm): + +``` +Text_ABoostedStringBuffer2ExpPoints:: + text "" + line "a boosted" + cont "@" + deciram StringBuffer2, 2, 4 + text " EXP. Points!" + prompt + +Text_StringBuffer2ExpPoints:: + text "" + line "@" + deciram StringBuffer2, 2, 4 + text " EXP. Points!" + prompt +``` + +**Fix:** Change `deciram StringBuffer2, 2, 4` to `deciram StringBuffer2, 2, 5`. + + +## Present damage is incorrect in link battles + +([Video](https://www.youtube.com/watch?v=XJaQoKtrEuw)) + +This bug existed for all battles in Gold and Silver, and was only fixed for single-player battles in Crystal to preserve link compatibility. + +This is a bug with `BattleCommand_Present` in [battle/effects/present.asm](battle/effects/present.asm): + +``` +BattleCommand_Present: ; 37874 +; present + + ld a, [wLinkMode] + cp LINK_COLOSSEUM + jr z, .colosseum_skippush + push bc + push de +.colosseum_skippush + + call BattleCommand_Stab + + ld a, [wLinkMode] + cp LINK_COLOSSEUM + jr z, .colosseum_skippop + pop de + pop bc +.colosseum_skippop +``` + +**Fix:** + +``` +BattleCommand_Present: ; 37874 +; present + + push bc + push de + call BattleCommand_Stab + pop de + pop bc +``` + + +## BRN/PSN/PAR do not affect catch rate + +This is a bug with `PokeBall` in [items/item_effects.asm](items/item_effects.asm): + +``` +.statuscheck +; This routine is buggy. It was intended that SLP and FRZ provide a higher +; catch rate than BRN/PSN/PAR, which in turn provide a higher catch rate than +; no status effect at all. But instead, it makes BRN/PSN/PAR provide no +; benefit. +; Uncomment the line below to fix this. + ld b, a + ld a, [EnemyMonStatus] + and 1 << FRZ | SLP + ld c, 10 + jr nz, .addstatus + ; ld a, [EnemyMonStatus] + and a + ld c, 5 + jr nz, .addstatus + ld c, 0 +.addstatus + ld a, b + add c + jr nc, .max_1 + ld a, $ff +.max_1 +``` + +**Fix:** Uncomment `ld a, [EnemyMonStatus]`. + + +## Moon Ball does not boost catch rate + +This is a bug with `MoonBallMultiplier` in [items/item_effects.asm](items/item_effects.asm): + +``` +MoonBallMultiplier: +; This function is buggy. +; Intent: multiply catch rate by 4 if mon evolves with moon stone +; Reality: no boost + +... + +; Moon Stone's constant from Pokémon Red is used. +; No Pokémon evolve with Burn Heal, +; so Moon Balls always have a catch rate of 1×. + push bc + ld a, BANK(EvosAttacks) + call GetFarByte + cp MOON_STONE_RED ; BURN_HEAL + pop bc + ret nz +``` + +**Fix:** Change `MOON_STONE_RED` to `MOON_STONE`. + + +## Love Ball boosts catch rate for the wrong gender + +This is a bug with `LoveBallMultiplier` in [items/item_effects.asm](items/item_effects.asm): + +``` +LoveBallMultiplier: +; This function is buggy. +; Intent: multiply catch rate by 8 if mons are of same species, different sex +; Reality: multiply catch rate by 8 if mons are of same species, same sex + +... + + ld a, d + pop de + cp d + pop bc + ret nz ; for the intended effect, this should be "ret z" +``` + +**Fix:** Change `ret nz` to `ret z`. + + +## Fast Ball only boosts catch rate for three Pokémon + +This is a bug with `FastBallMultiplier` in [items/item_effects.asm](items/item_effects.asm): + +``` +FastBallMultiplier: +; This function is buggy. +; Intent: multiply catch rate by 4 if enemy mon is in one of the three +; FleeMons tables. +; Reality: multiply catch rate by 4 if enemy mon is one of the first three in +; the first FleeMons table. + +... + + inc hl + cp -1 + jr z, .next + cp c + jr nz, .next ; for the intended effect, this should be "jr nz, .loop" + sla b + jr c, .max +``` + +**Fix:** Change `jr nz, .next` to `jr nz, .loop`. + + +## Friend Ball catches sent to the PC overwrite the wrong Pokémon's happiness + +This is a bug with `PokeBall` in [items/item_effects.asm](items/item_effects.asm): + +``` + ld a, [CurItem] + cp FRIEND_BALL + jr nz, .SkipBoxMonFriendBall + ; Bug: overwrites the happiness of the first mon in the box! + ld a, FRIEND_BALL_HAPPINESS + ld [sBoxMon1Happiness], a +.SkipBoxMonFriendBall: +``` + +`sBoxMon1Happiness` is written *before* the Friend Ball Pokémon is deposited. + + +## Dragon Scale. not Dragon Fang, boosts Dragon-type moves + +This is a bug with `ItemAttributes` in [items/item_attributes.asm](items/item_attributes.asm): + +``` +; DRAGON FANG + item_attribute 100, 0, 0, CANT_SELECT, ITEM, ITEMMENU_NOUSE, ITEMMENU_NOUSE + +... + +; DRAGON SCALE + item_attribute 2100, HELD_DRAGON_BOOST, 10, CANT_SELECT, ITEM, ITEMMENU_NOUSE, ITEMMENU_NOUSE +``` + +**Fix:** Move `HELD_DRAGON_BOOST` to the `DRAGON FANG` attributes and `0` to `DRAGON SCALE`. + + +## Daisy's massages don't always increase happiness + +This is a bug with `MassageOrHaircut` in [event/special.asm](event/special.asm): + +``` +; Bug: Subtracting $ff from $ff fails to set c. +; This can result in overflow into the next data array. +; In the case of getting a massage from Daisy, we bleed +; into CopyPokemonName_Buffer1_Buffer3, which passes +; $d0 to ChangeHappiness and returns $73 to the script. +; The end result is that there is a 0.4% chance your +; Pokemon's happiness will not change at all. +.loop + sub [hl] + jr c, .ok + inc hl + inc hl + inc hl + jr .loop + +.ok + inc hl + ld a, [hli] + ld [ScriptVar], a + ld c, [hl] + call ChangeHappiness + ret + +... + +Data_DaisyMassage: ; 746b + db $ff, 2, HAPPINESS_MASSAGE ; 99.6% chance + +CopyPokemonName_Buffer1_Buffer3: ; 746e + ld hl, StringBuffer1 + ld de, StringBuffer3 + ld bc, PKMN_NAME_LENGTH + jp CopyBytes +``` + +**Fix:** + +``` +Data_DaisyMassage: ; 746b + db $80, 2, HAPPINESS_MASSAGE ; 50% chance + db $ff, 2, HAPPINESS_MASSAGE ; 50% chance +``` + + +## No bump noise if standing on tile `$3E` + +This is a bug with `DoPlayerMovement.CheckWarp` in [engine/player_movement.asm](engine/player_movement.asm): + +``` +; Bug: Since no case is made for STANDING here, it will check +; [.edgewarps + $ff]. This resolves to $3e at $8035a. +; This causes wd041 to be nonzero when standing on tile $3e, +; making bumps silent. + + ld a, [WalkingDirection] + ld e, a + ld d, 0 + ld hl, .EdgeWarps + add hl, de + ld a, [PlayerStandingTile] + cp [hl] + jr nz, .not_warp + + ld a, 1 + ld [wd041], a + ld a, [WalkingDirection] + cp STANDING + jr z, .not_warp +``` + +**Fix:** + +``` + ld a, [WalkingDirection] + cp STANDING + jr z, .not_warp + ld e, a + ld d, 0 + ld hl, .EdgeWarps + add hl, de + ld a, [PlayerStandingTile] + cp [hl] + jr nz, .not_warp + + ld a, 1 + ld [wd041], a + ld a, [WalkingDirection] +``` + + +## `CheckOwnMon` only checks the first five letters of OT names + +([Video](https://www.youtube.com/watch?v=GVTTmReM4nQ)) + +This bug can allow you to talk to Eusine in Celadon City and encounter Ho-Oh with only traded legendary beasts. + +[engine/search.asm](engine/search.asm): + +``` +; check OT +; This only checks five characters, which is fine for the Japanese version, +; but in the English version the player name is 7 characters, so this is wrong. + + ld hl, PlayerName + +rept PLAYER_NAME_LENGTH_JAPANESE - 1 ; should be PLAYER_NAME_LENGTH - 1 + ld a, [de] + cp [hl] + jr nz, .notfound + cp "@" + jr z, .found ; reached end of string + inc hl + inc de +endr + + ld a, [de] + cp [hl] + jr z, .found + +.notfound + pop de + pop hl + pop bc + and a + ret +``` + +**Fix:** Change `rept PLAYER_NAME_LENGTH_JAPANESE - 1` to `rept PLAYER_NAME_LENGTH - 1`. + + +## `HELD_CATCH_CHANCE` has no effect + +This is a bug with `PokeBall` in [items/item_effects.asm](items/item_effects.asm): + +``` + ; BUG: callba overwrites a, + ; and GetItemHeldEffect takes b anyway. + + ; This is probably the reason + ; the HELD_CATCH_CHANCE effect + ; is never used. + + ; Uncomment the line below to fix. + + ld a, [BattleMonItem] +; ld b, a + callba GetItemHeldEffect + ld a, b + cp HELD_CATCH_CHANCE +``` + +**Fix:** Uncomment `ld b, a`. + + +## `ScriptCall` can overflow `wScriptStack` and crash + +[engine/scripting.asm](engine/scripting.asm): + +``` +ScriptCall: +; Bug: The script stack has a capacity of 5 scripts, yet there is +; nothing to stop you from pushing a sixth script. The high part +; of the script address can then be overwritten by modifications +; to ScriptDelay, causing the script to return to the rst/interrupt +; space. + + push de + ld hl, wScriptStackSize + ld e, [hl] + inc [hl] + ld d, $0 + ld hl, wScriptStack + add hl, de + add hl, de + add hl, de + pop de + ld a, [ScriptBank] + ld [hli], a + ld a, [ScriptPos] + ld [hli], a + ld a, [ScriptPos + 1] + ld [hl], a + ld a, b + ld [ScriptBank], a + ld a, e + ld [ScriptPos], a + ld a, d + ld [ScriptPos + 1], a + ret +``` + + +## `LoadSpriteGFX` does not limit the capacity of `UsedSprites` + +[engine/overworld.asm](engine/overworld.asm): + +``` +LoadSpriteGFX: ; 14306 +; Bug: b is not preserved, so +; it's useless as a next count. + + ld hl, UsedSprites + ld b, SPRITE_GFX_LIST_CAPACITY +.loop + ld a, [hli] + and a + jr z, .done + push hl + call .LoadSprite + pop hl + ld [hli], a + dec b + jr nz, .loop + +.done + ret + +.LoadSprite: + call GetSprite + ld a, l + ret +; 1431e +``` + +`GetSprite` modifies `b`. Surround it with `push bc`/`pop bc` to fix. + + +## `ChooseWildEncounter` doesn't really validate the wild Pokémon species + +[engine/wildmons.asm](engine/wildmons.asm): + +``` +ChooseWildEncounter: ; 2a14f +... + + ld a, b + ld [CurPartyLevel], a + ld b, [hl] + ; ld a, b + call ValidateTempWildMonSpecies + jr c, .nowildbattle + + ld a, b ; This is in the wrong place. + cp UNOWN + jr nz, .done + +... + +ValidateTempWildMonSpecies: ; 2a4a0 +; Due to a development oversight, this function is called with the wild Pokemon's level, not its species, in a. +``` + +**Fix:** + +``` + ld a, b + ld [CurPartyLevel], a + ld b, [hl] + ld a, b + call ValidateTempWildMonSpecies + jr c, .nowildbattle + + cp UNOWN + jr nz, .done +``` + +## `TryObjectEvent` arbitrary code execution + +[engine/events.asm](engine/events.asm): + +``` +; Bug: If IsInArray returns nc, data at bc will be executed as code. + push bc + ld de, 3 + ld hl, .pointers + call IsInArray + jr nc, .nope_bugged + pop bc + + inc hl + ld a, [hli] + ld h, [hl] + ld l, a + jp hl + +.nope_bugged + ; pop bc + xor a + ret +``` + +**Fix:** Uncomment `pop bc`. + + +## `Special_CheckBugContestContestantFlag` can read beyond its data table + +[event/bug_contest_2.asm](event/bug_contest_2.asm): + +``` +Special_CheckBugContestContestantFlag: ; 139ed +; Checks the flag of the Bug Catching Contestant whose index is loaded in a. + +; Bug: If a >= 10 when this is called, it will read beyond the table. + + ld hl, BugCatchingContestantEventFlagTable + ld e, a + ld d, 0 + add hl, de + add hl, de + ld e, [hl] + inc hl + ld d, [hl] + ld b, CHECK_FLAG + call EventFlagAction + ret +; 139fe + +BugCatchingContestantEventFlagTable: ; 139fe + dw EVENT_BUG_CATCHING_CONTESTANT_1A + dw EVENT_BUG_CATCHING_CONTESTANT_2A + dw EVENT_BUG_CATCHING_CONTESTANT_3A + dw EVENT_BUG_CATCHING_CONTESTANT_4A + dw EVENT_BUG_CATCHING_CONTESTANT_5A + dw EVENT_BUG_CATCHING_CONTESTANT_6A + dw EVENT_BUG_CATCHING_CONTESTANT_7A + dw EVENT_BUG_CATCHING_CONTESTANT_8A + dw EVENT_BUG_CATCHING_CONTESTANT_9A + dw EVENT_BUG_CATCHING_CONTESTANT_10A +; 13a12 +``` + + +## `ClearWRAM` only clears WRAM bank 1 + +[home/init.asm](home/init.asm): + +``` +ClearWRAM:: ; 25a +; Wipe swappable WRAM banks (1-7) +; Assumes CGB or AGB + + ld a, 1 +.bank_loop + push af + ld [rSVBK], a + xor a + ld hl, $d000 + ld bc, $1000 + call ByteFill + pop af + inc a + cp 8 + jr nc, .bank_loop ; Should be jr c + ret +; 270 +``` + +**Fix:** Change `jr nc, .bank_loop` to `jr c, .bank_loop`. -- cgit v1.2.3 From ad620243d937bf241a1feca8c96b18f805b946af Mon Sep 17 00:00:00 2001 From: Remy Oukaour Date: Tue, 12 Dec 2017 20:21:08 -0500 Subject: Fix `make compare` --- docs/bugs.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'docs') diff --git a/docs/bugs.md b/docs/bugs.md index bbf23d249..4e252699b 100644 --- a/docs/bugs.md +++ b/docs/bugs.md @@ -434,7 +434,7 @@ This bug can allow you to talk to Eusine in Celadon City and encounter Ho-Oh wit ld hl, PlayerName -rept PLAYER_NAME_LENGTH_JAPANESE - 1 ; should be PLAYER_NAME_LENGTH - 1 +rept NAME_LENGTH_JAPANESE +- 2 ; should be PLAYER_NAME_LENGTH +- 2 ld a, [de] cp [hl] jr nz, .notfound @@ -456,7 +456,7 @@ endr ret ``` -**Fix:** Change `rept PLAYER_NAME_LENGTH_JAPANESE - 1` to `rept PLAYER_NAME_LENGTH - 1`. +**Fix:** Change `rept NAME_LENGTH_JAPANESE +- 2` to `rept PLAYER_NAME_LENGTH +- 2`. ## `HELD_CATCH_CHANCE` has no effect -- cgit v1.2.3 From 370839cad72da50d6ef4024d9e9ad601755fb0b3 Mon Sep 17 00:00:00 2001 From: Remy Oukaour Date: Tue, 12 Dec 2017 20:50:34 -0500 Subject: Keep the "Bugs and Glitches" name --- docs/bugs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs') diff --git a/docs/bugs.md b/docs/bugs.md index 4e252699b..3f5679e50 100644 --- a/docs/bugs.md +++ b/docs/bugs.md @@ -1,4 +1,4 @@ -# Bugs +# Bugs and Glitches ## Belly Drum sharply boosts Attack even with under 50% HP -- cgit v1.2.3 From 7748b20c271d1802afce53ad6dc87d5d0e1c14b8 Mon Sep 17 00:00:00 2001 From: Remy Oukaour Date: Tue, 12 Dec 2017 21:16:15 -0500 Subject: GetForestTreeFrame is not technically a bug or glitch, but it's exceptional --- docs/bugs.md | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) (limited to 'docs') diff --git a/docs/bugs.md b/docs/bugs.md index 3f5679e50..06626d7db 100644 --- a/docs/bugs.md +++ b/docs/bugs.md @@ -687,3 +687,46 @@ ClearWRAM:: ; 25a ``` **Fix:** Change `jr nc, .bank_loop` to `jr c, .bank_loop`. + + +## `GetForestTreeFrame` works, but it's still bad + +[tilesets/animations.asm](tilesets/animations.asm): + +``` +GetForestTreeFrame: ; fc54c +; Return 0 if a is even, or 2 if odd. + and a + jr z, .even + cp 1 + jr z, .odd + cp 2 + jr z, .even + cp 3 + jr z, .odd + cp 4 + jr z, .even + cp 5 + jr z, .odd + cp 6 + jr z, .even +.odd + ld a, 2 + scf + ret +.even + xor a + ret +; fc56d +``` + +**Fix:** + +``` +GetForestTreeFrame: ; fc54c +; Return 0 if a is even, or 2 if odd. + and 1 + add a + ret +; fc56d +``` -- cgit v1.2.3 From c85587d973df6565f2863493acb9f9af88518662 Mon Sep 17 00:00:00 2001 From: Remy Oukaour Date: Tue, 12 Dec 2017 21:29:53 -0500 Subject: Remove unused constant Fix typo --- docs/bugs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs') diff --git a/docs/bugs.md b/docs/bugs.md index 06626d7db..cf92bbba2 100644 --- a/docs/bugs.md +++ b/docs/bugs.md @@ -307,7 +307,7 @@ This is a bug with `PokeBall` in [items/item_effects.asm](items/item_effects.asm `sBoxMon1Happiness` is written *before* the Friend Ball Pokémon is deposited. -## Dragon Scale. not Dragon Fang, boosts Dragon-type moves +## Dragon Scale, not Dragon Fang, boosts Dragon-type moves This is a bug with `ItemAttributes` in [items/item_attributes.asm](items/item_attributes.asm): -- cgit v1.2.3 From 10eb426e40f48df3ae9b40e3ea3aa7e92f890090 Mon Sep 17 00:00:00 2001 From: Remy Oukaour Date: Tue, 12 Dec 2017 22:58:20 -0500 Subject: Document more bugs --- docs/bugs.md | 333 +++++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 302 insertions(+), 31 deletions(-) (limited to 'docs') diff --git a/docs/bugs.md b/docs/bugs.md index cf92bbba2..a375fd6fb 100644 --- a/docs/bugs.md +++ b/docs/bugs.md @@ -1,13 +1,103 @@ # Bugs and Glitches +## Thick Club and Light Ball can decrease damage done with boosted (Special) Attack + +([Video](https://www.youtube.com/watch?v=rGqu3d3pdok&t=450)) + +This is a bug with `SpeciesItemBoost` in [battle/effect_commands.asm](battle/effect_commands.asm): + +```asm +; Double the stat + sla l + rl h + ret +``` + +**Fix:** + +```asm +; Double the stat + sla l + rl h + + ld a, 999 / $100 + cp h + jr c, .cap + ld a, 999 % $100 + cp l + ret nc + +.cap + ld h, 999 / $100 + ld l, 999 % $100 + ret +``` + + +## Metal Powder can increase damage taken with boosted (Special) Defense + +([Video](https://www.youtube.com/watch?v=rGqu3d3pdok&t=450)) + +This is a bug with `DittoMetalPowder` in [battle/effect_commands.asm](battle/effect_commands.asm): + +```asm + ld a, c + srl a + add c + ld c, a + ret nc + + srl b + ld a, b + and a + jr nz, .done + inc b +.done + scf + rr c + ret +``` + +**Fix:** + +```asm + ld a, c + srl a + add c + ld c, a + ret nc + + srl b + ld a, b + and a + jr nz, .done + inc b +.done + scf + rr c + + ld a, 999 / $100 + cp b + jr c, .cap + ld a, 999 % $100 + cp c + ret nc + +.cap + ld b, 999 / $100 + ld c, 999 % $100 + ret +``` + + ## Belly Drum sharply boosts Attack even with under 50% HP ([Video](https://www.youtube.com/watch?v=zuCLMikWo4Y)) This is a bug with `BattleCommand_BellyDrum` in [battle/effect_commands.asm](battle/effect_commands.asm): -``` +```asm BattleCommand_BellyDrum: ; 37c1a ; bellydrum ; This command is buggy because it raises the user's attack @@ -25,7 +115,7 @@ BattleCommand_BellyDrum: ; 37c1a **Fix:** -``` +```asm BattleCommand_BellyDrum: ; 37c1a ; bellydrum callab GetHalfMaxHP @@ -39,13 +129,13 @@ BattleCommand_BellyDrum: ; 37c1a ``` -## HP bar animation is slower with more HP +## HP bar animation is slow for high HP ([Video](https://www.youtube.com/watch?v=SE-BfsFgZVM)) This is a bug with `LongAnim_UpdateVariables` in [engine/anim_hp_bar.asm](engine/anim_hp_bar.asm): -``` +```asm ; This routine is buggy. The result from ComputeHPBarPixels is stored ; in e. However, the pop de opcode deletes this result before it is even ; used. The game then proceeds as though it never deleted that output. @@ -67,6 +157,32 @@ This is a bug with `LongAnim_UpdateVariables` in [engine/anim_hp_bar.asm](engine **Fix:** Move `ld a, e` to right after `call ComputeHPBarPixels`. +## HP bar animation off-by-one error for low HP + +([Video](https://www.youtube.com/watch?v=9KyNVIZxJvI)) + +This is a bug with `ShortHPBar_CalcPixelFrame` in [engine/anim_hp_bar.asm](engine/anim_hp_bar.asm): + +```asm + ld b, 0 +; This routine is buggy. If [wCurHPAnimMaxHP] * [wCurHPBarPixels] is divisible +; by 48, the loop runs one extra time. To fix, uncomment the line below. +.loop + ld a, l + sub 6 * 8 + ld l, a + ld a, h + sbc $0 + ld h, a + ; jr z, .done + jr c, .done + inc b + jr .loop +``` + +**Fix:** Uncomment `jr z, .done`. + + ## Experience underflow for level 1 Pokémon with Medium-Slow growth rate ([Video](https://www.youtube.com/watch?v=SXH8u0plHrE)) @@ -75,7 +191,7 @@ This can bring Pokémon straight from level 1 to 100 by gaining just a few exper This is a bug with `CalcExpAtLevel` in [main.asm](main.asm): -``` +```asm CalcExpAtLevel: ; 50e47 ; (a/b)*n**3 + c*n**2 + d*n - e ld a, [BaseGrowthRate] @@ -89,7 +205,7 @@ CalcExpAtLevel: ; 50e47 **Fix:** -``` +```asm CalcExpAtLevel: ; 50e47 ; (a/b)*n**3 + c*n**2 + d*n - e ld a, d @@ -121,7 +237,7 @@ CalcExpAtLevel: ; 50e47 This is a bug with `Text_ABoostedStringBuffer2ExpPoints` and `Text_StringBuffer2ExpPoints` in [text/common_2.asm](text/common_2.asm): -``` +```asm Text_ABoostedStringBuffer2ExpPoints:: text "" line "a boosted" @@ -138,7 +254,84 @@ Text_StringBuffer2ExpPoints:: prompt ``` -**Fix:** Change `deciram StringBuffer2, 2, 4` to `deciram StringBuffer2, 2, 5`. +**Fix:** Change both `deciram StringBuffer2, 2, 4` to `deciram StringBuffer2, 2, 5`. + + +## NPC use of Full Heal or Full Restore does not cure Nightmare status + +([Video](https://www.youtube.com/watch?v=rGqu3d3pdok&t=322) + +This is a bug with `AI_HealStatus` in [battle/ai/items.asm](battle/ai/items.asm): + +```asm +AI_HealStatus: ; 384e0 + ld a, [CurOTMon] + ld hl, OTPartyMon1Status + ld bc, PARTYMON_STRUCT_LENGTH + call AddNTimes + xor a + ld [hl], a + ld [EnemyMonStatus], a + ; Bug: this should reset SUBSTATUS_NIGHTMARE too + ; Uncomment the lines below to fix + ; ld hl, EnemySubStatus1 + ; res SUBSTATUS_NIGHTMARE, [hl] + ld hl, EnemySubStatus5 + res SUBSTATUS_TOXIC, [hl] + ret +; 384f7 +``` + +**Fix:** Uncomment `ld hl, EnemySubStatus1` and `res SUBSTATUS_NIGHTMARE, [hl]`. + + +## "Smart" AI encourages Mean Look if its own Pokémon is badly poisoned + +([Video](https://www.youtube.com/watch?v=cygMO-zHTls)) + +This is a bug with `AI_Smart_MeanLook` in [battle/ai/scoring.asm](battle/ai/scoring.asm): + +```asm +; 80% chance to greatly encourage this move if the enemy is badly poisoned (buggy). +; Should check PlayerSubStatus5 instead. + ld a, [EnemySubStatus5] + bit SUBSTATUS_TOXIC, a + jr nz, .asm_38e26 +``` + +**Fix:** Change `EnemySubStatus5` to `PlayerSubStatus5`. + + +## A Disabled, PP Up–enhanced move may not trigger automatic Struggling + +([Video](https://www.youtube.com/watch?v=1v9x4SgMggs)) + +This is a bug with `CheckPlayerHasUsableMoves` in [battle/core.asm](battle/core.asm): + +```asm +.done + ; Bug: this will result in a move with PP Up confusing the game. + ; Replace with "and $3f" to fix. + and a + ret nz + +.force_struggle + ld hl, BattleText_PkmnHasNoMovesLeft + call StdBattleTextBox + ld c, 60 + call DelayFrames + xor a + ret +``` + +**Fix:** Change `and a` to `and $3f`. + + +## Counter and Mirror Coat still work if the opponent uses an item + +([Video](https://www.youtube.com/watch?v=uRYyzKRatFk)) + +*To do:* Identify specific code causing this bug and fix it. ## Present damage is incorrect in link battles @@ -149,7 +342,7 @@ This bug existed for all battles in Gold and Silver, and was only fixed for sing This is a bug with `BattleCommand_Present` in [battle/effects/present.asm](battle/effects/present.asm): -``` +```asm BattleCommand_Present: ; 37874 ; present @@ -172,7 +365,7 @@ BattleCommand_Present: ; 37874 **Fix:** -``` +```asm BattleCommand_Present: ; 37874 ; present @@ -188,7 +381,7 @@ BattleCommand_Present: ; 37874 This is a bug with `PokeBall` in [items/item_effects.asm](items/item_effects.asm): -``` +```asm .statuscheck ; This routine is buggy. It was intended that SLP and FRZ provide a higher ; catch rate than BRN/PSN/PAR, which in turn provide a higher catch rate than @@ -220,7 +413,7 @@ This is a bug with `PokeBall` in [items/item_effects.asm](items/item_effects.asm This is a bug with `MoonBallMultiplier` in [items/item_effects.asm](items/item_effects.asm): -``` +```asm MoonBallMultiplier: ; This function is buggy. ; Intent: multiply catch rate by 4 if mon evolves with moon stone @@ -246,7 +439,7 @@ MoonBallMultiplier: This is a bug with `LoveBallMultiplier` in [items/item_effects.asm](items/item_effects.asm): -``` +```asm LoveBallMultiplier: ; This function is buggy. ; Intent: multiply catch rate by 8 if mons are of same species, different sex @@ -268,7 +461,7 @@ LoveBallMultiplier: This is a bug with `FastBallMultiplier` in [items/item_effects.asm](items/item_effects.asm): -``` +```asm FastBallMultiplier: ; This function is buggy. ; Intent: multiply catch rate by 4 if enemy mon is in one of the three @@ -294,7 +487,7 @@ FastBallMultiplier: This is a bug with `PokeBall` in [items/item_effects.asm](items/item_effects.asm): -``` +```asm ld a, [CurItem] cp FRIEND_BALL jr nz, .SkipBoxMonFriendBall @@ -311,7 +504,7 @@ This is a bug with `PokeBall` in [items/item_effects.asm](items/item_effects.asm This is a bug with `ItemAttributes` in [items/item_attributes.asm](items/item_attributes.asm): -``` +```asm ; DRAGON FANG item_attribute 100, 0, 0, CANT_SELECT, ITEM, ITEMMENU_NOUSE, ITEMMENU_NOUSE @@ -328,7 +521,7 @@ This is a bug with `ItemAttributes` in [items/item_attributes.asm](items/item_at This is a bug with `MassageOrHaircut` in [event/special.asm](event/special.asm): -``` +```asm ; Bug: Subtracting $ff from $ff fails to set c. ; This can result in overflow into the next data array. ; In the case of getting a massage from Daisy, we bleed @@ -366,18 +559,89 @@ CopyPokemonName_Buffer1_Buffer3: ; 746e **Fix:** -``` +```asm Data_DaisyMassage: ; 746b db $80, 2, HAPPINESS_MASSAGE ; 50% chance db $ff, 2, HAPPINESS_MASSAGE ; 50% chance ``` +## Magikarp in Lake of Rage are shorter, not longer + +This is a bug with `LoadEnemyMon.CheckMagikarpArea` in [battle/core.asm](battle/core.asm): + +```asm +.CheckMagikarpArea: +; The z checks are supposed to be nz +; Instead, all maps in GROUP_LAKE_OF_RAGE (mahogany area) +; and routes 20 and 44 are treated as Lake of Rage + +; This also means Lake of Rage Magikarp can be smaller than ones +; caught elsewhere rather than the other way around + +; Intended behavior enforces a minimum size at Lake of Rage +; The real behavior prevents size flooring in the Lake of Rage area + ld a, [MapGroup] + cp GROUP_LAKE_OF_RAGE + jr z, .Happiness + ld a, [MapNumber] + cp MAP_LAKE_OF_RAGE + jr z, .Happiness +``` + +**Fix:** Change both `jr z, .Happiness` to `jr nz, .Happiness`. + + +## Battle transitions fail to account for the enemy's level + +([Video](https://www.youtube.com/watch?v=eij_1060SMc)) + +This is a bug with `StartTrainerBattle_DetermineWhichAnimation` in [engine/battle_start.asm](engine/battle_start.asm): + +``` +StartTrainerBattle_DetermineWhichAnimation: ; 8c365 (23:4365) +; The screen flashes a different number of times depending on the level of +; your lead Pokemon relative to the opponent's. +; BUG: BattleMonLevel and EnemyMonLevel are not set at this point, so whatever +; values happen to be there will determine the animation. + ld de, 0 + ld a, [BattleMonLevel] + add 3 + ld hl, EnemyMonLevel + cp [hl] + jr nc, .okay + set 0, e +.okay + ld a, [wPermission] + cp CAVE + jr z, .okay2 + cp PERM_5 + jr z, .okay2 + cp DUNGEON + jr z, .okay2 + set 1, e +.okay2 + ld hl, .StartingPoints + add hl, de + ld a, [hl] + ld [wJumptableIndex], a + ret +; 8c38f (23:438f) + +.StartingPoints: ; 8c38f + db 1, 9 + db 16, 24 +; 8c393 +``` + +*To do:* Fix this bug. + + ## No bump noise if standing on tile `$3E` This is a bug with `DoPlayerMovement.CheckWarp` in [engine/player_movement.asm](engine/player_movement.asm): -``` +```asm ; Bug: Since no case is made for STANDING here, it will check ; [.edgewarps + $ff]. This resolves to $3e at $8035a. ; This causes wd041 to be nonzero when standing on tile $3e, @@ -401,7 +665,7 @@ This is a bug with `DoPlayerMovement.CheckWarp` in [engine/player_movement.asm]( **Fix:** -``` +```asm ld a, [WalkingDirection] cp STANDING jr z, .not_warp @@ -419,6 +683,13 @@ This is a bug with `DoPlayerMovement.CheckWarp` in [engine/player_movement.asm]( ``` +## Surfing directly across a map connection does not load the new map + +([Video](https://www.youtube.com/watch?v=XFOWvMNG-zw)) + +*To do:* Identify specific code causing this bug and fix it. + + ## `CheckOwnMon` only checks the first five letters of OT names ([Video](https://www.youtube.com/watch?v=GVTTmReM4nQ)) @@ -427,7 +698,7 @@ This bug can allow you to talk to Eusine in Celadon City and encounter Ho-Oh wit [engine/search.asm](engine/search.asm): -``` +```asm ; check OT ; This only checks five characters, which is fine for the Japanese version, ; but in the English version the player name is 7 characters, so this is wrong. @@ -463,7 +734,7 @@ endr This is a bug with `PokeBall` in [items/item_effects.asm](items/item_effects.asm): -``` +```asm ; BUG: callba overwrites a, ; and GetItemHeldEffect takes b anyway. @@ -487,7 +758,7 @@ This is a bug with `PokeBall` in [items/item_effects.asm](items/item_effects.asm [engine/scripting.asm](engine/scripting.asm): -``` +```asm ScriptCall: ; Bug: The script stack has a capacity of 5 scripts, yet there is ; nothing to stop you from pushing a sixth script. The high part @@ -525,7 +796,7 @@ ScriptCall: [engine/overworld.asm](engine/overworld.asm): -``` +```asm LoadSpriteGFX: ; 14306 ; Bug: b is not preserved, so ; it's useless as a next count. @@ -560,7 +831,7 @@ LoadSpriteGFX: ; 14306 [engine/wildmons.asm](engine/wildmons.asm): -``` +```asm ChooseWildEncounter: ; 2a14f ... @@ -583,7 +854,7 @@ ValidateTempWildMonSpecies: ; 2a4a0 **Fix:** -``` +```asm ld a, b ld [CurPartyLevel], a ld b, [hl] @@ -599,7 +870,7 @@ ValidateTempWildMonSpecies: ; 2a4a0 [engine/events.asm](engine/events.asm): -``` +```asm ; Bug: If IsInArray returns nc, data at bc will be executed as code. push bc ld de, 3 @@ -627,7 +898,7 @@ ValidateTempWildMonSpecies: ; 2a4a0 [event/bug_contest_2.asm](event/bug_contest_2.asm): -``` +```asm Special_CheckBugContestContestantFlag: ; 139ed ; Checks the flag of the Bug Catching Contestant whose index is loaded in a. @@ -665,7 +936,7 @@ BugCatchingContestantEventFlagTable: ; 139fe [home/init.asm](home/init.asm): -``` +```asm ClearWRAM:: ; 25a ; Wipe swappable WRAM banks (1-7) ; Assumes CGB or AGB @@ -693,7 +964,7 @@ ClearWRAM:: ; 25a [tilesets/animations.asm](tilesets/animations.asm): -``` +```asm GetForestTreeFrame: ; fc54c ; Return 0 if a is even, or 2 if odd. and a @@ -722,7 +993,7 @@ GetForestTreeFrame: ; fc54c **Fix:** -``` +```asm GetForestTreeFrame: ; fc54c ; Return 0 if a is even, or 2 if odd. and 1 -- cgit v1.2.3 From 138abd097d431bcb657b7842623ea6f36b8f287c Mon Sep 17 00:00:00 2001 From: Remy Oukaour Date: Tue, 12 Dec 2017 23:05:30 -0500 Subject: Document one more bug. --- docs/bugs.md | 1003 ------------------------------------------- docs/bugs_and_glitches.md | 1029 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 1029 insertions(+), 1003 deletions(-) delete mode 100644 docs/bugs.md create mode 100644 docs/bugs_and_glitches.md (limited to 'docs') diff --git a/docs/bugs.md b/docs/bugs.md deleted file mode 100644 index a375fd6fb..000000000 --- a/docs/bugs.md +++ /dev/null @@ -1,1003 +0,0 @@ -# Bugs and Glitches - - -## Thick Club and Light Ball can decrease damage done with boosted (Special) Attack - -([Video](https://www.youtube.com/watch?v=rGqu3d3pdok&t=450)) - -This is a bug with `SpeciesItemBoost` in [battle/effect_commands.asm](battle/effect_commands.asm): - -```asm -; Double the stat - sla l - rl h - ret -``` - -**Fix:** - -```asm -; Double the stat - sla l - rl h - - ld a, 999 / $100 - cp h - jr c, .cap - ld a, 999 % $100 - cp l - ret nc - -.cap - ld h, 999 / $100 - ld l, 999 % $100 - ret -``` - - -## Metal Powder can increase damage taken with boosted (Special) Defense - -([Video](https://www.youtube.com/watch?v=rGqu3d3pdok&t=450)) - -This is a bug with `DittoMetalPowder` in [battle/effect_commands.asm](battle/effect_commands.asm): - -```asm - ld a, c - srl a - add c - ld c, a - ret nc - - srl b - ld a, b - and a - jr nz, .done - inc b -.done - scf - rr c - ret -``` - -**Fix:** - -```asm - ld a, c - srl a - add c - ld c, a - ret nc - - srl b - ld a, b - and a - jr nz, .done - inc b -.done - scf - rr c - - ld a, 999 / $100 - cp b - jr c, .cap - ld a, 999 % $100 - cp c - ret nc - -.cap - ld b, 999 / $100 - ld c, 999 % $100 - ret -``` - - -## Belly Drum sharply boosts Attack even with under 50% HP - -([Video](https://www.youtube.com/watch?v=zuCLMikWo4Y)) - -This is a bug with `BattleCommand_BellyDrum` in [battle/effect_commands.asm](battle/effect_commands.asm): - -```asm -BattleCommand_BellyDrum: ; 37c1a -; bellydrum -; This command is buggy because it raises the user's attack -; before checking that it has enough HP to use the move. -; Swap the order of these two blocks to fix. - call BattleCommand_AttackUp2 - ld a, [AttackMissed] - and a - jr nz, .failed - - callab GetHalfMaxHP - callab CheckUserHasEnoughHP - jr nc, .failed -``` - -**Fix:** - -```asm -BattleCommand_BellyDrum: ; 37c1a -; bellydrum - callab GetHalfMaxHP - callab CheckUserHasEnoughHP - jr nc, .failed - - call BattleCommand_AttackUp2 - ld a, [AttackMissed] - and a - jr nz, .failed -``` - - -## HP bar animation is slow for high HP - -([Video](https://www.youtube.com/watch?v=SE-BfsFgZVM)) - -This is a bug with `LongAnim_UpdateVariables` in [engine/anim_hp_bar.asm](engine/anim_hp_bar.asm): - -```asm - ; This routine is buggy. The result from ComputeHPBarPixels is stored - ; in e. However, the pop de opcode deletes this result before it is even - ; used. The game then proceeds as though it never deleted that output. - ; To fix, uncomment the line below. - call ComputeHPBarPixels - ; ld a, e - pop bc - pop de - pop hl - ld a, e ; Comment or delete this line to fix the above bug. - ld hl, wCurHPBarPixels - cp [hl] - jr z, .loop - ld [hl], a - and a - ret -``` - -**Fix:** Move `ld a, e` to right after `call ComputeHPBarPixels`. - - -## HP bar animation off-by-one error for low HP - -([Video](https://www.youtube.com/watch?v=9KyNVIZxJvI)) - -This is a bug with `ShortHPBar_CalcPixelFrame` in [engine/anim_hp_bar.asm](engine/anim_hp_bar.asm): - -```asm - ld b, 0 -; This routine is buggy. If [wCurHPAnimMaxHP] * [wCurHPBarPixels] is divisible -; by 48, the loop runs one extra time. To fix, uncomment the line below. -.loop - ld a, l - sub 6 * 8 - ld l, a - ld a, h - sbc $0 - ld h, a - ; jr z, .done - jr c, .done - inc b - jr .loop -``` - -**Fix:** Uncomment `jr z, .done`. - - -## Experience underflow for level 1 Pokémon with Medium-Slow growth rate - -([Video](https://www.youtube.com/watch?v=SXH8u0plHrE)) - -This can bring Pokémon straight from level 1 to 100 by gaining just a few experience points. - -This is a bug with `CalcExpAtLevel` in [main.asm](main.asm): - -```asm -CalcExpAtLevel: ; 50e47 -; (a/b)*n**3 + c*n**2 + d*n - e - ld a, [BaseGrowthRate] - add a - add a - ld c, a - ld b, 0 - ld hl, GrowthRates - add hl, bc -``` - -**Fix:** - -```asm -CalcExpAtLevel: ; 50e47 -; (a/b)*n**3 + c*n**2 + d*n - e - ld a, d - cp 1 - jr nz, .UseExpFormula -; Pokémon have 0 experience at level 1 - xor a - ld hl, hProduct - ld [hli], a - ld [hli], a - ld [hli], a - ld [hl], a - ret - -.UseExpFormula - ld a, [BaseGrowthRate] - add a - add a - ld c, a - ld b, 0 - ld hl, GrowthRates - add hl, bc -``` - - -## Five-digit experience gain is printed incorrectly - -([Video](https://www.youtube.com/watch?v=o54VjpAEoO8)) - -This is a bug with `Text_ABoostedStringBuffer2ExpPoints` and `Text_StringBuffer2ExpPoints` in [text/common_2.asm](text/common_2.asm): - -```asm -Text_ABoostedStringBuffer2ExpPoints:: - text "" - line "a boosted" - cont "@" - deciram StringBuffer2, 2, 4 - text " EXP. Points!" - prompt - -Text_StringBuffer2ExpPoints:: - text "" - line "@" - deciram StringBuffer2, 2, 4 - text " EXP. Points!" - prompt -``` - -**Fix:** Change both `deciram StringBuffer2, 2, 4` to `deciram StringBuffer2, 2, 5`. - - -## NPC use of Full Heal or Full Restore does not cure Nightmare status - -([Video](https://www.youtube.com/watch?v=rGqu3d3pdok&t=322) - -This is a bug with `AI_HealStatus` in [battle/ai/items.asm](battle/ai/items.asm): - -```asm -AI_HealStatus: ; 384e0 - ld a, [CurOTMon] - ld hl, OTPartyMon1Status - ld bc, PARTYMON_STRUCT_LENGTH - call AddNTimes - xor a - ld [hl], a - ld [EnemyMonStatus], a - ; Bug: this should reset SUBSTATUS_NIGHTMARE too - ; Uncomment the lines below to fix - ; ld hl, EnemySubStatus1 - ; res SUBSTATUS_NIGHTMARE, [hl] - ld hl, EnemySubStatus5 - res SUBSTATUS_TOXIC, [hl] - ret -; 384f7 -``` - -**Fix:** Uncomment `ld hl, EnemySubStatus1` and `res SUBSTATUS_NIGHTMARE, [hl]`. - - -## "Smart" AI encourages Mean Look if its own Pokémon is badly poisoned - -([Video](https://www.youtube.com/watch?v=cygMO-zHTls)) - -This is a bug with `AI_Smart_MeanLook` in [battle/ai/scoring.asm](battle/ai/scoring.asm): - -```asm -; 80% chance to greatly encourage this move if the enemy is badly poisoned (buggy). -; Should check PlayerSubStatus5 instead. - ld a, [EnemySubStatus5] - bit SUBSTATUS_TOXIC, a - jr nz, .asm_38e26 -``` - -**Fix:** Change `EnemySubStatus5` to `PlayerSubStatus5`. - - -## A Disabled, PP Up–enhanced move may not trigger automatic Struggling - -([Video](https://www.youtube.com/watch?v=1v9x4SgMggs)) - -This is a bug with `CheckPlayerHasUsableMoves` in [battle/core.asm](battle/core.asm): - -```asm -.done - ; Bug: this will result in a move with PP Up confusing the game. - ; Replace with "and $3f" to fix. - and a - ret nz - -.force_struggle - ld hl, BattleText_PkmnHasNoMovesLeft - call StdBattleTextBox - ld c, 60 - call DelayFrames - xor a - ret -``` - -**Fix:** Change `and a` to `and $3f`. - - -## Counter and Mirror Coat still work if the opponent uses an item - -([Video](https://www.youtube.com/watch?v=uRYyzKRatFk)) - -*To do:* Identify specific code causing this bug and fix it. - - -## Present damage is incorrect in link battles - -([Video](https://www.youtube.com/watch?v=XJaQoKtrEuw)) - -This bug existed for all battles in Gold and Silver, and was only fixed for single-player battles in Crystal to preserve link compatibility. - -This is a bug with `BattleCommand_Present` in [battle/effects/present.asm](battle/effects/present.asm): - -```asm -BattleCommand_Present: ; 37874 -; present - - ld a, [wLinkMode] - cp LINK_COLOSSEUM - jr z, .colosseum_skippush - push bc - push de -.colosseum_skippush - - call BattleCommand_Stab - - ld a, [wLinkMode] - cp LINK_COLOSSEUM - jr z, .colosseum_skippop - pop de - pop bc -.colosseum_skippop -``` - -**Fix:** - -```asm -BattleCommand_Present: ; 37874 -; present - - push bc - push de - call BattleCommand_Stab - pop de - pop bc -``` - - -## BRN/PSN/PAR do not affect catch rate - -This is a bug with `PokeBall` in [items/item_effects.asm](items/item_effects.asm): - -```asm -.statuscheck -; This routine is buggy. It was intended that SLP and FRZ provide a higher -; catch rate than BRN/PSN/PAR, which in turn provide a higher catch rate than -; no status effect at all. But instead, it makes BRN/PSN/PAR provide no -; benefit. -; Uncomment the line below to fix this. - ld b, a - ld a, [EnemyMonStatus] - and 1 << FRZ | SLP - ld c, 10 - jr nz, .addstatus - ; ld a, [EnemyMonStatus] - and a - ld c, 5 - jr nz, .addstatus - ld c, 0 -.addstatus - ld a, b - add c - jr nc, .max_1 - ld a, $ff -.max_1 -``` - -**Fix:** Uncomment `ld a, [EnemyMonStatus]`. - - -## Moon Ball does not boost catch rate - -This is a bug with `MoonBallMultiplier` in [items/item_effects.asm](items/item_effects.asm): - -```asm -MoonBallMultiplier: -; This function is buggy. -; Intent: multiply catch rate by 4 if mon evolves with moon stone -; Reality: no boost - -... - -; Moon Stone's constant from Pokémon Red is used. -; No Pokémon evolve with Burn Heal, -; so Moon Balls always have a catch rate of 1×. - push bc - ld a, BANK(EvosAttacks) - call GetFarByte - cp MOON_STONE_RED ; BURN_HEAL - pop bc - ret nz -``` - -**Fix:** Change `MOON_STONE_RED` to `MOON_STONE`. - - -## Love Ball boosts catch rate for the wrong gender - -This is a bug with `LoveBallMultiplier` in [items/item_effects.asm](items/item_effects.asm): - -```asm -LoveBallMultiplier: -; This function is buggy. -; Intent: multiply catch rate by 8 if mons are of same species, different sex -; Reality: multiply catch rate by 8 if mons are of same species, same sex - -... - - ld a, d - pop de - cp d - pop bc - ret nz ; for the intended effect, this should be "ret z" -``` - -**Fix:** Change `ret nz` to `ret z`. - - -## Fast Ball only boosts catch rate for three Pokémon - -This is a bug with `FastBallMultiplier` in [items/item_effects.asm](items/item_effects.asm): - -```asm -FastBallMultiplier: -; This function is buggy. -; Intent: multiply catch rate by 4 if enemy mon is in one of the three -; FleeMons tables. -; Reality: multiply catch rate by 4 if enemy mon is one of the first three in -; the first FleeMons table. - -... - - inc hl - cp -1 - jr z, .next - cp c - jr nz, .next ; for the intended effect, this should be "jr nz, .loop" - sla b - jr c, .max -``` - -**Fix:** Change `jr nz, .next` to `jr nz, .loop`. - - -## Friend Ball catches sent to the PC overwrite the wrong Pokémon's happiness - -This is a bug with `PokeBall` in [items/item_effects.asm](items/item_effects.asm): - -```asm - ld a, [CurItem] - cp FRIEND_BALL - jr nz, .SkipBoxMonFriendBall - ; Bug: overwrites the happiness of the first mon in the box! - ld a, FRIEND_BALL_HAPPINESS - ld [sBoxMon1Happiness], a -.SkipBoxMonFriendBall: -``` - -`sBoxMon1Happiness` is written *before* the Friend Ball Pokémon is deposited. - - -## Dragon Scale, not Dragon Fang, boosts Dragon-type moves - -This is a bug with `ItemAttributes` in [items/item_attributes.asm](items/item_attributes.asm): - -```asm -; DRAGON FANG - item_attribute 100, 0, 0, CANT_SELECT, ITEM, ITEMMENU_NOUSE, ITEMMENU_NOUSE - -... - -; DRAGON SCALE - item_attribute 2100, HELD_DRAGON_BOOST, 10, CANT_SELECT, ITEM, ITEMMENU_NOUSE, ITEMMENU_NOUSE -``` - -**Fix:** Move `HELD_DRAGON_BOOST` to the `DRAGON FANG` attributes and `0` to `DRAGON SCALE`. - - -## Daisy's massages don't always increase happiness - -This is a bug with `MassageOrHaircut` in [event/special.asm](event/special.asm): - -```asm -; Bug: Subtracting $ff from $ff fails to set c. -; This can result in overflow into the next data array. -; In the case of getting a massage from Daisy, we bleed -; into CopyPokemonName_Buffer1_Buffer3, which passes -; $d0 to ChangeHappiness and returns $73 to the script. -; The end result is that there is a 0.4% chance your -; Pokemon's happiness will not change at all. -.loop - sub [hl] - jr c, .ok - inc hl - inc hl - inc hl - jr .loop - -.ok - inc hl - ld a, [hli] - ld [ScriptVar], a - ld c, [hl] - call ChangeHappiness - ret - -... - -Data_DaisyMassage: ; 746b - db $ff, 2, HAPPINESS_MASSAGE ; 99.6% chance - -CopyPokemonName_Buffer1_Buffer3: ; 746e - ld hl, StringBuffer1 - ld de, StringBuffer3 - ld bc, PKMN_NAME_LENGTH - jp CopyBytes -``` - -**Fix:** - -```asm -Data_DaisyMassage: ; 746b - db $80, 2, HAPPINESS_MASSAGE ; 50% chance - db $ff, 2, HAPPINESS_MASSAGE ; 50% chance -``` - - -## Magikarp in Lake of Rage are shorter, not longer - -This is a bug with `LoadEnemyMon.CheckMagikarpArea` in [battle/core.asm](battle/core.asm): - -```asm -.CheckMagikarpArea: -; The z checks are supposed to be nz -; Instead, all maps in GROUP_LAKE_OF_RAGE (mahogany area) -; and routes 20 and 44 are treated as Lake of Rage - -; This also means Lake of Rage Magikarp can be smaller than ones -; caught elsewhere rather than the other way around - -; Intended behavior enforces a minimum size at Lake of Rage -; The real behavior prevents size flooring in the Lake of Rage area - ld a, [MapGroup] - cp GROUP_LAKE_OF_RAGE - jr z, .Happiness - ld a, [MapNumber] - cp MAP_LAKE_OF_RAGE - jr z, .Happiness -``` - -**Fix:** Change both `jr z, .Happiness` to `jr nz, .Happiness`. - - -## Battle transitions fail to account for the enemy's level - -([Video](https://www.youtube.com/watch?v=eij_1060SMc)) - -This is a bug with `StartTrainerBattle_DetermineWhichAnimation` in [engine/battle_start.asm](engine/battle_start.asm): - -``` -StartTrainerBattle_DetermineWhichAnimation: ; 8c365 (23:4365) -; The screen flashes a different number of times depending on the level of -; your lead Pokemon relative to the opponent's. -; BUG: BattleMonLevel and EnemyMonLevel are not set at this point, so whatever -; values happen to be there will determine the animation. - ld de, 0 - ld a, [BattleMonLevel] - add 3 - ld hl, EnemyMonLevel - cp [hl] - jr nc, .okay - set 0, e -.okay - ld a, [wPermission] - cp CAVE - jr z, .okay2 - cp PERM_5 - jr z, .okay2 - cp DUNGEON - jr z, .okay2 - set 1, e -.okay2 - ld hl, .StartingPoints - add hl, de - ld a, [hl] - ld [wJumptableIndex], a - ret -; 8c38f (23:438f) - -.StartingPoints: ; 8c38f - db 1, 9 - db 16, 24 -; 8c393 -``` - -*To do:* Fix this bug. - - -## No bump noise if standing on tile `$3E` - -This is a bug with `DoPlayerMovement.CheckWarp` in [engine/player_movement.asm](engine/player_movement.asm): - -```asm -; Bug: Since no case is made for STANDING here, it will check -; [.edgewarps + $ff]. This resolves to $3e at $8035a. -; This causes wd041 to be nonzero when standing on tile $3e, -; making bumps silent. - - ld a, [WalkingDirection] - ld e, a - ld d, 0 - ld hl, .EdgeWarps - add hl, de - ld a, [PlayerStandingTile] - cp [hl] - jr nz, .not_warp - - ld a, 1 - ld [wd041], a - ld a, [WalkingDirection] - cp STANDING - jr z, .not_warp -``` - -**Fix:** - -```asm - ld a, [WalkingDirection] - cp STANDING - jr z, .not_warp - ld e, a - ld d, 0 - ld hl, .EdgeWarps - add hl, de - ld a, [PlayerStandingTile] - cp [hl] - jr nz, .not_warp - - ld a, 1 - ld [wd041], a - ld a, [WalkingDirection] -``` - - -## Surfing directly across a map connection does not load the new map - -([Video](https://www.youtube.com/watch?v=XFOWvMNG-zw)) - -*To do:* Identify specific code causing this bug and fix it. - - -## `CheckOwnMon` only checks the first five letters of OT names - -([Video](https://www.youtube.com/watch?v=GVTTmReM4nQ)) - -This bug can allow you to talk to Eusine in Celadon City and encounter Ho-Oh with only traded legendary beasts. - -[engine/search.asm](engine/search.asm): - -```asm -; check OT -; This only checks five characters, which is fine for the Japanese version, -; but in the English version the player name is 7 characters, so this is wrong. - - ld hl, PlayerName - -rept NAME_LENGTH_JAPANESE +- 2 ; should be PLAYER_NAME_LENGTH +- 2 - ld a, [de] - cp [hl] - jr nz, .notfound - cp "@" - jr z, .found ; reached end of string - inc hl - inc de -endr - - ld a, [de] - cp [hl] - jr z, .found - -.notfound - pop de - pop hl - pop bc - and a - ret -``` - -**Fix:** Change `rept NAME_LENGTH_JAPANESE +- 2` to `rept PLAYER_NAME_LENGTH +- 2`. - - -## `HELD_CATCH_CHANCE` has no effect - -This is a bug with `PokeBall` in [items/item_effects.asm](items/item_effects.asm): - -```asm - ; BUG: callba overwrites a, - ; and GetItemHeldEffect takes b anyway. - - ; This is probably the reason - ; the HELD_CATCH_CHANCE effect - ; is never used. - - ; Uncomment the line below to fix. - - ld a, [BattleMonItem] -; ld b, a - callba GetItemHeldEffect - ld a, b - cp HELD_CATCH_CHANCE -``` - -**Fix:** Uncomment `ld b, a`. - - -## `ScriptCall` can overflow `wScriptStack` and crash - -[engine/scripting.asm](engine/scripting.asm): - -```asm -ScriptCall: -; Bug: The script stack has a capacity of 5 scripts, yet there is -; nothing to stop you from pushing a sixth script. The high part -; of the script address can then be overwritten by modifications -; to ScriptDelay, causing the script to return to the rst/interrupt -; space. - - push de - ld hl, wScriptStackSize - ld e, [hl] - inc [hl] - ld d, $0 - ld hl, wScriptStack - add hl, de - add hl, de - add hl, de - pop de - ld a, [ScriptBank] - ld [hli], a - ld a, [ScriptPos] - ld [hli], a - ld a, [ScriptPos + 1] - ld [hl], a - ld a, b - ld [ScriptBank], a - ld a, e - ld [ScriptPos], a - ld a, d - ld [ScriptPos + 1], a - ret -``` - - -## `LoadSpriteGFX` does not limit the capacity of `UsedSprites` - -[engine/overworld.asm](engine/overworld.asm): - -```asm -LoadSpriteGFX: ; 14306 -; Bug: b is not preserved, so -; it's useless as a next count. - - ld hl, UsedSprites - ld b, SPRITE_GFX_LIST_CAPACITY -.loop - ld a, [hli] - and a - jr z, .done - push hl - call .LoadSprite - pop hl - ld [hli], a - dec b - jr nz, .loop - -.done - ret - -.LoadSprite: - call GetSprite - ld a, l - ret -; 1431e -``` - -`GetSprite` modifies `b`. Surround it with `push bc`/`pop bc` to fix. - - -## `ChooseWildEncounter` doesn't really validate the wild Pokémon species - -[engine/wildmons.asm](engine/wildmons.asm): - -```asm -ChooseWildEncounter: ; 2a14f -... - - ld a, b - ld [CurPartyLevel], a - ld b, [hl] - ; ld a, b - call ValidateTempWildMonSpecies - jr c, .nowildbattle - - ld a, b ; This is in the wrong place. - cp UNOWN - jr nz, .done - -... - -ValidateTempWildMonSpecies: ; 2a4a0 -; Due to a development oversight, this function is called with the wild Pokemon's level, not its species, in a. -``` - -**Fix:** - -```asm - ld a, b - ld [CurPartyLevel], a - ld b, [hl] - ld a, b - call ValidateTempWildMonSpecies - jr c, .nowildbattle - - cp UNOWN - jr nz, .done -``` - -## `TryObjectEvent` arbitrary code execution - -[engine/events.asm](engine/events.asm): - -```asm -; Bug: If IsInArray returns nc, data at bc will be executed as code. - push bc - ld de, 3 - ld hl, .pointers - call IsInArray - jr nc, .nope_bugged - pop bc - - inc hl - ld a, [hli] - ld h, [hl] - ld l, a - jp hl - -.nope_bugged - ; pop bc - xor a - ret -``` - -**Fix:** Uncomment `pop bc`. - - -## `Special_CheckBugContestContestantFlag` can read beyond its data table - -[event/bug_contest_2.asm](event/bug_contest_2.asm): - -```asm -Special_CheckBugContestContestantFlag: ; 139ed -; Checks the flag of the Bug Catching Contestant whose index is loaded in a. - -; Bug: If a >= 10 when this is called, it will read beyond the table. - - ld hl, BugCatchingContestantEventFlagTable - ld e, a - ld d, 0 - add hl, de - add hl, de - ld e, [hl] - inc hl - ld d, [hl] - ld b, CHECK_FLAG - call EventFlagAction - ret -; 139fe - -BugCatchingContestantEventFlagTable: ; 139fe - dw EVENT_BUG_CATCHING_CONTESTANT_1A - dw EVENT_BUG_CATCHING_CONTESTANT_2A - dw EVENT_BUG_CATCHING_CONTESTANT_3A - dw EVENT_BUG_CATCHING_CONTESTANT_4A - dw EVENT_BUG_CATCHING_CONTESTANT_5A - dw EVENT_BUG_CATCHING_CONTESTANT_6A - dw EVENT_BUG_CATCHING_CONTESTANT_7A - dw EVENT_BUG_CATCHING_CONTESTANT_8A - dw EVENT_BUG_CATCHING_CONTESTANT_9A - dw EVENT_BUG_CATCHING_CONTESTANT_10A -; 13a12 -``` - - -## `ClearWRAM` only clears WRAM bank 1 - -[home/init.asm](home/init.asm): - -```asm -ClearWRAM:: ; 25a -; Wipe swappable WRAM banks (1-7) -; Assumes CGB or AGB - - ld a, 1 -.bank_loop - push af - ld [rSVBK], a - xor a - ld hl, $d000 - ld bc, $1000 - call ByteFill - pop af - inc a - cp 8 - jr nc, .bank_loop ; Should be jr c - ret -; 270 -``` - -**Fix:** Change `jr nc, .bank_loop` to `jr c, .bank_loop`. - - -## `GetForestTreeFrame` works, but it's still bad - -[tilesets/animations.asm](tilesets/animations.asm): - -```asm -GetForestTreeFrame: ; fc54c -; Return 0 if a is even, or 2 if odd. - and a - jr z, .even - cp 1 - jr z, .odd - cp 2 - jr z, .even - cp 3 - jr z, .odd - cp 4 - jr z, .even - cp 5 - jr z, .odd - cp 6 - jr z, .even -.odd - ld a, 2 - scf - ret -.even - xor a - ret -; fc56d -``` - -**Fix:** - -```asm -GetForestTreeFrame: ; fc54c -; Return 0 if a is even, or 2 if odd. - and 1 - add a - ret -; fc56d -``` diff --git a/docs/bugs_and_glitches.md b/docs/bugs_and_glitches.md new file mode 100644 index 000000000..6f27f6087 --- /dev/null +++ b/docs/bugs_and_glitches.md @@ -0,0 +1,1029 @@ +# Bugs and Glitches + + +## Thick Club and Light Ball can decrease damage done with boosted (Special) Attack + +([Video](https://www.youtube.com/watch?v=rGqu3d3pdok&t=450)) + +This is a bug with `SpeciesItemBoost` in [battle/effect_commands.asm](battle/effect_commands.asm): + +```asm +; Double the stat + sla l + rl h + ret +``` + +**Fix:** + +```asm +; Double the stat + sla l + rl h + + ld a, 999 / $100 + cp h + jr c, .cap + ld a, 999 % $100 + cp l + ret nc + +.cap + ld h, 999 / $100 + ld l, 999 % $100 + ret +``` + + +## Metal Powder can increase damage taken with boosted (Special) Defense + +([Video](https://www.youtube.com/watch?v=rGqu3d3pdok&t=450)) + +This is a bug with `DittoMetalPowder` in [battle/effect_commands.asm](battle/effect_commands.asm): + +```asm + ld a, c + srl a + add c + ld c, a + ret nc + + srl b + ld a, b + and a + jr nz, .done + inc b +.done + scf + rr c + ret +``` + +**Fix:** + +```asm + ld a, c + srl a + add c + ld c, a + ret nc + + srl b + ld a, b + and a + jr nz, .done + inc b +.done + scf + rr c + + ld a, 999 / $100 + cp b + jr c, .cap + ld a, 999 % $100 + cp c + ret nc + +.cap + ld b, 999 / $100 + ld c, 999 % $100 + ret +``` + + +## Belly Drum sharply boosts Attack even with under 50% HP + +([Video](https://www.youtube.com/watch?v=zuCLMikWo4Y)) + +This is a bug with `BattleCommand_BellyDrum` in [battle/effect_commands.asm](battle/effect_commands.asm): + +```asm +BattleCommand_BellyDrum: ; 37c1a +; bellydrum +; This command is buggy because it raises the user's attack +; before checking that it has enough HP to use the move. +; Swap the order of these two blocks to fix. + call BattleCommand_AttackUp2 + ld a, [AttackMissed] + and a + jr nz, .failed + + callab GetHalfMaxHP + callab CheckUserHasEnoughHP + jr nc, .failed +``` + +**Fix:** + +```asm +BattleCommand_BellyDrum: ; 37c1a +; bellydrum + callab GetHalfMaxHP + callab CheckUserHasEnoughHP + jr nc, .failed + + call BattleCommand_AttackUp2 + ld a, [AttackMissed] + and a + jr nz, .failed +``` + + +## HP bar animation is slow for high HP + +([Video](https://www.youtube.com/watch?v=SE-BfsFgZVM)) + +This is a bug with `LongAnim_UpdateVariables` in [engine/anim_hp_bar.asm](engine/anim_hp_bar.asm): + +```asm + ; This routine is buggy. The result from ComputeHPBarPixels is stored + ; in e. However, the pop de opcode deletes this result before it is even + ; used. The game then proceeds as though it never deleted that output. + ; To fix, uncomment the line below. + call ComputeHPBarPixels + ; ld a, e + pop bc + pop de + pop hl + ld a, e ; Comment or delete this line to fix the above bug. + ld hl, wCurHPBarPixels + cp [hl] + jr z, .loop + ld [hl], a + and a + ret +``` + +**Fix:** Move `ld a, e` to right after `call ComputeHPBarPixels`. + + +## HP bar animation off-by-one error for low HP + +([Video](https://www.youtube.com/watch?v=9KyNVIZxJvI)) + +This is a bug with `ShortHPBar_CalcPixelFrame` in [engine/anim_hp_bar.asm](engine/anim_hp_bar.asm): + +```asm + ld b, 0 +; This routine is buggy. If [wCurHPAnimMaxHP] * [wCurHPBarPixels] is divisible +; by 48, the loop runs one extra time. To fix, uncomment the line below. +.loop + ld a, l + sub 6 * 8 + ld l, a + ld a, h + sbc $0 + ld h, a + ; jr z, .done + jr c, .done + inc b + jr .loop +``` + +**Fix:** Uncomment `jr z, .done`. + + +## Experience underflow for level 1 Pokémon with Medium-Slow growth rate + +([Video](https://www.youtube.com/watch?v=SXH8u0plHrE)) + +This can bring Pokémon straight from level 1 to 100 by gaining just a few experience points. + +This is a bug with `CalcExpAtLevel` in [main.asm](main.asm): + +```asm +CalcExpAtLevel: ; 50e47 +; (a/b)*n**3 + c*n**2 + d*n - e + ld a, [BaseGrowthRate] + add a + add a + ld c, a + ld b, 0 + ld hl, GrowthRates + add hl, bc +``` + +**Fix:** + +```asm +CalcExpAtLevel: ; 50e47 +; (a/b)*n**3 + c*n**2 + d*n - e + ld a, d + cp 1 + jr nz, .UseExpFormula +; Pokémon have 0 experience at level 1 + xor a + ld hl, hProduct + ld [hli], a + ld [hli], a + ld [hli], a + ld [hl], a + ret + +.UseExpFormula + ld a, [BaseGrowthRate] + add a + add a + ld c, a + ld b, 0 + ld hl, GrowthRates + add hl, bc +``` + + +## Five-digit experience gain is printed incorrectly + +([Video](https://www.youtube.com/watch?v=o54VjpAEoO8)) + +This is a bug with `Text_ABoostedStringBuffer2ExpPoints` and `Text_StringBuffer2ExpPoints` in [text/common_2.asm](text/common_2.asm): + +```asm +Text_ABoostedStringBuffer2ExpPoints:: + text "" + line "a boosted" + cont "@" + deciram StringBuffer2, 2, 4 + text " EXP. Points!" + prompt + +Text_StringBuffer2ExpPoints:: + text "" + line "@" + deciram StringBuffer2, 2, 4 + text " EXP. Points!" + prompt +``` + +**Fix:** Change both `deciram StringBuffer2, 2, 4` to `deciram StringBuffer2, 2, 5`. + + +## NPC use of Full Heal or Full Restore does not cure Nightmare status + +([Video](https://www.youtube.com/watch?v=rGqu3d3pdok&t=322) + +This is a bug with `AI_HealStatus` in [battle/ai/items.asm](battle/ai/items.asm): + +```asm +AI_HealStatus: ; 384e0 + ld a, [CurOTMon] + ld hl, OTPartyMon1Status + ld bc, PARTYMON_STRUCT_LENGTH + call AddNTimes + xor a + ld [hl], a + ld [EnemyMonStatus], a + ; Bug: this should reset SUBSTATUS_NIGHTMARE too + ; Uncomment the lines below to fix + ; ld hl, EnemySubStatus1 + ; res SUBSTATUS_NIGHTMARE, [hl] + ld hl, EnemySubStatus5 + res SUBSTATUS_TOXIC, [hl] + ret +; 384f7 +``` + +**Fix:** Uncomment `ld hl, EnemySubStatus1` and `res SUBSTATUS_NIGHTMARE, [hl]`. + + +## "Smart" AI encourages Mean Look if its own Pokémon is badly poisoned + +([Video](https://www.youtube.com/watch?v=cygMO-zHTls)) + +This is a bug with `AI_Smart_MeanLook` in [battle/ai/scoring.asm](battle/ai/scoring.asm): + +```asm +; 80% chance to greatly encourage this move if the enemy is badly poisoned (buggy). +; Should check PlayerSubStatus5 instead. + ld a, [EnemySubStatus5] + bit SUBSTATUS_TOXIC, a + jr nz, .asm_38e26 +``` + +**Fix:** Change `EnemySubStatus5` to `PlayerSubStatus5`. + + +## A Disabled, PP Up–enhanced move may not trigger automatic Struggling + +([Video](https://www.youtube.com/watch?v=1v9x4SgMggs)) + +This is a bug with `CheckPlayerHasUsableMoves` in [battle/core.asm](battle/core.asm): + +```asm +.done + ; Bug: this will result in a move with PP Up confusing the game. + ; Replace with "and $3f" to fix. + and a + ret nz + +.force_struggle + ld hl, BattleText_PkmnHasNoMovesLeft + call StdBattleTextBox + ld c, 60 + call DelayFrames + xor a + ret +``` + +**Fix:** Change `and a` to `and $3f`. + + +## Counter and Mirror Coat still work if the opponent uses an item + +([Video](https://www.youtube.com/watch?v=uRYyzKRatFk)) + +*To do:* Identify specific code causing this bug and fix it. + + +## Present damage is incorrect in link battles + +([Video](https://www.youtube.com/watch?v=XJaQoKtrEuw)) + +This bug existed for all battles in Gold and Silver, and was only fixed for single-player battles in Crystal to preserve link compatibility. + +This is a bug with `BattleCommand_Present` in [battle/effects/present.asm](battle/effects/present.asm): + +```asm +BattleCommand_Present: ; 37874 +; present + + ld a, [wLinkMode] + cp LINK_COLOSSEUM + jr z, .colosseum_skippush + push bc + push de +.colosseum_skippush + + call BattleCommand_Stab + + ld a, [wLinkMode] + cp LINK_COLOSSEUM + jr z, .colosseum_skippop + pop de + pop bc +.colosseum_skippop +``` + +**Fix:** + +```asm +BattleCommand_Present: ; 37874 +; present + + push bc + push de + call BattleCommand_Stab + pop de + pop bc +``` + + +## BRN/PSN/PAR do not affect catch rate + +This is a bug with `PokeBall` in [items/item_effects.asm](items/item_effects.asm): + +```asm +.statuscheck +; This routine is buggy. It was intended that SLP and FRZ provide a higher +; catch rate than BRN/PSN/PAR, which in turn provide a higher catch rate than +; no status effect at all. But instead, it makes BRN/PSN/PAR provide no +; benefit. +; Uncomment the line below to fix this. + ld b, a + ld a, [EnemyMonStatus] + and 1 << FRZ | SLP + ld c, 10 + jr nz, .addstatus + ; ld a, [EnemyMonStatus] + and a + ld c, 5 + jr nz, .addstatus + ld c, 0 +.addstatus + ld a, b + add c + jr nc, .max_1 + ld a, $ff +.max_1 +``` + +**Fix:** Uncomment `ld a, [EnemyMonStatus]`. + + +## Moon Ball does not boost catch rate + +This is a bug with `MoonBallMultiplier` in [items/item_effects.asm](items/item_effects.asm): + +```asm +MoonBallMultiplier: +; This function is buggy. +; Intent: multiply catch rate by 4 if mon evolves with moon stone +; Reality: no boost + +... + +; Moon Stone's constant from Pokémon Red is used. +; No Pokémon evolve with Burn Heal, +; so Moon Balls always have a catch rate of 1×. + push bc + ld a, BANK(EvosAttacks) + call GetFarByte + cp MOON_STONE_RED ; BURN_HEAL + pop bc + ret nz +``` + +**Fix:** Change `MOON_STONE_RED` to `MOON_STONE`. + + +## Love Ball boosts catch rate for the wrong gender + +This is a bug with `LoveBallMultiplier` in [items/item_effects.asm](items/item_effects.asm): + +```asm +LoveBallMultiplier: +; This function is buggy. +; Intent: multiply catch rate by 8 if mons are of same species, different sex +; Reality: multiply catch rate by 8 if mons are of same species, same sex + +... + + ld a, d + pop de + cp d + pop bc + ret nz ; for the intended effect, this should be "ret z" +``` + +**Fix:** Change `ret nz` to `ret z`. + + +## Fast Ball only boosts catch rate for three Pokémon + +This is a bug with `FastBallMultiplier` in [items/item_effects.asm](items/item_effects.asm): + +```asm +FastBallMultiplier: +; This function is buggy. +; Intent: multiply catch rate by 4 if enemy mon is in one of the three +; FleeMons tables. +; Reality: multiply catch rate by 4 if enemy mon is one of the first three in +; the first FleeMons table. + +... + + inc hl + cp -1 + jr z, .next + cp c + jr nz, .next ; for the intended effect, this should be "jr nz, .loop" + sla b + jr c, .max +``` + +**Fix:** Change `jr nz, .next` to `jr nz, .loop`. + + +## Friend Ball catches sent to the PC overwrite the wrong Pokémon's happiness + +This is a bug with `PokeBall` in [items/item_effects.asm](items/item_effects.asm): + +```asm + ld a, [CurItem] + cp FRIEND_BALL + jr nz, .SkipBoxMonFriendBall + ; Bug: overwrites the happiness of the first mon in the box! + ld a, FRIEND_BALL_HAPPINESS + ld [sBoxMon1Happiness], a +.SkipBoxMonFriendBall: +``` + +`sBoxMon1Happiness` is written *before* the Friend Ball Pokémon is deposited. + + +## Dragon Scale, not Dragon Fang, boosts Dragon-type moves + +This is a bug with `ItemAttributes` in [items/item_attributes.asm](items/item_attributes.asm): + +```asm +; DRAGON FANG + item_attribute 100, 0, 0, CANT_SELECT, ITEM, ITEMMENU_NOUSE, ITEMMENU_NOUSE + +... + +; DRAGON SCALE + item_attribute 2100, HELD_DRAGON_BOOST, 10, CANT_SELECT, ITEM, ITEMMENU_NOUSE, ITEMMENU_NOUSE +``` + +**Fix:** Move `HELD_DRAGON_BOOST` to the `DRAGON FANG` attributes and `0` to `DRAGON SCALE`. + + +## Daisy's massages don't always increase happiness + +This is a bug with `MassageOrHaircut` in [event/special.asm](event/special.asm): + +```asm +; Bug: Subtracting $ff from $ff fails to set c. +; This can result in overflow into the next data array. +; In the case of getting a massage from Daisy, we bleed +; into CopyPokemonName_Buffer1_Buffer3, which passes +; $d0 to ChangeHappiness and returns $73 to the script. +; The end result is that there is a 0.4% chance your +; Pokemon's happiness will not change at all. +.loop + sub [hl] + jr c, .ok + inc hl + inc hl + inc hl + jr .loop + +.ok + inc hl + ld a, [hli] + ld [ScriptVar], a + ld c, [hl] + call ChangeHappiness + ret + +... + +Data_DaisyMassage: ; 746b + db $ff, 2, HAPPINESS_MASSAGE ; 99.6% chance + +CopyPokemonName_Buffer1_Buffer3: ; 746e + ld hl, StringBuffer1 + ld de, StringBuffer3 + ld bc, PKMN_NAME_LENGTH + jp CopyBytes +``` + +**Fix:** + +```asm +Data_DaisyMassage: ; 746b + db $80, 2, HAPPINESS_MASSAGE ; 50% chance + db $ff, 2, HAPPINESS_MASSAGE ; 50% chance +``` + + +## Magikarp in Lake of Rage are shorter, not longer + +This is a bug with `LoadEnemyMon.CheckMagikarpArea` in [battle/core.asm](battle/core.asm): + +```asm +.CheckMagikarpArea: +; The z checks are supposed to be nz +; Instead, all maps in GROUP_LAKE_OF_RAGE (mahogany area) +; and routes 20 and 44 are treated as Lake of Rage + +; This also means Lake of Rage Magikarp can be smaller than ones +; caught elsewhere rather than the other way around + +; Intended behavior enforces a minimum size at Lake of Rage +; The real behavior prevents size flooring in the Lake of Rage area + ld a, [MapGroup] + cp GROUP_LAKE_OF_RAGE + jr z, .Happiness + ld a, [MapNumber] + cp MAP_LAKE_OF_RAGE + jr z, .Happiness +``` + +**Fix:** Change both `jr z, .Happiness` to `jr nz, .Happiness`. + + +## Battle transitions fail to account for the enemy's level + +([Video](https://www.youtube.com/watch?v=eij_1060SMc)) + +This is a bug with `StartTrainerBattle_DetermineWhichAnimation` in [engine/battle_start.asm](engine/battle_start.asm): + +```asm +StartTrainerBattle_DetermineWhichAnimation: ; 8c365 (23:4365) +; The screen flashes a different number of times depending on the level of +; your lead Pokemon relative to the opponent's. +; BUG: BattleMonLevel and EnemyMonLevel are not set at this point, so whatever +; values happen to be there will determine the animation. + ld de, 0 + ld a, [BattleMonLevel] + add 3 + ld hl, EnemyMonLevel + cp [hl] + jr nc, .okay + set 0, e +.okay + ld a, [wPermission] + cp CAVE + jr z, .okay2 + cp PERM_5 + jr z, .okay2 + cp DUNGEON + jr z, .okay2 + set 1, e +.okay2 + ld hl, .StartingPoints + add hl, de + ld a, [hl] + ld [wJumptableIndex], a + ret +; 8c38f (23:438f) + +.StartingPoints: ; 8c38f + db 1, 9 + db 16, 24 +; 8c393 +``` + +*To do:* Fix this bug. + + +## No bump noise if standing on tile `$3E` + +This is a bug with `DoPlayerMovement.CheckWarp` in [engine/player_movement.asm](engine/player_movement.asm): + +```asm +; Bug: Since no case is made for STANDING here, it will check +; [.edgewarps + $ff]. This resolves to $3e at $8035a. +; This causes wd041 to be nonzero when standing on tile $3e, +; making bumps silent. + + ld a, [WalkingDirection] + ld e, a + ld d, 0 + ld hl, .EdgeWarps + add hl, de + ld a, [PlayerStandingTile] + cp [hl] + jr nz, .not_warp + + ld a, 1 + ld [wd041], a + ld a, [WalkingDirection] + cp STANDING + jr z, .not_warp +``` + +**Fix:** + +```asm + ld a, [WalkingDirection] + cp STANDING + jr z, .not_warp + ld e, a + ld d, 0 + ld hl, .EdgeWarps + add hl, de + ld a, [PlayerStandingTile] + cp [hl] + jr nz, .not_warp + + ld a, 1 + ld [wd041], a + ld a, [WalkingDirection] +``` + + +## `LoadMetatiles` wrap around past 128 blocks + +[home/map.asm](home/map.asm): + +```asm + ; Set hl to the address of the current metatile data ([TilesetBlocksAddress] + (a) tiles). + ; This is buggy; it wraps around past 128 blocks. + ; To fix, uncomment the line below. + add a ; Comment or delete this line to fix the above bug. + ld l, a + ld h, 0 + ; add hl, hl + add hl, hl + add hl, hl + add hl, hl + ld a, [TilesetBlocksAddress] + add l + ld l, a + ld a, [TilesetBlocksAddress + 1] + adc h + ld h, a +``` + +**Fix:** Delete `add a` and uncomment `add hl, hl`. + + +## Surfing directly across a map connection does not load the new map + +([Video](https://www.youtube.com/watch?v=XFOWvMNG-zw)) + +*To do:* Identify specific code causing this bug and fix it. + + +## `CheckOwnMon` only checks the first five letters of OT names + +([Video](https://www.youtube.com/watch?v=GVTTmReM4nQ)) + +This bug can allow you to talk to Eusine in Celadon City and encounter Ho-Oh with only traded legendary beasts. + +[engine/search.asm](engine/search.asm): + +```asm +; check OT +; This only checks five characters, which is fine for the Japanese version, +; but in the English version the player name is 7 characters, so this is wrong. + + ld hl, PlayerName + +rept NAME_LENGTH_JAPANESE +- 2 ; should be PLAYER_NAME_LENGTH +- 2 + ld a, [de] + cp [hl] + jr nz, .notfound + cp "@" + jr z, .found ; reached end of string + inc hl + inc de +endr + + ld a, [de] + cp [hl] + jr z, .found + +.notfound + pop de + pop hl + pop bc + and a + ret +``` + +**Fix:** Change `rept NAME_LENGTH_JAPANESE +- 2` to `rept PLAYER_NAME_LENGTH +- 2`. + + +## `HELD_CATCH_CHANCE` has no effect + +This is a bug with `PokeBall` in [items/item_effects.asm](items/item_effects.asm): + +```asm + ; BUG: callba overwrites a, + ; and GetItemHeldEffect takes b anyway. + + ; This is probably the reason + ; the HELD_CATCH_CHANCE effect + ; is never used. + + ; Uncomment the line below to fix. + + ld a, [BattleMonItem] +; ld b, a + callba GetItemHeldEffect + ld a, b + cp HELD_CATCH_CHANCE +``` + +**Fix:** Uncomment `ld b, a`. + + +## `ScriptCall` can overflow `wScriptStack` and crash + +[engine/scripting.asm](engine/scripting.asm): + +```asm +ScriptCall: +; Bug: The script stack has a capacity of 5 scripts, yet there is +; nothing to stop you from pushing a sixth script. The high part +; of the script address can then be overwritten by modifications +; to ScriptDelay, causing the script to return to the rst/interrupt +; space. + + push de + ld hl, wScriptStackSize + ld e, [hl] + inc [hl] + ld d, $0 + ld hl, wScriptStack + add hl, de + add hl, de + add hl, de + pop de + ld a, [ScriptBank] + ld [hli], a + ld a, [ScriptPos] + ld [hli], a + ld a, [ScriptPos + 1] + ld [hl], a + ld a, b + ld [ScriptBank], a + ld a, e + ld [ScriptPos], a + ld a, d + ld [ScriptPos + 1], a + ret +``` + + +## `LoadSpriteGFX` does not limit the capacity of `UsedSprites` + +[engine/overworld.asm](engine/overworld.asm): + +```asm +LoadSpriteGFX: ; 14306 +; Bug: b is not preserved, so +; it's useless as a next count. + + ld hl, UsedSprites + ld b, SPRITE_GFX_LIST_CAPACITY +.loop + ld a, [hli] + and a + jr z, .done + push hl + call .LoadSprite + pop hl + ld [hli], a + dec b + jr nz, .loop + +.done + ret + +.LoadSprite: + call GetSprite + ld a, l + ret +; 1431e +``` + +`GetSprite` modifies `b`. Surround it with `push bc`/`pop bc` to fix. + + +## `ChooseWildEncounter` doesn't really validate the wild Pokémon species + +[engine/wildmons.asm](engine/wildmons.asm): + +```asm +ChooseWildEncounter: ; 2a14f +... + + ld a, b + ld [CurPartyLevel], a + ld b, [hl] + ; ld a, b + call ValidateTempWildMonSpecies + jr c, .nowildbattle + + ld a, b ; This is in the wrong place. + cp UNOWN + jr nz, .done + +... + +ValidateTempWildMonSpecies: ; 2a4a0 +; Due to a development oversight, this function is called with the wild Pokemon's level, not its species, in a. +``` + +**Fix:** + +```asm + ld a, b + ld [CurPartyLevel], a + ld b, [hl] + ld a, b + call ValidateTempWildMonSpecies + jr c, .nowildbattle + + cp UNOWN + jr nz, .done +``` + +## `TryObjectEvent` arbitrary code execution + +[engine/events.asm](engine/events.asm): + +```asm +; Bug: If IsInArray returns nc, data at bc will be executed as code. + push bc + ld de, 3 + ld hl, .pointers + call IsInArray + jr nc, .nope_bugged + pop bc + + inc hl + ld a, [hli] + ld h, [hl] + ld l, a + jp hl + +.nope_bugged + ; pop bc + xor a + ret +``` + +**Fix:** Uncomment `pop bc`. + + +## `Special_CheckBugContestContestantFlag` can read beyond its data table + +[event/bug_contest_2.asm](event/bug_contest_2.asm): + +```asm +Special_CheckBugContestContestantFlag: ; 139ed +; Checks the flag of the Bug Catching Contestant whose index is loaded in a. + +; Bug: If a >= 10 when this is called, it will read beyond the table. + + ld hl, BugCatchingContestantEventFlagTable + ld e, a + ld d, 0 + add hl, de + add hl, de + ld e, [hl] + inc hl + ld d, [hl] + ld b, CHECK_FLAG + call EventFlagAction + ret +; 139fe + +BugCatchingContestantEventFlagTable: ; 139fe + dw EVENT_BUG_CATCHING_CONTESTANT_1A + dw EVENT_BUG_CATCHING_CONTESTANT_2A + dw EVENT_BUG_CATCHING_CONTESTANT_3A + dw EVENT_BUG_CATCHING_CONTESTANT_4A + dw EVENT_BUG_CATCHING_CONTESTANT_5A + dw EVENT_BUG_CATCHING_CONTESTANT_6A + dw EVENT_BUG_CATCHING_CONTESTANT_7A + dw EVENT_BUG_CATCHING_CONTESTANT_8A + dw EVENT_BUG_CATCHING_CONTESTANT_9A + dw EVENT_BUG_CATCHING_CONTESTANT_10A +; 13a12 +``` + + +## `ClearWRAM` only clears WRAM bank 1 + +[home/init.asm](home/init.asm): + +```asm +ClearWRAM:: ; 25a +; Wipe swappable WRAM banks (1-7) +; Assumes CGB or AGB + + ld a, 1 +.bank_loop + push af + ld [rSVBK], a + xor a + ld hl, $d000 + ld bc, $1000 + call ByteFill + pop af + inc a + cp 8 + jr nc, .bank_loop ; Should be jr c + ret +; 270 +``` + +**Fix:** Change `jr nc, .bank_loop` to `jr c, .bank_loop`. + + +## `GetForestTreeFrame` works, but it's still bad + +[tilesets/animations.asm](tilesets/animations.asm): + +```asm +GetForestTreeFrame: ; fc54c +; Return 0 if a is even, or 2 if odd. + and a + jr z, .even + cp 1 + jr z, .odd + cp 2 + jr z, .even + cp 3 + jr z, .odd + cp 4 + jr z, .even + cp 5 + jr z, .odd + cp 6 + jr z, .even +.odd + ld a, 2 + scf + ret +.even + xor a + ret +; fc56d +``` + +**Fix:** + +```asm +GetForestTreeFrame: ; fc54c +; Return 0 if a is even, or 2 if odd. + and 1 + add a + ret +; fc56d +``` -- cgit v1.2.3 From cd88196b7fab887c41c73c448da05add9b036b79 Mon Sep 17 00:00:00 2001 From: Remy Oukaour Date: Tue, 12 Dec 2017 23:07:35 -0500 Subject: Missing close parenthesis --- docs/bugs_and_glitches.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs') diff --git a/docs/bugs_and_glitches.md b/docs/bugs_and_glitches.md index 6f27f6087..287b0324c 100644 --- a/docs/bugs_and_glitches.md +++ b/docs/bugs_and_glitches.md @@ -259,7 +259,7 @@ Text_StringBuffer2ExpPoints:: ## NPC use of Full Heal or Full Restore does not cure Nightmare status -([Video](https://www.youtube.com/watch?v=rGqu3d3pdok&t=322) +([Video](https://www.youtube.com/watch?v=rGqu3d3pdok&t=322)) This is a bug with `AI_HealStatus` in [battle/ai/items.asm](battle/ai/items.asm): -- cgit v1.2.3