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.

Beginners > what's wrong with this short code ?

#68553 - deltree - Wed Jan 25, 2006 5:50 pm

Hi,
I'm having trouble with this code not displaying anything:
here we go:
Code:
#include <mygba.h>
const unsigned short bg_Palette[256],i;
const unsigned char bg_Bitmap[38400],j;
 int main(void)
{
   for (i=0;i<256;i++)  {
      bg_Palette[i]=i*256;
   }
   for (j=0;j<38400;j++)  {
       bg_Bitmap[j]=j%256;
   }
    ham_Init();
    ham_SetBgMode(4);
    ham_LoadBGPal((void*)bg_Palette,256);
    ham_LoadBitmap((void*)bg_Bitmap);
    ham_FlipBGBuffer();
   while(TRUE) { }
   return 0;
}

this is supposed to display a full screen of regularly increasing color palette, but it doesnt display anything. white only. What is very weird, it's that even the "created with ham" logo doesn"'t display.
what's wrong with it ? I'm almost sure it as something to do with types, but I can't figure what

#68560 - FluBBa - Wed Jan 25, 2006 6:30 pm

const makes the array go into ROM, which mean Read Only Memory.
_________________
I probably suck, my not is a programmer.

#68561 - deltree - Wed Jan 25, 2006 6:33 pm

hi again
I removed the "const": it compiles properly, but i does the same. nothing exept a blanck screen of death.

Code:
#include <mygba.h>
unsigned short bg_Palette[256],i;
unsigned char bg_Bitmap[38400],j;
 int main(void)
{
   for (i=0;i<256;i++)  {
      bg_Palette[i]=i*256;
   }
   for (j=0;j<38400;j++)  {
       bg_Bitmap[j]=j%256;
   }
    ham_Init();
    ham_SetBgMode(4);
    ham_LoadBGPal((void*)bg_Palette,256);
    ham_LoadBitmap((void*)bg_Bitmap);
    ham_FlipBGBuffer();
   while(TRUE) { }
   return 0;
}

#68569 - Miked0801 - Wed Jan 25, 2006 7:30 pm

Your char array bg_Bitmap[38400] more than likely is being placed into IWRAM - which is only 32K in size. Boom.

#68586 - Cearn - Wed Jan 25, 2006 10:22 pm

deltree wrote:
hi again
I removed the "const": it compiles properly, but i does the same. nothing exept a blanck screen of death.

Code:
#include <mygba.h>
unsigned short bg_Palette[256],i;
unsigned char bg_Bitmap[38400],j;
 int main(void)
{
   for (i=0;i<256;i++)  {
      bg_Palette[i]=i*256;
   }
   for (j=0;j<38400;j++)  {
       bg_Bitmap[j]=j%256;
   }
    ham_Init();
    ham_SetBgMode(4);
    ham_LoadBGPal((void*)bg_Palette,256);
    ham_LoadBitmap((void*)bg_Bitmap);
    ham_FlipBGBuffer();
   while(TRUE) { }
   return 0;
}

Miked0801 is right: the arrays are killing IWRAM. What exactly is the point of having bg_Palette and bg_Bitmap anyway? You're initializing them first, then copying them to pal RAM and VRAM. Why not initialize those directly?

Code:

// These are my own names. There are many like them but these ones are mine.
// HAM and libgba will have others, but names are unimportant. What they stand for is.
#define pal_bg_mem ((u16*)0x05000000)
#define vid_mem ((u16*)0x06000000)

int ii;

// fill bg palette directly
for(ii=0; ii<256; ii++)
   pal_bg_mem[ii]= ii*256;

// fill VRAM directly (though this has to be done 2 pixels at a time)
for(ii=0; ii<240*160; ii += 2)
    vid_mem[ii/2]= (ii%256) | ((ii+1)%256)<<8;

Code is untested, but should work.

Also, DON'T USE NON-WORD (32bit) TYPES FOR VARIABLES! It kills performance for absolutely no good reason. Use int if you can, only char/short if you must. Sorry about sounding harsh, but this one just bugs me to no end.

Aside from that, Having your main loop variables (i,j) as globals is probably a very bad idea. Not just because it has an even bigger performance penalty than using non-words, it's going to be a maintainance nightmare when you're going to mix functions. Keep your loop counters nice and local unless you have a very good reason not to.

I see you chose to start with HAM. That is great if you want to get some result quickly, but it also hides important details from you so that you can't get a clear idea of what's really going on or what you're actually doing when you call HAM's functions. Spend some time browsing non-HAM tutorials as well to get a feel for the hardware. It will be very beneficial in the long run.

Oh, and read the FAQ if you haven't already.

#68689 - deltree - Thu Jan 26, 2006 10:54 am

hi,
thanx for the answer, but there are still a few things I don't get.
here's the way I mad my program, just adding "main" function, but it doesn't work, a blank white screen again.
Code:

#include <mygba.h>
int main(void)
{
   #define pal_bg_mem ((u16*)0x05000000)
   #define vid_mem ((u16*)0x06000000)
   int ii;
   // fill bg palette directly
   for(ii=0; ii<256; ii++)
      pal_bg_mem[ii]= ii*256;
   // fill VRAM directly (though this has to be done 2 pixels at a time)
   for(ii=0; ii<240*160; ii += 2)
      vid_mem[ii/2]= (ii%256) | ((ii+1)%256)<<8;
   while(1){ }
   return 0;
}

what's wrong with it ? did I implement properly your code ? (i guess no)
again, a few question:
can you explain the "define" 2 lines ?
and this line:
vid_mem[ii/2]= (ii%256) | ((ii+1)%256)<<8;
I don't understand it. what does the | or << mean ? I know it's something like "or" and bitshifting, but why using it here ?
why don't you initialize background mode? why don't you flip the buffer ?

