Move most data storage to separate bank; fix many banking bugs

This commit is contained in:
Lucas Scharenbroich 2022-05-18 21:00:06 -05:00
parent 01e92a7b62
commit 755ac3fbfd
30 changed files with 850 additions and 461 deletions

View File

@ -11,6 +11,8 @@
mx %00
TSZelda EXT ; tileset buffer
ScreenX equ 0
ScreenY equ 2
@ -29,12 +31,41 @@ ScreenY equ 2
pea #160
_GTESetScreenMode
; Load a tileset in from an uncompressed $C1 picture. The top-left 256x128 rectangle is used
; to populate the 512 tiles.
; Load a tileset
pea #^TSZelda
pea #TSZelda
_GTELoadTileSet
; Manually fill in the 41x26 tiles of the TileStore with a test pattern.
ldx #0
ldy #0
:loop
phx
phy
phx
phy
pei 0
_GTESetTile
lda 0
inc
and #$001F
sta 0
ply
plx
inx
cpx #41
bcc :loop
ldx #0
iny
cpy #26
bcc :loop
; Set the origin of the screen
stz ScreenX
@ -53,7 +84,7 @@ ScreenY equ 2
pei ScreenY
_GTESetBG0Origin
; _GTERender
_GTERender
inc ScreenX ; Just keep incrementing, it's OK
bra :loop

View File

@ -8,3 +8,8 @@
ASM App.Main.s
SNA Main
; Segment #2 -- Tileset
ASM Zelda.TileSet.s
SNA TSET

View File

@ -325,3 +325,57 @@ transparent
sta: ]3+1,y
next
eom
; Large code blocks that can be used in sprite blitters
; ]1: line number
OneSpriteToCodeField mac
lda blttmp+{]1*4}
andl spritemask+{]1*SPRITE_PLANE_SPAN},x
oral spritedata+{]1*SPRITE_PLANE_SPAN},x
sta: $0004+{]1*$1000},y
lda blttmp+{]1*4}+2
andl spritemask+{]1*SPRITE_PLANE_SPAN}+2,x
oral spritedata+{]1*SPRITE_PLANE_SPAN}+2,x
sta: $0001+{]1*$1000},y
eom
TwoSpritesToCodeField mac
ldy #{]1*SPRITE_PLANE_SPAN}
lda blttmp+{]1*4}
andl [spritemask_1],y
oral [spritedata_1],y
andl [spritemask_0],y
oral [spritedata_0],y
sta: $0004+{]1*$1000},x
ldy #{]1*SPRITE_PLANE_SPAN}+2
lda blttmp+{]1*4}+2
andl [spritemask_1],y
oral [spritedata_1],y
andl [spritemask_0],y
oral [spritedata_0],y
sta: $0001+{]1*$1000},x
eom
ThreeSpritesToCodeField mac
ldy #{]1*SPRITE_PLANE_SPAN}
lda blttmp+{]1*4}
andl [spritemask_2],y
oral [spritedata_2],y
andl [spritemask_1],y
oral [spritedata_1],y
andl [spritemask_0],y
oral [spritedata_0],y
sta: $0004+{]1*$1000},x
ldy #{]1*SPRITE_PLANE_SPAN}+2
lda blttmp+{]1*4}+2
andl [spritemask_2],y
oral [spritedata_2],y
andl [spritemask_1],y
oral [spritedata_1],y
andl [spritemask_0],y
oral [spritedata_0],y
sta: $0001+{]1*$1000},x
eom

View File

@ -150,8 +150,8 @@ IntShutDown
OneSecHandler mx %11
phb
pha
phk
plb
jsr _SetDataBank
rep #$20
inc OneSecondCounter
@ -167,10 +167,7 @@ OneSecHandler mx %11
rtl
mx %00
OneSecondCounter ENT
dw 0
OldOneSecVec ds 4
; This is OK, it's referenced by a long address
VBLTASK hex 00000000
dw 0
hex 5AA5
@ -270,11 +267,6 @@ ClearKbdStrobe sep #$20
rts
; Read the keyboard and paddle controls and return in a game-controller-like format
LastKey db 0
ReadControl ENT
jsr _ReadControl
rtl
_ReadControl
pea $0000 ; low byte = key code, high byte = %------AB

View File

