Mode 3 font hello world

Topics related to the API, programming discussions & questions, coding tips, bugs, etc. should go here.
User avatar
danboid
Posts: 1931
Joined: Sun Jun 14, 2020 12:14 am

Mode 3 font hello world

Post by danboid »

I spent most of today trying to get my head around using fonts on the Uzebox but I've not been able to pull off a successful 'hello world' yet.

My first observation/comment is whats wrong with Print(), the standard kernel API function to print a string to the screen? In nearly all of the examples I've looked at, everyone has devised their own function to print text to the screen. Does Print() have some major shortcoming(s)? The exception seems to be Loderunner. SetFontTable() seems to have been deprecated, or at least I only get errors when I try to use it.

Lets re-use the Loderunner inc files and create a hello world, re-using its font. Why doesn't this not work, if we replace LodeRunner.c with the following and build/run it:

Code: Select all

#include <avr/interrupt.h>
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <stdlib.h>
#include <uzebox.h>

#include "data/levelMaps.inc"
#include "data/tiles.inc"
#include "data/font_8x12.pic.inc"

int main() {
  SetTileTable(lode_tileset);
  SetFontTilesIndex(LODE_TILESET_SIZE);
  SetSpriteVisibility(false);
  ClearVram();
  Print(7,5,PSTR("CONGRATULATIONS!"));
}

Could someone fix this or otherwise provide a very minimal/simple example of how to use a font to print a string to a Mode 3 screen please?

Thanks!
User avatar
Artcfox
Posts: 1382
Joined: Thu Jun 04, 2015 5:35 pm
Contact:

Re: Mode 3 font hello world

Post by Artcfox »

I don't think I've ever used the Print() function ever. Space is usually so tight that I only include the letters and symbols that I use, and most of the time I can get away by displaying text using RAM tiles, which are highly compressed, and can be re-colored on the fly. Here is a post on it, if you scroll down through the posts, you'll see I went through multiple iterations: https://uzebox.org/forums/viewtopic.php ... 28&p=18461

The RAM font approach allows for special effects, which I used gratuitously in Circuit Puzzle, like fading the help text in and out on a pixel by pixel basis: https://github.com/artcfox/circuit/blob ... it.c#L2170
User avatar
danboid
Posts: 1931
Joined: Sun Jun 14, 2020 12:14 am

Re: Mode 3 font hello world

Post by danboid »

Thanks for the link Artcfox!

I cobbled all of the ramfont bits including the data from the font included in laser2 into a fully stripped down c file for IKD but unfortunately I was still unable to print anything to the screen, which shows I still don't have a hang of some of the very basics of UB graphics (or anything) yet.

My latest non-working attempt looks something like this:

Code: Select all

#include <avr/interrupt.h>
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <math.h>
#include <stdbool.h>
#include <stdlib.h>
#include <uzebox.h>

const uint8_t myramfont[] PROGMEM = {
  0x1c, 0x36, 0x63, 0x63, 0x7f, 0x63, 0x63, 0x00,
  0x3f, 0x63, 0x63, 0x3f, 0x63, 0x63, 0x3f, 0x00,
  0x3c, 0x66, 0x03, 0x03, 0x03, 0x66, 0x3c, 0x00,
  0x1f, 0x33, 0x63, 0x63, 0x63, 0x33, 0x1f, 0x00,
  0x7f, 0x03, 0x03, 0x3f, 0x03, 0x03, 0x7f, 0x00,
  0x7f, 0x03, 0x03, 0x3f, 0x03, 0x03, 0x03, 0x00,
  0x7c, 0x06, 0x03, 0x73, 0x63, 0x66, 0x7c, 0x00,
  0x63, 0x63, 0x63, 0x7f, 0x63, 0x63, 0x63, 0x00,
  0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x00,
  0x78, 0x30, 0x30, 0x30, 0x30, 0x31, 0x1e, 0x00,
  0x63, 0x33, 0x1b, 0x0f, 0x1f, 0x3b, 0x73, 0x00,
  0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x7e, 0x00,
  0x63, 0x77, 0x7f, 0x7f, 0x6b, 0x63, 0x63, 0x00,
  0x63, 0x67, 0x6f, 0x7f, 0x7b, 0x73, 0x63, 0x00,
  0x3e, 0x63, 0x63, 0x63, 0x63, 0x63, 0x3e, 0x00,
  0x3f, 0x63, 0x63, 0x63, 0x3f, 0x03, 0x03, 0x00,
  0x3e, 0x63, 0x63, 0x63, 0x7b, 0x33, 0x5e, 0x00,
  0x3f, 0x63, 0x63, 0x73, 0x1f, 0x3b, 0x73, 0x00,
  0x1e, 0x33, 0x03, 0x3e, 0x60, 0x63, 0x3e, 0x00,
  0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00,
  0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x3e, 0x00,
  0x63, 0x63, 0x63, 0x77, 0x3e, 0x1c, 0x08, 0x00,
  0x63, 0x63, 0x6b, 0x7f, 0x7f, 0x77, 0x63, 0x00,
  0x63, 0x77, 0x3e, 0x1c, 0x3e, 0x77, 0x63, 0x00,
  0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x00,
  0x7f, 0x70, 0x38, 0x1c, 0x0e, 0x07, 0x7f, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x06, 0x00,
  0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00,
};

