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 > Trouble with Tiles / Font

#165986 - Doogle - Thu Jan 15, 2009 7:20 am

I'm having some difficulties establishing a Font using Tiles.
I've been through the tutorials and examples and think I know what I'm doing but the results indicate that I do not and that I'm missing something fairly fundamental.
Code:

void initVideo(){

   powerOn(POWER_ALL_2D);
   
   vramSetMainBanks(VRAM_A_MAIN_BG_0x06000000,
                     VRAM_B_MAIN_BG_0x06020000,
                     VRAM_C_SUB_BG_0x06200000,
                     VRAM_D_LCD);

    /*  Set the video mode on the main screen. */
    videoSetMode(MODE_0_2D | // Set the graphics mode to Mode 0
                 DISPLAY_BG2_ACTIVE); // Enable BG2 for display

    /*  Set the video mode on the sub screen. */
    videoSetModeSub(MODE_0_2D | // Set the graphics mode to Mode 0
                    DISPLAY_BG2_ACTIVE); // Enable BG2 for display
}

uint16* map; //Pointer to the main screen Map
uint16* sub_map; //Pointer to the sub-screen Map

void initBackgrounds() {

   REG_BG2CNT = BG_COLOR_256 |
             BG_TILE_BASE(0) |
             BG_MAP_BASE(20) |
             BG_PRIORITY(3);
            
   REG_BG2X = 0; //main screen origin
   REG_BG2Y = 0;
   
   REG_BG2CNT_SUB = BG_COLOR_256 |
                BG_TILE_BASE(0) |
                BG_MAP_BASE(20) |
                BG_PRIORITY(3);
               
   REG_BG2X_SUB = 0; //sub-screen origin
   REG_BG2Y_SUB = 0;
   
   uint16* tile = (uint16 *) BG_TILE_RAM(0); //Initialise a pointer to the Tile Ram
   map = (uint16 *) BG_MAP_RAM(20); //Initialise the pointer to the main screen Map
   uint16* sub_tile = (uint16 *) BG_TILE_RAM_SUB(0); // Initialise a ponter to the sub-screen Tile Ram
   sub_map = (uint16 *) BG_MAP_RAM_SUB(20); //Initialise the pointer to the sub-screen Map

   int i;
   /*
   Populate the main and sub-screen tile Ram
   */
   for(i=0;i<font3TilesLen/sizeof(uint16);i++){
      tile[i]=sub_tile[i]=font3Tiles[i];
   }
   /*
   Populate the main and sub-screen Palettes
   */
   for(i = 0;i<font3PalLen/sizeof(uint16);i++){
      BG_PALETTE[i]=BG_PALETTE_SUB[i]=font3Pal[i];
   }
}
void PrintMsg() {

   int i;
   int j;
   
   char* msg[] = {
    "0123456789",
    "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
    "abcdefghijklmnopqrstuvwxyz",
  };
  /*
  Print to the main screen
  */
   for(i = 0; i < sizeof(msg); ++i) {
      for(j = 0; msg[i][j] != '\0'; ++j) {
          map[j + (i * 32)] = msg[i][j]-' ' ;   //Font starts with a space character
                                               //so we have to subtract the offset

      }
   }
   swiWaitForVBlank();
}
int main(void)
{
   initVideo();
   initBackgrounds();
   PrintMsg();
   return ;
}

The result is a pink background of some wierd character and black space and other wierd characters where the text should be displayed. Clearly either I'm not putting the tiles where I think I am, or I'm not mapping to them correctly.
I'm using the Font.bmp and .Grit file from the nds/2D/customfont example.(renamed to 'font3')
Any suggestions where I'm going wrong, or pointers to additional tutorials / information would be appreciated.
Thanks.

#165990 - samel - Thu Jan 15, 2009 6:33 pm

for(i=0;i<font3TilesLen/sizeof(uint16);i++){
tile[i]=sub_tile[i]=font3Tiles[i];
}

should not be

for(i=0;i<font3TilesLen;i++){
tile[i]=sub_tile[i]=font3Tiles[i];
}

and tile should not be u8* ?

#165992 - Cearn - Thu Jan 15, 2009 7:21 pm

