CPCWiki forum

General Category => Programming => Topic started by: zhulien on 13:02, 03 February 23

Title: Sprites Tiles and other superfast screen output approaches
Post by: zhulien on 13:02, 03 February 23
The questions I have here are most about CPC but the plus models might have some additional tricks.

As I was writing a sprite library I have been thinking of different approaches, especially since cpc can have lots of RAM and ROM.

Traditionally a software sprite might have some data and a fairly generic way to copy that to a location on the screen, perhaps anywhere.  It could have a mask or use xor to make it non detectructive.  To me this is tried and tested and also likely the slowest but gives a fair amount of flexibility for code size.  Perhaps a good use of this would be to construct a playfield dynamically in a nonscrolling single screen game.

Some optimisation I can think of above if a sprite was to move non destructive over a nice backdrop could be to keep an entire copy of that backdrop also somewhere in memory effectively creating backdrop sprites where ever a backdrop needs replacing. This means we don't need to capture a backdrop dynamically before placing a sprite at the expense of memory.

Then we have what I'd call a compiled sprite. Is this what is generally considered a compiled sprite? Eg. Ld hl.%c000; ld a,255; ld (hl), a

That would put a 1 byte compiled sprite on the screen.  I can see this removes need of looping and lookups to make a sprite as fast as possible (i think) and depending how much flexibility is required for placement then various branches and/or lookups would be used multiplying the amount of code necessary for a compiled sprite.  The amount of code and speed directly relates to the size and complexity (the colour makeup) of the sprite.  And how intelligent the sprite compiler can be.  This also might be good if the z80 did sprite compilation between levels perhaps, of just take more secondary storage for precompiled sprites to be stored.

Back to sprites and then vectors.  Is it faster to draw lines, or draw the result of compiled vector polygons to sprites?

If compiled sprites were used for tiles also, and perhaps scrolling, create compiled character height (for top bottom vertical scrolling)?  I haven't looked at eg... how Alcon works but I was thinking what if the entire screen was a sequence of compiled pixel high or character high sprites?  Super fast rendering?  At least for the scrolling.

Any other better methods or criticisms to the above methods?
Title: Re: Sprites Tiles and other superfast screen output approaches
Post by: gurneyh on 14:53, 03 February 23
I don't think we can get a satisfactory generic version on our old machines.

You talk about alcon but, it's a special case, vertical scrolling with reduced screen width.

Really, we have to think about the optimal solution on a case by case basis. And if not, what would be the interest to develop on 8/16 bits?
Title: Re: Sprites Tiles and other superfast screen output approaches
Post by: norecess464 on 14:54, 03 February 23
Hello!

Before anything, I would suggest to reduce the scope of the topic to 1 or 2 specific questions, otherwise it's going to be too vast to be discussed :)
Title: Re: Sprites Tiles and other superfast screen output approaches
Post by: TotO on 15:52, 03 February 23
Quote from: gurneyh on 14:53, 03 February 23You talk about alcon but, it's a special case, vertical scrolling with reduced screen width.
It is the arcade scrolling and screen width.
Title: Re: Sprites Tiles and other superfast screen output approaches
Post by: TotO on 16:01, 03 February 23
@zhulien I think that you can't provide a generic way to display sprites without defining some set of screen modes to use together. If the goal is to allow people to easy program arcade games on CPC and not have to took care about the technical side but more the gameplay side, they will do with, if the result worth it. 256x224+32, 256x256, 128x224+32, 128x256 is a good start.
Title: Re: Sprites Tiles and other superfast screen output approaches
Post by: roudoudou on 16:08, 03 February 23
there is already some (old) topics about drawing optimisations, take a look with "fast" "drawing" "optimisation"
Title: Re: Sprites Tiles and other superfast screen output approaches
Post by: Sykobee (Briggsy) on 16:18, 03 February 23
From previous discussions it seems that generic routines are good for early development, but you should then optimise and select the most appropriate sprite/tile mechanisms once your design is more grounded and you know what you need, and you need the clock cycles.

Obviously with cartridges (even on a standard CPC) and extra RAM systems, compiled sprites are very viable across the board. For a 64KB game perhaps only very specific sprites (bullets (small, lots of them), player (always visible)).

