spritesort reduces spriteflicker

Page 1/13
| 2 | 3 | 4 | 5 | 6

By hit9918

Prophet (2853)

hit9918's picture

07-03-2010, 01:33

Hello,
I made a spritesort that does reduce flicker!

I put a zip with proof of concept and
code at jf.peer.name/msx/spritesort.zip
there also is a README.TXT that explains how it works.

when you run the demo, press a cursor key to see
the classic ringbuffer method. a massive difference.

What a pity I did not have this idea 25 years earlier Big smile
I was watching 8bit stuff on youtube and then I had
this idea and I could not resist to try it out.

p.s. for emulator users, best result is when
msx Hz is in sync with your monitor. also bluemsx
speed dial should be set to 100% for correct output.

Login or register to post comments

By Hrothgar

Champion (479)

Hrothgar's picture

07-03-2010, 09:53

The result looks a lot nicer!

How much more CPU does this use than the traditional method? That might be an issue.

Also some people believe you should flicker entire characters (when they use multiple overlapping or combined sprites), that also might make things a bit more complicated.

By Leo

Paragon (1236)

Leo's picture

07-03-2010, 09:53

Thanks for sharing !
Could you give more details or overview of the sorting ?
Would you say it is a bit like in konami games where the planes are changed continiously ?

By Edwin

Paragon (1182)

Edwin's picture

07-03-2010, 13:35

Leo, everything you need to know is in the readme.

hit9918, interesting way to make a first post. Looks like a good algorithm. The ability to use with more than 32 sprites makes it especially nice. However, you do need to have the cpu time available since it's quite a bit slow than just splitting the sprite attribute table upload into two pieces.

About the ring buffer approach. You can improve its look by choosing an offset 5 or 7. This way you will increase the repeat of the flicker pattern from 8 frames to 32 frames.

By PingPong

Prophet (3281)

PingPong's picture

07-03-2010, 13:42

Hello,
I made a spritesort that does reduce flicker!


interesting, would be nice to have the same for msx2. however there is a problem. swapping sprites priority causes also the need to move sprite attribute table for colors. each sprite is 16 bytes long. so this solution does not work so well on msx2.

By Edwin

Paragon (1182)

Edwin's picture

07-03-2010, 14:22

PingPong: That's one of those horrible pieces of design that more problems than it should. I guess they just expanded the sprite colour attribute and never thought about whether it was practical. It would have been very little trouble to make colours per sprite pattern or even make it selectable through the unused byte in the SAT. This is probably proof that the chip designers aren't normally doing much game programming.

By ARTRAG

Enlighted (6173)

ARTRAG's picture

07-03-2010, 16:58

@hit9918
Good work, the idea gives good results, but seems very CPU expensive.

There is a lighter way to rotate sprites in an optimal way: using the S0 info.

The source is here
http://msxbr-mensa.googlegroups.com/web/spriterotation.asm?gda=w9mw6UUAAAABkWRJzrBz-60xfGzM9RFduj1Ql1gTRl5ThlN5W0c8Y4omvV85r9x_capiu-AemaoQYZAtvN_G4dVzKS_oSrMLGu1iLHeqhw4ZZRj3RjJ_-A
but I posted the code in this forume some time ago too.

The idea is simple:

If the 5th sprite bit in S0 is set, its plane is in S0 too.
All you need to do is to move it (and all the seguent sprites) on top of the SAT.
In this way it (and some other sprite that was hidden in the previous frame) will appear in the next frame

eg. assume all sprites on the same lines
frame0 = 0,1,2,3,4,5,6,endsat ; here 4,5,6 are hidden
frame1 = 4,5,6,0,1,2,3,endsat ; here 4,5,6 are shown and 1,2,3 disappear
frame2 = 1,2,3,4,5,6,0,endsat ; here 1,2,3,4 are shown and 5,6,9 disappear
etc

rotation is "optimal" if the 5th sprite problem ocuurs only once
as S0 holds only the last occurrence of 5th sprite condition

anyway the CPU use is very small and the result is the same of yours (when the the 5th sprite condition occurs once)

By hit9918

Prophet (2853)

hit9918's picture

07-03-2010, 19:01

The result looks a lot nicer!

How much more CPU does this use than the traditional method? That might be an issue.

The "konami attack cascade" sketch takes something like 32 rasterlines.

