RSS Bot Posted September 11, 2007 Share Posted September 11, 2007 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 http://www.atariage.com/forums/index.php?a...;showentry=3847 Link to comment Share on other sites More sharing options...
Recommended Posts