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.

Coding > problem with day-2 code from www.thepernproject.com

#13618 - GermanGBA - Thu Dec 18, 2003 3:57 pm

this is my code:
Code:
#include <gba.h>
#include <screenmode.h>
#include <sprite.h>
#include "spritedemo.h"
#define CharMem (u16*)0x6010000

u16* Screen = (u16*)VideoBuffer;
u16* paletteMem=(u16*)BGPaletteMem;

void PlotPixel(int x,int y, unsigned short int c){Screen[(y)*120+(x)]=(c);}

int main(void)
{
    SetMode(OBJ_MAP_2D | MODE_3 | OBJ_ENABLE);
   
    u8 spritedemoAttributes=0;
    s16 x=10, y=10;
    u16 char_number=0;
   
    sprites[spritedemoAttributes].attribute0=COLOR_256 + SQUARE + y;
    sprites[spritedemoAttributes].attribute1=SIZE_64 + x;
    sprites[spritedemoAttributes].attribute2=char_number;
   
    int xloop=0;
    int yloop=0;
    int index=0;
   
    for(yloop=0;yloop<8;yloop++)
    {
        for(xloop=0;xloop<256;xloop++)
        {
            CharMem[xloop+yloop*512]=spritedemoData[index];
            index++;
        }
    }
    return(0);
}


and this is the problem:
Quote:
c:/programs/dev-cpp/projects/gba-stuff/sprites/main.cpp:32: invalid types 'int[int]' for array subscript


what does it mean?

#13619 - poslundc - Thu Dec 18, 2003 4:07 pm

You are attempting to index into an array that you haven't declared yet.

Are you new to C? You should probably get more experience with basic C programming before you dive right into GBA programming.

Dan.

#13620 - GermanGBA - Thu Dec 18, 2003 4:10 pm

i'm not really new to c...
i only took the code out of the tutorial and tryed to compile it.

#13622 - GermanGBA - Thu Dec 18, 2003 4:23 pm

soory i recognized my mistake...

but why the hell doesn't it draw my sprite???

#13632 - poslundc - Thu Dec 18, 2003 9:27 pm

It draws your sprite (probably draws it, anyway), but then resets because you reach the end of the main() function. A GBA program should (generally speaking) never reach the end of the main function.

You need to start over from the beginning of the tutorials and work your way through them. They explain all of this; if you are just going to cut and paste code out of them and complain that they don't work then you will not get very far.

Dan.

#13634 - AcidGame - Thu Dec 18, 2003 10:04 pm

that is completely true. The main function is the first command called when a C program is run, and when it reaches the end, it will usually cut off. Try rooting off to a refresh ( the GBA runs on a screen refresh ( so i've heard ) and needs to be updated before anything changes on the screen ) Like i said, i've heard this, but i dont know. :X

#13639 - NoMis - Thu Dec 18, 2003 11:27 pm

there are other things missing.

1. you schould have an endless loop in the mainfunction.
2. i guess sprites is a shadow copy of the oam, so you need to update it during the vblank.

the pern project describes these things prety good so if you completly read it you shouldn't have problems to get this stuff running.

NoMis

#13644 - sgeos - Fri Dec 19, 2003 4:17 am

Add these three lines right before return 0.
Code:
while (1) {
   /* Endless Loop */
}


You could add this line instead, but it is harder to understand at a glance:
Code:
while (1);  /* Endless Loop */


Edit: This may not be enough to get the display to do anything. Please follow the advice of the other friendly posters.

-Brendan

#13681 - dagamer34 - Sat Dec 20, 2003 4:58 pm

OAMMem can only be changed during a VBlank and HBlank(its locked at any other time.)

1) Like other people have said, make a while loop at the end.

2) Big problem I see here. Your sprite array may point to OAMMem, BUT it does not change it. Look at the Pern Project code again. It is always best to download it off their site, the on-line tutorials only give snippets of code.

It would better help if you showed all your code, i don't see where sprites is declared.

add this to your code:

[code]
// Before main
void CopyOAM ();
void WaitSync ();

// your main function
int main ()
{

// Initialize your data, just like you have it,


// Now after all the copying but before return 0, put this
while (1)
{
WaitVSync ();
CopyOAM ();
}

return 0;
}

// Copys the data that controls the sprite to OAM memory
void CopyOAM ()
{
u16 loop;
u16* temp;
temp = (u16*)sprites;
for (loop = 0; loop < 128 * 4; loop++)
{
OAMMem [loop] = sprites [loop];
}
}

