Thursday, July 03, 2008

Minor increase.... But size isn't important...

Well, I've managed to shave 8 raster lines off the sort using the new system and it's all nice and stable now so I'm gonna stick with this new one. The good news is I'll be able to use this in the C64 version of XeO3 as well, so it's been a good couple days of playing. However, it's not the huge boost I was wanting, but its better than nothing! The new sort is shown below...

              ;---------------------------------
; 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:

TNT said...

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 :)

TNT said...

Swap ldy/lda at !SortAll too :)

Mike said...

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.

TNT said...

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 :)

Mike said...

Yup... nice one. Can't use that in the XeO3 version though as the top part of the loops a little different.