The problem is here:
Doogle wrote:
Code:
   uint16* tile = (uint16 *) BG_TILE_RAM(0); //Initialise a pointer to the Tile Ram
   uint16* sub_tile = (uint16 *) BG_TILE_RAM_SUB(0); // Initialise a ponter to the sub-screen Tile Ram

   ...

   int i;
   // Populate the main and sub-screen tile Ram
   for(i=0;i<font3TilesLen/sizeof(uint16);i++){
      tile[i]= sub_tile[i]= font3Tiles[i];
   }

The exported tiles are an u32 array, but you're copying them into an u16 array, causing you to lose half of the data. If you create your own copy loops, make sure the source and destination units are the same. Better yet, use a dedicated copier like dmaCopyWords (or even the standard memcpy) for large copies. These will be considerably faster, use less code and you won't have to worry about how the arrays are defined.

Code:
// memcpy example (args: dst, src, size):
#include <stdlib.h>
memcpy(BG_TILE_RAM(0), font3Tiles, font3TilesLen);

// dma example (args: channel, src, dst, size)
dmaCopyWords(3, font3Tiles, BG_TILE_RAM(0), font3TilesLen);


samel wrote:
Code:
for(i=0;i<font3TilesLen/sizeof(uint16);i++){
    tile[i]= sub_tile[i]= font3Tiles[i];
}

should not be

Code:
for(i=0;i<font3TilesLen;i++){
    tile[i]= sub_tile[i]= font3Tiles[i];
}

and tile should not be u8* ?

No; partly for the same reasons as given above, but also because you can't write in byte-size chunks to VRAM, OAM or the palette. There's also the speed issue: byte copies require twice as many loop iterations as halfword copies for a given array-size and as such are roughly twice as slow.

#165993 - Doogle - Thu Jan 15, 2009 7:24 pm

Thanks for the response. Unfortunately, having made the changes the result is very similar, with the exception that I just get the pink background with no text at all.

#165997 - elhobbs - Thu Jan 15, 2009 7:44 pm

do you have a priority issue on the background? you are using BG_PRIORITY(3) which is the lowest priority. Is another background covering your background?

#165998 - Doogle - Thu Jan 15, 2009 7:59 pm

Thanks for the responses. I've changed the population of the Tile Ram to
Code:

   dmaCopyWords(3, font3Tiles, BG_TILE_RAM(0), font3TilesLen);
   dmaCopyWords(3, font3Tiles, BG_TILE_RAM_SUB(0), font3TilesLen);

and also changed the Priority (although there are no other backgrounds)

I'm still getting the pink background and wierd characters.

I've got a feling that I'm missing something fairly fundamental.

#166000 - elhobbs - Thu Jan 15, 2009 9:42 pm

I patched up your code to work on desmume - see below
the main issues were you were not setting your backgrounds correctly. the tiles are 4 bit not 8bit and you were also not loading the palette for either screen. also sizeof(msg) is not correct for your print loop.


Code:
/*---------------------------------------------------------------------------------

   Simple console print demo
   -- dovoto

---------------------------------------------------------------------------------*/
#include <nds.h>
#include <stdio.h>

#include "font3.h"

//---------------------------------------------------------------------------------
void initVideo(){

   powerOn(POWER_ALL_2D);
   
   vramSetMainBanks(VRAM_A_MAIN_BG_0x06000000,
                     VRAM_B_MAIN_BG_0x06020000,
                     VRAM_C_SUB_BG_0x06200000,
                     VRAM_D_LCD);

    /*  Set the video mode on the main screen. */
    videoSetMode(MODE_0_2D | // Set the graphics mode to Mode 0
                 DISPLAY_BG2_ACTIVE); // Enable BG2 for display

    /*  Set the video mode on the sub screen. */
    videoSetModeSub(MODE_0_2D | // Set the graphics mode to Mode 0
                    DISPLAY_BG2_ACTIVE); // Enable BG2 for display
}

uint16* map; //Pointer to the main screen Map
uint16* sub_map; //Pointer to the sub-screen Map

