GP2X Rrootage Port Hang


GameGod

Still Fresh
Joined
Nov 26, 2006
Messages
89
Hi all,

I've been slowly (sllooooowly) working away on my rRootage port for the past few months. I've been stuck for quite some time on these random crashes that keep occurring. Long story short, I've done a ton of commenting out code to try to narrow it down so I could find a single line of code that I could blame for the crashes.

Take a look at this:

CODE
void drawBulletsWake() {
int i;
Foe *fe;
float x, y, sx, sy;
for ( i=0; i<FOE_MAX; i++ ) {
if ( foe.spc == NOT_EXIST || foe.spc == BATTERY || foe.cnt >= 64 ) continue;
fe = &(foe);
x = (float)fe->pos.x / FIELD_SCREEN_RATIO;
y = -(float)fe->pos.y / FIELD_SCREEN_RATIO;
sx = (float)fe->spos.x / FIELD_SCREEN_RATIO;
sy = -(float)fe->spos.y / FIELD_SCREEN_RATIO;
drawLine(x, y, 0, sx, sy, 0, 150, 180, 90, (63-fe->cnt)*3);
}
}

}


The crashes that occur at rRootage's title screen come from this function. I've been trying to blame it on gpu940 for quite some time, and when I spotted that call to drawLine() there, I thought I had found it.

Guess what? Commenting out the drawLine() call didn't stop the crashes at all. BUT, that continue statement irked me a little bit. You don't really see continue statements very often, so I decided to rework the logic so it works without the continue statement:

CODE
void drawBulletsWake() {
int i;
Foe *fe;
float x, y, sx, sy;
for ( i=0; i<FOE_MAX; i++ ) {
//if ( foe.spc == NOT_EXIST || foe.spc == BATTERY || foe.cnt >= 64 ) continue;
//Changed the above line to the logic below, because it causes hangs -- Albert
//(I know it sounds like gibberish, but it's true...)
if ( foe.spc != NOT_EXIST && foe.spc != BATTERY && foe.cnt < 64 )
{
fe = &(foe);
x = (float)fe->pos.x / FIELD_SCREEN_RATIO;
y = -(float)fe->pos.y / FIELD_SCREEN_RATIO;
sx = (float)fe->spos.x / FIELD_SCREEN_RATIO;
sy = -(float)fe->spos.y / FIELD_SCREEN_RATIO;
drawLine(x, y, 0, sx, sy, 0, 150, 180, 90, (63-fe->cnt)*3);
}
}
}



... and son of a vondruke, the title screen doesn't crash any more. Why the heck would commenting out that continue statement stop crashes from happening? (Could it be something like a compiler bug?)

Any C/ARM guru in here care give me their take?

Thanks guys,
Albert
 
First, is it C or C++ ?

Then, there is an unmatched parenth at the end of the for block. Obviously you edited the block to remove something you believed was irrelevant, but due to the very nature of this bug I would really like to see the whole function, however big.

Also, how is drawBulletsWake() called ? As this is perhaps a stack related issue, you should prototype it with void and no merely empty parenths. People often believe that it's equivalent but it's not (at least in C, I am not sure about C++) : "int foobar(void);" means that foobar takes no argument, while "int foobar();" means that the compiler must not check the parameter list, which leads to different stack cleaning code.

Finally, I still think that gpu940 can be responsible for the bug (since it may be stack related).

Apart from that, can we have the generated code for both versions ?
(all gp2x devkits come with an objdump binary : objdump -S youfile.o > youfile.asm and look for drawBulletWake)
 
aarrghh.. this is one of those situations where parantheses are your friends, and you should bloody well use them ..

CODE

// bloody awful operator precedence, which gives the compiler *no* clues what you really want:
//if ( foe.spc == NOT_EXIST || foe.spc == BATTERY || foe.cnt >= 64 ) continue;
// the fix:
if ( (foe.spc == NOT_EXIST) || (foe.spc == BATTERY) || (foe.cnt >= 64) ) continue;



... the thing is, depending on the cleverness of your compiler and how the NOT_EXIST and BATTERY macro's (if they are macros) are defined you may in fact be ending up trying to "||" NOT_EXIST with the value of foe[i.].spc, and then check if that value is equal to BATTERY "||"'ed with foe.cnt, and then check if the rest is >= 64 ..

In short: Use ()'s to make the compiler truly understand what you are doing and it probably won't try to optimize away code idiocy into a segfault or two or ten ..
 
torpor said:
aarrghh.. this is one of those situations where parantheses are your friends, and you should bloody well use them ..

CODE

// bloody awful operator precedence, which gives the compiler *no* clues what you really want:
//if ( foe.spc == NOT_EXIST || foe.spc == BATTERY || foe.cnt >= 64 ) continue;
// the fix:
if ( (foe.spc == NOT_EXIST) || (foe.spc == BATTERY) || (foe.cnt >= 64) ) continue;

... the thing is, depending on the cleverness of your compiler and how the NOT_EXIST and BATTERY macro's (if they are macros) are defined you may in fact be ending up trying to "||" NOT_EXIST with the value of foe[i.].spc, and then check if that value is equal to BATTERY "||"'ed with foe.cnt, and then check if the rest is >= 64 ..



If NOT_EXIST and BATTERY were defined to be macro (as the uppercases suggest), it would still need very malicious definitions to make this test fail, given the language is C or alike, were "==" and ">=" operators precedes the logical operator "||". Considering this is not obfuscated C contest but rRootage, I think it's highly improbable.