@ -92,7 +92,10 @@ TileStoreBankAndTileDataBank equ 108
TileStoreBankDoubled equ 110
UserId equ 112 ; Memory manager user Id to use
ToolNum equ 114 ; Tool number assigned to us
Next equ 116
LastKey equ 116
LastTick equ 118
Next equ 120
activeSpriteList equ 128 ; 32 bytes for the active sprite list (can persist across frames)
; tiletmp equ 178 ; 16 bytes of temp storage for the tile renderers
@ -141,8 +144,9 @@ _OP_CACHE equ 156 ; Cache of a relevant operand / oeprato
_TILE_ID equ 158 ; Copy of the tile descriptor
; Define free space the the application to use
FREE_SPACE_DP2 equ 160
; FREE_SPACE_DP2 equ 160
DP2_DIRTY_TILE_COUNT equ 160 ; Local copy of dirty tile count to avoid banking
DP2_DIRTY_TILE_CALLBACK equ 162
; End direct page values
; EngineMode definitions
@ -197,6 +201,7 @@ SPRITE_HFLIP equ $0200
; Stamp storage parameters
VBUFF_STRIDE_BYTES equ 12*4 ; Each line has 4 slots of 16 pixels + 8 buffer pixels
VBUFF_TILE_ROW_BYTES equ 8*VBUFF_STRIDE_BYTES ; Each row is comprised of 8 lines
VBUFF_TILE_COL_BYTES equ 4
VBUFF_SPRITE_STEP equ VBUFF_TILE_ROW_BYTES*3 ; Allocate space fo 16 rows + 8 rows of buffer
VBUFF_SPRITE_START equ {8*VBUFF_TILE_ROW_BYTES}+4 ; Start at an offset so $0000 can be used as an empty value
VBUFF_SLOT_COUNT equ 48 ; Have space for this many stamps
@ -204,31 +209,32 @@ VBUFF_SLOT_COUNT equ 48 ; Have space for this m
; This is 13 blocks wide
SPRITE_PLANE_SPAN equ VBUFF_STRIDE_BYTES
; Tile storage parameters
TILE_DATA_SPAN equ 4
TILE_STORE_WIDTH equ 41
TILE_STORE_HEIGHT equ 26
MAX_TILES equ {26*41} ; Number of tiles in the code field (41 columns * 26 rows)
TILE_STORE_SIZE equ {MAX_TILES*2} ; The tile store contains a tile descriptor in each slot
TS_TILE_ID equ TILE_STORE_SIZE*0 ; tile descriptor for this location
TS_DIRTY equ TILE_STORE_SIZE*1 ; Flag. Used to prevent a tile from being queued multiple times per frame
TS_SPRITE_FLAG equ TILE_STORE_SIZE*2 ; Bitfield of all sprites that intersect this tile. 0 if no sprites.
TS_TILE_ADDR equ TILE_STORE_SIZE*3 ; cached value, the address of the tiledata for this tile
TS_CODE_ADDR_LOW equ TILE_STORE_SIZE*4 ; const value, address of this tile in the code fields
TS_CODE_ADDR_HIGH equ TILE_STORE_SIZE*5
TS_WORD_OFFSET equ TILE_STORE_SIZE*6 ; const value, word offset value for this tile if LDA (dp),y instructions re used
TS_BASE_ADDR equ TILE_STORE_SIZE*7 ; const value, because there are two rows of tiles per bank, this is set to $0000 ot $8000.
TS_SCREEN_ADDR equ TILE_STORE_SIZE*8 ; cached value of on-screen location of tile. Used for DirtyRender.
;TS_VBUFF_ARRAY_ADDR equ TILE_STORE_SIZE*9 ; const value to an aligned 32-byte array starting at $8000 in TileStore bank
TS_BASE_TILE_COPY equ TILE_STORE_SIZE*9 ; derived from TS_TILE_ID to optimize tile copy to support sprite rendering
TS_BASE_TILE_DISP equ TILE_STORE_SIZE*10 ; derived from TS_TILE_ID to optimize base (non-sprite) tile dispatch in the Render function
TS_DIRTY_TILE_DISP equ TILE_STORE_SIZE*11 ; derived from TS_TILE_ID to optimize dirty tile dispatch in the Render function
; Hold values for up to 4 sprites per tile
TS_VBUFF_ADDR_0 equ TILE_STORE_SIZE*12
TS_VBUFF_ADDR_1 equ TILE_STORE_SIZE*13
TS_VBUFF_ADDR_2 equ TILE_STORE_SIZE*14
TS_VBUFF_ADDR_3 equ TILE_STORE_SIZE*15
TS_VBUFF_ADDR_COUNT equ TILE_STORE_SIZE*16 ; replace usage of TS_VBUFF_ARRAY_ADDR with this later
; External references to data bank
TileStore EXT
DirtyTileCount EXT
DirtyTiles EXT
_Sprites EXT
TileStore EXT
TileStoreLookupYTable EXT
TileStoreLookup EXT
Col2CodeOffset EXT
JTableOffset EXT
CodeFieldEvenBRA EXT
CodeFieldOddBRA EXT
ScreenAddr EXT
TileStoreYTable EXT
NextCol EXT
RTable EXT
BlitBuff EXT
BTableHigh EXT
BTableLow EXT
BRowTableHigh EXT
BRowTableLow EXT
BG1YTable EXT
BG1YOffsetTable EXT
OldOneSecVec EXT
OneSecondCounter EXT
Timers EXT
DefaultPalette EXT
ScreenModeWidth EXT
ScreenModeHeight EXT

