Be more cautious when manipulaitng the sorted list

This commit is contained in:
Lucas Scharenbroich 2023-03-08 20:09:57 -06:00
parent 6c5e133b17
commit c533d846d7
2 changed files with 193 additions and 379 deletions

View File

@ -24,6 +24,8 @@ Selected equ 10
Flips equ 12
DTile equ 14
Tmp2 equ 16
ScreenWidth equ 18
ScreenHeight equ 20
; Typical init
phk
@ -32,32 +34,30 @@ Tmp2 equ 16
sta MyUserId ; GS/OS passes the memory manager user ID for the application into the program
_MTStartUp ; GTE requires the miscellaneous toolset to be running
lda #ENGINE_MODE_USER_TOOL+ENGINE_MODE_TWO_LAYER
jsr GTEStartUp ; Load and install the GTE User Tool
; Initialize the graphics screen to a 256x160 playfield
pea #320
pea #160
pea #200
_GTESetScreenMode
; Load a tileset
pea 0
pea 120
pea #^TSZelda
pea #TSZelda
_GTELoadTileSet
; Set the palette
ldx #11*2
:ploop
lda palette,x
stal $E19E00,x
dex
dex
bpl :ploop
bra sprt
pea $0000
pea #^palette
pea #palette
_GTESetPalette
palette dw $0000,$08C1,$0C41,$0F93,$0777,$0FDA,$00A0,$0000,$0D20,$0FFF,$023E
sprt
jsr SetLimits
; Create stamps for the sprites we are going to use
HERO_SPRITE equ SPRITE_16X16+1
@ -68,23 +68,19 @@ HERO_SPRITE equ SPRITE_16X16+1
; Create sprites
stz Tmp0
stz Tmp1
stz Tmp1 ; Slot number
ldx Tmp0
:sloop
pea HERO_SPRITE ; sprite id
pei Tmp1 ; Put the sprite in this slot
pea SPRITE_16X16 ; with these flags (h/v flip)
pea VBUFF_SPRITE_START
lda PlayerX,x
pha
lda PlayerY,x
pha
pei Tmp1
_GTEAddSprite
pei Tmp1 ; update the sprite in this slot
pea $0000 ; with these flags (h/v flip)
pea VBUFF_SPRITE_START ; and use this stamp
_GTEUpdateSprite
inc Tmp1
ldx Tmp0
inx
@ -95,70 +91,7 @@ HERO_SPRITE equ SPRITE_16X16+1
; Manually fill in the 41x26 tiles of the TileStore with a test pattern of trees
; lda #TILE_DYN_BIT+TILE_PRIORITY_BIT+0 ; fill the screen the the dynamic tile slot 0
lda #TILE_DYN_BIT+0 ; fill the screen the the dynamic tile slot 0
jsr _fillTileStore
; brl :no_trees
ldx #0
ldy #0
jsr _drawTree
ldx #3
ldy #0
jsr _drawTreeH
ldx #0
ldy #3
jsr _drawTreeV
ldx #3
ldy #3
jsr _drawTreeHV
ldx #9
ldy #0
jsr _drawTree
ldx #9
ldy #3
jsr _drawTree
ldx #12
ldy #0
jsr _drawTree
ldx #12
ldy #3
jsr _drawTree
ldx #6
ldy #0
jsr _drawTreeFront
ldx #6
ldy #3
jsr _drawTreeFront
ldx #6
ldy #6
jsr _drawTreeFront
ldx #3
ldy #6
jsr _drawTreeFront
ldx #0
ldy #6
jsr _drawTreeFront
:no_trees
; Set up the dynamic tile
lda #65
sta DTile
pei DTile
pea $0000
_GTECopyTileToDynamic ; Copy DTile into the first dynamic tile slot
; Initialize the frame counter
@ -166,9 +99,9 @@ HERO_SPRITE equ SPRITE_16X16+1
; Set the screen coordinates
lda #128
lda #0
sta ScreenX
lda #128
lda #0
sta ScreenY
stz Selected
@ -179,225 +112,40 @@ HERO_SPRITE equ SPRITE_16X16+1
pha ; space for result, with pattern
_GTEReadControl
pla
and #$00FF
cmp #'q'
bne :2
brl :exit
:2
; cmp KeyState
; beq :evt_loop
; sta KeyState
; cmp #0
; beq :evt_loop
; cmp #' '
; bne :evt_loop ; only advance one frame at a time
; brl :next
:3
cmp #'1'
bcc :3a
cmp #'9'
bcs :3a
sec
sbc #'1'
asl
sta Selected
brl :next
:3a
cmp #'r'
bne :3b
lda Flips
clc
adc #SPRITE_HFLIP
and #SPRITE_VFLIP+SPRITE_HFLIP
sta Flips
pei Selected ; update the sprite in this slot
pei Flips ; with these flags (h/v flip)
pea VBUFF_SPRITE_START ; and use this stamp
_GTEUpdateSprite
:3b
cmp #'x'
bne :3d
ldx Selected
lda PlayerX,x
clc
adc PlayerU,x
sta PlayerX,x
lda PlayerY,x
clc
adc PlayerV,x
sta PlayerY,x
brl :next
:3d
cmp #'z'
bne :3e
ldx Selected
lda PlayerX,x
sec
sbc PlayerU,x
sta PlayerX,x
lda PlayerY,x
sec
sbc PlayerV,x
sta PlayerY,x
brl :next
:3e
cmp #'s'
bne :4
ldx Selected
inc PlayerY,x
brl :next
:4
cmp #'w'
bne :5
ldx Selected
dec PlayerY,x
brl :next
:5
cmp #'d'
bne :6
ldx Selected
inc PlayerX,x
brl :next
:6
cmp #'a'
bne :7
ldx Selected
dec PlayerX,x
brl :next
:7
cmp #$15 ; left = $08, right = $15, up = $0B, down = $0A
bne :8
inc ScreenX
bra :next
:8 cmp #$08
bne :9
dec ScreenX
brl :next
:9 cmp #$0B
bne :10
inc ScreenY
brl :next
:10 cmp #$0A
bne :11
dec ScreenY
brl :next
:11 cmp #'y'
bne :12
lda DTile
inc
jsr HandleKeys ; Do the generic key handlers
bcs :do_more
brl :do_render
:do_more
and #$007F
sta DTile
pha
pea $0000
_GTECopyTileToDynamic
brl :next
:12 cmp #'f'
bne :13
pea $0000
_GTEFillTileStore
brl :next
:13 cmp #'m'
bne :next
_GTERefresh
:next
; inc ScreenX
cmp #'a'
bne :skip_a
inc ScreenX
pei ScreenX
pei ScreenY
_GTESetBG0Origin
; brl no_animate
stz Tmp0
stz Tmp1
ldx Tmp0
loopX
lda PlayerX,x
clc
adc PlayerU,x
sta PlayerX,x
bpl is_posx
cmp #-15
bcs do_y
lda PlayerU,x
eor #$FFFF
inc
sta PlayerU,x
bra do_y
is_posx cmp #128
bcc do_y
lda PlayerU,x
eor #$FFFF
inc
sta PlayerU,x
do_y
lda PlayerY,x
clc
adc PlayerV,x
sta PlayerY,x
bpl is_posy
cmp #-15
bcs do_z
lda PlayerV,x
eor #$FFFF
inc
sta PlayerV,x
bra do_z
is_posy cmp #160
bcc do_z
lda PlayerV,x
eor #$FFFF
inc
sta PlayerV,x
do_z
inc Tmp1
ldx Tmp0
inx
inx
stx Tmp0
cpx #MAX_SPRITES*2
bcc loopX
no_animate
stz Tmp0
stz Tmp1
ldx Tmp0
loopY
pei Tmp1
lda PlayerX,x
brl :do_render
:skip_a
cmp #'z'
bne :skip_z
inc PlayerX
pea 0
lda PlayerX
pha
lda PlayerY,x
lda PlayerY
pha
_GTEMoveSprite
:skip_z
inc Tmp1
ldx Tmp0
inx
inx
stx Tmp0
cpx #MAX_SPRITES*2
bcc loopY
:do_render
jsr _moveSprites
pea #RENDER_WITH_SHADOWING
_GTERender
inc FrameCount
; Debug stuff
; Update the performance counters
inc FrameCount
pha
_GTEGetSeconds
pla
@ -405,22 +153,17 @@ loopY
beq :no_fps
sta LastSecond
lda FrameCount
ldx #0
ldy #$FFFF
jsr DrawWord
; lda FrameCount
; ldx #0
; ldy #$FFFF
; jsr DrawWord
stz FrameCount
:no_fps
; tdc
; ldx #160*32
; jsr DrawWord
brl :evt_loop
; Shut down everything
:exit
Exit
_GTEShutDown
_QuitGS qtRec
qtRec adrl $0000
@ -432,56 +175,98 @@ PlayerY dw 72,24,13,56,35,72,23,8,93,123,134,87,143,14,46,65
PlayerU dw 1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4
PlayerV dw 1,1,1,1,2,2,2,4,3,3,3,3,4,4,4,4
; Load the GTE User Tool and install it
GTEStartUp
pea $0000
_LoaderStatus
_moveSprites
stz Tmp0
:loop
ldx Tmp0
lda PlayerX,x
clc
adc PlayerU,x
sta PlayerX,x
bpl :chk_xpos
eor #$FFFF
inc
sta PlayerX,x
bra :rev_x
:chk_xpos
cmp ScreenWidth
bcc :ok_x
sbc ScreenWidth
eor #$FFFF
inc
clc
adc ScreenWidth
sta PlayerX,x
:rev_x
lda PlayerU,x ; reverse the velocity
eor #$FFFF
inc
sta PlayerU,x
:ok_x
lda PlayerY,x
clc
adc PlayerV,x
sta PlayerY,x
bpl :chk_ypos
eor #$FFFF
inc
sta PlayerY,x
bra :rev_y
:chk_ypos
cmp ScreenHeight
bcc :ok_y
sbc ScreenHeight
eor #$FFFF
inc
clc
adc ScreenHeight
sta PlayerY,x
:rev_y
lda PlayerV,x ; reverse the velocity
eor #$FFFF
inc
sta PlayerV,x
:ok_y
txa
lsr
pha
lda PlayerX,x
pha
lda PlayerY,x
pha
_GTEMoveSprite
lda Tmp0
inc
inc
sta Tmp0
cmp #2*MAX_SPRITES
bcc :loop
rts
; Called by StartUp function callbacks when the screen size changes
SetLimits
pha ; Allocate space for x, y, width, height
pha
pha
pha
_GTEGetScreenInfo
pla
pea $0000
pea $0000
pea $0000
pea $0000
pea $0000 ; result space
lda MyUserId
pha
pea #^ToolPath
pea #ToolPath
pea $0001 ; do not load into special memory
_InitialLoad
bcc :ok1
brk $01
:ok1
ply
pla ; Address of the loaded tool
plx
ply
ply
pea $8000 ; User toolset
pea $00A0 ; Set the tool set number
phx
pha ; Address of function pointer table
_SetTSPtr
bcc :ok2
brk $02
:ok2
clc ; Give GTE a page of direct page memory
tdc
adc #$0100
pha
pea #ENGINE_MODE_DYN_TILES+ENGINE_MODE_TWO_LAYER ; Enable Dynamic Tiles and Two Layer
lda MyUserId ; Pass the userId for memory allocation
pha
_GTEStartUp
bcc :ok3
brk $03
:ok3
pla ; Discard screen corner
pla
sec
sbc #8
sta ScreenWidth ; Pre-adjust to keep sprites on the visible playfield (for compiled sprites)
pla
sec
sbc #16
sta ScreenHeight
rts
_fillTileStore
@ -490,25 +275,22 @@ _fillTileStore
:oloop
stz Tmp1
:iloop
pei Tmp1
pei Tmp0
pei Tmp2
_GTESetTile
lda Tmp2
eor #TILE_PRIORITY_BIT
sta Tmp2
ldx Tmp1
ldy Tmp0
jsr _drawTree
lda Tmp1
inc
inc
sta Tmp1
cmp #41
cmp #40
bcc :iloop
lda Tmp0
inc
inc
sta Tmp0
cmp #26
cmp #25
bcc :oloop
rts
@ -646,9 +428,10 @@ _drawTreeHV
rts
MyUserId ds 2
ToolPath str '1/Tool160'
FrameCount ds 2
LastSecond dw 0
palette dw $0000,$08C1,$0C41,$0F93,$0777,$0FDA,$00A0,$0000,$0D20,$0FFF,$023E,$0,$0,$0,$0,$0
PUT ../kfest-2022/StartUp.s
PUT App.Msg.s
PUT font.s

