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.

C/C++ > Getting strange error moving variable into class

#177351 - MisterLogan - Sun Apr 29, 2012 9:48 pm

I am trying to move a variable (u16 MapBuffer[32*32];) declared in main, into a class (Map). So I'm switching from MapBuffer to Map.Buffer.

When I do this seemingly simple move, my game goes absolutely nuts. Looking through registers in desmume shows the BG3HOFS register is going crazy. The only thing in my code accessing that register is this code:

Code:

bool PlayerClass::CheckPlayerCollision() {
   return(true);
}

void PlayerClass::AcceptUserInput(int BG3Main_id) {

   int gfxOffset=0;
   
   ///start of animation (loop=0)==========
   if(AnimLoop == 0) {
      //Accept key presses
      scanKeys();
      if      (keysHeld() & KEY_RIGHT)   {Input.X =   1;   InputDirection=1;}
      else if   (keysHeld() & KEY_DOWN)      {Input.Y =   1;   InputDirection=2;}
      else if   (keysHeld() & KEY_LEFT)      {Input.X =  -1;   InputDirection=3;}      
      else if   (keysHeld() & KEY_UP)      {Input.Y =  -1;   InputDirection=4;}
      
      gfxOffset = ((InputDirection*2)-1) * 256*2;
      memcpy(pSpriteBase, GhostlyTiles_bin + gfxOffset, 256*2);
   }
   
   ///mid animation (loop=8)===============   
   if(AnimLoop == 8){
      gfxOffset = ((InputDirection-1)*2) * 256*2;
      memcpy(pSpriteBase, GhostlyTiles_bin + gfxOffset, 256*2);
   }
   
   AnimLoop+=1;

   if(CheckPlayerCollision() == true) {
      c_BGPixels.X += Input.X;
      c_BGPixels.Y += Input.Y;
   }
   else {
      AnimLoop+=1;
   }

   bgScroll(BG3Main_id, Input.X, Input.Y);
   
   ///end of animation loop (loop=16)=======
   if(AnimLoop == 16) {   
      AnimLoop=0;
      Input.X=0;
      Input.Y=0;
      InputDirection=0;
   }
}


This function is called from main using this:

Code:

scanKeys();
   if(keysHeld()   &
      (KEY_RIGHT   |
      KEY_DOWN   |
      KEY_LEFT           |
      KEY_UP)      || Player.AnimLoop !=0) {Player.AcceptUserInput(BG3Main_id); iprintf("direction pressed\n");}


When I comment this function call out, the error stops.

MapBuffer/Map.Buffer are being accessed by two functions, but commenting them both out doesn't stop the error.

So yeah, what the heck is going on here?

#177352 - Dwedit - Sun Apr 29, 2012 10:14 pm

Not enough information here, but I'm guessing memory corruption.
_________________
"We are merely sprites that dance at the beck and call of our button pressing overlord."

#177353 - MisterLogan - Sun Apr 29, 2012 10:33 pm

I don't really know what other useful info I can provide besides the entirety of the code. It's not that large I guess.

Code:

#include <nds.h>
#include <stdio.h>
#include <_ansi.h>

#include "Player.h"
#include "NPC.h"
#include "Layer1.h"

#include "GhostlyPal_bin.h"
#include "GhostlyTiles_bin.h"

#define Pal_Size 256
#define Map_Size_32x32 2048
#define SPRITE_TOP_PRIO      1
#define SPRITE_BOTTOM_PRIO   2

///Type Creations----------------------------------------------------------
   class Map{
     private:
    
     public:
      u16 Buffer[32*32];
   }Map;

///========================================================================


///Function Prototypes-----------------------------------------------------

///========================================================================

//void MapWrap(){
//
//}

void initBG(const u16 *pal, const u16 *tiles, const u16 *map, int tilesize, u16 *MapBuffer1, u16 *MapBuffer2) {

   int i, j;
   
   ///Palette init
   memcpy(BG_PALETTE, pal, Pal_Size);
   
   ///Tile init
    memcpy(BG_TILE_RAM(1), tiles, tilesize);
   
   ///Map init
   for(i=0;i<32;i++){
      for(j=0;j<32;j++){
         MapBuffer1[(i*32)+j] = map[(i*256)+j];
      }
   }
   for(i=0;i<32;i++){
      for(j=0;j<32;j++){
         MapBuffer2[(i*32)+j] = map[(i*256)+j+32];
      }
   }
}