View File

@ -73,21 +73,3 @@ AllocBank EXT
ScreenAddr EXT
OneSecondCounter EXT
BlitBuff EXT
;; Helper function to load the GTE User Toolset
;GTEInstall
; php
; ~InitialLoad userId;localToolPath;#0
; pea $8000 ; User tool
; pea $00A5 ; Tool 165
; PushLong toolPtr
; _SetTSPtr
; plp
; rtl
; Look for the tool set in the System Tools folder and then next to the application
;sysToolPath strl '*:System:Tools:ToolGTE'
;localToolPath strl '9:ToolGTE'
;toolPtr adrl 0

View File

@ -24,11 +24,6 @@ InitGraphics
:no_bg1
rts
DefaultPalette dw $0000,$007F,$0090,$0FF0
dw $000F,$0080,$0f70,$0FFF
dw $0fa9,$0ff0,$00e0,$04DF
dw $0d00,$078f,$0ccc,$0FFF
; Allow the user to dynamically select one of the pre-configured screen sizes, or pass
; in a specific width and height. The screen is automatically centered. If this is
; not desired, then SetScreenRect should be used directly
@ -47,18 +42,6 @@ DefaultPalette dw $0000,$007F,$0090,$0FF0
;
; X = mode number OR width in pixels (must be multiple of 2)
; Y = height in pixels (if X > 8)
ScreenModeWidth dw 320,272,256,256,280,256,240,288,160,288,160,320
ScreenModeHeight dw 200,192,200,176,160,160,160,128,144,192,102,1
SetScreenMode ENT
phb
phk
plb
jsr _SetScreenMode
plb
rtl
_SetScreenMode
cpx #11
bcs :direct ; if x > 10, then assume X and Y are the dimensions
@ -113,10 +96,6 @@ _GetBorderColor lda #0000
rts
; Set the border color to the accumulator value.
SetBorderColor ENT
jsr _SetBorderColor
rtl
_SetBorderColor sep #$20 ; ACC = $X_Y, REG = $W_Z
eorl BORDER_REG ; ACC = $(X^Y)_(Y^Z)
and #$0F ; ACC = $0_(Y^Z)
@ -135,17 +114,6 @@ _ClearToColor
rts
; Set a palette values
; A = high word of palette data pointer, X = low word of palette data pointer, Y = palette number
SetPalette ENT
phb ; save old data bank
pha ; push 16-bit value
plb ; pop 8-bit bank register
tya
jsr _SetPalette
plb ; pop the other half of the 16-bit push off
plb ; restore the original data bank
rtl
; A = palette number, X = palette address
_SetPalette
and #$000F ; palette values are 0 - 15 and each palette is 32 bytes
@ -307,7 +275,7 @@ SetScreenRect sty ScreenHeight ; Save the screen height and
ldx #0
ldy #0
:tsloop
stal TileStore+TS_SCREEN_ADDR,x
sta TileStore+TS_SCREEN_ADDR,x
clc
adc #4 ; Go to the next tile

View File

@ -28,9 +28,9 @@ InitMemory lda EngineMode
_NewHandle ; returns LONG Handle on stack
plx ; base address of the new handle
pla ; high address 00XX of the new handle (bank)
_Deref
stx Buff00
sta Buff00+2
; _Deref
; stx Buff00
; sta Buff00+2
:no_bnk0_buff
PushLong #0 ; space for result
@ -41,9 +41,9 @@ InitMemory lda EngineMode
_NewHandle ; returns LONG Handle on stack
plx ; base address of the new handle
pla ; high address 00XX of the new handle (bank)
_Deref
stx Buff01
sta Buff01+2
; _Deref
; stx Buff01
; sta Buff01+2
PushLong #0 ; space for result
@ -153,8 +153,8 @@ InitMemory lda EngineMode
:exit
rts
Buff00 ds 4
Buff01 ds 4
;Buff00 ds 4
;Buff01 ds 4
; Bank allocator (for one full, fixed bank of memory. Can be immediately deferenced)
@ -172,14 +172,6 @@ AllocOneBank PushLong #0
rts
; Variation that returns the pointer in the X/A registers (X = low, A = high)
AllocBank ENT
phb
phk
plb
jsr AllocOneBank2
plb
rtl
AllocOneBank2 PushLong #0
PushLong #$10000
PushWord UserId
@ -190,5 +182,3 @@ AllocOneBank2 PushLong #0
pla ; high address 00XX of the new handle (bank)
_Deref
rts