View File

@ -411,7 +411,8 @@ _AddSprite
jsr _PrecalcSpriteSize ; Cache sprite property values
jsr _PrecalcSpriteBounds
jmp _InsertSprite ; Insert it into the sorted list
jsr _InsertSprite ; Insert it into the sorted list
jmp _Validate
; _SortSprite
;
@ -468,7 +469,7 @@ _SortSprite
; Into
; a <=> b and c <=> x <=> y <=> d
:insert_before
jsr _OrphanNode
jsr _ReleaseNode
tya
sta _Sprites+SORTED_NEXT,x ; Link X to Y
@ -492,7 +493,7 @@ _SortSprite
; Into
; a <=> b and y <=> x -> nil
:insert_end
jsr _OrphanNode
jsr _ReleaseNode
lda #$FFFF
sta _Sprites+SORTED_NEXT,x
@ -520,7 +521,7 @@ _SortSprite
; Into
; a <=> b and c <=> y <=> x <=> d
:insert_after
jsr _OrphanNode
jsr _ReleaseNode
tya
sta _Sprites+SORTED_PREV,x ; c <=> y <-- x --- d
@ -544,7 +545,7 @@ _SortSprite
; Into
; a <=> b and head -> x <=> y
:insert_front
jsr _OrphanNode
jsr _ReleaseNode
stx _SortedHead
txa
@ -557,16 +558,10 @@ _SortSprite
:done
rts
; Take the node pointed at X and remove it from the doubly-linked list. Assumes it is not
; at the beginning or end of the list
_OrphanNode
; Take the node pointed at X and remove it from the doubly-linked list.
_ReleaseNode
phy
ldy _Sprites+SORTED_PREV,x ; Remove X from between A and B
lda _Sprites+SORTED_NEXT,x
sta _Sprites+SORTED_NEXT,y
tay
lda _Sprites+SORTED_PREV,x
sta _Sprites+SORTED_PREV,y
jsr _DeleteSprite
ply
rts
@ -663,7 +658,42 @@ _DeleteSprite
sta _SortedHead
rts
; Validate the integrity of the linked list
_Validate
:prev equ tmp0
:curr equ tmp1
ldy #$FFFF
ldx _SortedHead
bmi :done
:loop
sty :prev
stx :curr
lda _Sprites+SORTED_PREV,x
cmp :prev
beq *+4
brk $08
cpy #$FFFF
beq :skip
lda _Sprites+SORTED_NEXT,y
cmp :curr
beq *+4
brk $06
lda _Sprites+SPRITE_CLIP_TOP,x
cmp _Sprites+SPRITE_CLIP_TOP,y
bcs *+4
brk $0A
:skip
txy
lda _Sprites+SORTED_NEXT,x
tax
bpl :loop
:done
rts
; Macro to make the unrolled loop more concise
;
; 1. Load the tile store address from a fixed offset
@ -1211,4 +1241,5 @@ _MoveSprite
sta _Sprites+SPRITE_STATUS,x
jsr _PrecalcSpriteBounds ; Can be specialized to only update (x,y) values
jmp _SortSprite ; Update the sprite's sorted position
jsr _SortSprite ; Update the sprite's sorted position
jmp _Validate