;---------------------------------
; NEW multiplexor sort
;---------------------------------
ldx #15
!FindFirst: lda yy,x
bne !FoundFirst
!BackHere: dex
bpl !FindFirst
lda #0
sta yc
rts ; NO sprites on!
!FoundFirst lda Anim_Current,x ; if shape >= 200 then DONT multiplex
cmp #200
bcs !BackHere
;
; Found 1st sprite
;
lda #-1 ; set first active as last in list
sta SPNext+1,x
stx SPNext ; and set first active as FIRST
dex ; and move on one - we dont need to do the 1st one
bmi !AllDone
!SortAll
ldy yy,x
beq !DoNext
lda Anim_Current,x ; if shape >= 200 then DONT multiplex
cmp #200
bcs !DoNext
tya
stx xcount ; Sprite number we're inserting
ldx #-1 ; pLast
ldy SPNext ; pCurrent
;
; X and Y take turns about at being pCurrent and pLast...
; The first itteration X=pLast, Y=pCurrent. The second is reversed.
;
!FindSpace:
cmp yy,y
bcc !InsertHere
ldx SPNext+1,y ; get next
bmi !InsertHere2 ; Not end of list... so keep going!
cmp yy,x
bcc !InsertHere2
ldy SPNext+1,x ; get next
bpl !FindSPace ; Not end of list... so keep going!
!InsertHere
inx ; allow for -1 when head of list
lda xcount ; Set last->pNext to be this one
sta SPNext,x
tax ; Now move to the new entry
sty SPNext+1,x
ldx xcount ; Sprite number we're inserting
dex
bpl !SortAll
bmi !AlLDone
!InsertHere2
iny ; allow for -1 when head of list
lda xcount ; Set last->pNext to be this one
sta SPNext,y
tay ; Now move to the new entry
stx SPNext+1,y
ldx xcount ; Sprite number we're inserting
!DoNext
dex
bpl !SortAll
!AlLDone
So the idea here is that SPNext is a list of 17 bytes with 0 being the First in the 1D indexed-linked list. That way setting pFirst rather than an index is no different thanks to the inx/iny being used at the start of the insert code.
The only slight downer here is I need to loop forward to find the 1st allocated entry to start from rather than let the main loop do it itself. Still, its not really a slow down, just another bit of code to run.
The other trick is to run a paired inner loop. This lets me keep a LAST value without having to transfer it via A every frame, and that in turn lets me load A up with the Y value to compare at the start, and then I never have to reload it. It works pretty well although depending on the actual order of the sprites, timing may vary by a good few scanlines.
5 comments:
Can't you drop "iny" at !InsertHere2 and use "sta SPNext+1,y" instead? To me it looks like y is always positive at that point. Also, at the same point you have xcount in A already so do "tax" instead of "ldx xcount". At !InsertHere X already contains xcount, so you can drop "ldx xcount" straight away.
Regarding size increments: I decided to waste five bytes to make BuildLevel() 30% faster. As that one generates 16 KB of data the difference is easy to notice :)
Swap ldy/lda at !SortAll too :)
Oh yeah, good spot. I was too concentated on the inner loop :)
Saves an extra scanline overall...cool. Thats 9 scans saved from the original, and when theres less sprites on, it goes even faster.
It's not all about speed, you can save bytes too...
Use Y at !FoundFirst and you can drop "lda #0" when exiting without sprites :)
Yup... nice one. Can't use that in the XeO3 version though as the top part of the loops a little different.
Post a Comment