View File

@ -21,12 +21,12 @@
; used in all of the other loops
_Render
jsr _ApplyBG0YPos ; Set stack addresses for the virtual lines to the physical screen
jsr _ApplyBG1YPos
; jsr _ApplyBG1YPos
; _ApplyBG0Xpos need to be split because we have to set the offsets, then draw in any updated tiles, and
; finally patch out the code field. Right now, the BRA operand is getting overwritten by tile data.
jsr _ApplyBG0XPosPre
jsr _ApplyBG1XPosPre
; jsr _ApplyBG1XPosPre
; jsr _RenderSprites ; Once the BG0 X and Y positions are committed, update sprite data
@ -36,7 +36,7 @@ _Render
jsr _ApplyTilesFast ; This function actually draws the new tiles into the code field
jsr _ApplyBG0XPos ; Patch the code field instructions with exit BRA opcode
jsr _ApplyBG1XPos ; Update the direct page value based on the horizontal position
; jsr _ApplyBG1XPos ; Update the direct page value based on the horizontal position
; The code fields are locked in now and ready to be rendered
@ -99,26 +99,13 @@ _ApplyTilesFast
adc #$100 ; move to the next page
tcd
ldy DirtyTileCount
beq :out
:loop
; Retrieve the offset of the next dirty Tile Store items in the X-register
lda DirtyTileCount ; Cache the dirty tile count
sta DP2_DIRTY_TILE_COUNT
jsr _PopDirtyTile2
; Call the generic dispatch with the Tile Store record pointer at by the X-register.
stz DirtyTileCount
phb
jsr _RenderTileFast
plb
; Loop again until the list of dirty tiles is empty
ldy DirtyTileCount
bne :loop
:out
tdc ; Move back to the original direct page
sec
sbc #$100

View File

@ -35,8 +35,7 @@
; timer's user data section.
StartScript ENT
phb
phk
plb
jsr _SetDataBank
phx ; Save the script array address
pha
@ -69,14 +68,6 @@ ARG1 equ 2
ARG2 equ 4
ARG3 equ 6
DoScriptSeq ENT
phb
phk
plb
jsl _DoScriptSeq ; Yes, this is a special JSL, because _DoScriptSeq is a time callback
plb
rtl
_DoScriptSeq
phx ; save the timer index; will need to update user data at the end
phb ; save the current data bank
@ -180,9 +171,9 @@ _SetDTile
_UserCallback
lda: ARG1,y
sta :dispatch+1
stal :dispatch+1
lda: ARG1+1,y
sta :dispatch+2
stal :dispatch+2
lda: ARG3,y
:dispatch jsl $000000
brl _dss_cmd_rtn

View File

