Title: Multi-Steal-Fix Simplified Edition Author: SilentEnigma (updates), Imzogelmo (original implementation) Version: 1.0 Release Date: 2023-02-18 Applies to: Final Fantasy III (v1.0) (U) Final Fantasy III (v1.1) (U) Final Fantasy VI (J) Archive Contents ------------------------------- readme.txt = this file MultiStealFix-SE_J0_H.ips = patch for headered FF6j ROMs MultiStealFix-SE_J0_H_Anti.ips = anti-patch for headered FF6j ROMs MultiStealFix-SE_J0_NH.ips = patch for unheadered FF6j ROMs MultiStealFix-SE_J0_NH_Anti.ips = anti-patch for unheadered FF6j ROMs MultiStealFix-SE_U0_H.ips = patch for headered FF3us 1.0 ROMs MultiStealFix-SE_U0_H_Anti.ips = anti-patch for headered FF3us 1.0 ROMs MultiStealFix-SE_U0_NH.ips = patch for unheadered FF3us 1.0 ROMs MultiStealFix-SE_U0_NH_Anti.ips = anti-patch for unheadered FF3us 1.0 ROMs MultiStealFix-SE_U1_H.ips = patch for headered FF3us 1.1 ROMs MultiStealFix-SE_U1_H_Anti.ips = anti-patch for headered FF3us 1.1 ROMs MultiStealFix-SE_U1_NH.ips = patch for unheadered FF3us 1.1 ROMs MultiStealFix-SE_U1_NH_Anti.ips = anti-patch for unheadered FF3us 1.1 ROMs ROM Addresses ------------------------------- FF6j 1.0 (SFC): C1/5EEE, C1/5FFC - C1/5FFF, C2/13F5 - C2/13F7, C2/140B - C2/140C, C2/3999, C2/39A3, C2/39B2, C2/39C7, C2/39D8 - C2/39DE, C2/39F0 - C2/3A08, C2/3A15, C2/654D - C2/6564, C2/6783 - C2/67A7 FF3us 1.0 (SNES): C1/5F0A, C1/6046 - C1/6049, C2/13FA - C2/13FC, C2/1410 - C2/1411, C2/39A9, C2/39B3, C2/39C2, C2/39D7, C2/39E8 - C2/39EE, C2/3A00 - C2/3A18, C2/3A25, C2/6565 - C2/657C, C2/6783 - C2/67A7 FF3us 1.1 (SNES): C1/5F07, C1/6043 - C1/6046, C2/13FA - C2/13FC, C2/1410 - C2/1411, C2/39A9, C2/39B3, C2/39C2, C2/39D7, C2/39E8 - C2/39EE, C2/3A00 - C2/3A18, C2/3A25, C2/6565 - C2/657C, C2/6783 - C2/67A7 Additional RAM used ------------------------------- $7E2F35 - $7E2F3B Urgency ------------------------------- Low Medium. From Imzogelmo: "This bug will not crash or freeze your game, but it could lull you into a false sense of security if you believe everything you read. Therefore, I rate it at 0302/1000." TABLE OF CONTENTS ------------------------------- 0. Description 1. Relevant Offsets & Disassembly 2. Credits 3. Revision History 4. Legal ________________________________________________________________________________ 0. DESCRIPTION ________________________________________________________________________________ This patch updates Imzogelmo's "Multi-Steal-Fix" patch for easier integration with other FF3us/FF6j hacking projects. From Imzogelmo: "This patch corrects two small problems encountered when using the Thief Glove and Offering (or any other attack that does multiple steal attempts in a round). One problem is that normally only the first item reported stolen is actually stolen, yet the items of the rest of the enemies are lost forever. This patch lets you receive your rewards. The other bug is that the display does not normally reflect the supposedly stolen items (doesn't matter since they aren't really stolen though). Now the display works correctly as well." Imzogelmo's original Multi-Steal-Fix minimized free space usage by optimizing a large section of code in the C1 bank (C1/5EA0 - C1/6081 in FF3us 1.0). Unfortunately, several more recent FF6 hacking projects also modify this area of the code, necessitating special workarounds to maintain compatibility. This variant of the patch forgoes the optimization in the C1 bank and instead uses 32 additional bytes of free space in the C2 bank. The moved code has been optimized to use two fewer bytes of free space compared to a 1:1 transfer. A previously documented single-byte bug from Multi-Steal-Fix v1.01 has also been fixed (credit to Gi Nattak). This patch uses some RAM (7E bank) to function. From Imzogelmo: "Memory in $2F35-$2F3B is used by this patch. It is not 'previously unused'; it has simply been chosen for a new task by this patch. $2F35-$2F3A are used as six stolen item numbers (as parameters for the display window). $2F3B is used as the index for this array." ________________________________________________________________________________ 1. RELEVANT OFFSETS & DISASSEMBLY ________________________________________________________________________________ Contents: a. Final Fantasy VI (J/SFC) b. Final Fantasy III (U/SNES) 1.0 c. Final Fantasy III (U/SNES) 1.1 d. Final Fantasy III (U/SNES) Common e. Common ================================================== a. FINAL FANTASY VI (J/SFC) ================================================== Original: C1/5EED: 4C FE 5F JMP $5FFE ; x = 0x02 Modified: C1/5EED: 4C FC 5F JMP $5FFC Original: C1/5FFC: A7 48 LDA [$48] ; x = 0x1C C1/5FFE: C9 FF CMP #$FF Modified: C1/5FFC: 22 83 67 C2 JSL $C26783 ; new subroutine C2/6783 ------------------------------- Original: C2/13F5: A5 B5 LDA $B5 ; Load command C2/13F7: 0A ASL Modified: C2/13F5: 20 59 65 JSR $6559 ; new subroutine C2/6559 Original: C2/140A: 20 24 14 JSR $1424 Modified: C2/140A: 20 5E 65 JSR $655E ; new subroutine C2/655E Original: C2/3998: B0 5F BCS $39F9 ; Branch if monster Multi-Steal-Fix [Imzogelmo] v1.01: C2/3998: B0 62 BCS $39FC ; Branch if monster (bugged) Modified: C2/3998: B0 65 BCS $39FF ; Branch if monster Original: C2/39A2: F0 4D BEQ $39F1 ; Fail to steal if no items Modified: C2/39A2: F0 53 BEQ $39F3 ; Fail to steal if no items Original: C2/39B1: 90 3E BCC $39F1 ; Fail to steal if tgt lvl > actor lvl + 50 Modified: C2/39B1: 90 44 BCC $39F3 ; Fail to steal if tgt lvl > actor lvl + 50 Original: C2/39C6: B0 29 BCS $39F1 ; Fail to steal Modified: C2/39C6: B0 2F BCS $39F3 ; Fail to steal Original: C2/39D7: F0 18 BEQ $39F1 ; Fail to steal C2/39D9: 8D 35 2F STA $2F35 ; item stolen C2/39DC: 9D F4 32 STA $32F4,X Modified: C2/39D7: F0 1E BEQ $39F3 ; Fail to steal C2/39D9: 9D F4 32 STA $32F4,X ; item stolen C2/39DC: 20 4D 65 JSR $654D ; new subroutine C2/654D Original: C2/39F0: 60 RTS ; if no items to steal C2/39F1: E2 20 SEP #$20 C2/39F3: A9 00 LDA #$00 C2/39F5: 99 48 3D STA $3D48,Y C2/39F8: 60 RTS ; Steal for monsters C2/39F9: 9C 3A 2F STZ $2F3A C2/39FC: EE 01 34 INC $3401 ; Set message to "Couldn't steal!!" C2/39FF: 20 42 4B JSR $4B42 C2/3A02: C9 C0 CMP #$C0 C2/3A04: B0 EB BCS $39F1 ; Fail to steal 1/4 of the time C2/3A06: CE 01 34 DEC $3401 ; Set message to "Doesn't have anything!" Modified: C2/39F0: 20 AF 62 JSR $62AF ; Update inventory with newly stolen item C2/39F3: 60 RTS ; if no items to steal C2/39F4: EE 01 34 INC $3401 C2/39F7: E2 20 SEP #$20 ; usual entry point except one case C2/39F9: A9 00 LDA #$00 C2/39FB: 99 48 3D STA $3D48,Y C2/39FE: 60 RTS ; Steal for monsters C2/39FF: 9C 3A 2F STZ $2F3A C2/3A02: 20 42 4B JSR $4B42 C2/3A05: C9 C0 CMP #$C0 C2/3A07: B0 EB BCS $39F4 New Subroutine C2/654D: C2/654D: DA PHX C2/654E: AE 3B 2F LDX $2F3B ; Load index for array (custom var) C2/6551: 9D 35 2F STA $2F35,X ; Store item I.D. into array (custom vars) C2/6554: EE 3B 2F INC $2F3B ; Increment index for highest var stored C2/6557: FA PLX C2/6558: 60 RTS New Subroutine C2/6574: C2/6559: A5 B5 LDA $B5 C2/655B: 0A ASL C2/655C: 80 03 BRA $6561 ; only zeros $2F3B, the index New Subroutine C2/6579: C2/655E: 20 24 14 JSR $1424 ; original C2/140A C2/6561: 9C 3B 2F STZ $2F3B ; Zero the index for the array C2/6564: 60 RTS ================================================== b. FINAL FANTASY III (U/SNES) 1.0 ================================================== Original: C1/5F09: 4C 48 60 JMP $6048 ; x = 0x02 Modified: C1/5F09: 4C 46 60 JMP $6046 Original: C1/6046: A7 48 LDA [$48] ; x = 0x1C C1/6048: C9 FF CMP #$FF Modified: C1/6046: 22 83 67 C2 JSL $C26783 ; new subroutine C2/6783 ================================================== c. FINAL FANTASY III (U/SNES) 1.1 ================================================== Original: C1/5F06: 4C 45 60 JMP $6045 ; x = 0x02 Modified: C1/5F06: 4C 43 60 JMP $6043 Original: C1/6043: A7 48 LDA [$48] ; x = 0x1C C1/6045: C9 FF CMP #$FF Modified: C1/6043: 22 83 67 C2 JSL $C26783 ; new subroutine C2/6783 ================================================== d. FINAL FANTASY III (U/SNES) COMMON ================================================== Original: C2/13FA: A5 B5 LDA $B5 ; Load command C2/13FC: 0A ASL Modified: C2/13FA: 20 71 65 JSR $6571 ; new subroutine C2/6571 Original: C2/140F: 20 29 14 JSR $1429 Modified: C2/140F: 20 76 65 JSR $6576 ; new subroutine C2/6576 Original: C2/39A8: B0 5F BCS $3A09 ; Branch if monster Multi-Steal-Fix [Imzogelmo] v1.01: C2/39A8: B0 62 BCS $3A0C ; Branch if monster (bugged) Modified: C2/39A8: B0 65 BCS $3A0F ; Branch if monster ; MESSED UP U1.1 Original: C2/39B2: F0 4D BEQ $3A01 ; Fail to steal if no items Modified: C2/39B2: F0 53 BEQ $3A03 ; Fail to steal if no items Original: C2/39C1: 90 3E BCC $3A01 ; Fail to steal if tgt lvl > actor lvl + 50 Modified: C2/39C1: 90 44 BCC $3A03 ; Fail to steal if tgt lvl > actor lvl + 50 Original: C2/39D6: B0 29 BCS $3A01 ; Fail to steal Modified: C2/39D6: B0 2F BCS $3A03 ; Fail to steal Original: C2/39E7: F0 18 BEQ $3A01 ; Fail to steal C2/39E9: 8D 35 2F STA $2F35 ; item stolen C2/39EC: 9D F4 32 STA $32F4,X Modified: C2/39E7: F0 1E BEQ $3A03 ; Fail to steal C2/39E9: 9D F4 32 STA $32F4,X ; item stolen C2/39EC: 20 65 65 JSR $6565 ; new subroutine C2/6565 Original: C2/3A00: 60 RTS ; if no items to steal C2/3A01: E2 20 SEP #$20 C2/3A03: A9 00 LDA #$00 C2/3A05: 99 48 3D STA $3D48,Y C2/3A08: 60 RTS ; Steal for monsters C2/3A09: 9C 3A 2F STZ $2F3A C2/3A0C: EE 01 34 INC $3401 ; Set message to "Couldn't steal!!" C2/3A0F: 20 5A 4B JSR $4B5A C2/3A12: C9 C0 CMP #$C0 C2/3A14: B0 EB BCS $3A01 ; Fail to steal 1/4 of the time C2/3A16: CE 01 34 DEC $3401 ; Set message to "Doesn't have anything!" Modified: C2/3A00: 20 C7 62 JSR $62C7 ; Update inventory with newly stolen item C2/3A03: 60 RTS ; if no items to steal C2/3A04: EE 01 34 INC $3401 C2/3A07: E2 20 SEP #$20 ; usual entry point except one case C2/3A09: A9 00 LDA #$00 C2/3A0B: 99 48 3D STA $3D48,Y C2/3A0E: 60 RTS ; Steal for monsters C2/3A0F: 9C 3A 2F STZ $2F3A C2/3A12: 20 5A 4B JSR $4B5A C2/3A15: C9 C0 CMP #$C0 C2/3A17: B0 EB BCS $3A04 Original: C2/3A24: F0 DB BEQ $3A01 ; Branch if target had zero GP before steal Modified: C2/3A24: F0 DE BEQ $3A03 New Subroutine C2/6565 (Imzogelmo): C2/6565: DA PHX C2/6566: AE 3B 2F LDX $2F3B ; Load index for array (custom var) C2/6569: 9D 35 2F STA $2F35,X ; Store item I.D. into array (custom vars) C2/656C: EE 3B 2F INC $2F3B ; Increment index for highest var stored C2/656F: FA PLX C2/6570: 60 RTS New Subroutine C2/6571 (Imzogelmo): C2/6571: A5 B5 LDA $B5 C2/6573: 0A ASL C2/6574: 80 03 BRA $6579 ; only zeros $2F3B, the index New Subroutine C2/6576 (Imzogelmo): C2/6576: 20 29 14 JSR $1429 ; original C2/140F C2/6579: 9C 3B 2F STZ $2F3B ; Zero the index for the array C2/658C: 60 RTS ================================================== e. COMMON ================================================== New Subroutine C2/6783 (Imzogelmo/SilentEnigma): C2/6783: E0 02 00 CPX #$0002 ; Jumped to C1/6046 from C1/5F09 [U1.0]? C2/6786: F0 02 BEQ $678A C2/6788: A7 48 LDA [$48] ; original C1/6046 [U1.0] C2/678A: 48 PHA C2/678B: C2 20 REP #$20 ; 16 bit accum./memory C2/678D: B2 76 LDA ($76) ; first two bytes of current animation entry C2/678F: C9 02 03 CMP #$0302 ; animation opcode 2 (upper "Steal ")? C2/6792: E2 30 SEP #$30 ; 8 bit accum./memory, 8 bit index registers C2/6794: F0 03 BEQ $6799 ; If above condition was true, branch C2/6796: 68 PLA C2/6797: 80 0A BRA $67A3 ; Branch to just before original code C2/6799: 68 PLA C2/679A: AE 3B 2F LDX $2F3B ; Load index to stolen item array C2/679D: BD 35 2F LDA $2F35,X ; Get appropriate item index C2/67A0: EE 3B 2F INC $2F3B ; Increment array index C2/67A3: C2 10 REP #$10 ; 16 bit index register C2/67A5: C9 FF CMP #$FF ; original C1/6048 [U1.0] C2/67A7: 6B ________________________________________________________________________________ 2. CREDITS ________________________________________________________________________________ Contents: a. Original Multi-Steal-Fix (Imzogelmo) b. Updates (SilentEnigma) ================================================== a. ORIGINAL MULTI-STEAL-FIX (Imzogelmo) ================================================== From Imzogelmo: - Terii Senshi, whose bank 2 disassembly has been the basis of many finds in the area of game mechanics (though it's a bit outdated now, it's still a good start). - Master ZED, who was kind enough to give me permission to use the bug description from his Glitches and Bugs document. - Square, because they made this game, which is incredible even 10 years later (in spite of its flaws). - My girlfriend, who has not complained even once that I've been working too much on this thing (which I have). - ChibiChibi, who posted on GameFAQs about a problem encountered when non-battle message functions try to display an item name immediately after a successful steal by another character. Hopefully version 0.93 corrects this! - Hollywood Narrator, who reported a nasty bug in the ff3-1.1 patch in a previous version. - Anyone who reports a problem with this patch, which is likely, as huge as this thing is. Special Thanks to Assassin, who helped with the optimization of the Steal function that ultimately led to a savings of 7 precious FF-block bytes, and also for help freeing bytes in the C1 bank and testing of the final product. Also, I totally ripped off his readme style (hey, it's functional!). ================================================== b. UPDATES (SilentEnigma) ================================================== Imzogelmo ........... Original implementation (Multi-Steal-Fix 1.01) SilentEnigma ........ Updates & minor optimization Gi Nattak ........... C2/39A9 bugfix ________________________________________________________________________________ 3. REVISION HISTORY ________________________________________________________________________________ 2023-02-18 : Version 1.0 released ________________________________________________________________________________ 4. LEGAL ________________________________________________________________________________ Copyright (C) 2023 David R. Thompson (SilentEnigma). The copyright holder permits the free use of the attributed work referenced by this document exclusively for non-commercial purposes, provided that the following conditions are met: 1. The authors and all contributors credited in this readme document shall be given credit for their respective contributions wherever the attributed work is reused, redistributed, or modified. 2. This readme document shall accompany any of the files comprising the attributed work wherever they are redistributed in unmodified form. The work(s) and file(s) distributed with this document are provided "AS-IS", WITHOUT ANY WARRANTY. The author(s) shall not be held responsible for any damages related to the use of work(s) and file(s) distributed with this document. Multi-Steal-Fix copyright (C) Imzogelmo, 2004-2005. The copyright holder "David R. Thompson (SilentEnigma)" makes no claim to Multi-Steal-Fix or any intellectual property contained therein.