Title: Re: Sprites Tiles and other superfast screen output approaches
Post by: zhulien on 17:52, 03 February 23
If only the CPC had a better way to address screen positions - to make any sprite routines less calculation intensive.
Title: Re: Sprites Tiles and other superfast screen output approaches
Post by: gurneyh on 19:29, 03 February 23
Quote from: TotO on 15:52, 03 February 23
Quote from: gurneyh on 14:53, 03 February 23You talk about alcon but, it's a special case, vertical scrolling with reduced screen width.
It is the arcade scrolling and screen width.
It was not a criticism. Just a special case like many games!
Title: Re: Sprites Tiles and other superfast screen output approaches
Post by: TotO on 19:56, 03 February 23
Sure, it is not a 40x25 but 32x32 screen to have a vertical "overscan".
Title: Re: Sprites Tiles and other superfast screen output approaches
Post by: gurneyh on 22:49, 03 February 23
Quote from: zhulien on 17:52, 03 February 23If only the CPC had a better way to address screen positions - to make any sprite routines less calculation intensive.
there are solutions! But you need to be more specific in your questions :)

Title: Re: Sprites Tiles and other superfast screen output approaches
Post by: roudoudou on 23:11, 03 February 23
RST Z,#38 ;D
Title: Re: Sprites Tiles and other superfast screen output approaches
Post by: Anthony Flack on 00:47, 04 February 23
A few things:

First the obvious - use a lookup table to get the y address and then add x.

To jump to the line below the current line, you can use something like:

NewLine:
  LD A,H:ADD C:LD H,A ; character line jump
  AND &38: RET NZ ; if we're not at the end of the character line, we're done
  ADD HL,DE ; next character line
RET

nb. you should LD C,&8:LD DE,&c040 before you start. I'm assuming that the screen address is in HL. You could use ADD &8 instead of ADD C if C is in use already, but ADD C is faster.

You can use an unrolled 8 line loop and jump in part way through to avoid checking for the end of the character line.

If you are on an even scanline, you can jump to the next line down with a simple SET 3,H. This is an easy speed increase if you don't mind your sprites moving up or down in steps of two scanlines.

If you are on the top line of a character, you can access all the lines (out of order) like so:

;start on line 0
SET 3,H ; line 1
SET 4,H ; line 3
RES 3,H ; line 2
SET 5,H ; line 6
RES 4,H ; line 4
SET 3,H ; line 5
SET 4,H ; line 7

This can be useful for drawing things like tiles.

Draw alternating lines from left to right, then right to left to avoid having to reset the X position every line.
Title: Re: Sprites Tiles and other superfast screen output approaches
Post by: Anthony Flack on 03:51, 04 February 23
I should add - pretty much all of the above has been mentioned on the wiki already, in various places - but those are the things I personally have found most useful for improving the line jump. For narrow sprites especially, it can make quite a difference depending how you do it.

Oh, and come to think of it - those numbers are for a 64 byte wide screen, not 80 bytes. That also helps.
Title: Re: Sprites Tiles and other superfast screen output approaches
Post by: zhulien on 05:11, 04 February 23
Quote from: Anthony Flack on 00:47, 04 February 23A few things:

If you are on an even scanline, you can jump to the next line down with a simple SET 3,H. This is an easy speed increase if you don't mind your sprites moving up or down in steps of two scanlines.

If you are on the top line of a character, you can access all the lines (out of order) like so:

;start on line 0
SET 3,H ; line 1
SET 4,H ; line 3
RES 3,H ; line 2
SET 5,H ; line 6
RES 4,H ; line 4
SET 3,H ; line 5
SET 4,H ; line 7
Awesome, I never considered to use Set to move down.
Title: Re: Sprites Tiles and other superfast screen output approaches
Post by: zhulien on 05:12, 04 February 23
Is there already a very good PC to CPC sprite compiler?
Title: Re: Sprites Tiles and other superfast screen output approaches
Post by: BSC on 12:13, 04 February 23
Quote from: Anthony Flack on 00:47, 04 February 23A few things:

First the obvious - use a lookup table to get the y address and then add x.
[...]

Great collection of advice! All of this should be in the actual Wiki instead of being scattered all about the forums. Ideally addressable from a kind of wiki hub. Or maybe I missed that that's already there..?
Title: Re: Sprites Tiles and other superfast screen output approaches
Post by: roudoudou on 12:24, 04 February 23
Quote from: BSC on 12:13, 04 February 23
Quote from: Anthony Flack on 00:47, 04 February 23A few things:

First the obvious - use a lookup table to get the y address and then add x.
[...]

Great collection of advice! All of this should be in the actual Wiki instead of being scattered all about the forums. Ideally addressable from a kind of wiki hub. Or maybe I missed that that's already there..?

the Amstrad knowledge available is relative to Amstrad programmers. Low as we are only a few people.

+ it's time consuming to write articles, etc.

if you have time, feel free to gather everything already on forums ;)
Title: Re: Sprites Tiles and other superfast screen output approaches
Post by: Anthony Flack on 23:05, 04 February 23
Honestly, the Amstrad knowledge available is huge, and it's brilliant. The CRTC Compendium that was released recently, wow. Far more information than we ever had during the machines' commercial life. 

