gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

DS development > Time, clock & fonts.

#148219 - nipil - Thu Jan 03, 2008 6:03 pm

Good evening everone. I recently discovered i could program on my own DS and i'm fidling with the code samples, and porting some stuff i made for the PC.

But i have met some spots for which (despite me searching the wikis, docs and various tutorials) i couldn't find a good answer for.

The trouble is double :

- time & clock (time.h)

For info, I'm currently testing my work on emulators (no$gba, ideas, dsemume). These two functions give me strange, inconsistant results. I'm calling clock(), and time(NULL) before and after a for-wait loop. Clock returns 0 both times, or sometime -1 depending on the emulator, and time(NULL) returns a huge int but this number is the same before and after the wait (about 10 seconds).

What's the problem with the way i do it ? I heard about the RTC, is it the same thing (accessible via ARM7 if i'm correct) ; should i use it in place of time.h ?

- using fonts

Right now i'm running programs in console mode (to debug). The screen was initialized using the following code taken from devkitpro default arm9 template :
Code:
SUB_BG0_CR = BG_MAP_BASE(31);
BG_PALETTE_SUB[255] = RGB15(31,31,31);
consoleInitDefault((u16*)SCREEN_BASE_BLOCK_SUB(31), (u16*)CHAR_BASE_BLOCK_SUB(0), 16);


Questions are : as games display text in farious fonts (arial like, cartoon etc), are there any built-in other standard fonts ? If not, what's the "format" to specify the content of the font ?

Thanks for your attention.

#148225 - silent_code - Thu Jan 03, 2008 6:50 pm

hi!
i've got little time right now, but loading custom fonts is easy and if you are capable of doing it, even multiple fonts can be done. check my site, there's a demo that loads a custom font. but the examples also show that (at least i seem to remember). it's all just loading the tiles in the right place. :^)
happy coding!

#148238 - tepples - Thu Jan 03, 2008 9:08 pm

nipil wrote:
Questions are : as games display text in farious fonts (arial like, cartoon etc), are there any built-in other standard fonts ? If not, what's the "format" to specify the content of the font ?

Do you want to use NES-style 8x8 pixel fonts, or do you want to use proportional fonts where the glyphs for 'i' and 'm' are not the same width? If you want to use proportional fonts, you're going to have to somehow store the bitmaps that correspond to each glyph, and then draw the glyphs to tiles or to a bitmap background.
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.

#148259 - wintermute - Fri Jan 04, 2008 12:25 am

No current emulator supports the RTC code. In most cases you'll get the correct time at startup but it will remain constant.

The time functions work correctly on hardware.
_________________
devkitPro - professional toolchains at amateur prices
devkitPro IRC support
Personal Blog

#148282 - nipil - Fri Jan 04, 2008 9:48 am

silent_code wrote:
check my site, there's a demo that loads a custom font. but the examples also show that (at least i seem to remember).
Nice demo ! And you were right, there's an example in devkitpro / graphics / 2d / custom_font. It seems i skipped the "search hard drive" part ;)

wintermute wrote:
No current emulator supports the RTC code. In most cases you'll get the correct time at startup but it will remain constant.
The time functions work correctly on hardware.
Good to know it works on hardware !

Big thanks to all for these info =)

#148322 - silent_code - Fri Jan 04, 2008 4:19 pm

i'm happy i could help. and thanks. :^D

the libnds demo "clock" works fine on hw, but it's not updating in any emulator. maybe someone should talk to martin (no$) about that?

#148530 - nipil - Sun Jan 06, 2008 9:38 pm

