GP2X Struct Problems


zico

Member
Joined
Jun 3, 2006
Messages
273
Hey folks.

Currently I'm sitting on a big problem.

Here is some code:

Code:
void physics_set_rotvel_and_saturate(fix *dest, fix delta)
{
	if ((delta ^ *dest) < 0) {
		if (abs(delta) < F1_0/8) {
			// mprintf((0, "D"));
			*dest = delta/4;
		} else
			// mprintf((0, "d"));
			*dest = delta;
	} else {
		// mprintf((0, "!"));
		*dest = delta;
	}
}

void physics_turn_towards_vector(vms_vector *goal_vector, object *obj, fix rate)
{
	vms_angvec	dest_angles, cur_angles;
	fix			delta_p, delta_h;
	vms_vector	*rotvel_ptr = &obj->mtype.phys_info.rotvel;

	// Make this object turn towards the goal_vector.  Changes orientation, doesn't change direction of movement.
	// If no one moves, will be facing goal_vector in 1 second.

	//	Detect null vector.
	if ((goal_vector->x == 0) && (goal_vector->y == 0) && (goal_vector->z == 0))
		return;

	//	Make morph objects turn more slowly.
	if (obj->control_type == CT_MORPH)
		rate *= 2;

	vm_extract_angles_vector(&dest_angles, goal_vector);
	vm_extract_angles_vector(&cur_angles, &obj->orient.fvec);

	delta_p = (dest_angles.p - cur_angles.p);
	delta_h = (dest_angles.h - cur_angles.h);

	if (delta_p > F1_0/2) delta_p = dest_angles.p - cur_angles.p - F1_0;
	if (delta_p < -F1_0/2) delta_p = dest_angles.p - cur_angles.p + F1_0;
	if (delta_h > F1_0/2) delta_h = dest_angles.h - cur_angles.h - F1_0;
	if (delta_h < -F1_0/2) delta_h = dest_angles.h - cur_angles.h + F1_0;

	delta_p = fixdiv(delta_p, rate);
	delta_h = fixdiv(delta_h, rate);

	if (abs(delta_p) < F1_0/16) delta_p *= 4;
	if (abs(delta_h) < F1_0/16) delta_h *= 4;

 	physics_set_rotvel_and_saturate(&rotvel_ptr->x, delta_p);
	physics_set_rotvel_and_saturate(&rotvel_ptr->y, delta_h);
	
	rotvel_ptr->z = 0;
}

Some info:
type fix is int.
vms_vector is a packed struct that has
Code:
int x,y,z;

The problem here is:
rotvel_ptr->x,y

The values of them are correct and are in my case in ranges from -5000 to +5000.
The trouble begins when they get passed to the subfunction
Code:
physics_set_rotvel_and_saturate
"rotvel_ptr->x" is okay there but when "rotvel_ptr->y" is used WITHIN the subfunction (physics_set_rotvel_and_saturate) the value looks uninitated. I get very huge values (negative and positive).
For example if I print out "dest" while rotvel_ptr->y is used it gives insane values. rotvel_ptr->x however is okay. I could solve it by passing rotvel to an integer variable and use them to pass to physics_set_rotvel_and_saturate but my source is very big and I have similar problems on other places.

So my question is how to solve this in an easy way.

Hopefully I submitted enough information and someone can help me out.

I already tried -mstructure-size-boundary but it didn't help out.
 
Sounds strange... Of course, you know that rotvel_ptr->y isn't completely insane before you pass it correct? You said you did, so i'll move on.