void initBackgrounds() {

   REG_BG2CNT = BG_32x32 | BG_COLOR_16 |
             BG_TILE_BASE(0) |
             BG_MAP_BASE(20) |
             BG_PRIORITY(3);
             
   REG_BG2X = 0; //main screen origin
   REG_BG2Y = 0;
   
   REG_BG2CNT_SUB = BG_32x32| BG_COLOR_16 |
                BG_TILE_BASE(0) |
                BG_MAP_BASE(20) |
                BG_PRIORITY(3);
               
   REG_BG2X_SUB = 0; //sub-screen origin
   REG_BG2Y_SUB = 0;
   
   uint16* tile = (uint16 *) BG_TILE_RAM(0); //Initialise a pointer to the Tile Ram
   map = (uint16 *) BG_MAP_RAM(20); //Initialise the pointer to the main screen Map
   uint16* sub_tile = (uint16 *) BG_TILE_RAM_SUB(0); // Initialise a ponter to the sub-screen Tile Ram
   sub_map = (uint16 *) BG_MAP_RAM_SUB(20); //Initialise the pointer to the sub-screen Map

   int i;
   /*
   Populate the main and sub-screen tile Ram
   */
   dmaCopyWords(3, font3Pal, BG_PALETTE, font3PalLen);
   dmaCopyWords(3, font3Pal, BG_PALETTE_SUB, font3PalLen);
   
   dmaCopyWords(3, font3Tiles, BG_TILE_RAM(0), font3TilesLen);
   dmaCopyWords(3, font3Tiles, BG_TILE_RAM_SUB(0), font3TilesLen);
}
void PrintMsg() {

   int i;
   int j;
   
   char* msg[] = {
    "0123456789",
    "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
    "abcdefghijklmnopqrstuvwxyz",
  };
  /*
  Print to the main screen
  */
   for(i = 0; i < /*sizeof(msg)*/ 3; ++i) {
      for(j = 0; msg[i][j] != '\0'; ++j) {
          map[j + (i * 32)] = msg[i][j]-' ' ;   //Font starts with a space character
                                               //so we have to subtract the offset

      }
   }
  /*
  Print to the sub screen
  */
   for(i = 0; i < /*sizeof(msg)*/ 3; ++i) {
      for(j = 0; msg[i][j] != '\0'; ++j) {
          sub_map[j + (i * 32)] = msg[i][j]-' ' ;   //Font starts with a space character
                                               //so we have to subtract the offset

      }
   }
   swiWaitForVBlank();
}
int main(void)
{
   initVideo();
   initBackgrounds();
   PrintMsg();
   return 0;
}

#166002 - Doogle - Thu Jan 15, 2009 9:57 pm

Many thanks, your patches have solved the problem. I'm going to have to look at it closely to make sure I understand exactly where I went wrong.

(You may have gathered that I'm new to this as well as being new to C as a language. (I do have the book though))

Saying that, it's great fun !! Thanks again.

#166041 - Doogle - Sun Jan 18, 2009 1:19 pm

My latest issue is associated with using the default Keyboard on the bottom screen. After defining the keyboard etc on issuing keyboardInit(kb); the bottom screen displays a series of blue and black 'blobs'. On executing keyboardShow(), bits of the keyboard are displayed.

I'm guessing that it's something to do with mapping (or merging BGs together). According to the keyboard.h file its default BG is BG3 and the Map offset is 30, whereas I'm using BG2 and a Map offset of 20.
Any ideas?

#166045 - dovoto - Sun Jan 18, 2009 6:46 pm

Doogle wrote:
My latest issue is associated with using the default Keyboard on the bottom screen. After defining the keyboard etc on issuing keyboardInit(kb); the bottom screen displays a series of blue and black 'blobs'. On executing keyboardShow(), bits of the keyboard are displayed.

I'm guessing that it's something to do with mapping (or merging BGs together). According to the keyboard.h file its default BG is BG3 and the Map offset is 30, whereas I'm using BG2 and a Map offset of 20.
Any ideas?


The keyboard code in current release has a few issues. These have been corrected new release is forthcomming
_________________
www.drunkencoders.com

#166057 - Doogle - Mon Jan 19, 2009 6:26 am

Ah, I see. Thanks for the response. I was beginning to wonder if what little I thought I understood was wrong ! Perhaps an opportunity to make my own keyboard then.