Title: Sliding Dash fix Author: SilentEnigma Version: 1.1 Release Date: June 03 2019 Applies to: FF3us 1.0, FF3us 1.1 Tested on: FF3us 1.0 NOTE: These patches are for HEADERED ROMs (3146240 bytes) only! Contents: SlidingDash.ips = the patch SlidingDashN.ips = the anti-patch readme.txt = this file ROM Addresses: C0/5892 - C0/5894 C0/5885 - C0/5887 C0/D68D - C0/D69E Free space used: 18 bytes, C0/D68D - C0/D69E Urgency: Low. This design quirk becomes a painfully obvious bug only when using Master ZED's FF3DashB and FF3DashC patches. In vanilla FF3 the effect is only briefly noticeable with some of the slower-moving NPCs. ________________________________________________________________________________ TABLE OF CONTENTS 0. Description 1. Relevant Offsets & Disassembly 2. Other Learnings a. New comments for C0 bank assembly code b. "100+ bugs" insight 3. Revision History 4. Credits ________________________________________________________________________________ 0. DESCRIPTION When characters walk on the field, the game determines which sprite to display at any given moment by using an offset derived from the character's current position and direction, cycling through a set of four offsets for each 2-tile walking animation. The routine that determines this offset works smoothly when the character is decreasing its position value (moving up or left), but it lags by one sprite when the character is increasing its position value (moving down or right). This can become noticable with extra-slow NPCs, as they will often appear to slide mid-step when changing direction. More notably, this causes the bug in Master ZED's FF3dashB and FF3dashC patches where the sprite appears to be standing still when running down or right at maximum speed (Dash + Sprint Shoes). This occurs because two sprite instances are thrown out of the animation cycle when running at that speed; while Up/Left correctly omits the standing sprite, Down/Right omits the stepping sprites, since the offsets lag by an iteration. Final Fantasy Anthology attempted to remedy the dash issue by simply reordering the sprite I.D. table accessed with the offset; however, this made characters finish their walking animations in the 'stepping' pose after dashing - which is also undesirable. This fix instead rewrites the offset derivation function so that the flow of walking animations is consistent in all four directions. Slow NPCs will now walk a bit more believably, and there will be no more sliding-while-dashing nonsense when using Master ZED's patch. ________________________________________________________________________________ 1. RELEVANT OFFSETS & DISASSEMBLY Original code for sprite offset calculation: C0/5882: B9 6A 08 LDA $086A,Y ; Load horiz. position to be used for offset C0/5885: 4A LSR A ; Shift offset value such that C0/5886: 4A LSR A ; the least- significant bit will change C0/5887: 4A LSR A ; roughly two times in the course of one step. C0/5888: 80 13 BRA $589D C0/588A: BE 73 08 LDX $0873,Y C0/588D: F0 1B BEQ $58AA C0/588F: B9 6D 08 LDA $086D,Y ; Load vert. position to be used for offset C0/5892: 4A LSR A ; Shift offset value such that C0/5893: 4A LSR A ; the least- significant bit will change C0/5894: 4A LSR A ; roughly two times in the course of one step. C0/5895: 80 06 BRA $589D C0/5897: A5 46 LDA $46 C0/5899: 4A LSR A C0/589A: 4A LSR A C0/589B: 80 00 BRA $589D C0/589D: 29 03 AND #$03 ; Zero all but the last two bits C0/589F: 18 CLC C0/58A0: 65 1A ADC $1A ; Add offset determined by the direction C0/58A2: AA TAX C0/58A3: BF 1D 58 C0 LDA $C0581D,X ; Use offset to look up the sprite I.D. Modified code: C0/5885: 20 8D D6 JSR $D68D ; Jump to new subroutine $D68D C0/5892: 20 8D D6 JSR $D68D ; Jump to new subroutine $D68D New Subroutine $D68D: C0/D68D: 4A LSR ; Shift offset bits right C0/D68E: 4A LSR ; Shift offset bits right C0/D68F: 48 PHA ; Push offset value to stack C0/D690: B9 7F 08 LDA $087F,y ; Load direction value C0/D693: 3A DEA ; Check if direction is Right C0/D694: F0 03 BEQ $D699 ; Branch if the direction is Right C0/D696: 3A DEA ; Check if the direction is Down C0/D697: D0 03 BNE $D69C ; Branch if the direction is Down C0/D699: 68 PLA ; Pull position off of stack C0/D69A: 1A INC ; Increase the offset value by 1P C0/D68B: 48 PHA ; Push offset value to stack C0/D69C: 68 PLA ; Pull position off of stack C0/D69D: 4A LSR ; Shift position bits right C0/D69E: 60 RTS ; Return from subroutine ________________________________________________________________________________ 2. OTHER LEARNINGS a. New comments for C0 bank assembly code Here are a few snippets of the C0 bank that was able to decipher during the course of this hack: C0/4978: A507 LDA $07 ; Get value stored from controller1 byte 2 C0/497A: 2901 AND #$01 ; AND for Right button on d-pad C0/497C: F018 BEQ $4996 ; Branch if button not pressed or held in C0/497E: A947 LDA #$47 ; Load I.D. for sprite standing, facing right C0/4980: 997708 STA $0877,Y ; Store the sprite I.D. C0/4983: A901 LDA #$01 ; Load I.D. for the Right direction C0/4985: 997F08 STA $087F,Y ; Store direction I.D. C0/4988: 20514D JSR $4D51 C0/498B: D062 BNE $49EF C0/498D: A902 LDA #$02 C0/498F: 20164E JSR $4E16 C0/4992: F05B BEQ $49EF C0/4994: 806D BRA $4A03 C0/4996: A507 LDA $07 ; Get value stored from controller1 byte 2 C0/4998: 2902 AND #$02 ; AND for Left button on d-pad C0/499A: F018 BEQ $49B4 ; Branch if button not pressed or held in C0/499C: A907 LDA #$07 ; Load I.D. for sprite standing, facing left C0/499E: 997708 STA $0877,Y ; Store the sprite I.D. C0/49A1: A903 LDA #$03 ; Load I.D. for the Left direction C0/49A3: 997F08 STA $087F,Y ; Store direction I.D. C0/49A6: 20514D JSR $4D51 C0/49A9: D044 BNE $49EF C0/49AB: A904 LDA #$04 C0/49AD: 20164E JSR $4E16 C0/49B0: F03D BEQ $49EF C0/49B2: 804F BRA $4A03 C0/49B4: A507 LDA $07 ; Get value stored from controller1 byte 2 C0/49B6: 2908 AND #$08 ; AND for Up button on d-pad C0/49B8: F017 BEQ $49D1 ; Branch if button not pressed or held in C0/49BA: A904 LDA #$04 ; Load I.D. for sprite standing, facing forward C0/49BC: 997708 STA $0877,Y ; Store the sprite I.D. C0/49BF: 7B TDC ; Load I.D. for the Up direction (00h) C0/49C0: 997F08 STA $087F,Y ; Store direction I.D. C0/49C3: 20514D JSR $4D51 C0/49C6: D027 BNE $49EF C0/49C8: A901 LDA #$01 C0/49CA: 20164E JSR $4E16 C0/49CD: F020 BEQ $49EF C0/49CF: 8032 BRA $4A03 C0/49D1: A507 LDA $07 ; Get value stored from controller1 byte 2 C0/49D3: 2904 AND #$04 ; AND for Down button on d-pad C0/49D5: F018 BEQ $49EF ; Branch if button not pressed or held in C0/49D7: A901 LDA #$01 ; Load I.D. for sprite standing, facing backward C0/49D9: 997708 STA $0877,Y ; Store the sprite I.D. C0/49DC: A902 LDA #$02 ; Load I.D. for the Down direction C0/49DE: 997F08 STA $087F,Y ; Store direction I.D. C0/49E1: 20514D JSR $4D51 C0/49E4: D009 BNE $49EF C0/49E6: A903 LDA #$03 C0/49E8: 20164E JSR $4E16 C0/49EB: F002 BEQ $49EF C0/49ED: 8014 BRA $4A03 C0/49EF: AC0308 LDY $0803 C0/49F2: 7B TDC C0/49F3: 997E08 STA $087E,Y C0/49F6: 9C8608 STZ $0886 C0/49F9: 20A5C8 JSR $C8A5 C0/49FC: 20F446 JSR $46F4 C0/49FF: 20834B JSR $4B83 C0/4A02: 60 RTS ; Sprite offset table for walking animations: C0/580D: 04 05 04 03 ; Unknown C0/5811: 6E 6F 6E 6F ; Unknown C0/5815: 01 02 01 00 ; Unknown C0/5819: 2E 2F 2E 2F ; Unknown C0/581D: 04 05 04 03 ; Character sprite moving Up C0/5821: 47 48 47 46 ; Character sprite moving Right C0/5825: 01 02 01 00 ; Character sprite moving Down C0/5829: 07 08 07 06 ; Character sprite moving Left ---------------------------------------- b. "100+ bugs" insight In the "100+ bugs" thread, Novalia Spirit speculated that bug #103 "Stuck in a pose" is directly related to the dash bug in FFAnthology; however, this does not appear to be the case. This patch DOES fix the animation quirk that FFA failed to address properly; it DOES NOT fix the "Stuck in a pose" bug in general (which seems more like a pattern of sloppy design than a bug). Since version 1.0 of this patch, the "Stuck in a pose" bug has been addressed by the author's subsequent patch, aptly named "Stuck in a Pose fix." ________________________________________________________________________________ 3. REVISION HISTORY February 11, 2016 - Version 1.0 completed. June 03, 2019 - Version 1.1 completed. > Uses 3 fewer bytes of free space. ________________________________________________________________________________ 4. CREDITS Master ZED, for writing the FF3 Dash button hack. Imzogelmo, for his disassembly of bank C0 and for his patch allocation list. Novalia Spirit, for compiling an excellent bugs list. Squaresoft, for always leaving room for improvement ;) ________________________________________________________________________________ Copyright (C) 2019 David R. Thompson (SilentEnigma). The author intends for this readme document to accompany the distributed file. The author expects to be given credit whenever his work is re-used or modified.