+  RHDN Forum Archive
|-+  Romhacking
| |-+  ROM Hacking Discussion
| | |-+  Found the font... now what...
Pages: [1]
Author Topic: Found the font... now what...  (Read 789 times)
Rai
Guest
« on: February 26, 2007, 10:16:28 pm »

I'm thinking about translating this SNES game called Light Fantasy, and I was able to locate the uncompressed font in tlp using 1BPP. Now I'm able to change and manipulate the font, but what I'm not sure of is how I would find the particular byte counterparts, of what I'm viewing in TLP. After I figure that out, I just have to add lowercase letters, and find a translator.
akadewboy
Guest
« Reply #1 on: February 27, 2007, 12:48:39 am »

So are you asking how to build a table file? What I usually do is replace the Japanese font with English capitals and lowercase letters, then play the game until I find a good word (of course it will look scrambled) that's either all lowercase or all Capitals. Then I use WindHex and "Relative Search" for that word. Next Right Click on one of the results and select "Create table with selected values".

Of course your table will need fixing because WindHex puts a bunch of non alphabet characters in between the capital and lowercase letters, so only half of your table will be correct.

This method doesn't always work though, and I'm sure there's many other ways.
Rai
Guest
« Reply #2 on: February 27, 2007, 07:40:12 am »

Actually it's more like this, you know how in NES games, you can view tiles in a PPU viewer and view the bytes for those tiles? I want to find the bytes where every particular tile is loaded. After I know the bytes of the tiles, I can dump, and edit the text. The main script font uses mutiple tiles for single characters, so if I knew which tiles corresponded to each letter, I could make a table based on that(Since if I'm correct, you can make several bytes equal one letter), then dump the script. Based on the tiles, each lettershould consist of two or three bytes.
« Last Edit: February 27, 2007, 07:47:33 am by Rai »
Nightcrawler
Guest
« Reply #3 on: February 27, 2007, 09:28:57 am »

Ugh.. Several methods of discovering a table are described in the Getting Started section... Relative Searching, save state comparison etc.. Have you exhausted those methods? I the impression that you didn't.

On most any game that uses Kanji on the SNES, the entire font doesn't fit in VRAM. That means VRAM tile references will not help you one bit in table making. In fact, it's not all that common that even with games that fit the entire font in VRAM that the tile map values equate to table values in any way. Throw that misconception out the window. You can use VSNES to examine VRAM in a savestate and find out for yourself if you want.

In addition to methods in the Getting Started section, if you know assembly which you claim you mastered so quickly, it should be trivial to use a trace dump and simply trace back the routine that loads a font character back to the source text value and there you go.
Rai
Guest
« Reply #4 on: February 27, 2007, 04:07:15 pm »

Thanks for the advice, using relative searching I was able to successfully figure out where the menu font was stored. Still have to find the main font, but hey, it's progress.
Rai
Guest
« Reply #5 on: February 28, 2007, 08:36:11 am »

One more question, if the game uses a "big" font, made up of  more than one tile, will it still only take up one byte, or will it take up several bytes? I'm asking because I'm trying to find the games "main" font and haven't had any luck yet. Funny, I know the bytes for the menu font but can't actually find them using TLP, and I don't know the bytes for the main font, but I can view it in TLP.
KaioShin
Guest
« Reply #6 on: February 28, 2007, 08:37:06 am »

The amount of bytes the table values have has nothing to with how the font looks.
Rai
Guest
« Reply #7 on: February 28, 2007, 10:22:39 am »

Quote from: KaioShin on February 28, 2007, 08:37:06 am
The amount of bytes the table values have has nothing to with how the font looks.
Ah I see. So if the actual character is made up of 3 tiles, it can still be represented by one hex byte. Knowing that's going to help out a lot in finding the font.
hippiejake
Guest
« Reply #8 on: February 28, 2007, 08:07:14 pm »

I'm not particularly knowledgeable in this [hacking] field, but I'd imagine that a subroutine reads a letter of the font, and uses some sort of algorithm to locate the tiles needed.
At least, that's how it would be done in a higher-level language.
RedComet
Guest
« Reply #9 on: February 28, 2007, 09:30:41 pm »

Quote from: hippiejake on February 28, 2007, 08:07:14 pm
I'm not particularly knowledgeable in this [hacking] field, but I'd imagine that a subroutine reads a letter of the font, and uses some sort of algorithm to locate the tiles needed.
At least, that's how it would be done in a higher-level language.

We have a winner!

The simplest form would be that the character's hex value is an index in the tile array. Depending on how the tiles are laid out in rom this index may need to be altered a little (doubled, tripled, doubled then increment, or countless other ways).

Since I'm feeling generous here's an example from V Gundam (grab the Japanese rom if you want to follow along):