Or I missed your point completely.
 
Last edited by a moderator:
Operator priority certainly has nothing to do with this, looks more like memory corruption (something is writing beyond buffer limits) what causes random code to crash. I would try to run this under valgrind (this would require to port your code to normal Linux though).
 
Thanks guys, I really appreciate your advice. I'm going to try to make time for this soon-ish and I'll take another crack at it!

Thanks again!
 
torpor said:
In short: Use ()'s to make the compiler truly understand what you are doing..

You are correct - people shouldn't avoid using brackets, adding them makes the code more readable and... funnily enough.. a guy working for me had exactly this problem using a PIC32 compiler last week (C source); he'd (as he always has much to my frustration) written code with the minimum of brackets - sure enough adding them sorted out his problem (despite the operator precedence implying it should have been okay). A lesson here for us all methinks; it doesn't hurt to make sure :)
 
Last edited by a moderator:
Update:

I think I might be running out of memory, which is causing the freezes.

These captures were taken when rRootage was sitting there frozen:
CODE
[root@gp2x rRootage]$./vmstat
procs memory swap io system cpu
r b w swpd free buff cache si so bi bo in cs us sy id
1 0 0 0 660 1284 16672 0 0 6 11 414 208 8 15 77


Here's an even easier to read one:
CODE
[root@gp2x rRootage]$free
total used free shared buffers
Mem: 30884 30252 632 0 1284
Swap: 0 0 0
Total: 30884 30252 632


If rRootage is run out of RAM on the stack, is there a chance it could overwrite something in the upper 32M (ie. the part that belongs to gpu940)? This "freezing" thing is exactly the same as what happens when the second CPU crashes, so I'm wondering if something in the upper 32M is getting overwritten and causing the crash...

Ideas? Thanks!
 
tetsuomaki said:
Is there any chance you could upload the code that you have got running so far?
I'm sure there's a lot of people who would like to look at it :)
Yes it would probably be pretty easy to load some items into upper memory using custom malloc/free.
 
Last edited by a moderator:
I haven't been back to these forums in ages, so you're lucky I stumbled across this thread again. :)

Senor Quack: The upper memory is used by gpu940, so as far as I know we can't use it.

tetsuomaki: I've been meaning to get around to posting the source I have so far online, because I've been super busy with other projects (namely Mixxx).

I've uploaded the source/binary here:
http://www.2shared.com/file/2629608/67b025...ge_gp2xtar.html

If you go into the "src" directory, you can compile it for gp2x by just running "make". If you run "make -f Makefile.x86", you can compile it for x86. The precompiled gpu940 libs are already kicking around in those directories. You will probably have to modify the "Makefile" in order to set your CC and CXX paths for your cross compile environment.

Once you have it compiled, copy the "rr" binary and the "rr_share" directory somewhere on your SD card or whatever. I usually smbmount from my gp2x to my PC and telnet into the thing. Makes development a lot easier.

Off the top of my head, stuff that's working:
- Joystick and buttons are mapped properly
- Sound works
- Segfault on exit, but it exits :)
- Graphics aren't perfect, but with some tweaking they can be made good
- Tons of room for performance optimization, although disabling sound makes no performance difference, which tells you that the 940/graphics is where the bottleneck is. If you're going to optimize, optimize the graphics/rendering.

I don't remember exactly what state the code is in, I'm sure there's some stuff commented out. I had it to the point where it was playable (a bit sluggish) except for the random crashes. I don't know if this will be useful to anyone or not, but the last entry in my development log reads:

August 11th, 2007
• Got gpu940 rRootage port running on x86 again.
• Have to run the "gpu940" binary before running ./rr
• Used valgrind to try to find memory overflow, no luck...
• Keyboard input isn't working for some reason, so I just changed rr.c:267 to go straight into playing the game instead of going to the title screen.

My suspicion is that there's something wrong in gpu940 that causes the random crashes. I wasn't having any random crash issues until Cedric added support for alpha blending (at my request) to gpu940. I could be totally wrong though, maybe the flaw causing the crashes now was just better hidden before that. (Still could be running out of memory, I think.)

Anyways, that was quite a bit of info. If anyone makes any progress or finds any ideas, fire me an email at "gamegod at sympatico dot ca". I've really got my hands full with Mixxx, but I'll do whatever I can to help.

Thanks,
Albert aka GameGod
 
Oh, wow, thanks this is great that the binary and source are now released. I'm sure someone will pick this right up (probably not me, though.. don't have any experience in these areas).

One idea I had is to reduce memory usage by using uClibc (assuming rootage in its current form on the GP2X links to libc). That might gain ya a meg or so, I'd imagine.
 
Yeah, that might be worth a shot, thanks Senor Quack. Another idea along those lines is to get dynamic linking working (I don't think I used it).
 
Last I heard the author is splitting time between this and a complex UNIX audio application, probably why it's taking some time. Also, there aren't too many examples of usage of gpu940 on the GP2X, so relatively little code to base your own work off of and probably more than a sprinkle of remaining bugs in gpu940, I'd guess. Apparently Rrootage also makes no use of dynamic memory and instead loads absolutely everything onto the stack and that might be the source of some problems.
 
I'd really like to see this get finished. It sounds like its running but theres just some problems. Any chance rixed (author of gpu 940) can help? I noticed GameGod hasn't been active since December so a little worried this might not get released. I understand these things take time so sorry for being impatient.
 
Back
Top