I noticed that the typical C64 multiplexor game got always MAX 5 sprites
per scanline: 8 sprites hardware, 3 sprites reserved for player, shield, bullet.
And the top enemy row of the 9918 spritesort sketch got 6 colored sprites,
so it goes beyond C64 Cool

Also some people believe you should flicker entire characters (when they use multiple overlapping or combined sprites), that also might make things a bit more complicated.

oh, I have not thought about that! it is nicer when the whole character is flickering instead of parts.

it would need another byte in the struct to store chain info.
but the required checks might slow the engine much.

By hit9918

Prophet (2853)

hit9918's picture

07-03-2010, 20:13

Leo, everything you need to know is in the readme.

hit9918, interesting way to make a first post. Looks like a good algorithm. The ability to use with more than 32 sprites makes it especially nice.

Thank you! The demo can be hacked easy by fiddeling the BASIC code,
maybe you want to play a bit with the sketch:

adjust amount of sprites N=foo around line 160.
then for every sprite add DATA Y,X,C,P (it is 9918 layout order).

For example, add 12 more sprites, set N=39 (the demo was N=27).
then duplicate the first 12 data lines and add 100 to the first value in the DATA, the Y values.

now you got 39 sprites, hehe Smile

Then you can see the top sprite row was not degraded by the action going on below.
But when you press cursor key, you can see that the top row has gotten worse
with ringbuffer, because the action below makes the ringbuffer longer and though
the flicker roundtrip longer.

btw if e.g. bluemsx set to "500% speed", then one cannot see it, need 100%
and best is 100% speed and PC Hz same as MSX Hz.

About the ring buffer approach. You can improve its look by choosing an offset 5 or 7. This way you will increase the repeat of the flicker pattern from 8 frames to 32 frames.

Have not tried these, maybe it makes the look more "organic", break up groups.
But I doubt it can do much about the worst case sprite disappearance?
32 sprites, ringbuffer start addresses per frame:
0, 7, 14, 21, 28, 35->35 AND 32 = 3, 10, ...

"3,10,..." means: display 3,4,5,6 in a frame and then 10,11,12,13 in the next frame.
(imagine 32 sprites in a row, worst scenario).
so I found a case where sprite 7,8,9 are missing in TWO roundtrips!
you got the roundtrip down to something like 5 steps, but missing
two roundtrips means a worst case of 2 * 5 = 10 frames:
so for some sprites things got even worse than
the worst case of 7 sprites per frame.

So it looks like a simple ringbuffer aproach can never go beyond the
number "the average worst case with 32 sprites is disappearing for 7 frames".
trying to change the offset from 4 will make things better for some lucky sprites,
and make things worse for some unlucky sprites.

By hit9918

Prophet (2853)

hit9918's picture

07-03-2010, 20:20


interesting, would be nice to have the same for msx2. however there is a problem. swapping sprites priority causes also the need to move sprite attribute table for colors. each sprite is 16 bytes long. so this solution does not work so well on msx2.

this sounds like the MSX2 sprite color table is not adressed same way as sprite pattern
table, by 4th byte in sprite attribute table?

By hit9918

Prophet (2853)

hit9918's picture

07-03-2010, 21:03

@ARTRAG
@hit9918
Good work, the idea gives good results, but seems very CPU expensive.

That is the problem. In readme I mention further tradeoffs. Also maybe
the whole thing can be rewritten to snip IX IY and stuff them to the
EXX registerset.

In my first version I did not dare to trade too much accuracy.
The trade towards full speed is one scanline buffer entry is for
16 scanlines. Then spritesort only needs to touch 2 cells with
the DEC (HL) OR (HL) INC L cascade.


The idea is simple:

If the 5th sprite bit in S0 is set, its plane is in S0 too.
All you need to do is to move it (and all the seguent sprites) on top of the SAT.
In this way it (and some other sprite that was hidden in the previous frame) will appear in the next frame

rotation is "optimal" if the 5th sprite problem ocuurs only once
as S0 holds only the last occurrence of 5th sprite condition

Wow. Is this just a slight upgrade on the ringbuffer, or is it a trick that
makes spritesort unnessesary, I cannot imagine by now.

In first look, it looks like only a slight upgrade to the ringbuffer method.
On a second look however it does attack the problems where they are happening,
which was my goal.

It is not ideal, on the other hand it does attack the next problem right next frame
without the usual roundtrip time. I got to look into this.

Page 1/13
| 2 | 3 | 4 | 5 | 6