void oamSetBeing(int index, u16* pGFX, int X, int Y, bool Hide)
{
   oamSet(&oamMain,
         index,
         X, Y, //x and y
         SPRITE_TOP_PRIO, //priority
         0, //palette index for multiple palettes
         SpriteSize_16x16,
         SpriteColorFormat_256Color,
         pGFX, //pointer to loaded graphics
         0,  //rot/scale matrix index
         false, //double size when rot/scale?
         Hide, //hide sprite?
         false, false, //vflip, hflip?
         false  //mosiac?
         );
         
   oamSet(&oamMain,
         index+1, //+1 for bottom half offset
         X, Y+16, //x and y; +16 for bottom half offset
         SPRITE_BOTTOM_PRIO, //priority
         0, //palette index for multiple palettes
         SpriteSize_16x16,
         SpriteColorFormat_256Color,
         pGFX+128, //pointer to loaded graphics; +128 for bottom sprite offset
         0,  //rot/scale matrix index
         false, //double size when rot/scale?
         Hide, //hide sprite?
         false, false, //vflip, hflip?
         false  //mosiac?
         );
}

//------------------------------------------------------
int main() {
//------------------------------------------------------

   consoleDemoInit();

   ///Variables===============================///

   int BG3Main_id=0;

   u16 MapBuffer1[32*32], MapBuffer2[32*32];


   PlayerClass Player;
   Player.pSpriteBase = oamAllocateGfx(&oamMain, SpriteSize_16x32, SpriteColorFormat_256Color);
//   NPCClass *NPCPool[32], *CurrentNPC;
   

   ///========================================///

   videoSetMode(MODE_0_2D);
   BG3Main_id = bgInit(3, //layer (doesn't work)
             BgType_Text8bpp,
             BgSize_T_512x256,
             0, //Map base
             1 //Tile base
             );
   bgSetPriority(BG3Main_id, 3);
   
   initBG(Layer_1Pal, Layer_1Tiles, Layer_1Map, sizeof(Layer_1Tiles), MapBuffer1, MapBuffer2);

   vramSetBankB(VRAM_B_MAIN_SPRITE); //64kb bank
   
   oamInit(&oamMain, SpriteMapping_1D_32, false);// last argument for extended palette
   
   memcpy(SPRITE_PALETTE, GhostlyPal_bin, GhostlyPal_bin_size);
   memcpy(Player.pSpriteBase, GhostlyTiles_bin, 256*2);
   
   oamSetBeing(0, //index
            Player.pSpriteBase, //pointer to where graphics should be loaded
            15*8, 10*8, //x and y in tiles * tile to pixel conversion
            false); //hide sprite?
   
   
   ///MAIN LOOP==============================================================================
   while(1) {

   swiWaitForVBlank();
   memcpy(BG_MAP_RAM(0), MapBuffer1, Map_Size_32x32);
   memcpy(BG_MAP_RAM(1), MapBuffer2, Map_Size_32x32);
   bgUpdate();
   oamUpdate(&oamMain);
   
   scanKeys();
   if(keysHeld()   &
      (KEY_RIGHT   |
      KEY_DOWN   |
      KEY_LEFT   |
      KEY_UP)      || Player.AnimLoop !=0) {Player.AcceptUserInput(BG3Main_id); iprintf("direction pressed\n");} //accepts udlr keypresses, moves the background
                                                            //and animates the main player sprite
   
   
   }///======================================================================================

    return 0;
}


That's main, minus some planning comments up top.

Playerclass.h is this:

Code:

#include <nds.h>
#include "Structs.h"

#ifndef PLAYER_H
#define PLAYER_H

   class PlayerClass {
     private:
     public:
      XY c_BGPixels, c_BGTiles, Input; //counters for tracking, Input is for accepting user input
      u16* pSpriteBase;
      int InputDirection;//Right, Down, Left, Up; make this 1,2,3, or 4 depending on which direction player is moving
      int AnimLoop;
      
      void AcceptUserInput (int);
      bool CheckPlayerCollision();
   };

#endif


Structs.h just has xy, which contains (shockingly) int x and y.

That's everything save some yet unused files (NPC.h) and graphical data.

#177354 - Cearn - Mon Apr 30, 2012 8:55 am

I see two suspicious things here in PlayerClass::AcceptUserInput:

Code:
      if      (keysHeld() & KEY_RIGHT)   {Input.X =   1;   InputDirection=1;}
      else if   (keysHeld() & KEY_DOWN)  {Input.Y =   1;   InputDirection=2;}
      else if   (keysHeld() & KEY_LEFT)  {Input.X =  -1;   InputDirection=3;}     
      else if   (keysHeld() & KEY_UP)   {Input.Y =  -1;   InputDirection=4;}

You only set one coordinate here without clearing the other. Say you go right, then Input.X==1. then you press up, then Input.Y becomes -1, but Input.X is still 1, so you'd move diagonally. I know you reset the Input coordinates later, but it's still worth looking into.

Secondly,
Code:
   bgScroll(BG3Main_id, Input.X, Input.Y);

Don't you mean c_BGPixels.X and .Y here?

If that's not it, define "nuts".