#68696 - keldon - Thu Jan 26, 2006 12:11 pm

You are not setting the video mode. Try the tonc tutorials.

#68697 - Cearn - Thu Jan 26, 2006 12:19 pm

deltree wrote:
hi,
thanx for the answer, but there are still a few things I don't get.
here's the way I mad my program, just adding "main" function, but it doesn't work, a blank white screen again.
Code:

#include <mygba.h>
int main(void)
{
   #define pal_bg_mem ((u16*)0x05000000)
   #define vid_mem ((u16*)0x06000000)
   int ii;
   // fill bg palette directly
   for(ii=0; ii<256; ii++)
      pal_bg_mem[ii]= ii*256;
   // fill VRAM directly (though this has to be done 2 pixels at a time)
   for(ii=0; ii<240*160; ii += 2)
      vid_mem[ii/2]= (ii%256) | ((ii+1)%256)<<8;
   while(1){ }
   return 0;
}

what's wrong with it ? did I implement properly your code ? (i guess no)

No you didn't. Mostly because there's one thing that I didn't mention explicitly, namely that you need to set the video mode as well. That's what ham_SetBgMode() does for you. Aside from that, you also need to enable the background that the bitmap uses, but I can't tell if ham_SetBgMode() does that as well, or if it's in hamInit().
Either way, here's something that 'should' work (modified for use with HAM's own defines from mygba.h).
Code:

#include <mygba.h>

// From mygba.h
//#define MEM_PAL_BG_PTR    (u16*) 0x05000000  // pal_bg_mem
//#define MEM_VRAM_PTR      (u16*) 0x06000000   // vid_mem

int main(void)
{
    int ii;
    ham_Init();
    ham_SetBgMode(4);

    for(ii=0; ii<256; ii++)
        (MEM_PAL_BG_PTR)[ii]= ii*256;
       
    for(ii=0; ii<240*160; ii += 2)
        (MEM_VRAM_PTR)[ii/2]= (ii%256) | ((ii+1)%256)<<8;
   
    while(1);
}

This one is tested and works. At least for the old HAM version that I have. mygba.h is absolutely filled with #defines for all possible uses so the things that you need are all in there, but you'd have to find them and know how to use them.
The pointers needed to operate on the palette and VRAM directly are called MEM_PAL_BG_PTR and MEM_VRAM_PTR, which appear around lilne 800 in that file, but I've added them here for convenience. Note that the definitions are actually somewhat flawed. Because in C, the array operator [] has precedence over casts (u16*), you can't use the pointers as arrays directly. That's why I need to use (MEM_VRAM_PTR), rather than just MEM_VRAM_PTR. The extra parentheses should be part of the #defines.

Instead of calling ham_Init() and ham_SetBgMode(), you can also do
Code:
R_DISPCNT= 0;
M_DISCNT_BGMODE_SET(4);
M_DISCNT_BG2_ON;

or even
Code:
R_DISPCNT= 0x0400 | 0x0004;

as that's the only thing you really need in terms of initialization here. 0x0400 activates background 2 and 0x0004 sets the video mode. HAM doesn't have #defines for those for some reason, so I'm just using the actual numbers here. Because I don't work with an API, I (have to) know what's really going on underneath to get things working.

deltree wrote:
again, a few question:
can you explain the "define" 2 lines ?

#define is a preprocessor directive.
Code:
#define vid_mem ((u16*)0x06000000)

Means that every time the compiler encounters vid_mem, it replaces it with what it's defined as, in this case ((u16*)0x06000000). This helps coding because vid_mem is (VIDeo MEMory) says more about what the section is for than 0x06000000 does.
C++ has depreciated much of what #define is used for because the common opinion is that #define is EEEvil. Common opinion is correct here, but it's just so damn useful to toss aside. Look in that mygba.h, it's full of #defines.

deltree wrote:
and this line:
vid_mem[ii/2]= (ii%256) | ((ii+1)%256)<<8;
I don't understand it. what does the | or << mean ? I know it's something like "or" and bitshifting, but why using it here ?

Because "this has to be done 2 pixels at a time". Or, rather, with at least 16bits at a time. PAL RAM, VRAM and OAM have a restriction that won't let you write in byte-sized chunks to those sections. That's one of the major problems with mode 4: you can't access individual pixels, you have to write two at a time. In this case, (ii%256) is the even pixel, and the shifted one is the odd pixel. The 'OR' combines them into one value. Again, because I work with the hardware directly rather than through an API, I know these things.

deltree wrote:
why don't you initialize background mode?

Because I have the habit of only giving the code snippets directly required for the topic at hand, rather than fully cut&pastable code. I'm flawed that way, it's been said.

deltree wrote:
why don't you flip the buffer ?
Because I know the hardware enough to know it's not necessary (is this getting old yet? :P ). I'm guessing that ham_LoadBitmap() always writes to the back-page. It is more proper, but not required. If you just want something on screen, what I did is just easier.

As you seem to be new to C too, you might want to pick up a book or tutorial on that as well. If you don't know your way around the preprocessor, hex, bit-ops and pointers, you're in for a bumpy ride. The GBA isn't really a platform on which you can get a way with not knowing what you're doing. You will get smacked down if you don't spend some time on getting comfortable with C (or asm) first.

#70965 - Red XIII - Thu Feb 09, 2006 8:06 pm

EDIT: Ok man,sorry,I just thought that you had solved your problem as the last post was 2 weeks ago... You don't have to act like that.

Last edited by Red XIII on Thu Feb 09, 2006 9:23 pm; edited 1 time in total

#70967 - deltree - Thu Feb 09, 2006 8:25 pm

it was my post