Previous: Oh no, not another Learning Experience!

Next: Finally some example code!

Z88dk and C gotchas - episode 1

Still working on experimental stuff (partly to get the hang of Z88dk, and partly to scrape the rust off my underutilized C-coding “skillz” before doing anything important), I got stung by a nasty little gotcha.

I created a source file, 2player.c, which is expanding on the first bit of z88dk/Spritepack 3 code I wrote, to have two graphics on screen, both player controllable.

Every build attempt met with this error:

zcc +zx -vn 2player.c -o 2player.bin -create-app -lsp1 -lballoc
1 errors occurred during assembly
Errors in source file 2player.c:
File '/tmp/tmpXXTIgPHd.opt', at line 10, Illegal identifier
make: *** [2player] Error 1

Ouch. Where’s the error? Line 10 is in the middle of my descriptive comment section! This is meaningless!! Eventually I stripped out just about everything to the point where it couldn’t possibly NOT compile and…still the same error! WTF?

Then it occurred to me: somewhere in the build process, perhaps the filename is being used as an identifier. And perhaps identifiers starting with a number are illegal. A quick rollback to the proper code I’d written first time around (Vim 7 undo rocks!), rename to twoplayer.c and the bugger builds first time.

Attempting to run the thing resulted in a spectacular crash, but at least it built! Now for some trial and error debugging (my kingdom for a z88dk equivalent to gdb). I look at the pointer stuff first and find that it doesn’t like the following code:

for (p = 0; p != 2; p++) {
    player[p]->sprite = sp1_CreateSpr(sp1_SprId2Type(SP1_ID_MASK2_LB) | SP1_TYPE_2BYTE, 3, 0, 0);
    sp1_AddColSpr(player[p]->sprite, sp1_SprId2Type(SP1_ID_MASK2), 48, 0);
    sp1_AddColSpr(player[p]->sprite, sp1_SprId2Type(SP1_ID_MASK2_RB), 0, 0);
    sp1_MoveSprAbs(player[p]->sprite, &drawarea, man + 16, 10, 14, 0, 4);
    player[p]->frameoffset = (uchar *) 0;   /* no frame offset */
    /* make sure player[p] isn't in motion */
    player[p]->dx = player[p]->dy = 0;
}

Changing it to this code (with the appropriate pointer-to-player-struct declared at the top of main()) gets over that speed bump, by pointing a pointer at the array element and then using the pointer instead of the subscripted reference. It’s not clear why the first fails and the second appears to work. I probably need to go read K&R again…

for (p = 0; p != 2; p++) {
    pl = &player[p];
    pl->sprite = sp1_CreateSpr(sp1_SprId2Type(SP1_ID_MASK2_LB) | SP1_TYPE_2BYTE, 3, 0, p);
    sp1_AddColSpr(pl->sprite, sp1_SprId2Type(SP1_ID_MASK2), 48, p);
    sp1_AddColSpr(pl->sprite, sp1_SprId2Type(SP1_ID_MASK2_RB), 0, p);
    sp1_MoveSprAbs(pl->sprite, &drawarea, man + 16, 10, 14, 0, 4);
    pl->frameoffset = (uchar *) 0;  /* no frame offset */
    /* make sure pl isn't in motion */
    pl->dx = pl->dy = 0;
}

Referencing the players array via a temporary pointer like this, the program builds and runs exactly as designed.

Comments

Posted by Stefano at 8:56 am on March 9, 2008.

Z88DK still has many limits, but is a good compromise in, my opinion.
The first issue you met is just because you begun your file name with a number, and it is not allowed.

Leave a comment

Spam is filtered, and in the unlikely event it survives will be removed. Comments with hyperlinks will be held for moderation. Spammers really stink, don't they?

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>