tepples wrote:
If you want to use proportional fonts, you're going to have to somehow store the bitmaps that correspond to each glyph, and then draw the glyphs to tiles or to a bitmap background.
That's what i want to do today. The way i planned it was to make create 1 sprite per possible letter, and display them. But i just realized i'd have to put 1 sprite per displayed letter in the OAM, because i just realized a sprite had just ONE position ; it doesn't seem possible to render one specific sprite multiple times... Maybe i mis-read something. Anyways, now i'm stuck. OAM contains only 128 sprites, so i cannot do it the way i tought. (besides, 128 sprites doesn't look that much when you think about it ; does it mean you'll *never* have more than 128 moving objects on the screen ? What about shoot'em up?)

I looked up on the web for homebrews displaying any kind of non-fixed fonts. Among others, i found PuzzleManiak, DSLibris, DS Reader, DS Organize and some others. Sadly, few of them offer their source code as download... I'm surprised.

So now, i'm looking for a way to go further. I'm using Mode 0, BG0 is a tiled background (map base 0, tile base 1, 4 tiles defined). Loading the "character" bitmaps is not a problem actually. I guess the solution lies within using some of BG1-BG3 to "render" the text maybe. But as i understand it, backgrounds are tiled, and as such, i don't know how to draw something on any pixel (not using 8x8 tiles) ; Plus, what's the "transparent" color i should fill them, if i display more than 1 background ? I don't want to "go back" and use the framebuffer, as the 2d engines offer much more...

I kindly ask for advices.

#148536 - nipil - Sun Jan 06, 2008 10:36 pm

Ok, i think found how to do it. Mode 0 offers only text (tiled) backgrounds. As i'm not using BG3 yet, i can simply switch to mode 5, and use one extended rotation background which can be used like a framebuffer (with bit 15 being transparency). An extended rotation background of 256x256@16bits takes an entire 128K bank, with only 256x192 being displayed, and 256x64 being hidden. I'll make a 256x64 picture (max possible size in this case, can be smaller) containing all the letters, then write it to the start of the bank, and then scroll the background up to "hide" the letters. Then when i need to "print" something, i'll copy each letter where i need it in the remaining 256x192 background space.

I'll try this, let me know if i'm running my head in the wall ;)

#148538 - tepples - Sun Jan 06, 2008 10:45 pm

nipil wrote:
tepples wrote:
If you want to use proportional fonts, you're going to have to somehow store the bitmaps that correspond to each glyph, and then draw the glyphs to tiles or to a bitmap background.
That's what i want to do today. The way i planned it was to make create 1 sprite per possible letter, and display them. But i just realized i'd have to put 1 sprite per displayed letter in the OAM, because i just realized a sprite had just ONE position ; it doesn't seem possible to render one specific sprite multiple times

A lot of people confuse sprites with sprite cels.
  • Sprites are entries in the display list. Each core has a display list of 128 elements, called OAM (object attribute memory).
  • Sprite cels are stored in VRAM. Multiple sprites can point to one sprite cel.

In Super Mario Bros., have you ever noticed how all the Goombas look the same? That's because they're all pointing to the same sprite cels.

Quote:
... Maybe i mis-read something. Anyways, now i'm stuck. OAM contains only 128 sprites, so i cannot do it the way i tought. (besides, 128 sprites doesn't look that much when you think about it ; does it mean you'll *never* have more than 128 moving objects on the screen ? What about shoot'em up?)

Galaga and Gradius have far fewer than 128 moving objects per scene. Are you talking about bullet hell? Even in this case, Vulkanon demonstrates advanced tricks to change the position of a sprite after half the screen has already been rendered.

Quote:
I looked up on the web for homebrews displaying any kind of non-fixed fonts. Among others, i found PuzzleManiak, DSLibris, DS Reader, DS Organize and some others. Sadly, few of them offer their source code as download... I'm surprised.

DSOrganize uses DragonMinded's libfb, which comes with source code. RAC and Lockjaw also use proportional fonts and also come with source code.

Quote:
So now, i'm looking for a way to go further. I'm using Mode 0, BG0 is a tiled background (map base 0, tile base 1, 4 tiles defined). Loading the "character" bitmaps is not a problem actually. I guess the solution lies within using some of BG1-BG3 to "render" the text maybe. But as i understand it, backgrounds are tiled, and as such, i don't know how to draw something on any pixel (not using 8x8 tiles)

It's possible to draw pictures in a tiled mode. On the Game Boy, this was the only way there was, and products such as Qix and the camera used it. It looked like this:
  1. Fill the background map with a unique tile in each space.
  2. Figure out which tile a pixel should be in.
  3. Draw the pixel by modifying the tile memory.

Quote:
Plus, what's the "transparent" color i should fill them, if i display more than 1 background ?

The transparent color in 4- and 8-bit bitmaps on GBA and DS is index 0.
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.

#148543 - nipil - Sun Jan 06, 2008 11:06 pm

