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 > Re-graphics error again

#177172 - blessingta@hotmail.co.uk - Wed Jan 11, 2012 1:47 am

I handed in my coursework with the ridiculous graphic bug still in nearly a month ago... and long story short just recently I've gone back to it trying to fix it and I'm still hitting the same barrier.

Link to the gba executable

http://dl.dropbox.com/u/42518274/STUDENT50398201_MAKE_LINE_GAME.gba


Problem:
The sprites will refuse to render randomly, after a series of regular button presses and then randomly decide to turn back on again (the text which indicates what's suppose to be rendered demonstrates this).

Additional notes:
This issue only happens in the game state (others states are fine)


Code:
void redcircle_sprites(int i_x_sp,int i_y_sp, int oam_pos)
{//2x2 size
//priority = layer 0
if (!(oam_pos > 0 && oam_pos < 10))
{oam_pos = 1;}

int i_layer = 0;
int i_sprite_shape = 0,i_sprite_size = 1;
int pallete = 3;
///////////////////////////////////////
///////////ANIMATE_SPRITE/////////////
static int sprite_reference;//1;
sprite_reference += 4;
if (sprite_reference > 9) //9 is the largest sprite
{sprite_reference = 1;} //restart frame (loop)
///////////////////////////////////////

   psMy_OAM_Sprites16[oam_pos * 4 + 0] = ((i_sprite_shape<<14)|(0<<7)|(i_y_sp<<0));
    psMy_OAM_Sprites16[oam_pos * 4 + 1] = ((i_sprite_size<<14)|(0<<13)|(0<<12)|(0<<8)|(i_x_sp<<0));
    psMy_OAM_Sprites16[oam_pos * 4 + 2] = ((pallete<<12)|(i_layer<<10)|(0<<8)|(sprite_reference<<0));
    psMy_OAM_Sprites16[oam_pos * 4 + 3] = 0;

}



//this is the code I use to clear the screen every frame, which works relatively well.
Code:
void clear_sprites()
{
int ixasm = 0;
while (ixasm < 512)
{
   //do stuff here
   psMy_OAM_Sprites16[ixasm] = 0;
   ixasm++;
}      
}

#177173 - Dwedit - Wed Jan 11, 2012 2:21 am

I'm seeing tons of bugs here...
If you hit any button that isn't start immediately after booting the rom, it proceeds to write a bunch of bytes to an address starting at NULL. Then it keeps trying to do that at various points in the program.

From what I can see, it appears to be some sort of Tic-Tac-Toe game.

If you win, it jumps to address 0 and crashes.
_________________
"We are merely sprites that dance at the beck and call of our button pressing overlord."

#177177 - headspin - Thu Jan 12, 2012 10:45 am

Also (0 << 7) does nothing. You can't bit shift 0. If you need to set a bit use 1. ie. (1 << 7)
_________________
Warhawk DS | Manic Miner: The Lost Levels | The Detective Game

#177187 - blessingta@hotmail.co.uk - Sun Jan 15, 2012 12:35 am

Dwedit wrote:
I'm seeing tons of bugs here...
If you hit any button that isn't start immediately after booting the rom, it proceeds to write a bunch of bytes to an address starting at NULL. Then it keeps trying to do that at various points in the program.

From what I can see, it appears to be some sort of Tic-Tac-Toe game.

If you win, it jumps to address 0 and crashes.


Yes it is a tic tac toe "remix" to say. (it deletes the winner's pieces after they are arranged in a line (adds 100 points), then it makes the player use the alternate pieces: the process repeats for five minutes and it displays the final score)

@Writes to a bunch of bytes
It is meant to write to a bunch of bytes because when a key is pressed it is written into an unsigned char which is listen for at various points within the program. IE

If (A and B pressed) ucKeyMessage = anb_pressed
if (B pressed)...

here is an updated version with a few more bugs iron out (though issue still persists):

http://dl.dropbox.com/u/42518274/STUDENT50398201_MAKE_LINE_GAME.gba

Plus here is my project (Its written in fairly tidy way with headerfiles and cfiles being to separate individual components).

http://dl.dropbox.com/u/42518274/STUDENT50398201_MAKE_LINE_GAME.rar

#177188 - blessingta@hotmail.co.uk - Sun Jan 15, 2012 12:38 am

the graphics bugs really consumed an unhealthy amount of my time (which is the root course of not having a lot of the other stuff iron out)

#177190 - Cearn - Sun Jan 15, 2012 12:38 pm

Here's a few more random (potential) problems.

  • When compiling, there are a few undeclared/undefined variables and functions warnings. Best to get those sorted out.
  • Your graphics converter does not output 'const' arrays. THIS IS BAD! Without 'const', the data goes into IWRAM (8000h bytes) instead of ROM. IWRAM is currently filled up to ~0300:7000. If you were to add anymore graphics data, you'd probably run out completely and then you'd really be in trouble.
  • The reason the 'Makeline' text goes bad is twofold. First, it starts at tile 33, not 36. Second, there's a empty tile missing after the 'A', which misaligns the letters after it.
  • clear_sprites() doesn't actually clear the sprites; it just sets all of them to a 8x8 size sprite with an empty tile. As far as I know, this still counts towards the sprite-pixel limit that each line has. Instead, use something like this:
Code:

// OBJATTR is a struct for sprites located inside <gba_sprites.h>
// Please use it instead of just an u16 array,
// and its bit defines instead of magic numbers and shifts.
#include <gba_sprites.h>

void clear_sprites()
{
   int i;
   OBJATTR *oam= (OBJATTR*)psMy_OAM_Sprites16;
   
   for(i=0; i<128; i++)
   {
      oam[i].attr0= OBJ_DISABLE;      // This actually disables sprites.
      oam[i].attr1= 0;
      oam[i].attr2= 0;
      oam[i].dummy= 0;
   }
}

  • And here's one that might actually be related to the non-random blinking and disappearing of the dots. Inside redcircle_sprites() and bluecircle_sprites(), you're using a static variable to keep track of the animation state, which runs in a {1,5,9} loop. However, becuase it's a static variable, it's effectively shared between all sprites of that type. This means that things get tricky once you have multiple sprites, because the animation states of the different sprites will interfere with eachother. For example with 2 sprites, you'd get
  • Code:
    sprite 1: 1 9 5 1 ...
    sprite 2: 5 1 9 5 ...

    and with 3 you'd get
    Code:
    sprite 1: 1 1 1
    sprite 2: 5 5 5
    sprite 3: 9 9 9 ...

    The easiest way to fix this would be to store the animation state separately for each dot. Create a Dot struct with color and animation state and use that to define the gameboard. If you condense blue/redcircle_sprites() to a single function that just used a Dot instance to do it's work, you can condense Render_gameboard() to a <5 line for-loop using some simple table lookups for the differences between red and blue.
  • If you have a switch-block where the cases different only by a number/string, it's often simpler to use a lookup table or some arithmetic instead. Example:
  • Code:
    switch(position)
    {
    case 1:
       x= 30;
       y= 40;
       break;
    case 2:
       x= 60;
       y= 40;
       break;

    // ... 7 more cases.

    }


    // or, via lookup

    static const int coordinates[9][2]= { {30,40}, {60,40}, ...  };

    x= coordinates[position][0];
    y= coordinates[position][1];


    // or, via arithmatic (note, slow on GBA because of division)

    x= (position-1)%3 * 30 + 30;
    y= (position-1)/3 * 30 + 40;