News: 11 March 2016 - Forum Rules

Author Topic: Handling a SNES 16x16 Japanese Font  (Read 2958 times)

Polinym

  • Jr. Member
  • **
  • Posts: 71
    • View Profile
Handling a SNES 16x16 Japanese Font
« on: June 29, 2021, 01:16:59 am »
Howdy, folks! :)

I'm beginning my first real venture from NES translation into SNES translation. The particular challenge I have to overcome here is a 16x16 size font. The game in question I'm looking at is Nage Libre: Seijaku no Suishin, but this will be useful information if I end up giving up for some reason anyway. I figured it'd be wise to ask for advice before trying to blindly go at it and wind up banging my head against the wall. There really doesn't seem to be much out there on the internet about exactly how to modify fonts like this.

Obviously, trying to make a font out of a 16x16 tile will look ugly. Therefore, I'm looking for a way to reduce the width. VWF is the dream, but it's probably easier just to cut the width in half to 8x16. So, what would be the steps involved in going about this? For reference, I have a bit of experience with NES ASM and I'm currently trying to learn the BSNES debugger.

"Where are you going, soldier? Get back to the battle!" - Some Battlefront Clone
My YouTube Channel: https://www.youtube.com/channel/UCJqSB4xw29TTKlia5E0NYtQ

[Unknown]

  • Jr. Member
  • **
  • Posts: 77
    • View Profile
    • PPSSPP
Re: Handling a SNES 16x16 Japanese Font
« Reply #1 on: June 29, 2021, 02:44:46 am »
First: look at the layers and tilesets to see how the text is drawn.

A possible scenario is that it has a section of tiles dedicated to that textbox layer, and if you change that VRAM directly (say, using the debugger), the displayed text image would change.

Let's say that's the case.  Most likely, there's some function that writes to those tiles when decoding the string from the game data, probably copying the font into the tileset, one letter at a time.

If so, you'd want to set a breakpoint (BEFORE the text appears/changes) on that video memory, and then make the text show/change.  This will point you near the code that modifies that memory.  You might have to step around, in case you find yourself in a utility function that copies memory based on parameters.

At some point, you'll likely find a loop, decoding one character from the string at a time and translating that to a font index, then copying the respective font character image to the tileset.

You'd essentially just change how it updates this destination position to account for an 8x16 font (or even VWF.)  Depending on how the tiles are formatted, you may have to adjust the stride it uses to copy a bit too.

"Exactly how" really depends on exactly how the game works, but the above is a guideline.  It should work pretty much the same way for most tile-based systems, not just the SNES.

-[Unknown]

KingMike

  • Forum Moderator
  • Hero Member
  • *****
  • Posts: 7253
  • *sigh* A changed avatar. Big deal.
    • View Profile
Re: Handling a SNES 16x16 Japanese Font
« Reply #2 on: June 29, 2021, 10:09:02 am »
SNES games often made a copy of the tilemap inside WRAM.
They would write the tile ID of the top-left corner of the character, followed by the ID of the top right, then 0x40 bytes (one row down on the screen, since standard SNES resolution is 0x20 tiles wide x 2 bytes per tile), write the bottom and bottom right.

Would need to NOP the right-side tile writes, as well as adjust the code that sets up the tilemap address for the following character (usually +4, would want to reduce that to +2).

Also, you basically need to reduce the font size anyways.
You aren't going to fit any worthwhile English into a textbox that looks about 11 characters wide anyways. :D
"My watch says 30 chickens" Google, 2018

Polinym

  • Jr. Member
  • **
  • Posts: 71
    • View Profile
Re: Handling a SNES 16x16 Japanese Font
« Reply #3 on: July 04, 2021, 12:15:37 am »
Thanks for the advice! Now I have an idea as to what I'm doing. :)

So I tried to do this and managed to blank out the writes to the right bytes with NOPs, which is almost what I want. However, I'm having to look up the opcodes for the instructions I'm viewing in an external document and do some tedious searches in WindHex, not mention having to reload the ROM every time I want to check the changes. In FCEUX, I was able to just paste the opcodes into its hex editor searchbar and find the code in the ROM in a few seconds. How do I do this sort of thing in BSNES, or can I even? A guide for BSNES I found online told me that changes made to the "ROM" section of the hex editor aren't saved.

"Where are you going, soldier? Get back to the battle!" - Some Battlefront Clone
My YouTube Channel: https://www.youtube.com/channel/UCJqSB4xw29TTKlia5E0NYtQ

Alasker

  • Jr. Member
  • **
  • Posts: 5
    • View Profile
Re: Handling a SNES 16x16 Japanese Font
« Reply #4 on: July 04, 2021, 05:29:13 pm »
You could use Tools->Memory Editor to find specific code line and update code with manually assembled hex values.

Polinym

  • Jr. Member
  • **
  • Posts: 71
    • View Profile
Re: Handling a SNES 16x16 Japanese Font
« Reply #5 on: July 11, 2021, 11:57:06 pm »
So I've messed around with this for several days now and still have had no luck. I've set breakpoints for when the font characters are written to Background 3 (shown partially in screenshot), but in messing with the code around it I haven't gotten rid of the printing slide for the second half of the character. I found where the font characters are written first in VRAM, but no breakpoints trigger for them. I'm very lost. Anyone have any advice?

"Where are you going, soldier? Get back to the battle!" - Some Battlefront Clone
My YouTube Channel: https://www.youtube.com/channel/UCJqSB4xw29TTKlia5E0NYtQ

KingMike

  • Forum Moderator
  • Hero Member
  • *****
  • Posts: 7253
  • *sigh* A changed avatar. Big deal.
    • View Profile
