| |
Oswald
Registered: Apr 2002 Posts: 5086 |
Sorting
are sorters really so slow in games? :) I have made my unrolled version for my theoretical game (;), and it takes 132 rlines to sort 32 numbers o_O worst case is ~200 lines. tho when its the case of 4 numbers have to be swapped only it does the job in ~10 lines. wastes a lot of memory but I like it :) |
|
... 193 posts hidden. Click here to view all posts.... |
| |
Rastah Bar Account closed
Registered: Oct 2012 Posts: 336 |
Quoting ChristopherJamOk, a few random thoughts.
I see now that the routine in comment #103 takes the same number of cycles as that in #105; it just fetches an actor ID with TYA:DEY instead of PLA, and fetches the next Y coordinate with lda YV,Y instead of PLA.
Even if the Y coordinates are on the stack, you still need the DEY to update the actor index.
I can't see a way to combine them, so suspect I'd lean towards my routine (same speed, 5k less unrolled code, 64 bytes more stack usage, faster performance when many actors are on the one line).
Rather than copying the Y coordinates to the stack, I'd make that their home, and also only write the actor IDs once at startup. You would of course have to be very careful to ensure no interrupts while running that section of code, NMI included
Yes, your approach has some advantages, including not having to assume that the maximum number of actors per bucket is never exceeded. Unfortunately it does not use any illegals though :-( |
| |
Trash
Registered: Jan 2002 Posts: 122 |
So i examined the tickcounts of the code I've got, with heavy use of zeropage it can sort 32 elements in 1188 cycles, without zp it does the same job in 1448 cycles (unless my calculations are incorrect). The drawback is that every value you want to sort has to be reduced in accuracy in order for it to work (eg two lda, sta in two different tables)...'
*edit*
HCL actually drops a hint for this sorter in the commentsection of Classics |
| |
Rastah Bar Account closed
Registered: Oct 2012 Posts: 336 |
Quote: re. SKW etc: Ooh, dangerous! So I think we're up to around 10k for the PHA routines now?
Will have to see if that can be sanely(!) combined with my thinking from today:
I managed to trim two cycles off the populate routine by switching to just using even numbers for the actor IDs (can interleave most of the data tables), and using a section of the stack to store Y values interleaved with actor IDs.
ldx bucketK+1
ldy newBranchTableValue,x
sty bucketK+1
pla ; grab this actor's index
sta bucketK+3,y ;21
pla ; grab next Yvalue
sta *+4
jmp (jumptable) ;11
(I was going to read the actor ID out of one of the CIA timers while pulling Y value off the stack, but realised that the timer will be counting down while the stack address increases, so had to abandon that idea).
so, 220*3+41*32=1972 cycles, 61.6 per actor, 31.3 raster lines :)
I'm sorry, but I think you missed 2 cycles: PLA / STA *+4 / JMP (jumptable) takes 13 cycles. This means that the approach in post #103 is 2 cycles faster. |
| |
ChristopherJam
Registered: Aug 2004 Posts: 1408 |
Quoting Color BarI'm sorry, but I think you missed 2 cycles: PLA / STA *+4 / JMP (jumptable) takes 13 cycles. This means that the approach in post #103 is 2 cycles faster.
Damn, you're right. The SBX#$06 takes two cycles less than the LDY newBranchTableValue,x
FWIW, the 'more than one sprites on a line' case could be improved by replacing the SKW instructions with JMP *+3; it saves a cycle. And you're still using SBX at least :) |
| |
ChristopherJam
Registered: Aug 2004 Posts: 1408 |
Quoting Trash. The drawback is that every value you want to sort has to be reduced in accuracy in order for it to work
Ah, it's not a perfect sort of eight bit values? Comparing apples and oranges in that case.. |
| |
Axis/Oxyron Account closed
Registered: Apr 2007 Posts: 91 |
Quote: So i examined the tickcounts of the code I've got, with heavy use of zeropage it can sort 32 elements in 1188 cycles, without zp it does the same job in 1448 cycles (unless my calculations are incorrect). The drawback is that every value you want to sort has to be reduced in accuracy in order for it to work (eg two lda, sta in two different tables)...'
*edit*
HCL actually drops a hint for this sorter in the commentsection of Classics
That ADC STA sequence mentioned in the comments of classics looks like 1 of the passes of a radix-sort. But in pure speed that wont be competitive to the ideas already posted here. Atleast as long as you dont reduce accuracy and really work with 200 different y-positions. My latest version has around 2400 cycles for the given use-case, if I remember right.
But the radix approach has some really nice properties compared to the bucket-sort mostly used here. It sorts in perfect 8 bit accuracy and sorts stable. That makes it more generally usable (e.g. for sorting 3D Bobs and polygons without any flickery). And in critical cases it can even avoid bugs in multiplexing. E.g. when big groups of sprites batch in small areas. |
| |
Rastah Bar Account closed
Registered: Oct 2012 Posts: 336 |
Quote: Quoting Color BarI'm sorry, but I think you missed 2 cycles: PLA / STA *+4 / JMP (jumptable) takes 13 cycles. This means that the approach in post #103 is 2 cycles faster.
Damn, you're right. The SBX#$06 takes two cycles less than the LDY newBranchTableValue,x
FWIW, the 'more than one sprites on a line' case could be improved by replacing the SKW instructions with JMP *+3; it saves a cycle. And you're still using SBX at least :)
Yes, I was a bit too eager to use illegals. Nevertheless, what I don't like about post #103 is that it will crash when there are more than 10 sprites on a line.
So I lean to sticking to the combination of posts #91 and #101. |
| |
Rastah Bar Account closed
Registered: Oct 2012 Posts: 336 |
Quoting Axis/OxyronThat ADC STA sequence mentioned in the comments of classics looks like 1 of the passes of a radix-sort. But in pure speed that wont be competitive to the ideas already posted here. Atleast as long as you dont reduce accuracy and really work with 200 different y-positions. My latest version has around 2400 cycles for the given use-case, if I remember right.
But the radix approach has some really nice properties compared to the bucket-sort mostly used here. It sorts in perfect 8 bit accuracy and sorts stable. That makes it more generally usable (e.g. for sorting 3D Bobs and polygons without any flickery). And in critical cases it can even avoid bugs in multiplexing. E.g. when big groups of sprites batch in small areas.
The approach proposed here (the combination of posts #91 and #101 or #103) counts down the actor list, so when there are multiple actors with the same Y value, they are added to the bucket in reverse order, but in the second pass the order is restored. So I think this approach is stable as well.
If think the method also has full 8 bit accuracy. The numbers of cycles mentioned are for visible sprite positions and that means 220 buckets. This can be increased to 255 buckets. |
| |
lft
Registered: Jul 2007 Posts: 369 |
Field Sort |
| |
Rastah Bar Account closed
Registered: Oct 2012 Posts: 336 |
Nice!
I think this 32K of ram usage you refer to applies to combining posts #91 and #103. When combining #91 and #101 it can be considerably lower (but it will still be a lot).
Btw, how many sprites with the same Y value can your routine handle? |
Previous - 1 | ... | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | ... | 21 - Next |