Alien Experiment Laboratories

December 3, 2006

Finally some example code!

It took long enough (these things happened so much quicker before I got a life ;-) ) but here, at last, is some code making use of the most current version of z88dk and version 3 of Sprite Pack.

It’s mostly self-documenting, but there are a few places where it begs explanation, particularly when setting up sprites, so I’ve expanded heavily on the comments in the code.

Well, whaddya waiting for? Go download the source code and have a look (But don’t blame me if it makes your eyes go all funny).

November 27, 2006

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.