Actually, i give up. Have you tried:
Code:
void physics_set_rotvel_and_saturate(fix dest, fix delta)
{
	if ((delta ^ *dest) < 0) {
		if (abs(delta) < F1_0/8) {
			// mprintf((0, "D"));
			*dest = delta/4;
		} else
			// mprintf((0, "d"));
			*dest = delta;
	} else {
		// mprintf((0, "!"));
		*dest = delta;
	}
}
void physics_turn_towards_vector(vms_vector *goal_vector, object *obj, fix rate)
{
	vms_angvec	dest_angles, cur_angles;
	fix			delta_p, delta_h;
	vms_vector	*rotvel_ptr = &obj->mtype.phys_info.rotvel;

	// Make this object turn towards the goal_vector.  Changes orientation, doesn't change direction of movement.
	// If no one moves, will be facing goal_vector in 1 second.

	//	Detect null vector.
	if ((goal_vector->x == 0) && (goal_vector->y == 0) && (goal_vector->z == 0))
		return;

	//	Make morph objects turn more slowly.
	if (obj->control_type == CT_MORPH)
		rate *= 2;

	vm_extract_angles_vector(&dest_angles, goal_vector);
	vm_extract_angles_vector(&cur_angles, &obj->orient.fvec);

	delta_p = (dest_angles.p - cur_angles.p);
	delta_h = (dest_angles.h - cur_angles.h);

	if (delta_p > F1_0/2) delta_p = dest_angles.p - cur_angles.p - F1_0;
	if (delta_p < -F1_0/2) delta_p = dest_angles.p - cur_angles.p + F1_0;
	if (delta_h > F1_0/2) delta_h = dest_angles.h - cur_angles.h - F1_0;
	if (delta_h < -F1_0/2) delta_h = dest_angles.h - cur_angles.h + F1_0;

	delta_p = fixdiv(delta_p, rate);
	delta_h = fixdiv(delta_h, rate);

	if (abs(delta_p) < F1_0/16) delta_p *= 4;
	if (abs(delta_h) < F1_0/16) delta_h *= 4;

	physics_set_rotvel_and_saturate((fix)rotvel_ptr->x, delta_p);
	physics_set_rotvel_and_saturate((fix)rotvel_ptr->y, delta_h);
	
	rotvel_ptr->z = 0;
}

have you? if so, best of luck. Not to sure whats wrong here, but it seems your pointing to a local variable and i don't think you can use a pointer from another function, but that doesn't explain why X works but Y doesn't... Perhaps an expert can tell us where this code is wrong at?
 
Can you show the code where the value is initiated.

Is there any reason why you are passing everything around as pointers can you not use references, not the problem I know but would make code cleaner.
 
I guess I would start the debugging process by swapping the

physics_set_rotvel_and_saturate(&rotvel_ptr->x, delta_p);
physics_set_rotvel_and_saturate(&rotvel_ptr->y, delta_h);

lines around to see if the call with rotvel_ptr->x is clobbering the y value.

I would also print all three of the struct members (x,y,z) before and between calls just to see what was happening where.

Also make really sure your print function works the way you think, I've tried to solve more non-problems because of a bad print function than I would like to admit!

Charlie

---------------------------------------------------------

Nmn posted on Dec 17 2006 at 09:59 AM said:
Actually, i give up. Have you tried:
Code:
void physics_set_rotvel_and_saturate(fix dest, fix delta)
{
	if ((delta ^ *dest) < 0) {
		if (abs(delta) < F1_0/8) {
			// mprintf((0, "D"));
			*dest = delta/4;
		} else
			// mprintf((0, "d"));
			*dest = delta;
	} else {
		// mprintf((0, "!"));
		*dest = delta;
	}
}