tepples wrote:
Multiple sprites can point to one sprite cel.
I'm ashamed, i didn't even realize i was handling a pointer... *gasp*

Quote:
bullet hell .... (snip) Vulkanon demonstrates advanced tricks to change the position of a sprite after half the screen has already been rendered.
This is the kind of game i was speaking of (or Ikaruga). Nice trick to enhance the number of things rendered !

Quote:
DSOrganize uses DragonMinded's libfb, which comes with source code. RAC and Lockjaw also use proportional fonts and also come with source code.
In fact i was surprised i didn't find a "main" repository for homebrews (i'm quite used to freshmeat)
And i was surprised that not all programs offered their source for download.
But thanks a lot for the pointers, it's hard for a newbie to find what you want when you don't really know what you're looking for !

Quote:
It's possible to draw pictures in a tiled mode. (snip) Step 1: Figure out which tile a pixel should be in. Step 2: Draw the pixel.
Nice trick, again ;)

#148579 - nipil - Mon Jan 07, 2008 2:08 pm

I had problems with libFB ("Source object libfb.a has EABI version 0, but target sample1.elf has EABI version 4 ; failed to merge target specific data of file libfb" when using precompiled libFB version. Building the libFB from source and building sample against it completes. But nothing happens when i run sample1.nds. So i thought, i code for fun after all, so why not try it once ? ;) And ... Yay ! I got it working. So here's a screenshot : [Images not permitted - Click here to view it]

On the screenshot (it's aweful, i know) you'll see :
- 2 sprites (taken from patater's manual)
- vertical/horizontal bars on a tiled, scrolling BG0
- letters, turquoise and random pixels are on 256x256@16 extended BG3
- top left pixel is hand drawing (red pixels where the touchscreen is pressed)

I'm displaying the text on BG3 : 256x192px of it's memory is directly displayed on the screen (we'll draw the text to it), remains 256x64=16k worth of memory for various usages; I'm using this "hidden" part of the 256x256 BG3 to store my font. Please note that you could also keep it simply in main RAM (when linked statically to the .nds), instead of loading it to video memory (i'd say you'd load it to video memory when you're accessing your data from some file system).

The letters are found in a 467x12 png file "font" image. The image contains a line of all the characters you want to be available for display. For this method to work, your font map sould be less than 16k pixels. Mine is about 5k, so i could eventually show 3 fonts at the same time. Generating such a bitmap by hand takes approximately 30 seconds (gimp/mspaint/phtoshop) so i find it easy to use. No order nor any character alignement is required, as i wanted it to be flexible. Only constraint is that the image be a single line. Here's the font image : [Images not permitted - Click here to view it]

The "random" pixels in fact show the font image, 468byte-memory aligned image, copied directly to BG3 (i have no reason to align it on the display to make it display smoothly). On the screenshot i offseted the font back about 6k to be able to see it and verifiy it's loaded, but it is normally hidden.

In order to display the letters on the screen, i needed to know which character is available, and at which "x" offset in the font image it appears. This is done using a hand-typed structure, with one entry per character. It's (imho) faster to type than aligning the characters on a specific image grid by hand, and the struct method uses only nchar*3 bytes, while the image-align method would waste much more memory. So, the following struct can be typed in about 5 minutes maximum :
Code:
typedef struct { u8 c; u16  xoff; } font_info;
font_info font_tahoma_info[] = { { 'a',0 }, ... , { '!',464 } };
This structure is used to initialize a frame-bounded word-wrapping text-display class. But basically, to display the characters, i'm just copying from BG3 off-screen memory to BG3 on-screen memory. For example, if i want to put the "circ e" (image xoffset 333, width 6) on screen pixel 100,48 here's a sample loop (with bg3 being the base pointer of BG3 memory, and fs the pointer to the start of the font image) :
Code:
const int font_img_h=12, font_img_w=468
uint16 *dst_base = bg3 + 100 + 48*SCREEN_WIDTH ;
uint16 *src_base = fs + 333;
for (int y=0; y < font_img_h; y++) {
   for (int x= 0; x < 6; x++) {
      dst_base[y*SCREEN_WIDTH+x] = src_base[y*font_img_w+x];
   }
}
Please note that haven't yet done any kind of stress test, but i thought i had to share this, as someone might find it useful.