Majora's Mask 3D: Where might I find glyph offset values for the VWF?

Started by MysticalNinja, March 23, 2022, 12:09:48 AM

Previous topic - Next topic



I am a total newbie, but had a question on where I might get started looking for the 'width values' for the variable width font used for dialog text in Majora's Mask 3D. The game already uses a variable width font which is great and all of the glyphs are in a 256 x 256 texture. However, if you wanted to use a custom texture and change the font to a different variable width font, since some characters might be thinner the the originals, you'd want to modify the...width table(?) so that the kerning would still look good.

If anyone could explain how the variable width font might work in this game and point me in the right direction by maybe telling me what to look for in Citra's debugger or if it's a simple thing, to show me how to modify a value or two to indicate that the lowercase 'm' is thinner than it currently is (I don't care if it causes other characters to overlap it when using the original texture, I'd just like to see something change), that's all I'd need help with to get me started and I'm sure I could figure out what to do from there and adjust the rest of the characters by trial and error.

Any help would be appreciated, thanks!


How many characters do you want and are there alternatives to replace somewhere in there? Have to ask that as a practical thing (many people asking this sort of thing just want the 5-10 characters with various accents and squiggles that don't exist in English so no sense going through all the aggravation if you can get rid of some punctuation or something and adjust your insertion font accordingly), which could also include using another European language or even Japanese as a base.

Anyway I have not played with 3ds fonts that much. Back on the DS though, which the 3ds pulls from, then most of the time tile size or character size (not necessarily the same thing -- you can have everything 16x16 or whatever and have it soft crop it, as opposed to having tile size match the character) were stored in the same file or in the same directory. There are three things in any font -- the characters/vector data (vector fonts are rare on consoles even to this day), the size values (and anything like descender handling) and the encoding values which for the purposes of most consoles are optional but I did see many on the DS. Add in some basic stuff like magic stamp, file size, locations of said parts and you have your font format. You may or may not find palettes for the font in the font as well. Graphics tend to be fairly obvious and the bulk of the file, which pretty much leaves the rest to elimination.
On rare occasion I have seen size values mixed in with graphical data so each tile essentially has a mini header/footer.

Some footage shows a text roll out, others appear more instant. If it was not available by analysis of the font format* then you are probably going to have to get hands dirty. I did not see any animated text in that which can both help matters and hinder them, though start with static.
For a 2d setup, which text might well be still on the 3ds, then you would watch the parts of BG (traditionally text should be on this) or OAM (what handles the sprites, you don't find much text here as sprite memory is limited and you don't need to waste it on it) as they determine the placement on screen. You can then place a breakpoint on the area just written, load an earlier savestate and let it roll. The breakpoint would then flash up saying something wrote this area, you work backwards from there to find how it calculated the value to put in there (some of it might be spacing if it is not inherently part of the font, the rest will be the width value and any height stuff too) -- if it read it from a table in the font then great, if table in memory then search the ROM for that or work backwards again to figure what put that there.
If the text in this case is going to be a texture on a simple cuboid then you still probably get to figure it out via similar means, just whatever is controlling its placement.

*don't be afraid to grab all regions of the game and compare their font files to see differences, and if the game provides you with multiple examples of fonts then that works too.


Thank you for the response. I'm trying to process everything you're saying, lol.

I'm trying to change all 192 characters of the original font to a new font and I'm able to easily do that by replacing the original texture with a new one. The issue is though, that my new font is slightly thinner than the original, and because of that, the width table needs to be adjusted too so the kerning is correct for the new font. I believe this is what you are referring to when you said that there are 3 elements to every font: character data, size values, and encoding values. I think it's the 'size values' I want to mess with.

Maybe I didn't explain what I already know well enough.

So, Majora's Mask 3D uses a 256 x 256 texture for the dialog font and each glyph is in a 16 x 18 tile in that texture, and there are 192 characters altogether. GREZZO used the font FOT-RocknRoll Std, scaled it down, and squished some characters a little to create a 'sprite sheet' which is really a texture.

Well, Citra allows hi-res textures, so I have created a new 2048 x 2048 texture using FOT-RocknRoll Std and everything is great. Now when I play the game using 8x internal resolution, the dialog text looks crystal clear. Perfect.

Well, FOT-RocknRoll Std doesn't really fit the tone of Majora's Mask. It's a 'happier' looking font, but I understand why GREZZO used it. It's bolder and easier to read on a small screen like the 3DS.

So, now that I'm able to replace the original texture with a hi-res one, I'd like to change the font to use the original Majora's Mask font: FOT-Chiaro Std. Some characters in this font, however, are slightly thinner than their RocknRoll counterpart, so I would need to adjust values in a width table for those characters so the kerning looks good with this new font. One character specifically is the lowercase 'e,' but there are many more. If I can figure out how to modify the width table for the lowercase 'e,' I can probably figure out the rest of the characters by trial and error.

I honestly don't mind spending hours and hours of trial and error. I have learned a lot already just by replacing this one texture, messing around with the location of the 'e' within it's 'tile' on the texture, and re-loading the game over and over and seeing what happens. I just don't know where to even start looking in Citra's 'graphics debugger' though to figure out what is telling the game 'lowercase e should be <x> width.' Although I might out of luck anyways as no matter what computer I run Citra on, when turning on the Graphics Debugger, it slows emulation to a halt and eventually crashes...

But since the dialog text uses a texture, I guess I can assume that the way it displays it on the screen is by this 'texture-on-a-simple-cuboid' method?

Thank you again for the detailed response. I have to re-read it a few times to understand what I'm reading, lol.


Fair enough. I must admit looking at the video earlier the font was not as fitting as some others I have seen. Sounds like intellectual curiosity which is great, however I will note the PC port of the Ocarina decompilation dropped less than 24 hours ago at time of writing and the MM decompilation is fairly far along by most accounts, with the same team handling the PC effort as and when (Mario 64 and Zelda Ocarina were quite different code, I can't imagine Ocarina and MM are going to be too radically different). If it is anything like it was for the same when Mario 64 happened then that might be the easier path of attack if you want high res stuff.

Anyway giant sprite sheet/image/texture sliced up is probably the standard for most things going back and for a while to come yet.

In really old systems the ability to change position of background layer tiles arbitrary amounts was not a thing (all on a grid as it were) so there is that, obviously sprites can go where they like but wasting limited sprites on text is not great.
Later systems added the ability for background to shuffle where it likes.
3d is much the same if it is going to be the projected onto a cube/flat plane facing the camera, just using the 3d hardware to either make many little flat cuboids or slice up said texture at given X and Y coordinates* and put that somewhere. Whether the 3ds will be doing this for this will vary, though if it is indeed a 3d texture format (as opposed to various 2d formats) being edited then OK.

*whether x1,x2,y1,y2 forming a bounding box, some kind of parent (say bottom left is 0,0 and it gives a coordinate for the start of the character) - child with diagonal, or x1,y1,width,height will be dealer's choice.

Basic fixed width text will fetch character, position, add 8/12/16 to horizontal width and repeat. Maybe it gets fancy and adds its own gap (annoying if you want to use a skinny font but smoosh two characters together to make a wider character like W or M look good).
Variable width font will fetch character, fetch width from table/information somewhere (could be right next to the character/in an ignored pixel in some cases), add width to running total (and again maybe extra gap to spread things out), repeat for next character. Better ones will have end of line/max length detection (easy enough to do an IF greater than, or cmp and bhi if instructions are more your thing, if it is fixed width then it might have used an equal to instead which your variable width might break should this instead be a VFW conversion), maybe even shuffle the whole word down, others will have forced new line presumably in the text, and maybe end of screen/page detection as well but that is a lot more rare.

There will probably be a running internal total as well as that which is sent to the graphics handler. As you can see graphics and said graphics have their own handler you can play with/see then that forms the approach for most. You could find the text and follow that on through being decoded as it will be happening as part of that but that is going to be longer to get there than work backwards in most cases. At the same time 3d stuff can be a bit of a black box rather than some nice OAM or BG that is sitting there in memory with whole numbers you could almost watch change in real time to follow the text appearing on screen so there could be a case for following text on up.