judgement impaired
The sprite judgement simplifications triggered by (among other things) trying to get a 6507 to divide by 7 repeatedly in VBLANK have begun ...
The new judgement system is inspired by an "all or nothing" approach: either draw the full sprite, or don't try. I also got rid of the temporary drawing list expansion, and some more convoluted logic, by making the drawing-list into two byte-lists, one for a sprite index, one for a positioning code. During judgement, the positioning codes are Y values, afterwards, they're converted to X codes for RESPx/HMPx adjustments. The X values have to be recomputed as the list is being chained together, since they're all relative anyways.
Here's the "first" draft of the new judgement code. $1 is 1 or 2 for each drawing list. (The subroutine/macro is expanded twice.) Note that a sprite could potentially be drawn on both lists, if it's very lucky, but that would mean there was nobody else who wanted that slot anyways. Also, there are any number of inefficiencies here, probably.
Yeah, there are TODO's still -- I have to run in the middle of a rewrite :-( as usual. You (for certain values of "you") get the gist.
sprite_judgement:
;;
;; Sprite handling: judgement code
;;
;; This is unrolled twice, with different postfixes to expand
;; it into drawlist1 and drawlist2.
define({[MAKE_DRAWING_LIST]}, {[
subroutine
;; clear the drawing list
ldy #DRAWING_LIST_LENGTH
lda #$ff
ldx #0
.clear_drawing_list:
sta drawlist$1-1,y
stx drawlist$1pos-1,y
dey
bne .clear_drawing_list
if [ $1 == 1 ]
;; if this is an odd field, inject the player-character
lda field_counter
and #1
beq .skip_player
lda #0
sta drawlist1
lda player_y
sta drawlistpos1
;; fall through and consider the first non-player sprite as usual
.skip_player:
endif
;; set the current search sprite to the next sprite in cycle,
;; and bump the start_sprite index.
ldx start_sprite
lda num_sprites
inc start_sprite
cmp start_sprite
bne .start_ok
lda #1
sta start_sprite
.start_ok:
;; if slot 0 is open, claim it
lda drawlist$1
cmp #$ff
bne .consider_sprite
stx drawlist$1
lda sprite_y,x
sta drawlist$1pos
jmp .consider_next_sprite
.consider_sprite:
lda sprite_y,x
sta my_y
ldy #DRAWING_LIST_LENGTH
clc ;safety
.walk_list:
lda drawlist$1pos,y ;his position
adc #8 ;his height in linesets
cmp my_y
;; am I after him? then it's too late, since we're going
;; backwards, I don't get a slot here.
bpl .consider_next_sprite
;; who's before him?
cpy #0 ;anybody before?
beq .try_to_claim
dey
;; am I before the guy before? then I need to keep walking the list
lda drawlist$1pos,y
cmp my_y
bmi .walk_list
;; I fall between the slots, that's good, let's try to claim it
iny
.try_to_claim:
;; We want this slot, but will we fit with horizontal repositioning?
sty want_slot
;; Repositioning in scanlines -- 8px per HMPx or 48px per RESPx
;; Following sprite
lda drawlist$1,y
cmp #$ff
beq .no_following
tay
lda sprite_x,y
sbc sprite_x,x
bpl .sign_ok
eor #$ff ;invert to positive number
bpl .sign_ok ;always taken
.no_following:
lda #0
.sign_ok:
sta tmp0 ;the number of clocks by which to move, so far
;; TODO: make sure that this occurs before sprite starts
ldy want_slot
beq .no_prior
dey
lda drawlist$1,y
cmp #$ff
beq .no_prior
tay
lda sprite_x,y
sbc sprite_x,x
bpl .sign_ok_too
eor #$ff
bpl .sign_ok_too
.no_prior:
lda #0
.sign_ok_too:
adc tmp0 ;total number of movement clocks
;; TODO: make sure this occurs before the following sprite starts
.claim_it:
;; TODO: move up subsequent sprites in the list
lda my_y
ldy want_slot
sta drawlist$1pos,y
stx drawlist$1,y
.consider_next_sprite:
inx
cpx num_sprites
bne .consider_sprite
.no_slots:
;; This drawing-list is full. Stop looking at it.
]})
EDIT: lda #1 after bne .start_ok -- don't consider the player-character, it's special-cased on odd fields.
EDIT2: correct slot 0 claiming for new RAM layout

0 Comments
Recommended Comments
There are no comments to display.