+  RHDN Forum Archive
|-+  Romhacking
| |-+  ROM Hacking Discussion
| | |-+  Changing dialogue font in Final Fantasy IV (J2E)
Pages: [1]
Author Topic: Changing dialogue font in Final Fantasy IV (J2E)  (Read 1 times)
JeanMarieStaub
Guest
« on: June 18, 2011, 10:13:09 am »

I am currently working on a German translation of J2E's Final Fantasy IV Translation.
I've already succesfully created my table files, located most of the text (dialogue, items, monsters, places, etc) and pointers, as well as the font graphics.
However, I now have to add several German special characters (the 'umlauts' like ä, ö, ü, ß, both capital and lower). From looking at the font used for dialogue, this does not seem to be as straightforward as I initially thought (just replacing some single 8x8 tiles in the rom with my umlauts). It seems the game uses a 8x16 font for its dialogue, whose addresses do not seem to map to my table file.
Am I correct in assuming that there is a table somewhere in the ROM that maps the 2 8x8 tiles for each character to the hexcode that is then used in the dialogue? And if yes, how would I go about finding this table and add/replace entries?
Mind you that I am just starting romhacking and am not yet very well versed in stuff like ASM, etc, although I definitely want to learn it. I can, however, use a debugger and have a very rough (though growing) understanding of SNES CPU instructions.
I would be very glad about any pointers on how to solve my problem :-)
Oh, and if anybody knows how to contact team members of J2E so I can talk directly to the creaters of the English translation, that would be incredible!

Here is the font I found in the ROM:


And here my table file for the dialogue:
Code:
10=B
11=C
12=D
13=E
14=F
15=G
16=H
17=I
18=J
19=K
1A=L
1B=M
1C=N
1D=O
1E=P
1F=Q
20=R
21=S
22=T
23=U
24=V
25=W
26=X
27=Y
28=Z
29=b
2A=d
2B=f
2C=h
2D=i
2E=j
2F=k
30=l
31=t
32='
33=!
34=?
94=x
A6=,
A8=w
C1=.
C2=-
C4=o
C5=u
C8=:
C9=v
D4=z
DD=a
DE=c
DF=e
E0=g
E1=m
E2=n
E3=y
E4=p
E5=q
E6=r
E7=s
FF=
0400=[Cecil]
0401=[Cain]
0402=[Rydia]
0403=[Tellah]
0404=[Gilbert]
0405=[Rosa]
0406=[Yang]
0407=[Palom]
0408=[Porom]
0409=[Cid]
040A=[Edge]
040B=[Fusoya]
040C=[Golbez]
040D=[Anna]
Gemini
Guest
« Reply #1 on: June 18, 2011, 10:20:56 am »

Quote from: JeanMarieStaub on June 18, 2011, 10:13:09 am
Am I correct in assuming that there is a table somewhere in the ROM that maps the 2 8x8 tiles for each character to the hexcode that is then used in the dialogue? And if yes, how would I go about finding this table and add/replace entries?
You stand correct, there is a table declaring which tiles to use for a particular range of characters. This is the routine in the original:
Code:
.org 0x00B670
Char2Tiles:
                CMP.B   #$42            ; 'A'
                BCS     @@regular
                PHX
                SEC
                SBC.B   #$0F            ; -15
                ASL     A
                TAX
                LDA.L   nigori_lookup, X ; kana/character
                XBA
                LDA.L   (nigori_lookup+1), X ; nigori
                XBA
                PLX
                JMP     @@end_line
; ---------------------------------------------------------------------------

@@regular:
                XBA
                LDA.B   #$FF            ; AL=empty nigori
                XBA

@@end_line:
                RTS
; End of function Char2Tiles

; ---------------------------------------------------------------------------
nigori_lookup:  .DB $CC, $C0
                .DB $8F, $C0
                .DB $90, $C0
                .DB $91, $C0
                .DB $92, $C0
                .DB $93, $C0
                .DB $94, $C0
                .DB $95, $C0
                .DB $96, $C0
                .DB $97, $C0
                .DB $98, $C0
                .DB $99, $C0
                .DB $9A, $C0
                .DB $9B, $C0
                .DB $9C, $C0
                .DB $9D, $C0
                .DB $A3, $C0
                .DB $A4, $C0
                .DB $A5, $C0
                .DB $A6, $C0
                .DB $A7, $C0
                .DB $A3, $C1
                .DB $A4, $C1
                .DB $A5, $C1
                .DB $A6, $C1
                .DB $A7, $C1
                .DB $CF, $C0
                .DB $D0, $C0
                .DB $D1, $C0
                .DB $D2, $C0
                .DB $D3, $C0
                .DB $D4, $C0
                .DB $D5, $C0
                .DB $D6, $C0
                .DB $D7, $C0
                .DB $D8, $C0
                .DB $D9, $C0
                .DB $DA, $C0
                .DB $DB, $C0
                .DB $DC, $C0
                .DB $DD, $C0
                .DB $E3, $C0
                .DB $E4, $C0
                .DB $E5, $C0
                .DB $E6, $C0
                .DB $E7, $C0
                .DB $E3, $C1
                .DB $E4, $C1
                .DB $E5, $C1
                .DB $E6, $C1
                .DB $E7, $C1