I don't know about sprite compilers, that's a good question. I tend to write my own tools for that kind of thing, but they're not general purpose or fit for pubic release.
Title: Re: Sprites Tiles and other superfast screen output approaches
Post by: zhulien on 18:27, 05 February 23
How many hw sprites can we have on 6128 plus? The wiki says 16 per scan line, but we have lots of scan lines... if sprites are also 16x16, then we can fill 256x200 with sprites?
Title: Re: Sprites Tiles and other superfast screen output approaches
Post by: roudoudou on 18:48, 05 February 23
you can have more than 16 sprites in a row (time consuming, not really usable)
you can multiplex easily sprites positions, see https://www.cpc-power.com/index.php?page=detail&num=17425 (all red bullets are in reality 3 sprites)
but when you change a sprite position, the position is changed (no sh1t sherlock!) so it wont appear where it was previously, until you change again his position.
if you take a look at Sonic preview from NoRecess, you can see some vertical rows of rings (which are obviously multiplexed)
in the prehistorik 2 game, the tree trunk is made with multiplexing and the leaf too (two trees below two trees)
Title: Re: Sprites Tiles and other superfast screen output approaches
Post by: andycadley on 18:50, 05 February 23
Quote from: zhulien on 18:27, 05 February 23How many hw sprites can we have on 6128 plus? The wiki says 16 per scan line, but we have lots of scan lines... if sprites are also 16x16, then we can fill 256x200 with sprites?
There are 16 sprites and you have to reload them by resetting all the pixels, which you can't do while they're on screen as the ASIC will automatically disable them while you're writing to them. So not much chance of covering 256*200 unless they're repeating images.

It's also possible, though difficult, to reuse the same sprite on a single line but again not practical in most cases.
Title: Re: Sprites Tiles and other superfast screen output approaches
Post by: BSC on 00:24, 06 February 23
Quote from: roudoudou on 12:24, 04 February 23
Quote from: BSC on 12:13, 04 February 23Great collection of advice! All of this should be in the actual Wiki instead of being scattered all about the forums. Ideally addressable from a kind of wiki hub. Or maybe I missed that that's already there..?
if you have time, feel free to gather everything already on forums ;)
I don't  ;)
Title: Re: Sprites Tiles and other superfast screen output approaches
Post by: arnolde on 20:02, 15 February 23
Quote from: Anthony Flack on 00:47, 04 February 23AND &38: RET NZ ; if we're not at the end of the character line, we're done
If you're only using the main screen (&C000-&FFFF), you don't even need AND &38, you can just RET C.
And if double buffering between &40 and &C0, I use ADD A:RET P instead, saves 1 byte & 1 nop
Title: Re: Sprites Tiles and other superfast screen output approaches
Post by: martin464 on 12:57, 16 February 23
I think the great SET trick has another advantage if hardware scrolling by reg 12 and 13 which makes it even more awkward

normally getting next character pos you add 1 but it can wrap round in this case
so on INC HL have to RES 3, H, eg C7FF should go to C000 not C800

but if using SET it doesn't matter if bit 3 was set by the INC HL, cause that's what you want anyway

you can also use a different order to make HL ends up back on line 1 again so you can keep using it, or you could make it end up on the line you want HL to be on i guess. it adds 2 nops though for the extra set

00001000 +8
00011000 +16
00010000 -8
00110000 +32
00111000 +8
00101000 -16
00100000 -32
00000000 back to row 1
Title: Re: Sprites Tiles and other superfast screen output approaches
Post by: abalore on 18:02, 16 February 23
The sprite drawing technique in Alcon is this:

- Three buffers (two for double buffering and a third with an intact image of the background)
- The third buffer can be in normal RAM (for an all-system cartridge game) or in expanded RAM for 128K only.
- The sprites are compiled and address for screen line increments are in a lookup table, so they don't need to be computed all time.

an example of a 6x2 lsprite:

ld bc,&3020
xor a
ld (hl),a : inc l : ld (hl),b : inc l : ld (hl),c : pop de : add hl,de
ld (hl),a : inc l : ld (hl),&30 : inc l : ld (hl),c

- You can cache the 3 most common values in a,b,c for quicker drawing
- All transparent bytes don't require ld (hl)..., you can just skip with "inc l", great for rounded or hollow sprites
- Bytes with only one transparent pixel require special treatment, but I won't reveal everything >D
- Non common values are written directly in (hl), like "ld (hl),&30", no need for intermediate registers
- All the painting requires the interruptions to be disabled, since you use stack to retrieve line increments
- You can do "inc l" in 32 char width screens, for other sizes you need to do "inc hl" with less performance
- I have an utility on PC to import and create the compiled sprites but it's not available
- Obviously some previous code is required to load the initial address in HL and the increment table offset in SP

