About the routine text from right to left(RTL) - q8fft - 01-30-2018
hello, i wondering about the correct way, to flip the routine text dialogues from right to left (LTR to RTL) using ASM.
I have try this before in NES, but not sure about SNES Game because i know nothing really...
is there anyone give tips or guide to this challenge.
hope to find someone interested in this.
thanks...
RE: About the routine text from right to left(RTL) - madsiur - 01-30-2018
It has more to do with FF3us than SNES games meaning the SNES is not limited in this regard. Simply put you need to look at bank $C0. There is a RAM value for position on line ($BF). Instead of starting at #$04 (beginning X position) and checking for ((position += character width) > #$E0 (max X position)) to go to the next line, you start at #$E0 and decrease each time you draw a character, checking for ((#$E0 - position) >= #$04), where position is increased each time you draw (position += current character width).
It's not well documented but by studying the code in bank $C0 it is doable. There would be special stuff like actor names to take care of, check $C08067 for special opcodes cases. I made a text centering opcode and got a good idea of the system. Here is my code to center text:
Code: ;------------------------------------------------------------------------
; Centring Control Character code (OP#$17)
;------------------------------------------------------------------------
CChar:
LDA $BF ; Load current line position
CMP #$04 ; Beginning of line
BNE brn_exitB ; Branch if we are not at the start of a line
STZ $3F ; Current word length: 0
sub_loop:
LDY $00 ; Current dialogue character: pointer + 0
LDA [$C9],Y ; Load dialogue character
BPL notDTE ; Branch if not DTE
AND #$7F ; Isolate DTE ID
ASL A ; Multiply by 2
TAX ; Index it
LDA $CF ; Load text buffer byte
CMP #$80 ; Check if buffer is empty
BEQ .sub_loopB ; branch if buffer is empty
LDA #$80 ;
STA $CF ; Set buffer as not empty
BRA secondDTE ; Verify second DTE character
.sub_loopB
LDA $C0DFA0,X ; Load DTE character 1
TAY ; Transfer A to X
LDA [$1A],Y ; Load width for variable font cell
CLC ; Prepare addition (no carry)
ADC $3F ; Add font cell width to sentence width
STA $3F ; Save as sentence width
secondDTE:
LDA $C0DFA1,X ; Load DTE character 2
TAY ; Save character index
LDA [$1A],Y ; Load width for variable font cell
CLC ; Prepare addition (no carry)
ADC $3F ; Add font cell width to sentence width
STA $3F ; Save as sentence width
BRA checkEol ; Check end of line an increment pointer if necessary
notDTE:
LDY $00 ; Clear Index
LDA [$C9],Y ; Load dialogue character
CMP #$01 ; Is it new line character?
BEQ calcMiddle ; branch if so (calculate center)
CMP #$11 ; Is it end parameter character?
BEQ calcMiddle ; branch if so (calculate center)
CMP #$12 ; Is it end parameter character?
BEQ calcMiddle ; branch if so (calculate center)
CMP #$13 ; Is it end of page character?
BEQ calcMiddle ; branch if so (calculate center)
CMP #$20 ; Is the character a character code?
BCC incDialog ; Branch if so (increment dialogue pointer and loop)
TAY ; Save character index
LDA [$1A],Y ; Load width for variable font cell
CLC ; Prepare addition (no carry)
ADC $3F ; Add font cell width to sentence width
STA $3F ; Save as sentence width
checkEol:
CMP #$E0 ; Compare to line max width
BCS brn_exitB ; we have ended the line, there's nothing to center...
incDialog:
INC $C9 ; Increment dialogue
BNE sub_loop
INC $CA
BNE sub_loop
INC $CB
BRA sub_loop
brn_exitB:
RTS
calcMiddle:
LDA #$E0 ; Load line width
SBC $3F ; Subtract sentence width
LSR A ; Divide by 2
STA $BF ; Store as position in line
TAY
STY $4204 ; Whatever is left, store as to be divided
LDA #$10
STA $4206 ; Divide Y by 16
NOP
NOP
NOP
NOP
NOP
NOP
NOP
LDA $4214 ; Load the division result
STA $4202 ; Store as a multiplier
LDA #$20
STA $4203 ; Multiply previous result by 32
NOP
NOP
NOP
LDA $4216 ; Get the multiplication result
ADC $C1
STA $C1
BRA brn_exitB
RE: About the routine text from right to left(RTL) - madsiur - 01-30-2018
I wanted to add last night that the main entry point for dialogue display and decoding seems to be $C0814C. There are call to code before and after this offset. Here is also some RAM values from the FF6 wiki that could help:
Code: $BA-$BC Dialog Window
---------------------
$BA Enable Dialog Window ($01 = open, $80 = close)
$BB Dialog Window Size ($00: smallest, $05: fully open)
$BC Dialog Window Top Y Position ($01: top, $12: bottom)
$BD-$D3 Dialog Text
-------------------
$BD Current Dialog Character
$BE Next Dialog Character
$BF Text's Current X Position on Dialog Window ($04-$E0)
$C0 Width of Current Word
+ $C1 Pointer to Next Tile in VRAM (+$3800)
+ $C3 Pointer to Current Tile in VRAM (+$3800)
$C5 Text Graphics Needs to be Copied to VRAM
+ $C6 Unused (set to #$0700)
$C8 Max X Position on Dialog Window (always $E0?)
++ $C9 Pointer to Current Dialog Character
$CC current region of dialog window that needs to be cleared in VRAM (starts at 9, decrements once per frame)
9 = none, waiting for keypress
+-----------+-----------+
| 8 | 7 |
+-----------+-----------+
| 6 | 5 |
+-----------+-----------+
| 4 | 3 |
+-----------+-----------+
| 2 | 1 |
+-----------+-----------+
0 = none, no text displayed (or map name displayed)
+ $CD Character to Display (top byte is for extra characters from FF6j)
$CF eppppppp
e: text buffer is empty
p: dialog text buffer position (+$7E9183)
+ $D0 Dialog Index
$D2 -
$D3 Keypress State (decrements when button is pressed or released)
0 = not waiting for keypress
1 = waiting for keypress
2 = waiting for key release
|