I think J2E changed it a bit so that it would out correct English characters instead of kana+nigori sets, so it's probably a 1:1 copy of the code above and you'll have only to alter the table to add umlauts and other special characters.
JeanMarieStaub
Guest
« Reply #2 on: June 18, 2011, 02:09:20 pm »

Thank you for the quick reply :-)
I found the routine and the table indeed and already changed my palette and the table to accomodate for the new characters.
However, where do I tell the ROM to make the reference from e.g. 0x65 (="ä") to the appropriate entry in my lookup table?
Setting a breakpoint on the execution of the lookup routine doesn't help much, as I don't know how I can find out from where it is JMPed to :-/ (Is there a way to find out? I'm using Geiger's Snes9X)


---
edit:
Nevermind, I think I just understood it :-)
Correct me if I'm wrong, but here's how I understand it:

1. The character code (0x65) is in the accumulator when the routine is called.
2. 0x0F is subtracted from it.
2. The accumulator is shifted 1 bit to the left (i.e. multiplied by 0x02)
3. The content of the accumulator is stored in register X
4. The byte at LOOKUPTABLE_OFFSET + X is the pointer to the first tile of the character

Which in short gives the following formula for getting from tile-offset to character code:
Code:
($tileaddr - $tableoffset)/2 + 0f
« Last Edit: June 18, 2011, 03:10:10 pm by JeanMarieStaub »
Gemini
Guest
« Reply #3 on: June 18, 2011, 03:39:03 pm »

It's more like this:
Code:
if(AL>=0x42) {char.lo=AL; char.hi=0xFF;}
else {char.lo=nigori_lookup[AL-0xF].lo; char.hi=nigori_lookup[AL-0xF].hi;}
And yes, AL contains the character to be processed.
JeanMarieStaub
Guest
« Reply #4 on: June 18, 2011, 08:06:35 pm »

Okay, I got it working now, only to encounter another problem (as it usually goes with things like that...).
My font lookup table now reaches from $23:800E to $23:8111, with 7 new characters added (i.e. 14 bytes longer than previously)
The codes for the 7 new characters:
Code:
8A=ä
8B=ö
8C=ü
8D=ß
8E=Ä
8F=Ö
90=Ü

The code of the routine was changed to accomodate for them, it now reads:
Code:
CMP.B   #$91          ; formerly #$8A

This works fine for all characters 0x8A-0x8E. However, a problem occurs for 0x8F and 0x90:
When shifting these two values, the leftmost bit gets cut off (e.g. '10000000' [for 8F-0F=80] becomes '00000000') and consequently the wrong tiles are loaded (the very first ones of the table in the example).

Is there a 'pretty' way to make the last two characters accessible as well? (an 'ugly' way I thought of would be to throw out 'X' and 'Y', as almost no word in German starts with those letters and I couldn't find any proper names starting with them in the script either)
KingMike
Guest
« Reply #5 on: June 18, 2011, 11:07:49 pm »

You'd have to modify the one table into two smaller tables, one table with just the first tile of every pair, and another table with just the second tile

So instead of
Code:
$CC, $C0
$8F, $C0
$90, $CC

Replacement Table 1 would be
Code:
$CC, $8F, $90
and table 2 would be
Code:
$C0, $C0, $C0
then change the ASM code
Code:
                CMP   #$42            ; 'A'
                BCS     regular
                PHX
               SEC
                SBC   #$0F            ; -15
                NOP                                       ;this was the ASL instruction
                TAX
                LDA   $Table1, X ; kana/character          ;24-bit address of table 1
                XBA
                LDA   $Table2, X ; nigori                         ;24-bit address of table 2
                XBA
                PLX
                JMP     end_line
regular:
                XBA
                LDA   #$FF            ; A=empty nigori
                XBA

end_line:
                RTS
(Changed to Gemini's code to standard 65816 notation Smiley )
I believe the hex is
38 E9 0F 0A (this should be changed to EA) AA BF xx xx xx EB BF yy yy yy BF FA, where xx is the address of the "kana/character" table, and yy is the address of the "nigori" table.
« Last Edit: June 18, 2011, 11:12:54 pm by KingMike »
Pages: [1]  


Powered by SMF 1.1.4 | SMF © 2006-2007, Simple Machines LLC