Re: Handling a SNES 16x16 Japanese Font
« Reply #6 on: July 12, 2021, 01:20:54 am »
You need to find if there is a tilemap in WRAM (that's 7Exxxx to 7Fxxxx).
Only the first 8KB of WRAM is accessible outside bank 7E/7F (such as 000000-001FFF). 002000+ is memory-mapped I/O, which isn't were you want to look for data.
The remaining 120KB (where a nametable copy is likely to be stored can only be accessed with bank 7E/7F addresses.

However, what that code block you pasted IS telling you that the VRAM DMA parameters are at a block at $000812. Such as that the VRAM tilemap address it is at is stored at $00085E. (It is adding 0x7C00 because VRAM address are in WORDS, which means 7C00 needs to be doubled to get the BYTE address, or that that code wants to write a table to VRAM $F800.
The data itself that is writing has already been copied to $00085A, it looks like.
"My watch says 30 chickens" Google, 2018

Polinym

  • Jr. Member
  • **
  • Posts: 71
    • View Profile
Re: Handling a SNES 16x16 Japanese Font
« Reply #7 on: August 15, 2021, 10:00:36 pm »
So I've gotten back to working on this.

You need to find if there is a tilemap in WRAM (that's 7Exxxx to 7Fxxxx).
Only the first 8KB of WRAM is accessible outside bank 7E/7F (such as 000000-001FFF). 002000+ is memory-mapped I/O, which isn't were you want to look for data.
The remaining 120KB (where a nametable copy is likely to be stored can only be accessed with bank 7E/7F addresses.

However, what that code block you pasted IS telling you that the VRAM DMA parameters are at a block at $000812. Such as that the VRAM tilemap address it is at is stored at $00085E. (It is adding 0x7C00 because VRAM address are in WORDS, which means 7C00 needs to be doubled to get the BYTE address, or that that code wants to write a table to VRAM $F800.
The data itself that is writing has already been copied to $00085A, it looks like.

Thanks for this awesome tip! With it, I was able to get closer to the goal. I managed to get the game to not print the second half of the characters. Thinking that there's a tilemap at 0x85E, I set a write breakpoint there and eventually found some relevant code. I changed a LDY #$02 into a LDY #$01, which I believe is making it write to the first half of the character twice. I think the code at that location (80f439) checks the amount of characters printed in the subroutine, writes to the right side of the character, and then to the left side. It seems to work fine for the smaller "in-battle" textboxes, but it's definitely not printing right in the intro cutscenes. The text starts printing out at the other side of the box at the same time as the left side. Sometimes it just prints out in two random places at the same time.



Spoiler:
Incorrect behavior:

Correct behavior:


I hate to sound like a n00b with all these questions, but I'm determined to figure this out. I wouldn't ask if I wasn't lost. I'd like some context on why the SNES writes data where it does and how it handles these 2-byte wide tiles. I'm used to the one-byte stuff on the NES. Please bear with me! Once I'm through this font stuff and get a table made I should be fine on translating this! :)
"Where are you going, soldier? Get back to the battle!" - Some Battlefront Clone
My YouTube Channel: https://www.youtube.com/channel/UCJqSB4xw29TTKlia5E0NYtQ

KingMike

  • Forum Moderator
  • Hero Member
  • *****
  • Posts: 7253
  • *sigh* A changed avatar. Big deal.
    • View Profile
Re: Handling a SNES 16x16 Japanese Font
« Reply #8 on: August 15, 2021, 10:52:49 pm »
Do you mean "why are font characters two tiles wide?"
Because bigger characters make for easier to read kanji.

Or do you mean "why is each tilemap entry two bytes?"
Because tile data uses 2 bytes per tile. I believe it is possible to have 512 tiles in one tileset (or was the max 1024?), depending on graphics mode. That alone necessitates a second byte.
But also, the remaining bits are used for other data such as the palette (SNES doesn't use an Attribute Table, like NES tilemaps do) as well as flipping and priority.
"My watch says 30 chickens" Google, 2018

Polinym

  • Jr. Member
  • **
  • Posts: 71
    • View Profile
Re: Handling a SNES 16x16 Japanese Font
« Reply #9 on: August 15, 2021, 11:52:47 pm »
Do you mean "why are font characters two tiles wide?"
Because bigger characters make for easier to read kanji.

Or do you mean "why is each tilemap entry two bytes?"
Because tile data uses 2 bytes per tile. I believe it is possible to have 512 tiles in one tileset (or was the max 1024?), depending on graphics mode. That alone necessitates a second byte.
But also, the remaining bits are used for other data such as the palette (SNES doesn't use an Attribute Table, like NES tilemaps do) as well as flipping and priority.
What I mean is... with the NES, graphics are very simple. Whether it's sprites or background, anything you see is represented by a 8x8 tile to some degree. The solitary byte you see is the byte you get. Fire Emblem 1, for example, writes a sequence of tiles to a spot in RAM, and then copies them one-by-one to, uh... somewhere in the PPU where it can show up on the screen.

On the SNES, however, it's more confusing to me. The Tile Viewer seems to be like the PPU, and this game seems to write the tiles for individual characters there. I don't know where those tiles are being stored, though. It sounds like it's either in the SNES-VRAM area or $7e0000-$7f0000 are of the "CPU-BUS". The "address" shown in the Tile Viewer of BSNES doesn't seem to tell me where the address is. I'd assume VRAM, but write breakpoints don't trigger there. I'm not even sure what a tilemap would look like in the VRAM or RAM either. Would that look like 00020103, 04060507, ...?

"Where are you going, soldier? Get back to the battle!" - Some Battlefront Clone
My YouTube Channel: https://www.youtube.com/channel/UCJqSB4xw29TTKlia5E0NYtQ