From 3cc885d4dd72ec978c3983532cb22fa134adb690 Mon Sep 17 00:00:00 2001 From: ABelliqueux Date: Fri, 29 Oct 2021 14:41:49 +0200 Subject: [PATCH] Add font page --- FONT.md | 146 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 146 insertions(+) create mode 100644 FONT.md diff --git a/FONT.md b/FONT.md new file mode 100644 index 0000000..442e604 --- /dev/null +++ b/FONT.md @@ -0,0 +1,146 @@ +# Change the debug font appearance and color + +![Funky!](https://wiki.arthus.net/assets/debug_font.gif) + +Changing the debug font face and color can be useful if you don't want or don't have time to implement a full-fledged font atlas solution, but still want to be able to customize the default font a bit. + +## Basics + +According to PsyQ's doc, the `FntLoad()` function is in charge of loading the texture and [CLUT](https://www.computerhope.com/jargon/c/clut.htm) in the PSX vram. +By default it will load a 128x32 image to xy coordinates `960, 0`, and its clut will be loaded at `960,0+128`. + +Using a custom debug font is then a simple matter of loading an image into vram at those coordinates, and/or altering the clut. + +## Color + +![A custom debug font color](https://wiki.arthus.net/assets/debug_font_color.png) + +The CLUT is loaded at `x,y+128` ( 960,128 by default ) and consists of two horizontal pixels for the default font; the first is black (RGB 0,0,0) and is the background colour. +The second one is white (RGB 255,255,255) and is the foreground (or text) colour. +You can use the `ClearImage()` function to draw a colored rectangle anywhere in vram, so why not draw a 1x1 pixel at 961,128 and see the result ? + +**Note that setting the pixel at 960x128 to a different color overides `FntOpen()`'s `isbg` value.** + +```c +// Used for font texture position in vram +#define FONTX 960 +#define FONTY 0 + +// Two color vectors R,G,B +CVECTOR fntColor = { 255, 0, 0 }; +CVECTOR fntColorBG = { 0, 0, 0 }; + +void FntColor(CVECTOR fgcol, CVECTOR bgcol ) +{ + // The debug font clut is at tx, ty + 128 + // tx = bg color + // tx + 1 = fg color + // We can override the color by drawing a rect at these coordinates + // + // Define 1 pixel at 960,128 (background color) and 1 pixel at 961, 128 (foreground color) + RECT fg = { FONTX+1, FONTY + 128, 1, 1 }; + RECT bg = { FONTX, FONTY + 128, 1, 1 }; + // Set colors + ClearImage(&fg, fgcol.r, fgcol.g, fgcol.b); + ClearImage(&bg, bgcol.r, bgcol.g, bgcol.b); +} +``` + +All you have to do after that is calling `FntColor()` after `FntLoad()` and `FntOpen()` : + +```c +FntLoad(FONTX, FONTY); // Load font to vram at FONTX,FONTY +FntOpen(100, 100, 48, 20, 0, 12 ); // FntOpen(x, y, width, height, black_bg, max. nbr. chars) +FntColor(fntColor, fntColorBG); +``` + +You can check in a vram viewer that the pixels at those coordinates have the new colors ; + +![the debug font texture in VRAM](https://wiki.arthus.net/assets/debug_font_vram.png) + +## Fontface + +Changing the font face allows you to use customized 7x7 pixels glyph and a full 4bpp CLUT, that's quite nice ! +The latin aphabet debug font has 64 glyphs ; 4 lines, 16 glyphs per line in this order : + +**Notice that the first glyph on the first line is empty** + +``` + !"#$%&'()*+,-./ +0123456789:;<=^? +@ABCDEFGHIJKLMNO +PQRSTUVWXYZ[\]> +``` + +The fontface should be a 128x32, 16 colors palettized image with each glyphs taking 7x7 pixels : + +![template](https://wiki.arthus.net/assets/debug_font_tpl.png) + +For reference, here is an example : + +![template](https://wiki.arthus.net/assets/debug_font_spr.png) + +Gimp or Aseprite are tools that would do the trick. + +### Converting the image to TIM + +Using Lameguy64's `img2tim` utility, convert the image to [tim](https://github.com/ABelliqueux/nolibgs_hello_worlds/wiki/TIM) : + +``` +img2tim -b -usealpha -org 960 0 -plt 960 128 -bpp 4 -o output.tim input.png +``` + +### Including the tim file + +If using nugget+psyq, as described [here](https://github.com/ABelliqueux/nolibgs_hello_worlds/wiki/(Archived)--Embedding-binary-data-in-your-psx-executable), you have to add the tim file to your `SRCS`, +then add these conversion instructions in your makefile : +```mk +%.o: %.tim + $(PREFIX)-objcopy -I binary --set-section-alignment .data=4 --rename-section .data=.rodata,alloc,load,readonly,data,contents -O elf32-tradlittlemips -B mips $< $@ +``` + +To access the data in code, use the following declarations : + +``` +extern unsigned long _binary_output_tim_start[]; +extern unsigned long _binary_output_tim_end[]; +extern unsigned long _binary_output_tim_length; +``` + +### Loading the image to vram + +Using a nice function written by Lameguy64 ; + +```c +extern unsigned long _binary_fnt_tim_start[]; +extern unsigned long _binary_fnt_tim_end[]; +extern unsigned long _binary_fnt_tim_length; + +// Loading an image to vram. See https://github.com/ABelliqueux/nolibgs_hello_worlds/blob/main/hello_sprt/hello_sprt.c#L42 +TIM_IMAGE fontface; +void LoadTexture(u_long * tim, TIM_IMAGE * tparam){ + OpenTIM(tim); + ReadTIM(tparam); + LoadImage(tparam->prect, tparam->paddr); + DrawSync(0); + if (tparam->mode & 0x8){ // check 4th bit + LoadImage(tparam->crect, tparam->caddr); + DrawSync(0); + } +} +``` + +Then in `main()`, call it once after init: + +```c +LoadTexture(_binary_fnt_tim_start, &fontface); +``` + +## Full code + +A full example is available here : [https://github.com/ABelliqueux/nolibgs_hello_worlds/tree/main/hello_font](https://github.com/ABelliqueux/nolibgs_hello_worlds/tree/main/hello_font) + +## Doc & Sources + +- `FntLoad()` ref : [http://psx.arthus.net/sdk/Psy-Q/DOCS/FileFormat47.pdf](http://psx.arthus.net/sdk/Psy-Q/DOCS/LibRef47.pdf), p.292 +- Nolibgs wiki TIM page : [https://github.com/ABelliqueux/nolibgs_hello_worlds/wiki/TIM](https://github.com/ABelliqueux/nolibgs_hello_worlds/wiki/TIM) \ No newline at end of file