void physics_turn_towards_vector(vms_vector *goal_vector, object *obj, fix rate)
{
<snip>
	physics_set_rotvel_and_saturate((fix)rotvel_ptr->x, delta_p);
	physics_set_rotvel_and_saturate((fix)rotvel_ptr->y, delta_h);

have you? if so, best of luck. Not to sure whats wrong here, but it seems your pointing to a local variable and i don't think you can use a pointer from another function, but that doesn't explain why X works but Y doesn't... Perhaps an expert can tell us where this code is wrong at?

This change will result in bad things happening. If you're lucky i'll just be a compiler error about trying to dereference something not a pointer, if not unspecified behaviour as program dereferences something not a pointer and not the right size for a pointer either (pointers are usually long integers)!

You can pass pointers to local variables because they will still be in scope, the problem you are thinking about only happens when you return a pointer to a local variable because the variable will be automatically deallocated and your pointer will be pointing to nothing useful if you're lucky and somewhere important if your not.

Charlie
 
Last edited by a moderator:
I tried to print out X and Y berfore, IN and after returning from the subfunction.
X is nice in all three times. Y is okay BEFORE it goes to the subfunction. In it it's just horrible...
As said it would be no problem to fix that here.
I can give rotvel to integer variables and pass them but the AI code I'm working on has similar symptoms:
Enemies fly to the ceiling (Y-Axis) and hang there. The AI code is very complex - i just do the re-engineering (porting) and it's VERY hard to find the correct places so I still hope there will be a unique solution.

I know the code isn't that clean (it never was) and I would love to rewrite it but on PC (x86 and x86_64) it works correctly so it's hard and I need to find the RESON why it happens before I can dig into the source an wipe it out.
 
zico posted on Dec 17 2006 at 10:39 AM said:
I know the code isn't that clean (it never was) and I would love to rewrite it but on PC (x86 and x86_64) it works correctly so it's hard and I need to find the RESON why it happens before I can dig into the source an wipe it out.

In that case I would comment most of the main function and try to do the absolute minimum to show the problem within the context of the program and return. That should help you narrow down the problem area. Sorry if I sound patronising, it's hard to tell how experienced someone is from a single post.

Charlie
 
Last edited by a moderator:
Not sure if this world help or if I am understand the code here. The "fixed" type is I assume fixed point representation? You are not keeping tract of where you fixed point is. When you add or subtract two fixed point numbers they should be the same fixed point format. When you multiply fixed point numbers together the number of places in the fractional part of the result in the sum of the number of places of both number being multiplied. Division is the difference between the (places in the numerator - the places in the denominator). This stuff was handled in elementary school when they introduced decimal point notation, but we tend to forget.

If your notation is ".8" notation the a 1 in that form 1<<8 or 256 so printing the value will look "wrong".

Of course if you are not using fixed point number then all the previous is worthless.
 
charlieb posted on Dec 17 2006 at 04:59 PM said:
zico posted on Dec 17 2006 at 10:39 AM said:
I know the code isn't that clean (it never was) and I would love to rewrite it but on PC (x86 and x86_64) it works correctly so it's hard and I need to find the RESON why it happens before I can dig into the source an wipe it out.

In that case I would comment most of the main function and try to do the absolute minimum to show the problem within the context of the program and return. That should help you narrow down the problem area. Sorry if I sound patronising, it's hard to tell how experienced someone is from a single post.

Charlie

Hehe that would be probably harder than to print out every variable that COULD be wrong (I have a 30MB sourcecode). :)
But you are right - I am not that experienced. I can only say how it is in that example... and I still know such effects happen on other places in my source as well... I suspected some memory overwrites but I was wrong, there are none.
I'm just interested WHY rotvel->y is getting malformed the moment it comes to another function. It simply makes not sense to me, but it happens...

But thanks for all the help till now
 
Last edited by a moderator:
I don't understand the fuction:
Code:
void physics_set_rotvel_and_saturate(fix dest, fix delta)
{
	if ((delta ^ *dest) < 0) {
		if (abs(delta) < F1_0/8) {
			// mprintf((0, "D"));
			*dest = delta/4;
		} else
			// mprintf((0, "d"));
			*dest = delta;
	} else {
		// mprintf((0, "!"));
		*dest = delta;
	}
}
if the "fix" data type is a pointer then why are the assignment the way they are. If you want to return the value in delta based on it's range then why do the assignment the way you are doing it. You provide no definition for "fix" so I am unsure why you deal with the "*dest" to do the assignment but check the value without the "*" for delta. The mixture is not clear. If "fix" is a pointer then the code should be:
Code:
void physics_set_rotvel_and_saturate(fix dest, fix delta)
{
	if ((*delta ^ *dest) < 0) {
		if (abs(*delta) < F1_0/8) {
			// mprintf((0, "D"));
			*dest = (*delta)/4;
		} else
			// mprintf((0, "d"));
			*dest = *delta;
	} else {
		// mprintf((0, "!"));
		*dest = *delta;
	}
}
 
Gary seems spot on with his assumption. From what I can tell, you cannot use whatever fix is as both a pointer and a regular variable.

My guess is that because the original code was x86 and modern x86's processors have a floating point co-processor (Remember when you had to buy a math coproccessor to do floating point math? Back in the 386 days :D ) you had to write (or borrow) some fixed point math routines.

I bet the original game code is fine, and its the fixed point math routines you are using that are the problem.

--Jon

