FFoulkes wrote: ↑Mon Feb 11, 2019 1:16 am
Well, I'm running into a problem now. I'd like to print a UDG at a certain place on the screen.
I think there's a bit of a context shift required for people coming to C on the Spectrum. UDGs are largely a concept from BASIC which don't make a lot of sense in the C world. C is much closer to assembly language, so you need to think at a lower level. OTOH, the stdio stuff is a high level concept from UNIX, and although it's a useful starting point I personally have never been convinced of its value on the Spectrum. Once you get past "hello world," unless you're doing something which requires a lot of text manipulation, you'll probably just turn it off. Mixing these disparate concepts together is, as you've found, a bit of a headache. It's possible to make it work, as per Alvin's post which you found in the z88dk forum, but it doesn't really happen naturally.
So, at the risk of telling you you're asking the wrong question then answering my own, let's take a step back.
As soon as you start thinking about UDGs, you're thinking about graphics, and graphics, once you step outside the world of BASIC, means you need to start thinking about how to directly change the Spectrum's display. The display is memory mapped, so you change it by POKEing (to use the BASIC terminology) values into it. If you want an 8x8 pixel graphic to appear in the middle of the display you can do it like this:
Code: Select all
#include <arch/zx.h>
unsigned char hash_udg[] = { 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA };
void printc(unsigned char x, unsigned char y, unsigned char* udg)
{
unsigned char *p;
unsigned char i;
p = zx_cxy2saddr(x, y);
for (i = 0; i < 8; ++i)
{
*p = *udg++;
p += 256;
}
}
int main( void )
{
printc(15, 12, hash_udg);
return 0;
}
which you can compile with:
Code: Select all
zcc +zx -vn -clib=sdcc_iy -startup=31 printc.c -o printc -create-app
The zx_cxy2saddr() function is described along with all its friends
here, but in essence it takes an x,y character coordinates pair and returns you the address in the Spectrum's display of the top byte of that character cell. Adding 256 to it returns the address of the byte directly below it, hence the loop POKEs the 8 UDG byte values directly into the display at the place required.
That's the simple and fast way. At the other extreme you can use the SP1 library. You're not at that level yet, and I haven't written the tutorial article which tells you how to do it, but as a peek ahead you can see the control characters of the SP1 library's very sophisticated print facility
here. SP1 isn't to everyone's taste, nor the answer to all problems, but if you're after a powerful library to experiment with for graphics it's worth looking into when you're ready.
Quite where this all leaves you I'm not sure.
I suppose it depends on what you're trying to learn or what problem you're trying to solve.