@ -27,24 +27,6 @@ InitSprites
; dex
; bpl :loop3
; Initialize the VBUFF address offsets in the data and mask banks for each sprite
;
; The internal grid 12 tiles wide where each sprite has a 2x2 interior square with a
; tile-size buffer all around. We pre-render each sprite with all four vert/horz flips
;
; Eventually we should be able to have a separate rendering path for vertically flipped
; sprites and will be able to double the capacity of the stamp buffer
ldx #0
lda #VBUFF_SPRITE_START
clc
:loop4 sta VBuffAddrTable,x
adc #VBUFF_SPRITE_STEP
inx
inx
cpx #VBUFF_SLOT_COUNT*2
bcc :loop4
; Precalculate some bank values
jsr _CacheSpriteBanks
rts
@ -68,38 +50,25 @@ InitSprites
; the stamp every time. So this allows users to create stamps in advance and then
; assign them to the sprites as needed.
;
; Currently, we support a maximum of 48 stamps.
; Note that the user had full freedom to create a stamp at any VBUFF address, however,
; without leaving a buffer around each stamp, graphical corruption will occur. It is
; recommended that the defines for VBUFF_SPRITE_START, VBUFF_TILE_ROW_BYTES and
; VBUFF_TILE_COL_BYTES to calculate tile-aligned corner locations to lay out the
; sprite stamps in VBUFF memory.
;
; Input:
; A = sprite descriptor
; X = stamp slot
; Return:
; A = vbuff address to be assigned to Sprite[VBUFF_ADDR]
CreateSpriteStamp ENT
phb
phk
plb
jsr _CreateSpriteStamp
plb
rtl
; Y = vbuff address
;
; The Sprite[VBUFF_ADDR] property must be set to the vbuff address passed into this function
; to bind the sprite stamp to the sprite record.
_CreateSpriteStamp
pha ; Save the descriptor
jsr _GetBaseTileAddr ; Get the address of the tile data
pha
txa
asl
tax
ldy VBuffAddrTable,x ; Load the address of the stamp slot
plx ; Pop the tile address
tax ; Tile data address
pla ; Pop the sprite ID
phy ; VBUFF_ADDR value
jsr _DrawSpriteStamp ; Render the sprite data and create a stamp
pla ; Pop the VBUFF_ADDR and return
rts
jmp _DrawSpriteStamp ; Render the sprite data and create a stamp
; Add a new sprite to the rendering pipeline
;
@ -123,14 +92,6 @@ _CreateSpriteStamp
; A = tileId + flags
; Y = High Byte = x-pos, Low Byte = y-pos
; X = Sprite Slot (0 - 15)
AddSprite ENT
phb
phk
plb
jsr _AddSprite
plb
rtl
_AddSprite
pha
txa
@ -888,14 +849,6 @@ _PrecalcAllSpriteInfo
; picked up in the next AddSprite.
;
; A = Sprite ID
RemoveSprite ENT
phb
phk
plb
jsr _RemoveSprite
plb
rtl
_RemoveSprite
cmp #MAX_SPRITES
bcc :ok
@ -917,14 +870,6 @@ _RemoveSprite
; A = Sprite ID
; X = New Sprite Flags
; Y = New Sprite Stamp Address
UpdateSprite ENT
phb
phk
plb
jsr _UpdateSprite
plb
rtl
_UpdateSprite
cmp #MAX_SPRITES
bcc :ok
@ -961,14 +906,6 @@ _UpdateSprite
; A = sprite ID
; X = x position
; Y = y position
MoveSprite ENT
phb
phk
plb
jsr _MoveSprite
plb
rtl
_MoveSprite
cmp #MAX_SPRITES
bcc :ok
@ -999,57 +936,3 @@ _MoveSprite
sta _Sprites+SPRITE_STATUS,x
jmp _PrecalcAllSpriteInfo ; Can be specialized to only update (x,y) values
; Sprite data structures. We cache quite a few pieces of information about the sprite
; to make calculations faster, so this is hidden from the caller.
;
;
; Number of "off-screen" lines above logical (0,0)
; NUM_BUFF_LINES equ 24
MAX_SPRITES equ 16
SPRITE_REC_SIZE equ 52
; Mark each sprite as ADDED, UPDATED, MOVED, REMOVED depending on the actions applied to it
; on this frame. Quick note, the same Sprite ID cannot be removed and added in the same frame.
; A REMOVED sprite if removed from the sprite list during the Render call, so it's ID is not
; available to the AddSprite function until the next frame.
SPRITE_STATUS_EMPTY equ $0000 ; If the status value is zero, this sprite slot is available
SPRITE_STATUS_OCCUPIED equ $8000 ; Set the MSB to flag it as occupied
SPRITE_STATUS_ADDED equ $0001 ; Sprite was just added (new sprite)
SPRITE_STATUS_MOVED equ $0002 ; Sprite's position was changed
SPRITE_STATUS_UPDATED equ $0004 ; Sprite's non-position attributes were changed
SPRITE_STATUS_REMOVED equ $0008 ; Sprite has been removed.
SPRITE_STATUS equ {MAX_SPRITES*0}
; TILE_DATA_OFFSET equ {MAX_SPRITES*2}
VBUFF_ADDR equ {MAX_SPRITES*4} ; Base address of the sprite's stamp in the data/mask banks
SPRITE_ID equ {MAX_SPRITES*6}
SPRITE_X equ {MAX_SPRITES*8}
SPRITE_Y equ {MAX_SPRITES*10}
; TILE_STORE_ADDR_1 equ {MAX_SPRITES*12}
TS_LOOKUP_INDEX equ {MAX_SPRITES*12} ; The index into the TileStoreLookup table corresponding to the top-left corner of the sprite
; TILE_STORE_ADDR_2 equ {MAX_SPRITES*14}
TS_COVERAGE_SIZE equ {MAX_SPRITES*14} ; Index into the lookup table of how many TileStore tiles are covered by this sprite
;TILE_STORE_ADDR_3 equ {MAX_SPRITES*16}
TS_VBUFF_BASE_ADDR equ {MAX_SPRITES*16} ; Fixed address of the TS_VBUFF_X memory locations
;TILE_STORE_ADDR_4 equ {MAX_SPRITES*18}
;TILE_STORE_ADDR_5 equ {MAX_SPRITES*20}
;TILE_STORE_ADDR_6 equ {MAX_SPRITES*22}
;TILE_STORE_ADDR_7 equ {MAX_SPRITES*24}
;TILE_STORE_ADDR_8 equ {MAX_SPRITES*26}
;TILE_STORE_ADDR_9 equ {MAX_SPRITES*28}
;TILE_STORE_ADDR_10 equ {MAX_SPRITES*30}
SPRITE_DISP equ {MAX_SPRITES*32} ; cached address of the specific stamp based on flags
SPRITE_CLIP_LEFT equ {MAX_SPRITES*34}
SPRITE_CLIP_RIGHT equ {MAX_SPRITES*36}
SPRITE_CLIP_TOP equ {MAX_SPRITES*38}
SPRITE_CLIP_BOTTOM equ {MAX_SPRITES*40}
IS_OFF_SCREEN equ {MAX_SPRITES*42}
SPRITE_WIDTH equ {MAX_SPRITES*44}
SPRITE_HEIGHT equ {MAX_SPRITES*46}
SPRITE_CLIP_WIDTH equ {MAX_SPRITES*48}
SPRITE_CLIP_HEIGHT equ {MAX_SPRITES*50}
_Sprites ds SPRITE_REC_SIZE*MAX_SPRITES