Gary Miller posted on Dec 17 2006 at 01:02 PM said:
I don't understand the fuction:
Code:
void physics_set_rotvel_and_saturate(fix dest, fix delta)
{
	if ((delta ^ *dest) < 0) {
		if (abs(delta) < F1_0/8) {
			// mprintf((0, "D"));
			*dest = delta/4;
		} else
			// mprintf((0, "d"));
			*dest = delta;
	} else {
		// mprintf((0, "!"));
		*dest = delta;
	}
}
if the "fix" data type is a pointer then why are the assignment the way they are. If you want to return the value in delta based on it's range then why do the assignment the way you are doing it. You provide no definition for "fix" so I am unsure why you deal with the "*dest" to do the assignment but check the value without the "*" for delta. The mixture is not clear. If "fix" is a pointer then the code should be:
Code:
void physics_set_rotvel_and_saturate(fix dest, fix delta)
{
	if ((*delta ^ *dest) < 0) {
		if (abs(*delta) < F1_0/8) {
			// mprintf((0, "D"));
			*dest = (*delta)/4;
		} else
			// mprintf((0, "d"));
			*dest = *delta;
	} else {
		// mprintf((0, "!"));
		*dest = *delta;
	}
}
 
Last edited by a moderator:
Gary Miller posted on Dec 17 2006 at 09:02 PM said:
You provide no definition for "fix" so I am unsure why you deal with the "*dest" to do the assignment but check the value without the "*" for delta. The mixture is not clear.

The code you quoted does not align with the code originally posted. Zico's function started:
Code:
void physics_set_rotvel_and_saturate(fix *dest, fix delta)

In this case, 'dest' will be a pointer to a 'fix' type, irregardless of what 'fix' is actually defined as.
Obviously without this in the arguements it wouldn't work, as you say.
 
Last edited by a moderator:
Hm I will look at all the tips closely next days.

If it helps:
typedef int fix;

(could int probably be the problem in general because here it's not specified if signed or unsigned?)
 
zico posted on Dec 17 2006 at 03:04 PM said:
Hm I will look at all the tips closely next days.

If it helps:
typedef int fix;

(could int probably be the problem in general because here it's not specified if signed or unsigned?)

Why are you using a pointer for dest as it is? Why not pass the variable to the function and have the function return its change instead of using a global pointer.

Code:
fix physics_set_rotvel_and_saturate(fix dest,fix delta)
{
	if ((delta ^ dest) < 0) {
		if (abs(delta) < F1_0/8) {
			// mprintf((0, "D"));
			dest = delta/4;
		} else
			// mprintf((0, "d"));
			dest = delta;
	} else {
		// mprintf((0, "!"));
		dest = delta;

	}
 return dest;
}

And then you would call it something like this:

Code:
fix temp = rotvel_ptr->x;
rotvel_ptr->x = physics_set_rotvel_and_saturate(temp, delta_p);

No guarantee this will work, it just seems like a much cleaner way than using the global pointers.
 
Last edited by a moderator:
Yes this fix works for me perfectly - thank you for that :D
Now I just need to find these critical points in the rest of my source as well
 
zico posted on Dec 17 2006 at 03:58 PM said:
Yes this fix works for me perfectly - thank you for that :D
Now I just need to find these critical points in the rest of my source as well

Glad I could help.

Remember that using local variables instead of global ones is a lot safer. When in doubt pass the data your manipulating to the function instead of directly manipulating that variable.

Doing not only makes the code easier to read and debug, but it discourages accidental data corruption.
 
Last edited by a moderator:
Dr_Ian posted on Dec 17 2006 at 05:02 PM said:
Gary Miller posted on Dec 17 2006 at 09:02 PM said:
You provide no definition for "fix" so I am unsure why you deal with the "*dest" to do the assignment but check the value without the "*" for delta. The mixture is not clear.

The code you quoted does not align with the code originally posted. Zico's function started:
Code:
void physics_set_rotvel_and_saturate(fix *dest, fix delta)

In this case, 'dest' will be a pointer to a 'fix' type, irregardless of what 'fix' is actually defined as.
Obviously without this in the arguements it wouldn't work, as you say.

Your right i picked the wrong version from the replies ... sorry about that.
 
Last edited by a moderator:
Back
Top