void RamFont_Load(const uint8_t* ramfont, uint8_t len, uint8_t fg_color, uint8_t bg_color)
{
  SetUserRamTilesCount(len);
  for (uint8_t tile = 0; tile < len; ++tile) {
    uint8_t* ramTile = GetUserRamTile(tile);
    for (uint8_t row = 0; row < 8; ++row) {
      uint8_t data = (uint8_t)pgm_read_byte(&ramfont[tile * 8 + row]);
      for (uint8_t bit = 0; bit < 8; ++bit)
        if (data & (1 << bit))
          ramTile[row * 8 + bit] = fg_color;
        else
          ramTile[row * 8 + bit] = bg_color;
    }
  }
}

void RamFont_Print(uint8_t x, uint8_t y, const char *message, uint8_t len)
{
  for (uint8_t i = 0; i < len; ++i) {
    int8_t tileno = (int8_t)pgm_read_byte(&message[i]) - 'A';
    if (tileno >= 0)
      SetRamTile(x + i, y, tileno);
  }
}

const char pgm_press_a[] PROGMEM = "PRESS A TO CONTINUE";

int main() {
  ClearVram();
// Calls to DrawMap, or SetTile go here
RamFont_Load(myramfont, sizeof(myramfont) / 8, 0x00, 0xad);
  //WaitVsync(1);
  // Wait for button presses, etc...
  // Optionally call RamFont_Load() again here to change the FG and BG color of text
  RamFont_Print(5, 5, pgm_press_a, sizeof(pgm_press_a));

}
I have tried putting RamFont_Print() in a while loop, using different foreground colours and a few other things with no sign of text yet.

Can I not use these (1 BPP) ramfonts on the same screen as some 8 BPP tiles or sprites?
User avatar
Artcfox
Posts: 1382
Joined: Thu Jun 04, 2015 5:35 pm
Contact:

Re: Mode 3 font hello world

Post by Artcfox »

There is a fontman.zip file attached to this post: https://uzebox.org/forums/viewtopic.php ... 461#p18469 which includes the minimal amount of stuff that you need to get it working, including the Makefile inside the default/ directory.
Create a directory under the uzebox directory called MY_GAMES, and extract that .zip file into it, and then

Code: Select all

cd uzebox/MY_GAMES/fontman/default
and run:

Code: Select all

./scratch
and then run fontman.uze under the emulator.

If you look at the fontman.c, you'll see that you're missing the call to SetTileTable(tileset); and you aren't including a tileset.inc, and your Makefile will need to specify -DMAX_SPRITES and -DRAM_TILES_COUNT as part of the KERNEL_OPTIONS.

Feel free to start with that project, and change it to suit your needs.
User avatar
danboid
Posts: 1931
Joined: Sun Jun 14, 2020 12:14 am

Re: Mode 3 font hello world

Post by danboid »

I have got fontman to build and run but unfortunately its code is too advanced for a newb like me to understand how it works. I am reverting to writing a Hello World using the standard Print() function because I think it will be easier to understand.
User avatar
danboid
Posts: 1931
Joined: Sun Jun 14, 2020 12:14 am

Re: Mode 3 font hello world

Post by danboid »

It looks like I'm close to having a working, basic "Hello World" using the regular print function but I'm not quite there yet. I seem to be getting blocks filled with random coloured pixels in place of the font tiles. This test is using the font-8x8.inc included in the uzebox/gfx/fonts/8x8 dir of the UB repo:
Screenshot at 2022-10-04 20-38-25.png
Screenshot at 2022-10-04 20-38-25.png (20.12 KiB) Viewed 1242 times

Code: Select all

#include <avr/interrupt.h>
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <stdbool.h>
#include <stdlib.h>
#include <uzebox.h>

#include "data/tileset.inc"
#include "data/font-8x8.inc"


int main() {
  SetTileTable(tileset);
  SetFontTilesIndex(TILESET_SIZE);
  ClearVram();
  while (1) {
  Print(10,10,PSTR("TEST"));
  }
}
User avatar
danboid
Posts: 1931
Joined: Sun Jun 14, 2020 12:14 am

Re: Mode 3 font hello world

Post by danboid »

The way I'm testing this code is by using IKD as a base so I'm using the same Makefile, kernel options as that, I'm just replacing the code within IKD.c. Maybe I should upload my shitty test code to github in full?

I've tried different fonts, I've tried removing all of the kernel options except the video mode one, I've tried using video mode 5 too but I get the same result in all cases - just a rectangle of seemingly rendomly coloured pixels.

I presumed I had set a kernel build option incorrectly but I'm at a bit of a loss as to what I'm dong wrong now. Surely this is one of the simplest dev tasks you could attempt yet its proving to be too much for me to master. There seems to be something about the Makefile or build config of IKD that is preventing the print function from working?
User avatar
danboid
Posts: 1931
Joined: Sun Jun 14, 2020 12:14 am

Re: Mode 3 font hello world

Post by danboid »

Indeed there is something wrong with IKD that is breaking the Print() function. I know because I modified the code from Mode5Demo.c to something I could fully understand that works to output text when I run the Mode5 demo but if I re-use that exact same code within IKD the Print() function just produces garbage on the screen.
User avatar
danboid
Posts: 1931
Joined: Sun Jun 14, 2020 12:14 am

Re: Mode 3 font hello world

Post by danboid »

Mystery solved!

In IKD, I was including avr/interrupt.h for no reason whatsoever other than mindless copy/pasting. I'm not using it and for some reason it breaks the Print() function so I have removed it from IKD.
User avatar
danboid
Posts: 1931
Joined: Sun Jun 14, 2020 12:14 am

Re: Mode 3 font hello world

Post by danboid »

It wasn't interrupt.h that broke Print(), it was an incorrect choice of CFLAGS.
Post Reply