View File

@ -134,8 +134,11 @@ InitTiles
lda :row ; Set the long address of where this tile
asl ; exists in the code fields
tay
lda BRowTableHigh,y
lda #>TileStore ; get middle 16 bits: "00 -->BBHH<-- LL"
and #$FF00 ; merge with code field bank
ora BRowTableHigh,y
stal TileStore+TS_CODE_ADDR_HIGH,x ; High word of the tile address (just the bank)
lda BRowTableLow,y
stal TileStore+TS_BASE_ADDR,x ; May not be needed later if we can figure out the right constant...

View File

@ -1,37 +1,5 @@
; Timer implementation
;
; The engire provides four timer slot that can be used by one-shot or
; recurring timers. Each timer is given an initial tick count, a
; reset tick count (0 = one-shot), and an action to perform.
;
; The timers handle overflow, so if a recurring timer has a tick count of 3
; and 7 VBL ticks have passed, then the timer will be fired twice and
; a tick count of 2 will be set.
;
; As such, the timers are appropriate to drive physical and other game
; behaviors at a frame-independent rate.
;
; A collection of 4 timers that are triggered when their countdown
; goes below zero. Each timer takes up 16 bytes
;
; A timer can fire multiple times during a singular evaluation. For example, if the
; timer delay is set to 1 and 3 VBL ticks happen, then the timer delta is -2, will fire,
; have the delay added and get -1, fire again, increment to zero, first again and then
; finally reset to 1.
;
; +0 counter decremented by the number of ticks since last run
; +2 reset copied into counter when triggered. 0 turns off the timer.
; +4 addr long address of timer routine
; +8 user 8 bytes of user data space for timer state
MAX_TIMERS equ 4
TIMER_REC_SIZE equ 16
mx %00
lastTick ds 2
Timers ds TIMER_REC_SIZE*MAX_TIMERS
GetVBLTicks ENT
jsr _GetVBLTicks
rtl
_GetVBLTicks
PushLong #0
_GetTick
@ -42,7 +10,7 @@ _GetVBLTicks
; Initialize the timers
InitTimers
jsr _GetVBLTicks
sta lastTick
sta LastTick
lda #0
ldx #{TIMER_REC_SIZE*MAX_TIMERS}-2
@ -71,8 +39,7 @@ AddTimer ENT
pha
phy
phk
plb
jsr _SetDataBank
ldx #0
:loop lda Timers,x ; If the counter is zero, timer is free
@ -125,8 +92,7 @@ AddTimer ENT
; A = Timer ID
RemoveTimer ENT
phb
phk
plb
jsr _SetDataBank
cmp #{TIMER_REC_SIZE*{MAX_TIMERS-1}}+1
bcs :exit
@ -143,17 +109,16 @@ RemoveTimer ENT
; Execute the timer functions
DoTimers ENT
phb
phk
plb
jsr _SetDataBank
jsr _GetVBLTicks
cmp lastTick ; Throttle to 60 fps
cmp LastTick ; Throttle to 60 fps
beq :exit
tax ; Calculate the increment
sec
sbc lastTick
stx lastTick
sbc LastTick
stx LastTick
; We don't want times to fire excessively. If the timer has nt been evaluated for over
; one second, then just skip processing and wait for the next call.
@ -186,9 +151,9 @@ _DoTimers
phx ; Save our index
lda Timers+4,x ; execute the timer callback
sta :dispatch+1
stal :dispatch+1
lda Timers+5,x
sta :dispatch+2
stal :dispatch+2
:dispatch jsl $000000
plx