Code:
;char read
$84/855B C2 20       REP #$20                A:0006 X:0006 Y:00B6 D:0000 DB:80
$84/855D AE 70 16    LDX $1670  [$80:1670]   A:0006 X:0006 Y:00B6 D:0000 DB:80
$84/8560 86 00       STX $00    [$00:0000]   A:0006 X:C0D7 Y:00B6 D:0000 DB:80
$84/8562 AE 72 16    LDX $1672  [$80:1672]   A:0006 X:C0D7 Y:00B6 D:0000 DB:80
$84/8565 86 02       STX $02    [$00:0002]   A:0006 X:00A5 Y:00B6 D:0000 DB:80
$84/8567 AD 7A 16    LDA $167A  [$80:167A]   A:0006 X:00A5 Y:00B6 D:0000 DB:80
$84/856A 0A          ASL A                   A:0004 X:00A5 Y:00B6 D:0000 DB:80
$84/856B A8          TAY                     A:0008 X:00A5 Y:00B6 D:0000 DB:80
$84/856C B7 00       LDA [$00],y[$A5:C0DF]   A:0008 X:00A5 Y:0008 D:0000 DB:80
$84/856E 8D 84 16    STA $1684  [$80:1684]   A:0406 X:00A5 Y:0008 D:0000 DB:80
$84/8571 6B          RTL                     A:0406 X:00A5 Y:0008 D:0000 DB:80

;check for control codes
$84/8247 AD 84 16    LDA $1684  [$80:1684]   A:0406 X:00A5 Y:0008 D:0000 DB:80
$84/824A C9 FF FF    CMP #$FFFF              A:0406 X:00A5 Y:0008 D:0000 DB:80
$84/824D F0 34       BEQ $34    [$8283]      A:0406 X:00A5 Y:0008 D:0000 DB:80
$84/824F C9 F1 FF    CMP #$FFF1              A:0406 X:00A5 Y:0008 D:0000 DB:80
$84/8252 F0 35       BEQ $35    [$8289]      A:0406 X:00A5 Y:0008 D:0000 DB:80
$84/8254 C9 F0 FF    CMP #$FFF0              A:0406 X:00A5 Y:0008 D:0000 DB:80
$84/8257 F0 3D       BEQ $3D    [$8296]      A:0406 X:00A5 Y:0008 D:0000 DB:80
$84/8259 C9 00 D0    CMP #$D000              A:0406 X:00A5 Y:0008 D:0000 DB:80
$84/825C B0 51       BCS $51    [$82AF]      A:0406 X:00A5 Y:0008 D:0000 DB:80
$84/825E 22 72 85 84 JSL $848572[$84:8572]   A:0406 X:00A5 Y:0008 D:0000 DB:80

;load/store tiles in wram
$84/8572 C2 20       REP #$20                A:0406 X:00A5 Y:0008 D:0000 DB:80
$84/8574 64 00       STZ $00    [$00:0000]   A:0406 X:00A5 Y:0008 D:0000 DB:80
$84/8576 A2 00 80    LDX #$8000              A:0406 X:00A5 Y:0008 D:0000 DB:80
$84/8579 86 02       STX $02    [$00:0002]   A:0406 X:8000 Y:0008 D:0000 DB:80
$84/857B A2 86 00    LDX #$0086              A:0406 X:8000 Y:0008 D:0000 DB:80
$84/857E 86 04       STX $04    [$00:0004]   A:0406 X:0086 Y:0008 D:0000 DB:80

;$167c - ram index
$84/8580 AD 7C 16    LDA $167C  [$80:167C]   A:0406 X:0086 Y:0008 D:0000 DB:80
$84/8583 0A          ASL A                   A:0006 X:0086 Y:0008 D:0000 DB:80
$84/8584 0A          ASL A                   A:000C X:0086 Y:0008 D:0000 DB:80
$84/8585 0A          ASL A                   A:0018 X:0086 Y:0008 D:0000 DB:80
$84/8586 0A          ASL A                   A:0030 X:0086 Y:0008 D:0000 DB:80
$84/8587 AA          TAX                     A:0060 X:0086 Y:0008 D:0000 DB:80

;$1684 - char to load
$84/8588 AD 84 16    LDA $1684  [$80:1684]   A:0060 X:0060 Y:0008 D:0000 DB:80
$84/858B 0A          ASL A                   A:0406 X:0060 Y:0008 D:0000 DB:80
$84/858C 0A          ASL A                   A:080C X:0060 Y:0008 D:0000 DB:80
$84/858D 0A          ASL A                   A:1018 X:0060 Y:0008 D:0000 DB:80
$84/858E 0A          ASL A                   A:2030 X:0060 Y:0008 D:0000 DB:80
$84/858F A8          TAY                     A:4060 X:0060 Y:0008 D:0000 DB:80

