Address Error when running a rom on hardware

SGDK only sub forum

Moderator: Stef

Post Reply
BroOfTheSun
Interested
Posts: 33
Joined: Fri Dec 12, 2014 2:41 am
Location: USA - Chicago, IL

Address Error when running a rom on hardware

Post by BroOfTheSun » Wed Mar 25, 2015 12:54 pm

Hi, I've run into an issue with a game I'm developing. I use Kega Fusion as an emulator to test out my rom, and I'm able to load and play through the rom on Kega Fusion. When I try running the rom on hardware (using a Sega Nomad), it immediately gives me an address error. I've tried fixing the checksum, and that did not resolve the issue. I'm unsure as to what could be causing the error. Does anyone have some ideas as to what could cause this issue, or tips on how I can figure this out?

Stef
Very interested
Posts: 3131
Joined: Thu Nov 30, 2006 9:46 pm
Location: France - Sevres
Contact:

Post by Stef » Wed Mar 25, 2015 1:13 pm

You probably have some piece of code in assembly ? That type of error happen when you access word data at odd address.

BroOfTheSun
Interested
Posts: 33
Joined: Fri Dec 12, 2014 2:41 am
Location: USA - Chicago, IL

Post by BroOfTheSun » Wed Mar 25, 2015 1:20 pm

All my code is in C. I do allocate memory for certain objects. I allocate memory for an object struct, sprites, and background images. Could the error be caused from allocating memory? I'm able to run the rom on an emulator, and it looks like the sprites and images are loaded correctly. So I didn't think memory allocation was the issue.

Stef
Very interested
Posts: 3131
Joined: Thu Nov 30, 2006 9:46 pm
Location: France - Sevres
Contact:

Post by Stef » Wed Mar 25, 2015 2:25 pm

I remember some people experiencing the address error while using the Sprite Engine in inadequate ways, it may be related. Are you doing something fancy with sprites ? :p
Maybe posting a bit of your code can help to investigate also..

BroOfTheSun
Interested
Posts: 33
Joined: Fri Dec 12, 2014 2:41 am
Location: USA - Chicago, IL

Post by BroOfTheSun » Wed Mar 25, 2015 5:38 pm

It's very likely that I'm not using Sprites correctly. Here is a general idea of how I'm updating sprites:

Code: Select all

typedef struct Object
{
     Sprite* sprite;  // Points to the sprite used in the Sprite List passed to SPR_update()
     
     fix32 posX;
     fix32 posY;
     
     void (*updateFunction)(struct Object* obj); // USe SPR_updatePosition here to update the sprite position
     ...
} Object;

Object* CreateObject(Object* obj, Sprite* sprite, fix32 x, fix32 y)
{
     if( (obj = MEM_alloc(sizeof(Object))) != NULL)
     {
          obj->sprite = MEM_alloc(sizeof(Sprite));
          obj->sprite = sprite;

          obj->posX = x;
          obj->posY = y;

          obj->updateFunction = myUpdateFunction;

          SPR_initSprite(sprite, &mySpriteDef, fix32ToInt(x), fix32ToInt(y), TILE_ATTR(PAL0, TRUE, FALSE, FALSE));
     }

     return obj;
}

void CreateSpriteList(void)
{
     sprList = MEM_alloc(sizeof(Sprite) * NUMOFSPRITES);  // sprList is an array of sprites that I pass to SPR_update. Declared in main, and set as extern in a global.h file. So any source file that includes the global.h file can see the sprite array.

     u16 i;
     for( i = 0; i < NUMOFSPRITES; i++)
     {
          Sprite sprite;
          sprList[i] = sprite;
     }
}

void CreateObjectList(void)
{
     u16 i;
     for(i = 0; i < NUMOFSPRITES; i++)
     {
          Object* obj;
          objList[i] = (Object*) MEM_alloc(sizeof(Object));  // objList is an array of Objects, and is declared in main. It holds objects that are displayed on screen. It is also set as extern in the global.h file.
          objList[i] = obj;
     }
}

void main(void)
{
     Object* objList[NUMOFSPRITES];
     Sprite* sprList;

     Object* objTest;

     CreateSpriteList();
     CreateObjectList();

     objTest = CreateObject(objTest, &sprList[0], FIX32(0), FIX32(0));
     
     objList[0] = objTest;

     while(1)
     {
          ...
          UpdateObjects(); // Loops through the objList, use the updateFunction for each object to update their positions, velocities, etc. Also updates visibility depending on if object goes on/off screen.
          SPR_update(sprList, NUMOFSPRITES);
          ...
     }
}

Arrovs
Interested
Posts: 18
Joined: Wed Sep 11, 2013 3:44 pm

Post by Arrovs » Wed Mar 25, 2015 11:25 pm

Code: Select all

#define new(struktura) MEM_alloc(sizeof(struktura))
#define newm(struktura,daudzums) MEM_alloc(daudzums*sizeof(struktura))
I like to close creation more or less to C# style so i use macro

Code: Select all