// We can only alter OAM memory during a VSync(scanline = 160) so wait for it.
void WaitVSync ()
{
while ((volatile u16)REG_VCOUNT != 160) {}
}
_________________
Little kids and Playstation 2's don't mix. :(

#13688 - GermanGBA - Sat Dec 20, 2003 6:28 pm

thx for the advices, but now it displays a black line in the middle of the picture..

my current code looks like this:
Code:
#include <gba.h>
#include <screenmode.h>
#include <sprite.h>

#include "sprite1.h"
#include "start.h"

u16* videoBuffer=(u16*)VideoBuffer;
u16* paletteMem=(u16*)BGPaletteMem;
u16* CharMem=(u16*)OAMdata;
u16* ObjPaletteMem=(u16*)OBJPaletteMem;

void PlotPixel(int x,int y, unsigned short int c) {videoBuffer[(y) *120 + (x)] = (c);}
void CopyOAM(void);
void WaitForVsync(void);
void InitializeSprites(void);

int main(void)
{
   
    u16 x=10;
    u16 y=10;
    u16 char_number=0;
   
    int index=0;
    int loop;
    SetMode(MODE_4 + OBJ_MAP_2D + OBJ_ENABLE + BG2_ENABLE);
   
    for(loop=0;loop<256;loop++)
        paletteMem[loop]=startPalette[loop];

    for(loop=0;loop<256;loop++)
        ObjPaletteMem[loop]=sprite1Palette[loop];

    for(x=0;x<120;x++)
        for(y=0;y<160;y++)
            PlotPixel(x, y, startData[y*120+x]);
   
    InitializeSprites();
   
    sprites[0].attribute0=COLOR_256 + SQUARE + y;
    sprites[0].attribute1=SIZE_64 + x;
    sprites[0].attribute2=char_number+512;

    for(index=0;index<256*8;index++)
        CharMem[index+(512*16)] = sprite1Data[index];
       
    while(1)
    {
        WaitForVsync();
        CopyOAM();
    }
}

void WaitForVsync(void)
{
   while((volatile u16)REG_VCOUNT != 160){}   
}

void CopyOAM(void)
{
   u16 loop;
   u16* temp;
   temp = (u16*)sprites;
   for(loop = 0; loop < 128*4; loop++)
   {
      OAM[loop] = temp[loop];
   }
}

void InitializeSprites(void)
{
   int loop;
   for(loop = 0; loop < 128; loop++)
   {
      sprites[loop].attribute0 = 160;
      sprites[loop].attribute1 = 240;
   }
}

#13691 - sajiimori - Sat Dec 20, 2003 7:29 pm

For the most part, there's no way to tell what's happening here because many of your symbols (OAMdata, sprites, sprite1Data, etc) are not defined in the code you posted.
Code:

    u16 x=10;
    u16 y=10;

    ...

    for(x=0;x<120;x++)
        for(y=0;y<160;y++)
            PlotPixel(x, y, startData[y*120+x]);

    ...

    sprites[0].attribute0=COLOR_256 + SQUARE + y;
    sprites[0].attribute1=SIZE_64 + x;

I don't suppose that will do what you were expecting.
Code:

   while((volatile u16)REG_VCOUNT != 160){}   

What is your definition of REG_VCOUNT?

#13696 - mtg101 - Sat Dec 20, 2003 9:38 pm

Code:

    for(x=0;x<120;x++)
        for(y=0;y<160;y++)
            PlotPixel(x, y, startData[y*120+x]);


So what's going on here? Are you trying to draw a background image to the screen before displaying your sprite? It would help if startData had a better name (like gBackgroundImage), and was documented in its first use to explain where it's come from.

Anyway let's concentrate on getting the sprite to display before we go drawing funky background images.

Code:

    InitializeSprites();

    sprites[0].attribute0=COLOR_256 + SQUARE + y;
    sprites[0].attribute1=SIZE_64 + x;
    sprites[0].attribute2=char_number+512;


When you do "sprites[0].attribute0=COLOR_256 + SQUARE + y;", what is the value of the 'y' variable? It'll be 160, because 'y' was used as a loop variable during the PlotPixel() loops above. Thus your sprite will be drawn off the bottom of the screen.


Cheers
Russell
_________________
---
Speaker for the Dead

#13698 - dagamer34 - Sat Dec 20, 2003 9:54 pm

Use VBA and see if the data is correctly being loaded.

One other thing is that most people (well, at least me) don't load sprites in 2D mode because it is too much of a hassle. 1D is simpler for loading and when you decide to creat animations.

And if you are using the Pern Project headers, VideoBuffer, BGPaletteMem, OBJPaletteMem, and OAMData are already defined as pointers to registers. It isn't very usefil to make a pointer to a pointer in this case.

Thats all i can say for now.
_________________
Little kids and Playstation 2's don't mix. :(

#13763 - GermanGBA - Mon Dec 22, 2003 3:38 pm

but if i do not define a pointer to the defines of the headers, i will get the error described above