;top half
$84/8590 B7 02       LDA [$02],y[$86:C060]   A:4060 X:0060 Y:4060 D:0000 DB:80
$84/8592 9F 00 40 7F STA $7F4000,x[$7F:4060] A:0000 X:0060 Y:4060 D:0000 DB:80
$84/8596 E8          INX                     A:0000 X:0060 Y:4060 D:0000 DB:80
$84/8597 E8          INX                     A:0000 X:0061 Y:4060 D:0000 DB:80
$84/8598 C8          INY                     A:0000 X:0062 Y:4060 D:0000 DB:80
$84/8599 C8          INY                     A:0000 X:0062 Y:4061 D:0000 DB:80
$84/859A E6 00       INC $00    [$00:0000]   A:0000 X:0062 Y:4062 D:0000 DB:80
$84/859C A5 00       LDA $00    [$00:0000]   A:0000 X:0062 Y:4062 D:0000 DB:80
$84/859E C9 10 00    CMP #$0010              A:0001 X:0062 Y:4062 D:0000 DB:80
$84/85A1 90 ED       BCC $ED    [$8590]      A:0001 X:0062 Y:4062 D:0000 DB:80

$84/85A3 48          PHA                     A:0010 X:0080 Y:4080 D:0000 DB:80
$84/85A4 98          TYA                     A:0010 X:0080 Y:4080 D:0000 DB:80
$84/85A5 18          CLC                     A:4080 X:0080 Y:4080 D:0000 DB:80
$84/85A6 69 E0 00    ADC #$00E0              A:4080 X:0080 Y:4080 D:0000 DB:80
$84/85A9 A8          TAY                     A:4160 X:0080 Y:4080 D:0000 DB:80
$84/85AA 68          PLA                     A:4160 X:0080 Y:4160 D:0000 DB:80

$84/85AB 48          PHA                     A:0010 X:0080 Y:4160 D:0000 DB:80
$84/85AC 8A          TXA                     A:0010 X:0080 Y:4160 D:0000 DB:80
$84/85AD 18          CLC                     A:0080 X:0080 Y:4160 D:0000 DB:80
$84/85AE 69 E0 01    ADC #$01E0              A:0080 X:0080 Y:4160 D:0000 DB:80
$84/85B1 AA          TAX                     A:0260 X:0080 Y:4160 D:0000 DB:80
$84/85B2 68          PLA                     A:0260 X:0260 Y:4160 D:0000 DB:80
$84/85B3 64 00       STZ $00    [$00:0000]   A:0010 X:0260 Y:4160 D:0000 DB:80

;bottom half
$84/85B5 B7 02       LDA [$02],y[$86:C160]   A:0010 X:0260 Y:4160 D:0000 DB:80
$84/85B7 9F 00 40 7F STA $7F4000,x[$7F:4260] A:6100 X:0260 Y:4160 D:0000 DB:80
$84/85BB E8          INX                     A:6100 X:0260 Y:4160 D:0000 DB:80
$84/85BC E8          INX                     A:6100 X:0261 Y:4160 D:0000 DB:80
$84/85BD C8          INY                     A:6100 X:0262 Y:4160 D:0000 DB:80
$84/85BE C8          INY                     A:6100 X:0262 Y:4161 D:0000 DB:80
$84/85BF E6 00       INC $00    [$00:0000]   A:6100 X:0262 Y:4162 D:0000 DB:80
$84/85C1 A5 00       LDA $00    [$00:0000]   A:6100 X:0262 Y:4162 D:0000 DB:80
$84/85C3 C9 10 00    CMP #$0010              A:0001 X:0262 Y:4162 D:0000 DB:80
$84/85C6 90 ED       BCC $ED    [$85B5]      A:0001 X:0262 Y:4162 D:0000 DB:80
$84/85C8 6B          RTL     

What happens is it takes the 16-bit value of the character to read and uses that as an index to grab the top 16x8 (the top two tile of the 16x16), drops them off in ram, increases the tile pointer by #$00e0 (the number of bytes in rom between the end of the top right tile and the start of the bottom left tile), and then repeats the process for the bottom half of the 16x16. Later the 20 bytes of memory containing the font graphic are DMA'd to VRAM. That last part might be a little off. It's been a while since I looked at the game without trying to gut it for a VWF.

For the record, the source for the VWF as well as the LZSS decompressor/compressor is available if you want an example to work through.
satsu
Guest
« Reply #10 on: February 28, 2007, 10:05:54 pm »

Relative searching works fine. Despite the layout of the tiles, no jiggerypokery is required to find out their values. Also:


This took 10 minutes including the time it took to get the ROM. Go over the basics again, because taking a very basic approach can help get you started here.

Another hint: That "..." is E009. E0+any other byte causes weirdness, suggesting dictionary compression.
Pages: [1]  


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