View File

@ -10,6 +10,7 @@
use Core.MACS.s
use Defs.s
use static/TileStoreDefs.s
ToStrip equ $E10184
@ -18,8 +19,7 @@ _TSEntry mac
phd
phb
tcd
phk ; Default to setting the data back to the current bank.
plb
jsr _SetDataBank
<<<
_TSExit mac
@ -53,6 +53,14 @@ _CallTable
adrl _TSLoadTileSet-1
_CTEnd
; Helper function to set the data back to the toolset default
_SetDataBank sep #$20
lda #^TileStore
pha
plb
rep #$20
rts
; Do nothing when the tool set is installed
_TSBootInit
lda #0
@ -86,8 +94,7 @@ zpToUse = userId+4
sta EngineMode
phb
phk
plb
jsr _SetDataBank
jsr _CoreStartUp ; Initialize the library
plb
@ -114,8 +121,7 @@ _TSShutDown
tcd ; Set the direct page for the toolset
phb
phk
plb
jsr _SetDataBank
jsr _CoreShutDown ; Shut down the library
plb
@ -201,7 +207,7 @@ xTile equ FirstParam+4
tax
lda yTile,s ; Valid range [0, 25] (26 rows)
tay
lda tileId
lda tileId,s
jsr _SetTile
_TSExit #0;#6
@ -255,7 +261,6 @@ TSPtr equ FirstParam
put blitter/BG1.s
put blitter/Template.s
put blitter/TemplateUtils.s
put blitter/Tables.s
put blitter/Blitter.s
put blitter/TileProcs.s
put blitter/Tiles00000.s

View File

@ -8,14 +8,6 @@ _InitBG0
;
; A=low word of picture address
; X=high word of pixture address
CopyBinToField ENT
phb
phk
plb
jsr _CopyBinToField
plb
rtl
_CopyBinToField
:srcptr equ tmp0
:line_cnt equ tmp2
@ -222,14 +214,6 @@ _CopyBinToField
; X=high workd of pixture address
;
; Picture must be within one bank
CopyPicToField ENT
phb
phk
plb
jsr _CopyPicToField
plb
rtl
_CopyPicToField
:srcptr equ tmp0
:line_cnt equ tmp2

View File

@ -9,14 +9,6 @@ _InitBG1
; A=low word of picture address
; X=high word of pixture address
; Y=high word of BG1 bank
CopyBinToBG1 ENT
phb
phk
plb
jsr _CopyBinToBG1
plb
rtl
_CopyBinToBG1
:src_width equ tmp6
:src_height equ tmp7
@ -39,14 +31,6 @@ _CopyBinToBG1
; A=low word of picture address
; X=high word of pixture address
; Y=high word of BG1 bank
CopyPicToBG1 ENT
phb
phk
plb
jsr _CopyPicToBG1
plb
rtl
_CopyPicToBG1
:src_width equ tmp6
:src_height equ tmp7
@ -221,6 +205,8 @@ _ApplyBG1YPos
:draw_count equ tmp2
:ytbl_idx equ tmp3
phb ; Save the bank
lda BG1StartY
jsr Mod208
sta BG1StartYMod208
@ -277,7 +263,6 @@ _ApplyBG1YPos
jne :loop
phk
plb
rts
@ -369,16 +354,14 @@ CopyBG1YTableToBG1Addr2
phx
phb
phk ; restore access to this bank
plb
jsr _SetDataBank ; restore access to this bank
ldy BG1OffsetIndex ; Get the offset and save the values
jsr SaveBG1OffsetValues
plb
plx ; x is used directly in this routine
ply
jsr ApplyBG1OffsetValues
rts
jmp ApplyBG1OffsetValues
SaveBG1OffsetValues
jmp (:tbl,x)

View File

@ -33,10 +33,10 @@ _BltRange
sep #$20 ; 8-bit Acc
lda BTableHigh,x ; patch in the bank
sta blt_entry+3
stal blt_entry+3
lda BTableLow+1,x ; patch in the page
sta blt_entry+2
stal blt_entry+2
; The way we patch the exit code is subtle, but very fast. The CODE_EXIT offset points to
; an JMP/JML instruction that transitions to the next line after all of the code has been
@ -74,6 +74,7 @@ _BltRange
tsc ; save the stack pointer
stal stk_save+1
bra blt_return
blt_entry jml $000000 ; Jump into the blitter code $XX/YY00
blt_return _R0W0
@ -88,5 +89,6 @@ stk_save lda #0000 ; load the stack
sta [:exit_ptr],y
rep #$20
blt_out
plb ; restore the bank
rts

