XeO3-CPC

Tuesday, November 07, 2006

Pages and pages of flipping pixels

Ok, time for a brief aside from scrolling and a quick look at the CPC's pixel format and a nifty Z80 technique.

In Mode 0 we have 2 pixels encoded within each byte of display memory, but not in the worlds most straightforward format (as demonstrated by the diagram showing the bit mappings.)

Now what happens if we want to flip the left and right pixels over? No simple combination of rotates is going to manage it, so instead we'd have to resort to some basic arithmetic. And so, our naive Z80 routine looks something like this:

LD C, %01010101  ; [2]  This is our pixel mask

LD A, (HL) ; [2] Fetch the byte to flip
AND C ; [1] Strip out the right pixel
RLCA ; [1] Shift it left
LD B,A ; [1]
LD A,C ; [1]
RLCA ; [1] Shift the mask
AND (HL) ; [2] Strip out the left pixel
RRCA ; [1]
OR B ; [1] Recombine the pixels


So that's a massive 11 NOPS per pixel pair (ignoring the setup cost). It's glacially slow. Damn. Clearly we can't afford to spend anything like that long, but pre-shifting all our graphics will surely be prohibitively expensive? Time for a rethink. Given that there are 256 possible combinations of pixels, all we need is a 256 byte table that maps any given byte on to it's flipped alternative. The Z80s 16-bit register pairs make this very efficient, as long as we page align the data. A page is a block of 256 bytes which share a common high byte (eg 0xFEnn), allowing us to perform an index lookup by direct manipulation of the least significant register.

So our improved code looks more like:
LD D,page        ; [2]  Initialise the lookup table pointer

LD E,(HL) ; [2] Fetch byte
LD A,(DE) ; [2] Flip the pixels


That's a mere 4 NOPs per pixel pair ignoring setup costs. A significant enough saving that we can easily justify the extra memory it requires. And it has the added advantage that by using a different lookup table we can apply special effects to our drawing, which may come in handy later on.

As an aside to the aside, Z80 coders not familiar with the CPC may well be wondering whats with all the odd timing info and the mention of NOPs. I'll make a proper post on it before I post too much more code, but for now just accept that 1 NOP = 1us and gives us a much more accurate instruction timing on the CPC.

4 Comments:

  • Slow coder, fast blogger? ;) Interesting read! I'm not from a Z80 background and I didn't know about the pixel encoding on CPC.
    Btw, I could look it up but I'm kinda lazy... What are the limitations (or should I rather say possibilities ;) ) in Mode 0?

    And what's the screen resolution for the stretched screen? Is the two pixel shifting visible when your display shows "everything"? Or will it be hidden underneath something?

    Coincidently, a couple of weeks ago I browsed through cpcgamereviews and spotted some awesome graphics (and many poor Spectrum ports, too). But screen shots just don't scroll. It's interesting that "demo code" helps because very often those "tricks" have limitations that makes them not well suited for games.

    Cheers!

    By Blogger Chicken, at 3:23 AM  

  • Hehe, just having a bit of a brain dump whilst I try to remember all this stuff. :)

    Mode 0 gives us 160*200 pixels in 16 colours without any restrictions on where colours can be placed (well a 16K bitmap had to be good for something, right!). It has "fat" pixels, much like a C64's low res mode.

    The resolution I'm aiming at for XeO3 will give us 192*128 pixels. We won't see the pixel shift because our display is actually slightly wider than the visible area on the monitor and so it ends up looking nice and smooth.

    By Blogger XeO3-CPC, at 8:13 AM  

  • Say, who not drop by cpcwiki.com and add your project to the, um, projects article? Would be nice to spread the word... :) Cheers,
    Gryzor

    By Blogger Gryzor, at 8:17 AM  

  • Ok, thought it would be 160x200 but wasn't sure. And yes, that's the C64's and plus/4's multicolor mode resolution as well.
    Unfortunately, we have to deal with those restrictions on colors and thus save a few bytes for the bitmap.

    Is 192 pixels the max "stretched" resolution you can get?

    On plus/4 left and right side borders are each 4 chars wide (32 hires pixels or 16 multicolor pixels) and some monitors (if adjustable) display the entire border area. So if you could display anything in the borders it would be 192 multicolor pixels, too. (Well, it's possible to display something but colors in the side border but it's not a trivial task and many restrictions apply.)

    Anyway, looking forward to see this project evolve. Have you talked to Mike or/and Luca about being officially XeO3ed?

    By Blogger Chicken, at 6:15 PM  

Post a Comment

<< Home