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.

Graphics > Text System

#46669 - ProblemBaby - Tue Jun 28, 2005 10:38 pm

Hi

Ive tried to code a Text System I want it to be like Zelda - Minish Cap.
Every character has its own width, not forced to 8.
My idea is to put all characters in a image and have a map were all tiles are uniqe and then read and draw every pixel seperatly.
This is damn slow!
About 80% for one row=)

Do you have any ideas to do this in a faster way?!
Thanks in advance

#46671 - strager - Tue Jun 28, 2005 10:51 pm

ProblemBaby wrote:
My idea is to put all characters in a image and have a map were all tiles are uniqe and then read and draw every pixel seperatly.
This is damn slow!
About 80% for one row=)


I've done this method, and it works fine. If you could, paste the code that you're using.

#46674 - ProblemBaby - Tue Jun 28, 2005 11:17 pm

Well it isnt hardly optimized, probably its a lot that can speed it up:

The actual Pixel Plotting function

Code:

void SetPixel(u32 x, u32 y)
{
   u16 Data;
   u32 TileOffset, PixelOffset;
   u32 xTile, yTile;
   xTile = x >> 3;
   yTile = y >> 3;
   x &= 0x7;
   y &= 0x7;   
   TileOffset = yTile * 30 + xTile;
   PixelOffset = y * 2 + (x >> 2);

   Data = BACKGROUND_DATAMEM[0x4000 + (TileOffset*0x10) + PixelOffset];

   Data |= 1 << ((x&0x3) * 4);

   BACKGROUND_DATAMEM[0x4000 + (TileOffset*0x10) + PixelOffset] = Data;




And here is the DrawChar function:
c = character
x, y = destination pos

Code:


u32 a, b;

u32 RowLength = 256;
u32 SourceOffset;
SourceOffset = c * 2;

for (b = 0; b < 16; b++)
{
   for (a = 0; a < 2; a++)
   {
      if (g_gfxFont_[SourceOffset + b * RowLength + a] & 0xF)
         Print_SetPixel(x+a*4, y+b);
      if (g_gfxFont_[SourceOffset + b * RowLength + a] & 0xF0)
         Print_SetPixel(x+a*4+1, y+b);
      if (g_gfxFont_[SourceOffset + b * RowLength + a] & 0xF00)
         Print_SetPixel(x+a*4+2, y+b);
      if (g_gfxFont_[SourceOffset + b * RowLength + a] & 0xF000)
         Print_SetPixel(x+a*4+3, y+b);
   }
}

#46676 - sajiimori - Tue Jun 28, 2005 11:27 pm

To make this fast, you need pointer math. Here's a thread from a long time ago that might be helpful:

http://forum.gbadev.org/viewtopic.php?t=2305

#46679 - ProblemBaby - Wed Jun 29, 2005 1:13 am

Well the only place I see where I can use it is in the PutChar-function
I got some improvement.
But it must be better ways to draw pixels, right?

#46681 - sajiimori - Wed Jun 29, 2005 1:26 am

Yeah, you should use a pointer to iterate through VRAM addresses rather than recalculating them from scratch for every pixel.

#46713 - ProblemBaby - Wed Jun 29, 2005 9:59 am

Well I think its hard because you never know in which tile you should draw.

Is this really the best method?

#46722 - poslundc - Wed Jun 29, 2005 4:12 pm

ProblemBaby wrote:
Is this really the best method?


It's one of only two methods that'll let you use other BG layers. The other is to use sprites and to multiplex them with an HBlank interrupt. But most games opt to do it with a BG, since the resources are more plentiful.

Here is another thread that discusses some strategies for painting BG chars. There is no easy solution to the problem, unfortunately.

Dan.

#46744 - ProblemBaby - Wed Jun 29, 2005 11:54 pm

I really want to use BG's
Ive started to rewrite in ASM now. I write one character in ~0,13%
and I think that is quite good. I'll see if I can do some more omptimizations. my Goal is about ~0,06 per character.
But Probably it wont be that fast.

#46791 - Miked0801 - Thu Jun 30, 2005 6:30 pm

Question - why does your text rendering system need to be so fast? Text is usually rendered while the screen is transitioning so you don't notice small spped hits - and if you're re-drawing a menu, it's ok to see a tic of blank screen. Just seems you're optimizing something that really doesn't need it.

#46799 - ProblemBaby - Thu Jun 30, 2005 9:24 pm

The most important thing is the music.
I want to be able to write while music plays.

#47115 - Mucca - Tue Jul 05, 2005 10:40 am

You could process music in an interrupt. DMA then becomes a worry however. Or Im sure with some fancy ASM you could set up a text rendering "thread" that is serviced when time is available, and halts in a stable state when required.

#47141 - Miked0801 - Tue Jul 05, 2005 7:17 pm

Yes, music should be handled on an interrupt level. If that isn't possible, then only render out a few lines at a time or check the LY counter against a threshold and pause in the middle.