mirror of
https://github.com/lscharen/iigs-game-engine.git
synced 2024-12-27 11:30:10 +00:00
Checkpoint of work
This commit is contained in:
parent
3848c98a21
commit
027f9746ec
@ -166,7 +166,7 @@ There are four subroutines that are available to provide sprite support in GTE:
|
||||
|
||||
# Rendering a Frame
|
||||
|
||||
There is a single `Render` subroutine that applies all of the frame changes and efficiently renders to the super hires screen. It bear repeating here that most of the GTE functions operate in a deferred manner; any expensive operation that involved updating internal data structures is delayed until the `Render` function in called.
|
||||
There is a single `Render` subroutine that applies all of the frame changes and efficiently renders to the super hires screen. It bears repeating here that most of the GTE functions operate in a deferred manner; any expensive operation that involved updating internal data structures is delayed until the `Render` function in called.
|
||||
|
||||
```asm
|
||||
jsl Render
|
||||
@ -185,4 +185,5 @@ GTE provides the following capabilities
|
||||
* [Apple IIgs Graphics and Sound College](https://www.kansasfest.org/wp-content/uploads/1992-heineman-gs.pdf)
|
||||
* [Adaptive Tile Refresh](https://en.wikipedia.org/wiki/Adaptive_tile_refresh)
|
||||
* [A Guide to the Graphics of the Sega Mega Drive / Genesis](https://rasterscroll.com/mdgraphics/)
|
||||
* [Jon Burton / Traveller's Tales / Coding Secrets](https://ttjontt.wixsite.com/gamehut/coding-secrets)
|
||||
* [Jon Burton / Traveller's Tales / Coding Secrets](https://ttjontt.wixsite.com/gamehut/coding-secrets)
|
||||
* [Lou's Pseudo 3d Page](http://www.extentofthejam.com/pseudo/)
|
@ -158,3 +158,4 @@ TS_CODE_ADDR_HIGH equ TILE_STORE_SIZE*5 ; const value
|
||||
TS_WORD_OFFSET equ TILE_STORE_SIZE*6
|
||||
TS_BASE_ADDR equ TILE_STORE_SIZE*7
|
||||
TS_SPRITE_ADDR equ TILE_STORE_SIZE*8
|
||||
TS_SCREEN_ADDR equ TILE_STORE_SIZE*9
|
||||
|
@ -48,6 +48,7 @@ StopScript EXT
|
||||
AddSprite EXT
|
||||
MoveSprite EXT ; Set an existing sprite's position
|
||||
UpdateSprite EXT ; Change an existing sprite's flags
|
||||
RemoveSprite EXT
|
||||
|
||||
; Direct access to internals
|
||||
DoScriptSeq EXT
|
||||
@ -60,6 +61,8 @@ RenderTile EXT ; Y = address from GetTileStoreOffset
|
||||
GetTileStoreOffset EXT ; X = column, Y = row
|
||||
TileStore EXT ; Tile store internal data structure
|
||||
|
||||
RenderDirty EXT ; Render only dirty tiles + sprites directly to the SHR screen
|
||||
|
||||
GetSpriteVBuffAddr EXT ; X = x-coordinate (0 - 159), Y = y-coordinate (0 - 199). Return in Acc.
|
||||
|
||||
; Allocate a full 64K bank
|
||||
|
138
src/Render.s
138
src/Render.s
@ -140,3 +140,141 @@ _Render
|
||||
|
||||
stz DirtyBits
|
||||
rts
|
||||
|
||||
; This is a specialized redner function that only updated the dirty tiles *and* draws them
|
||||
; directly onto the SHR graphics buffer. The playfield is not used at all. In some way, this
|
||||
; ignores almost all of the capabilities of GTE, but it does provide a convenient way to use
|
||||
; the sprite subsystem + tile attributes for single-screen games which should be able to run
|
||||
; close to 60 fps.
|
||||
RenderDirty ENT
|
||||
phb
|
||||
phk
|
||||
plb
|
||||
jsr _RenderDirty
|
||||
plb
|
||||
rtl
|
||||
|
||||
; In this renderer, we assume that thwere is no scrolling, so no need to update any information about
|
||||
; the BG0/BG1 positions
|
||||
_RenderDirty
|
||||
jsr _RenderSprites
|
||||
jsr _ApplyDirtyTiles
|
||||
rts
|
||||
|
||||
_ApplyDirtyTiles
|
||||
bra :begin
|
||||
|
||||
:loop
|
||||
; Retrieve the offset of the next dirty Tile Store items in the Y-register
|
||||
|
||||
jsr _PopDirtyTile2
|
||||
|
||||
; Call the generic dispatch with the Tile Store record pointer at by the Y-register.
|
||||
|
||||
phb
|
||||
jsr _RenderDirtyTile
|
||||
plb
|
||||
|
||||
; Loop again until the list of dirty tiles is empty
|
||||
|
||||
:begin ldx DirtyTileCount
|
||||
bne :loop
|
||||
rts
|
||||
|
||||
; Only render solid tiles and sprites
|
||||
_RenderDirtyTile
|
||||
lda TileStore+TS_TILE_ID,y ; build the finalized tile descriptor
|
||||
and #TILE_VFLIP_BIT+TILE_HFLIP_BIT ; get the lookup value
|
||||
xba
|
||||
|
||||
ldx TileStore+TS_SPRITE_FLAG,y ; This is a bitfield of all the sprites that intersect this tile, only care if non-zero or not
|
||||
beq :nosprite
|
||||
|
||||
ldx TileStore+TS_SPRITE_ADDR,y
|
||||
stx _SPR_X_REG
|
||||
|
||||
tax
|
||||
lda DirtyTileSpriteProcs,x
|
||||
sta :tiledisp+1
|
||||
bra :sprite
|
||||
|
||||
:nosprite
|
||||
tax
|
||||
lda DirtyTileProcs,x ; load and patch in the appropriate subroutine
|
||||
sta :tiledisp+1
|
||||
|
||||
:sprite
|
||||
ldx TileStore+TS_TILE_ADDR,y ; load the address of this tile's data (pre-calculated)
|
||||
lda TileStore+TS_SCREEN_ADDR,y ; Get the on-screen address of this tile
|
||||
pha
|
||||
|
||||
lda TileStore+TS_WORD_OFFSET,y
|
||||
ply
|
||||
pea $0101
|
||||
plb
|
||||
plb ; set the bank
|
||||
|
||||
; B is set to Bank 01
|
||||
; A is set to the tile word offset (0 through 80 in steps of 4)
|
||||
; Y is set to the top-left address of the tile in SHR screen
|
||||
; X is set to the address of the tile data
|
||||
|
||||
:tiledisp jmp $0000 ; render the tile
|
||||
|
||||
DirtyTileProcs dw _TBDirtyTile_00,_TBDirtyTile_0H,_TBDirtyTile_V0,_TBDirtyTile_VH
|
||||
DirtyTileSpriteProcs dw _TBDirtySpriteTile_00,_TBDirtySpriteTile_0H,_TBDirtySpriteTile_V0,_TBDirtySpriteTile_VH
|
||||
|
||||
; Blit tiles directly to the screen.
|
||||
_TBDirtyTile_00
|
||||
_TBDirtyTile_0H
|
||||
]line equ 0
|
||||
lup 8
|
||||
ldal tiledata+{]line*4},x
|
||||
sta: $0000+{]line*160},y
|
||||
ldal tiledata+{]line*4}+2,x
|
||||
sta: $0002+{]line*160},y
|
||||
]line equ ]line+1
|
||||
--^
|
||||
rts
|
||||
|
||||
_TBDirtyTile_V0
|
||||
_TBDirtyTile_VH
|
||||
]src equ 7
|
||||
]dest equ 0
|
||||
lup 8
|
||||
ldal tiledata+{]src*4},x
|
||||
sta: $0000+{]dest*160},y
|
||||
ldal tiledata+{]src*4}+2,x
|
||||
sta: $0002+{]dest*160},y
|
||||
]src equ ]src-1
|
||||
]dest equ ]dest+1
|
||||
--^
|
||||
rts
|
||||
|
||||
_TBDirtySpriteTile_00
|
||||
_TBDirtySpriteTile_0H
|
||||
jsr _TBCopyTileDataToCBuff ; Copy the tile into the compositing buffer (using correct x-register)
|
||||
jmp _TBApplyDirtySpriteData ; Overlay the data from the sprite plane (and copy into the code field)
|
||||
|
||||
_TBDirtySpriteTile_V0
|
||||
_TBDirtySpriteTile_VH
|
||||
jsr _TBCopyTileDataToCBuffV
|
||||
jmp _TBApplyDirtySpriteData
|
||||
|
||||
_TBApplyDirtySpriteData
|
||||
ldx _SPR_X_REG ; set to the unaligned tile block address in the sprite plane
|
||||
|
||||
]line equ 0
|
||||
lup 8
|
||||
lda blttmp+{]line*4}
|
||||
andl spritemask+{]line*SPRITE_PLANE_SPAN},x
|
||||
oral spritedata+{]line*SPRITE_PLANE_SPAN},x
|
||||
sta: $0000+{]line*160},y
|
||||
|
||||
lda blttmp+{]line*4}+2
|
||||
andl spritemask+{]line*SPRITE_PLANE_SPAN}+2,x
|
||||
oral spritedata+{]line*SPRITE_PLANE_SPAN}+2,x
|
||||
sta: $0002+{]line*160},y
|
||||
]line equ ]line+1
|
||||
--^
|
||||
rts
|
169
src/Sprite.s
169
src/Sprite.s
@ -177,7 +177,8 @@ _RenderSprites
|
||||
ora forceSpriteFlag
|
||||
and #SPRITE_STATUS_DIRTY ; If the dirty flag is set, do the things....
|
||||
bne :render
|
||||
:next iny
|
||||
:next
|
||||
iny
|
||||
iny
|
||||
bra :loop
|
||||
:out rts
|
||||
@ -312,7 +313,8 @@ erase_16x8
|
||||
erase_16x16
|
||||
clc
|
||||
ldx _Sprites+OLD_VBUFF_ADDR,y
|
||||
jsr _EraseTileSprite
|
||||
jmp _EraseTileSprite16x16
|
||||
; jsr _EraseTileSprite
|
||||
|
||||
txa
|
||||
adc #4
|
||||
@ -449,7 +451,9 @@ draw_16x16
|
||||
ldx _Sprites+VBUFF_ADDR,y
|
||||
lda _Sprites+TILE_DATA_OFFSET,y
|
||||
tay
|
||||
jsr _DrawTile8x8
|
||||
jmp _DrawTile16x16
|
||||
|
||||
; jsr _DrawTile8x8
|
||||
txa
|
||||
adc #4
|
||||
tax
|
||||
@ -605,6 +609,102 @@ _DrawTile8x8
|
||||
plb
|
||||
rts
|
||||
|
||||
; X = sprite vbuff address
|
||||
; Y = tile data pointer
|
||||
_DrawTile16x16
|
||||
phb
|
||||
pea #^tiledata ; Set the bank to the tile data
|
||||
plb
|
||||
|
||||
]line equ 0
|
||||
lup 8
|
||||
lda: tiledata+32+{]line*4},y
|
||||
andl spritemask+{]line*256},x
|
||||
stal spritemask+{]line*256},x
|
||||
|
||||
ldal spritedata+{]line*SPRITE_PLANE_SPAN},x
|
||||
and: tiledata+32+{]line*4},y
|
||||
ora: tiledata+{]line*4},y
|
||||
stal spritedata+{]line*SPRITE_PLANE_SPAN},x
|
||||
|
||||
lda: tiledata+32+{]line*4}+2,y
|
||||
andl spritemask+{]line*SPRITE_PLANE_SPAN}+2,x
|
||||
stal spritemask+{]line*SPRITE_PLANE_SPAN}+2,x
|
||||
|
||||
ldal spritedata+{]line*SPRITE_PLANE_SPAN}+2,x
|
||||
and: tiledata+32+{]line*4}+2,y
|
||||
ora: tiledata+{]line*4}+2,y
|
||||
stal spritedata+{]line*SPRITE_PLANE_SPAN}+2,x
|
||||
|
||||
lda: tiledata+32+128+{]line*4},y
|
||||
andl spritemask+{]line*SPRITE_PLANE_SPAN}+4,x
|
||||
stal spritemask+{]line*SPRITE_PLANE_SPAN}+4,x
|
||||
|
||||
ldal spritedata+{]line*SPRITE_PLANE_SPAN}+4,x
|
||||
and: tiledata+32+128+{]line*4},y
|
||||
ora: tiledata+128+{]line*4},y
|
||||
stal spritedata+{]line*SPRITE_PLANE_SPAN}+4,x
|
||||
|
||||
lda: tiledata+32+128+{]line*4}+2,y
|
||||
andl spritemask+{]line*SPRITE_PLANE_SPAN}+6,x
|
||||
stal spritemask+{]line*SPRITE_PLANE_SPAN}+6,x
|
||||
|
||||
ldal spritedata+{]line*SPRITE_PLANE_SPAN}+6,x
|
||||
and: tiledata+32+128+{]line*4}+2,y
|
||||
ora: tiledata+128+{]line*4}+2,y
|
||||
stal spritedata+{]line*SPRITE_PLANE_SPAN}+6,x
|
||||
|
||||
]line equ ]line+1
|
||||
--^
|
||||
|
||||
TILE_ROW_STRIDE equ 32*128
|
||||
SPRITE_ROW_STRIDE equ 8*SPRITE_PLANE_SPAN
|
||||
|
||||
]line equ 0
|
||||
lup 8
|
||||
lda: tiledata+TILE_ROW_STRIDE+32+{]line*4},y
|
||||
andl spritemask+SPRITE_ROW_STRIDE+{]line*256},x
|
||||
stal spritemask+SPRITE_ROW_STRIDE+{]line*256},x
|
||||
|
||||
ldal spritedata+SPRITE_ROW_STRIDE+{]line*SPRITE_PLANE_SPAN},x
|
||||
and: tiledata+TILE_ROW_STRIDE+32+{]line*4},y
|
||||
ora: tiledata+TILE_ROW_STRIDE+{]line*4},y
|
||||
stal spritedata+SPRITE_ROW_STRIDE+{]line*SPRITE_PLANE_SPAN},x
|
||||
|
||||
lda: tiledata+TILE_ROW_STRIDE+32+{]line*4}+2,y
|
||||
andl spritemask+SPRITE_ROW_STRIDE+{]line*SPRITE_PLANE_SPAN}+2,x
|
||||
stal spritemask+SPRITE_ROW_STRIDE+{]line*SPRITE_PLANE_SPAN}+2,x
|
||||
|
||||
ldal spritedata+SPRITE_ROW_STRIDE+{]line*SPRITE_PLANE_SPAN}+2,x
|
||||
and: tiledata+TILE_ROW_STRIDE+32+{]line*4}+2,y
|
||||
ora: tiledata+TILE_ROW_STRIDE+{]line*4}+2,y
|
||||
stal spritedata+SPRITE_ROW_STRIDE+{]line*SPRITE_PLANE_SPAN}+2,x
|
||||
|
||||
lda: tiledata+TILE_ROW_STRIDE+32+128+{]line*4},y
|
||||
andl spritemask+SPRITE_ROW_STRIDE+{]line*SPRITE_PLANE_SPAN}+4,x
|
||||
stal spritemask+SPRITE_ROW_STRIDE+{]line*SPRITE_PLANE_SPAN}+4,x
|
||||
|
||||
ldal spritedata+SPRITE_ROW_STRIDE+{]line*SPRITE_PLANE_SPAN}+4,x
|
||||
and: tiledata+TILE_ROW_STRIDE+32+128+{]line*4},y
|
||||
ora: tiledata+TILE_ROW_STRIDE+128+{]line*4},y
|
||||
stal spritedata+SPRITE_ROW_STRIDE+{]line*SPRITE_PLANE_SPAN}+4,x
|
||||
|
||||
lda: tiledata+TILE_ROW_STRIDE+32+128+{]line*4}+2,y
|
||||
andl spritemask+SPRITE_ROW_STRIDE+{]line*SPRITE_PLANE_SPAN}+6,x
|
||||
stal spritemask+SPRITE_ROW_STRIDE+{]line*SPRITE_PLANE_SPAN}+6,x
|
||||
|
||||
ldal spritedata+SPRITE_ROW_STRIDE+{]line*SPRITE_PLANE_SPAN}+6,x
|
||||
and: tiledata+TILE_ROW_STRIDE+128+32+{]line*4}+2,y
|
||||
ora: tiledata+TILE_ROW_STRIDE+128+{]line*4}+2,y
|
||||
stal spritedata+SPRITE_ROW_STRIDE+{]line*SPRITE_PLANE_SPAN}+6,x
|
||||
|
||||
]line equ ]line+1
|
||||
--^
|
||||
|
||||
plb ; pop extra byte
|
||||
plb
|
||||
rts
|
||||
|
||||
; X = sprite vbuff address
|
||||
; Y = tile data pointer
|
||||
;
|
||||
@ -695,6 +795,38 @@ _EraseTileSprite
|
||||
plb
|
||||
rts
|
||||
|
||||
_EraseTileSprite16x16
|
||||
phb ; Save the bank to switch to the sprite plane
|
||||
|
||||
pea #^spritedata
|
||||
plb
|
||||
|
||||
lda #0
|
||||
]line equ 0
|
||||
lup 16
|
||||
sta: {]line*SPRITE_PLANE_SPAN}+0,x
|
||||
sta: {]line*SPRITE_PLANE_SPAN}+2,x
|
||||
sta: {]line*SPRITE_PLANE_SPAN}+4,x
|
||||
sta: {]line*SPRITE_PLANE_SPAN}+6,x
|
||||
]line equ ]line+1
|
||||
--^
|
||||
|
||||
pea #^spritemask
|
||||
plb
|
||||
|
||||
lda #$FFFF
|
||||
]line equ 0
|
||||
lup 16
|
||||
sta: {]line*SPRITE_PLANE_SPAN}+0,x
|
||||
sta: {]line*SPRITE_PLANE_SPAN}+2,x
|
||||
sta: {]line*SPRITE_PLANE_SPAN}+4,x
|
||||
sta: {]line*SPRITE_PLANE_SPAN}+6,x
|
||||
]line equ ]line+1
|
||||
--^
|
||||
|
||||
pla
|
||||
plb
|
||||
rts
|
||||
; Add a new sprite to the rendering pipeline
|
||||
;
|
||||
; The tile id ithe range 0 - 511. The top 7 bits are used as sprite control bits
|
||||
@ -785,6 +917,36 @@ _GetSpriteVBuffAddr
|
||||
pla
|
||||
rts
|
||||
|
||||
|
||||
; Remove a sprite from the list. Just mark its STATUS as FREE and it will be
|
||||
; picked up in the next AddSprite. We have to be carful not to set it to zero
|
||||
; as that will truncate the sprite list
|
||||
;
|
||||
; A = Sprite ID
|
||||
RemoveSprite ENT
|
||||
phb
|
||||
phk
|
||||
plb
|
||||
jsr _RemoveSprite
|
||||
plb
|
||||
rtl
|
||||
|
||||
|
||||
_RemoveSprite
|
||||
cmp #MAX_SPRITES*2 ; Make sure we're in bounds
|
||||
bcc :ok
|
||||
rts
|
||||
|
||||
:ok
|
||||
lda #SPRITE_STATUS_FREE
|
||||
sta _Sprites+SPRITE_STATUS,x
|
||||
|
||||
lda tmp0 ; Update the Tile ID
|
||||
sta _Sprites+SPRITE_ID,x ; Keep a copy of the full descriptor
|
||||
jsr _GetTileAddr ; This applies the TILE_ID_MASK
|
||||
sta _Sprites+TILE_DATA_OFFSET,x
|
||||
rts
|
||||
|
||||
; Update the sprite's flags. We do not allow the size fo a sprite to be changed. That required
|
||||
; the sprite to be removed and re-added.
|
||||
;
|
||||
@ -878,6 +1040,7 @@ SPRITE_REC_SIZE equ 34
|
||||
SPRITE_STATUS_EMPTY equ 0
|
||||
SPRITE_STATUS_CLEAN equ 1
|
||||
SPRITE_STATUS_DIRTY equ 2
|
||||
SPRITE_STATUS_FREE equ 4
|
||||
|
||||
SPRITE_STATUS equ {MAX_SPRITES*0}
|
||||
TILE_DATA_OFFSET equ {MAX_SPRITES*2}
|
||||
|
@ -124,6 +124,38 @@ SetScreenRect sty ScreenHeight ; Save the screen height and
|
||||
inx
|
||||
dey
|
||||
bne :loop
|
||||
|
||||
; Calculate the screen locations for each tile cornder
|
||||
|
||||
lda ScreenY0 ; Calculate the address of the first byte
|
||||
asl ; of the right side of the playfield
|
||||
tax
|
||||
lda ScreenAddr,x ; This is the address for the left edge of the physical screen
|
||||
clc
|
||||
adc ScreenX0
|
||||
|
||||
ldx #0
|
||||
ldy #0
|
||||
:tsloop
|
||||
sta TileStore+TS_SCREEN_ADDR,X
|
||||
|
||||
clc
|
||||
adc #4 ; Go to the next tile
|
||||
|
||||
iny
|
||||
cpy #41 ; If we've done 41 columns, move to the next line
|
||||
bcc :nohop
|
||||
ldy #0
|
||||
clc
|
||||
adc #{8*160}-{4*41}
|
||||
:nohop
|
||||
|
||||
inx
|
||||
inx
|
||||
cpx #TILE_STORE_SIZE-2
|
||||
bcc :tsloop
|
||||
|
||||
; Return
|
||||
rts
|
||||
|
||||
; Clear the SHR screen and then infill the defined field
|
||||
@ -725,7 +757,7 @@ snippets lup 82
|
||||
|
||||
bcs :byte ; if C = 0, just push the data and return
|
||||
pha ; 1 byte
|
||||
jmp loop+3+{3*]index}-base ; 3 bytes : use relative branch for convenience
|
||||
jmp loop+3+{3*]index}-base ; 3 bytes
|
||||
:byte jmp jmp_rtn-base ; 3 bytes
|
||||
]index equ ]index+1
|
||||
--^
|
||||
|
@ -505,9 +505,10 @@ _CopyBG1Tile
|
||||
; TileStore+TS_CODE_ADDR_HIGH : High word of the address in the code field that receives the tile
|
||||
; TileStore+TS_WORD_OFFSET : Logical number of word for this location
|
||||
; TileStore+TS_BASE_ADDR : Copy of BTableAddrLow
|
||||
; TileStore+TS_SCREEN_ADDR : Address ont he physical screen corresponding to this tile (for direct rendering)
|
||||
|
||||
TileStore ENT
|
||||
ds TILE_STORE_SIZE*10
|
||||
ds TILE_STORE_SIZE*11
|
||||
|
||||
; A list of dirty tiles that need to be updated in a given frame
|
||||
DirtyTileCount ds 2
|
||||
|
Loading…
Reference in New Issue
Block a user