Users browsing this thread: 1 Guest(s)
Mod-agnostic no-text patch

Posts: 4
Threads: 1
Thanks Received: 8
Thanks Given: 0
Joined: Apr 2021
Reputation: 0
This is a no-text patch I've been working on that doesn't depend on the state of the event or dialogue banks. Instead, it slices into the default handlers for event codes $4B and $48 (dialogue with and without wait for input, respectively) and just... doesn't display them. Unless it detects they contain a treasure indicator or multiple choice prompt, in which case it does display them (in case one wants to apply a randomizer to their ROM).

In its current form, it seems to be entirely playable, though it hasn't been subjected to a full playthrough quite yet (one can at least reach the WoR, that much I can confirm). EDIT: can now confirm it is playable through the whole game.

The following is a list of things this hack does not do yet, though I still intend to implement them:
  • display the amount of coral found in chests in Ebot's Rock
  • skip in-combat dialogue
  • display dialogue boxes when obtaining Espers (again, as a QoL for randomizers, mostly)
This patch does not try to skip cutscenes, so there is a bit of jankiness during the more elaborate ones, e.g. the Opera. I may try to expand its functionality to cover this in the future, but that seems like a scary undertaking using the approach I've taken for the dialogue. Nothing breaks, but it can seem like things are hanging at times because sprites have already executed their movements before they should have been able to do so.

The patch comes in 2 parts; one is a minor optimization that eliminates some redundancy between the handlers for event codes $48 and $4B (there's a lot of duplication between them). This sets up the common behaviour as a subroutine that the two handlers can then call.

; header

; First, turn the majority of the "display dialogue" action 48 handler
;   into a subroutine, since its implementation is duplicated in action 4B

org $C0A49F
 rts                   ; Return instead of the load and jump
 padbyte $FF           ; Erase the rest of this routine
 pad $C0A4A6           ; 6B free space... hooray?

!loadtext = $A475       ; The start of the old 48 handler, now a
                       ;   subroutine for loading text without
                       ;   displaying the dialogue window

; Next, rip the old 4B handler apart, turning it into two routines:
;   one, a handler for action 48, the other a handler for action 4B
;   (AND free up 31B to boot)

org $C0A4BC

 jsr !loadtext         ; Call the subroutine above
 sta $BA               ; Dialogue box open = true
 lda #$03              ; Number of bytes to advance event queue
 jmp $9B5C             ; Continue

 jsr !loadtext         ; See above
 sta $BA               ; Dialogue box open = true
 lda #$01              ;
 sta $EB               ;
 lda #$00              ; The rest of this is something about calling
 sta $EC               ;   a subroutine (action B2). Has something to
 sta $ED               ;   do with the waiting for player input to
 lda #$03              ;   dismiss the dialogue box, perhaps..?
 jmp $B1A3             ;   Preserved from original implmentation.

 padbyte $FF           ; Erase the rest of this routine
 pad $C0A4F9           ; 31B free space

; Finally, slice into the event handler jump table

org $C098EA             ; action 48
 dw Handler48

org $C098F0             ; action 4B
 dw Handler4B

The second part is the actual no-text patch, which reclaims the space freed up in the optimization patch, and uses the newly created subroutine as part of its implementation. In a nutshell, it preloads the dialog for the current dialogue event (without displaying the window), scans through it until it reaches a control code for multiple choice, treasure, or GP, and returns when it either finds one or hits the end of string. If it found a code, it loads the dialogue window as normal. If it does not, it skips the event.

; header

; Recycle the largely redundant 4B handler to make some nearby space
incsrc "optimize_dialog.asm"

; The space freed up by optimize_dialog.asm
!recycledspace = RecycledSpace

; Existing free space in C0 (this location is for BNW, but can be
;   as early as $C0D613 for vanilla) for field dialogue handler
!freespaceC0 = $C0DA17
; !freespaceC0 = $C0D613

; The text loading subroutine set up for the 48 and 4B handlers in
;   optimize_dialog.asm
!loadtext = $A475

; $C0 General actions jump table
org $C098EA           ; Dialogue without wait
 dw Action48

org $C098F0           ; Dialogue, wait for input
 dw Action4B

org !recycledspace    ; This chunk conveniently packs into 30 of the
                     ;   31B just freed up, so that's a nice bonus

 jsr CheckWhitelist  ; Check against the control code whitelist
 cmp #$FF            ; See if we found one
 bne ShortCircuit    ;   - if not, do nothing
 jmp Handler48       ;   - if so, call original (optimize_dialog.asm)

 jsr CheckWhitelist  ; Check against the control code whitelist
 cmp #$FF            ; See if we found one
 bne ShortCircuit    ;   - if not, do nothing
 jmp Handler4B       ;   - if so, call original (optimize_dialog.asm)

ShortCircuit:         ; Default behaviour for both
 jmp Cleanup         ; Tidy, skip dialog, advance to the next event

 jsr !loadtext       ; Preload the current dialog, but do not display
 jmp CheckCodes

org !freespaceC0      ; The rest of this lives in an unused region of
                     ;   $C0. See note at the top about the location
                     ;   of this space.
 ldy $00             ; start at first character of text
.loop                 ; v---------------------------------<
 lda [$C9],Y         ; Load letter at index Y            |
 beq .end            ; - exit if EOS is reached          |
 cmp #$15            ; - is it a choice control code?    |
 beq .found          ;   => found one, break out of loop |
 cmp #$19            ; - is it a GP control code?        |
 beq .found          ;   => found one, break out of loop |
 cmp #$1A            ; - is it an item control code?     |
 beq .found          ;   => found one, break out of loop |
 iny                 ; - else, increment index           |
 jmp .loop           ; Check next character -------------^
 lda #$FF
 jmp CheckCodes_return
 jmp CheckWhitelist_return

 stz $D0
 stz $BC
 stz $0564
 stz $CB
 stz $C9
 stz $0568
 jmp AdvanceQueue    ; The end of the 48 handler, see optimize_dialog.asm

This patch was assembled using asar on an unheadered ROM, and I have not tested it with xkas. It was developed originally for BNW, but should be applicable to vanilla, or any other flavor of FF6 that does not seriously rearrange bank $C0. As-is, the portion that uses pre-existing free space is pointed to a region of free space for BNW, but it contains a comment to adjust for vanilla.

Enjoy, and please let me know if you discover any issues (or have any ideas for optimizations, I'm pretty new to this).

Attached Files
.zip (3.52 KB, 3 downloads)
[-] The following 7 users say Thank You to SirNewtonFig for this post:
  • Gens (04-10-2021), Gi Nattak (04-10-2021), madsiur (04-10-2021), NPCnextdoor (04-30-2021), seibaby (04-10-2021), SSJ Rick (04-11-2021), Warrax (04-11-2021)

Posts: 3,849
Threads: 271
Thanks Received: 779
Thanks Given: 439
Joined: Oct 2011
Reputation: 63
This is a nice patch! Thanks for sharing!

Forum Jump:

Users browsing this thread: 1 Guest(s)

Theme by Madsiur2017Custom Graphics by JamesWhite