View File

@ -21,6 +21,8 @@ _RestoreBG0Opcodes
:draw_count_x2 equ tmp3
:exit_offset equ tmp4
phb ; Save data bank
asl
sta :virt_line_x2 ; Keep track of it
@ -75,7 +77,6 @@ _RestoreBG0Opcodes
stz LastPatchOffset ; Clear the value once completed
:out
phk
plb
rts
@ -279,6 +280,7 @@ _ApplyBG0XPos
; 2. Writes the BRA instruction to exit the code field
; 3. Writes the JMP entry point to enter the code field
phb ; Save the existing bank
:loop
lda :virt_line
asl ; This will clear the carry bit
@ -353,7 +355,7 @@ _ApplyBG0XPos
ldx :draw_count_x2
ldy :base_address ; Y-register is preserved, this can be removed
pei :exit_address
jmp :SaveHighOperand ; Only used once, so "inline" it
jmp :SaveHighOperand ; Only used once, so "inline" it
:save_high_op_rtn
:not_odd
@ -374,7 +376,6 @@ _ApplyBG0XPos
jne :loop
phk
plb
rts

View File

@ -15,13 +15,13 @@
_PEISlam
lda ScreenWidth
dec
sta :screen_width_1 ; save the width-1 outside of the direct page
stal :screen_width_1 ; save the width-1 outside of the direct page
lda #:pei_end ; patch the PEI entry address
and #$FFFE ; should always be even, but....
sec
sbc ScreenWidth
sta :inner+1
stal :inner+1
phx
tya
@ -43,7 +43,7 @@ _PEISlam
tcd ; screen address to the direct page register
tsc
sta :stk_save ; save the stack pointer to restore later
stal :stk_save ; save the stack pointer to restore later
clc ; clear before the loop -- nothing in the loop affect the carry bit
brl :outer ; hop into the entry point.
@ -57,7 +57,7 @@ _PEISlam
tdc ; Move to the next line
adc #160
tcd
adc :screen_width_1
adcl :screen_width_1
tcs
dey ; decrement the total counter, if zero then we're done
@ -79,7 +79,7 @@ _PEISlam
:restore
tsx ; save the current stack
_R0W0 ; restore the execution environment and
lda :stk_save ; give a few cycles to catch some interrupts
ldal :stk_save ; give a few cycles to catch some interrupts
tcs
cli ; fall through here -- saves a BRA instruction
@ -92,7 +92,7 @@ _PEISlam
:exit
_R0W0
lda :stk_save
ldal :stk_save
tcs
cli

View File

@ -10,14 +10,6 @@
; of the BG1 data buffer provides the "fill value".
ANGLEBNK ext
ApplyBG1XPosAngle ENT
phb
phk
plb
jsr _ApplyBG1XPosAngle
plb
rtl
_ApplyBG1XPosAngle
; phy
@ -62,14 +54,6 @@ _ApplyBG1XPosAngle
pld
rts
ApplyBG1YPosAngle ENT
phb
phk
plb
jsr _ApplyBG1YPosAngle
plb
rtl
_ApplyBG1YPosAngle
:virt_line equ tmp0
:lines_left equ tmp1
@ -90,6 +74,7 @@ _ApplyBG1YPosAngle
lda ScreenHeight
sta :lines_left
phb
:loop
lda :virt_line
asl
@ -141,7 +126,6 @@ _ApplyBG1YPosAngle
jne :loop
phk
plb
rts
@ -155,14 +139,13 @@ CopyAngleYTableToBG1Addr
phx
phb
phk ; restore access to this bank
plb
jsr _SetDataBank ; restore access to this bank
jsr SaveBG1AngleValues
plb
plx ; x is used directly in this routine
jsr ApplyBG1OffsetValues
rts
jmp ApplyBG1OffsetValues
SaveBG1AngleValues
jmp (:tbl,x)

View File

@ -9,15 +9,7 @@
; on the SHR screen or the current value of StartY
;
; This could be made faster by forcing a SCB array to be copied into PEAs ahead of time, but this
; is a bit more flexible
BltSCB ENT
phb
phk
plb
jsr _BltSCB
plb
rtl
; is a bit more flexible
_BltSCBOut
rts
_BltSCB