Object* CreateObject(Sprite* sprite, fix32 x, fix32 y)
{
    Object* obj = new(Object);
     if(obj != NULL)
     {
          obj->sprite = sprite;

          obj->posX = x;
          obj->posY = y;

          obj->updateFunction = myUpdateFunction;

          SPR_initSprite(sprite, &mySpriteDef, fix32ToInt(x), fix32ToInt(y), TILE_ATTR(PAL0, TRUE, FALSE, FALSE));
     }

     return obj;
}
You dont need to point obj twice - just to look better. Also obj->sprite = MEM_alloc(sizeof(Sprite)); is lost in memory so remove it.

Code: Select all

void CreateSpriteList(void)
{
     sprList = newm(Sprite, NUMOFSPRITES);
}
You dont need to use

Code: Select all

u16 i;
     for( i = 0; i < NUMOFSPRITES; i++)
     {
          Sprite sprite;
          sprList[i] = sprite;
     }
you already made unintialized struct array. This loop just copies other unintialized variable in place of other ones.

Code: Select all

void CreateObjectList()
{
     u16 i;
     for(i = 0; i < NUMOFSPRITES; i++)
     {
          objList[i] = (Object*) new(Object);
     }
} 
you dont need Object* obj; and objList = obj;. In this way you again are flooding memory by changing allocated memory with undefined pointer;

But overall i dont see why it should make invalid adress error.

Stef
Very interested
Posts: 3131
Joined: Thu Nov 30, 2006 9:46 pm
Location: France - Sevres
Contact:

Post by Stef » Thu Mar 26, 2015 10:05 am

As Arrovs pointed out, you are copying initialized data in your allocated memory, even worst when you do that :

Code: Select all

objList[i] = (Object*) MEM_alloc(sizeof(Object)); 
objList[i] = obj;
You actually allocate the object then lost the allocated pointer and replace it with local memory allocated on stack... That will totally screw up your stack at some point and may lead to the address error problem (when returning from function) ! So you definitely need to remove

Code: Select all

objList[i] = obj;
Also I think your code is a bit over complicated, you are duplicating the position information in your Object structure. By the way if you want to add a specific field to the Sprite struc, you have the free "data" field for that. It's a 32 bits integer field but you can use it for whatever you want (and for instance a function pointer as you have in your object structure) :) So you don't need to create a new struc to embed the Sprite struc here.

Arrovs
Interested
Posts: 18
Joined: Wed Sep 11, 2013 3:44 pm

Post by Arrovs » Thu Mar 26, 2015 10:58 am

Its not so bad to wrap into Object im doing same with almost everything what needs advanced behaviour. One free field is too less for such case. You could remove it at all in most cases for more memory. Only thing what it could be good is for storing flags.
And you are true, using pointers who lead to nowhere can easely raise address errors(objList = obj;) .

BroOfTheSun
Interested
Posts: 33
Joined: Fri Dec 12, 2014 2:41 am
Location: USA - Chicago, IL

Post by BroOfTheSun » Thu Mar 26, 2015 1:07 pm

Thank you for the help. I obviously do not have a good understanding of how memory allocation works. I will go back and fix my code.

In terms of using an Object wrapper around the Sprite. I'm using the Object position X and Y to track where the object is in an area, and the Sprite positions to track the object's position on screen.

Stef
Very interested
Posts: 3131
Joined: Thu Nov 30, 2006 9:46 pm
Location: France - Sevres
Contact:

Post by Stef » Thu Mar 26, 2015 1:10 pm

Arrovs wrote:Its not so bad to wrap into Object im doing same with almost everything what needs advanced behaviour. One free field is too less for such case. You could remove it at all in most cases for more memory. Only thing what it could be good is for storing flags.
And you are true, using pointers who lead to nowhere can easely raise address errors(objList = obj;) .


You can wrap into an object but the single data field is actually enough to point on another structure if you need it (as an Object structure), It's why i dedicated only a single field for that. But you can embed in an Object, why not... at least if you need only a single extra information or just for flags data is here ;)

BroOfTheSun
Interested
Posts: 33
Joined: Fri Dec 12, 2014 2:41 am
Location: USA - Chicago, IL

Post by BroOfTheSun » Sun Mar 29, 2015 5:59 pm

I was able to resolve the issue. It is unrelated to the area of code I posted above. The issue in my code was with how I was loading the background image for a level. Here is the code:

Code: Select all

Image *bgImage = unpackImage(&ImageFile, bgImage);
	
VDP_drawImageEx(APLAN, &ImageFile, TILE_ATTR_FULL(PAL1, FALSE, FALSE, FALSE, ind), 0, 0,FALSE, TRUE);
I think unpacking the image, and also using VDP_drawImageEx was causing the issue. I removed the code to unpack the image, and this resolved the memory issue.

Thank you all for the help and input. I also went back and made updates to allocating memory for my objects.

Stef - I didn't think of using that free data field as a pointer to a struct. I need the Object wrapper to hold flags for my objects, but having all that information on the Sprite struct is what I originally wanted to do. So that free data field will help me do this. Thanks again for the help.

Post Reply