Further optimizations:

- You can use inc l and dec l in alternate lines for smaller lookup tables
- If you agree with having few colors, you can use bitwise operations to draw and delete sprites with same routine
- If you have to skip many bytes, instead of inc l : inc l :inc l : inc l : inc l  you can do ld a,l : add 5 : ld l,a
Title: Re: Sprites Tiles and other superfast screen output approaches
Post by: gurneyh on 18:22, 16 February 23
Quote from: abalore on 18:02, 16 February 23The sprite drawing technique in Alcon is this:

- Three buffers (two for double buffering and a third with an intact image of the background)
- The third buffer can be in normal RAM (for an all-system cartridge game) or in expanded RAM for 128K only.
- The sprites are compiled and address for screen line increments are in a lookup table, so they don't need to be computed all time.

an example of a 6x2 lsprite:

ld bc,&3020
xor a
ld (hl),a : inc l : ld (hl),b : inc l : ld (hl),c : pop de : add hl,de
ld (hl),a : inc l : ld (hl),&30 : inc l : ld (hl),c

- You can cache the 3 most common values in a,b,c for quicker drawing
- All transparent bytes don't require ld (hl)..., you can just skip with "inc l", great for rounded or hollow sprites
- Bytes with only one transparent pixel require special treatment, but I won't reveal everything >D
- Non common values are written directly in (hl), like "ld (hl),&30", no need for intermediate registers
- All the painting requires the interruptions to be disabled, since you use stack to retrieve line increments
- You can do "inc l" in 32 char width screens, for other sizes you need to do "inc hl" with less performance
- I have an utility on PC to import and create the compiled sprites but it's not available
- Obviously some previous code is required to load the initial address in HL and the increment table offset in SP

Further optimizations:

- You can use inc l and dec l in alternate lines for smaller lookup tables
- If you agree with having few colors, you can use bitwise operations to draw and delete sprites with same routine
- If you have to skip many bytes, instead of inc l : inc l :inc l : inc l : inc l  you can do ld a,l : add 5 : ld l,a
Great. Can you explain how you manage sprite clipping in Alcon? 
Title: Re: Sprites Tiles and other superfast screen output approaches
Post by: abalore on 18:54, 16 February 23
Quote from: gurneyh on 18:22, 16 February 23
Quote from: abalore on 18:02, 16 February 23The sprite drawing technique in Alcon is this:

- Three buffers (two for double buffering and a third with an intact image of the background)
- The third buffer can be in normal RAM (for an all-system cartridge game) or in expanded RAM for 128K only.
- The sprites are compiled and address for screen line increments are in a lookup table, so they don't need to be computed all time.

an example of a 6x2 lsprite:

ld bc,&3020
xor a
ld (hl),a : inc l : ld (hl),b : inc l : ld (hl),c : pop de : add hl,de
ld (hl),a : inc l : ld (hl),&30 : inc l : ld (hl),c

- You can cache the 3 most common values in a,b,c for quicker drawing
- All transparent bytes don't require ld (hl)..., you can just skip with "inc l", great for rounded or hollow sprites
- Bytes with only one transparent pixel require special treatment, but I won't reveal everything >D
- Non common values are written directly in (hl), like "ld (hl),&30", no need for intermediate registers
- All the painting requires the interruptions to be disabled, since you use stack to retrieve line increments
- You can do "inc l" in 32 char width screens, for other sizes you need to do "inc hl" with less performance
- I have an utility on PC to import and create the compiled sprites but it's not available
- Obviously some previous code is required to load the initial address in HL and the increment table offset in SP

Further optimizations:

- You can use inc l and dec l in alternate lines for smaller lookup tables
- If you agree with having few colors, you can use bitwise operations to draw and delete sprites with same routine
- If you have to skip many bytes, instead of inc l : inc l :inc l : inc l : inc l  you can do ld a,l : add 5 : ld l,a
Great. Can you explain how you manage sprite clipping in Alcon?

The sprites clip a maximum of 8 pixels in horizontal, by painting on black over them (there are a two 1 char black columns at both sides), and 32 pixels in vertical (that's easy)

The sprites with 1 pixel horizontal movement have preshifted versions thanks to the huge capacity of cartridges
Title: Re: Sprites Tiles and other superfast screen output approaches
Post by: Anthony Flack on 21:51, 18 February 23
Quote from: martin464 on 12:57, 16 February 23you can also use a different order to make HL ends up back on line 1 again so you can keep using it, or you could make it end up on the line you want HL to be on i guess. 
Yeah, with a bit of thought you can cover all kinds of different situations with a series of single SETs and RESs. You just have to be prepared to draw your lines out of order. 
Powered by SMFPacks Menu Editor Mod