mirror of
https://github.com/lscharen/iigs-game-engine.git
synced 2024-11-22 11:34:14 +00:00
Add basic tilemap support back in
This commit is contained in:
parent
19070fa194
commit
1d17b802ad
@ -276,35 +276,3 @@ _DoTimers
|
||||
|
||||
pla
|
||||
rts
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -1196,23 +1196,4 @@ qtRec adrl $0000
|
||||
put blitter/Tiles.s
|
||||
put blitter/Vert.s
|
||||
put blitter/BG1.s
|
||||
; put RotData.s
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
PUT TileMap.s
|
||||
|
@ -64,4 +64,3 @@ tiledata ENT
|
||||
hex 89ABCDEF
|
||||
|
||||
tileend
|
||||
|
||||
|
58
src/App.s
58
src/App.s
@ -25,61 +25,5 @@
|
||||
ASM RotData.s
|
||||
DS 0
|
||||
KND #$1001 ; Type and Attributes ($11=Static+Bank Relative,$01=Data)
|
||||
; ALI BANK
|
||||
ALI BANK
|
||||
SNA RotData
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
11
src/Render.s
11
src/Render.s
@ -92,14 +92,3 @@ Render
|
||||
jsr _RestoreBG0Opcodes
|
||||
|
||||
rts
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
325
src/TileMap.s
Normal file
325
src/TileMap.s
Normal file
@ -0,0 +1,325 @@
|
||||
; Routines for handling tilemaps
|
||||
;
|
||||
; This module contains higher-level functions than the low-level tile rendering routines. The
|
||||
; goal here is to take a rectangular tilemap data structure and efficiently render it into
|
||||
; code buffer. Especially inportant is to only draw new tiles as they come into view.
|
||||
;
|
||||
; Also, we maintain a tilemap cache to track the current state of the tiles rendered into
|
||||
; the code field so if, by chance, a tile that comes into view is the same as a tile that
|
||||
; has already been drawn, then there is no reason to update it. This happen quite often
|
||||
; in actual games since the primary background is often large empty areas, or runs
|
||||
; of repeating tiles.
|
||||
|
||||
_UpdateBG0TileMap
|
||||
:Left equ tmp0
|
||||
:Right equ tmp1
|
||||
:Top equ tmp2
|
||||
:Bottom equ tmp3
|
||||
|
||||
:Width equ tmp4 ; Used in DrawRectBG0
|
||||
:Height equ tmp5
|
||||
|
||||
:MulA equ tmp6 ; Scratch space for multiplication
|
||||
:MulB equ tmp7
|
||||
|
||||
:Offset equ tmp8 ; Address offset into the tilemap
|
||||
:Span equ tmp9
|
||||
|
||||
:GlobalTileIdxX equ tmp10
|
||||
:GlobalTileIdxY equ tmp11
|
||||
|
||||
:BlkX equ tmp12
|
||||
:BlkY equ tmp13
|
||||
|
||||
lda StartY ; calculate the tile index of the current location
|
||||
and #$FFF8
|
||||
lsr
|
||||
lsr
|
||||
sta BG0TileOriginY
|
||||
|
||||
lda OldStartY
|
||||
and #$FFF8
|
||||
lsr
|
||||
lsr
|
||||
sta OldBG0TileOriginY
|
||||
|
||||
lda StartX
|
||||
and #$FFF8
|
||||
lsr
|
||||
lsr
|
||||
sta BG0TileOriginX
|
||||
|
||||
lda OldStartX
|
||||
and #$FFF8
|
||||
lsr
|
||||
lsr
|
||||
sta OldBG0TileOriginY
|
||||
|
||||
; Figure out the two rectangular regions that need to be updated. We check for changes in Y-direction
|
||||
; first because it's a bit more efficient to redraw tiles in long horizontal strips, because we do not
|
||||
; have to skip to different banks.
|
||||
;
|
||||
; +---------------------------+----------+ <-- Top
|
||||
; | | |
|
||||
; | | New |
|
||||
; | | |
|
||||
; | Old Area | (drawn) |
|
||||
; | | (second) |
|
||||
; | | |
|
||||
; +---------------------------+==========|
|
||||
; | |
|
||||
; | New Area (drawn first) |
|
||||
; | |
|
||||
; +--------------------------------------+ <-- Bottom
|
||||
; ^ ^
|
||||
; | |
|
||||
; +--- Left Right --+
|
||||
|
||||
stz :Left ; prepare to do the entire screen
|
||||
lda ScreenTileWidth ; and then whack off the parts
|
||||
sta :Right ; that are not needed
|
||||
|
||||
stz :Top
|
||||
lda ScreenTileHeight
|
||||
sta :Bottom
|
||||
|
||||
lda BG0TileOriginY
|
||||
cmp OldBG0TileOriginY
|
||||
beq :NoYUpdate ; if equal, don't change Y
|
||||
|
||||
sec
|
||||
sbc OldBG0TileOriginY ; find the difference; D = Y_new - Y_old
|
||||
bpl :DoBottom ; if we scrolled up, fill in the bottom row(s)
|
||||
|
||||
eor #$FFFF ; if we scrolled down, Y_new < Y_old and we need
|
||||
sta :Bottom ; to fill in the top row(s) from 0 to Y_new - Y_old - 1
|
||||
bra :DoYUpdate
|
||||
|
||||
:DoBottom
|
||||
eor #$FFFF ; same explanation as above, except we are filling in from
|
||||
inc a ; Bottom - (Y_new - Y_old) to Bottom
|
||||
clc
|
||||
adc ScreenTileHeight
|
||||
sta :Top
|
||||
|
||||
:DoYUpdate
|
||||
jsr :DrawRectBG0 ; Fill in the rectangle.
|
||||
|
||||
; We performed an update in the Y-direction, so now change the bounds so
|
||||
; an update in the X-direction will not draw too many rows
|
||||
;
|
||||
; +---------------------------+----------+
|
||||
; | | |
|
||||
; | | New |
|
||||
; | | |
|
||||
; | Old Area | (drawn) |
|
||||
; | | (second) |
|
||||
; | | |
|
||||
; +---------------------------+==========| <-- Top
|
||||
; |//////////////////////////////////////|
|
||||
; |// New Area (drawn first) ////////////|
|
||||
; |//////////////////////////////////////|
|
||||
; +--------------------------------------+ <-- Bottom
|
||||
; ^ ^
|
||||
; | |
|
||||
; +--- Left Right --+
|
||||
|
||||
lda :Top
|
||||
beq :drewTop
|
||||
dec a ; already did Y to HEIGHT, so only need to draw from
|
||||
sta :Bottom ; 0 to (Y-1) for any horizontal updates
|
||||
stz :Top
|
||||
bra :NoYUpdate
|
||||
|
||||
:drewTop
|
||||
lda :Bottom ; opposite, did 0 to Y
|
||||
inc a ; so do Y+1 to HEIGHT
|
||||
sta :Top
|
||||
lda ScreenTileHeight
|
||||
sta :Bottom
|
||||
|
||||
; +---------------------------+----------+ <-- Top
|
||||
; | | |
|
||||
; | | New |
|
||||
; | | |
|
||||
; | Old Area | (drawn) |
|
||||
; | | (second) |
|
||||
; | | | <-- Bottom
|
||||
; +---------------------------+==========|
|
||||
; |//////////////////////////////////////|
|
||||
; |// New Area (drawn first) ////////////|
|
||||
; |//////////////////////////////////////|
|
||||
; +--------------------------------------+
|
||||
; ^ ^
|
||||
; | |
|
||||
; +--- Left Right --+
|
||||
|
||||
; The Top an Bottom are set the the correct values to draw in whatever potential range of tiles
|
||||
; need to be draws if there was any horizontal displacement
|
||||
:NoYUpdate
|
||||
lda BG0TileOriginX ; Did the first column of the tile map change from before?
|
||||
cmp OldBG0TileOriginX ; Did it change from before?
|
||||
beq :NoXUpdate ; no, so we can ignore this
|
||||
|
||||
sec
|
||||
sbc BG0TileOriginX ; find the difference
|
||||
bpl :DoRightSide ; did we move in a pos or neg?
|
||||
|
||||
; Handle the two sides in an analagous way as the vertical code
|
||||
|
||||
eor #$FFFF
|
||||
sta :Right
|
||||
bra :DoXUpdate
|
||||
|
||||
:DoRightSide
|
||||
eor #$FFFF
|
||||
inc
|
||||
clc
|
||||
adc ScreenTileWidth
|
||||
sta :Left
|
||||
|
||||
:DoXUpdate
|
||||
jsr :DrawRectBG0 ; Fill in the rectangle.
|
||||
|
||||
:NoXUpdate
|
||||
rts
|
||||
|
||||
; This is a private subroutine that draws in tiles into the code fields using the
|
||||
; data from the tilemap and the local :Top, :Left, :Bottom and :Right parameters.
|
||||
:DrawRectBG0
|
||||
|
||||
lda :Bottom
|
||||
sec
|
||||
sbc :Top
|
||||
inc
|
||||
sta :Height
|
||||
|
||||
lda :Right
|
||||
sec
|
||||
sbc :Left
|
||||
inc
|
||||
sta :Width
|
||||
|
||||
; Compute the offset into the tile array of the top-left corner
|
||||
|
||||
lda :Left
|
||||
clc
|
||||
adc BG0TileOriginX
|
||||
sta :GlobalTileIdxX
|
||||
|
||||
lda :Top
|
||||
clc
|
||||
adc BG0TileOriginY ; This is the global verical index
|
||||
sta :GlobalTileIdxY
|
||||
|
||||
ldx TileMapWidth
|
||||
jsr :MulAX
|
||||
clc
|
||||
adc :GlobalTileIdxX
|
||||
asl ; Double for word sizes
|
||||
sta :Offset ; Stash the pointer offset in Y
|
||||
|
||||
lda TileMapWidth
|
||||
sec
|
||||
sbc :Width
|
||||
asl ; This is the number of bytes to move the Offset to advance from the end of
|
||||
sta :Span ; one line to the beginning of the next
|
||||
|
||||
; Now we need to figure out the code field tile coordinate of corner of
|
||||
; play field. That is, becuase the screen is scrolling, the location of
|
||||
; tile (0, 0) could be anywhere within the code field
|
||||
|
||||
lda StartYMod208 ; This is the code field line that is at the top of the screen
|
||||
and #$FFF8 ; Clamp to the nearest block
|
||||
lsr
|
||||
lsr
|
||||
lsr ; Could optimize because the Tile code shifts back....
|
||||
clc
|
||||
adc :Top
|
||||
sta :BlkY ; This is the Y-block we start drawing from
|
||||
|
||||
lda StartXMod164 ; Dx the same thing for X, except only need to clamp by 4
|
||||
and #$FFFC
|
||||
lsr
|
||||
lsr
|
||||
clc
|
||||
adc :Left
|
||||
sta :BlkX
|
||||
|
||||
|
||||
; Call the copy tile routine to blit the tile data into the playfield
|
||||
;
|
||||
; A = Tile ID (0 - 1023)
|
||||
; X = Tile column (0 - 40)
|
||||
; Y = Tile row (0 - 25)
|
||||
|
||||
pei :BlkX ; cache the starting X-block index to restore later
|
||||
pei :Width ; cache the Width value to restore later
|
||||
:yloop
|
||||
:xloop
|
||||
ldy :Offset ; Set up the arguments and call the tile blitter
|
||||
lda [TileMapPtr],y
|
||||
iny ; pre-increment the address. A bit faster than two "INC DP" instructions
|
||||
iny
|
||||
sty :Offset
|
||||
|
||||
ldx :BlkX
|
||||
ldy :BlkY
|
||||
jsr CopyTile
|
||||
|
||||
inc :BlkX ; Move to the next block
|
||||
dec :Width ; Decrement out count
|
||||
bne :xloop
|
||||
|
||||
lda :Offset ; Move to the next line of the Tile Map
|
||||
clc
|
||||
adc :Span
|
||||
sta :Offset
|
||||
|
||||
lda 3,s ; Reset the BlkX
|
||||
sta :BlkX
|
||||
|
||||
lda 1,s ; Reset the width
|
||||
sta :Width
|
||||
|
||||
inc :BlkY
|
||||
dec :Height ; Have we done all of the rows?
|
||||
bne :yloop
|
||||
|
||||
pla ; Pop off cached values
|
||||
pla
|
||||
|
||||
rts
|
||||
|
||||
|
||||
; Quick multiplication of the accumulator and x-register
|
||||
; A = A * X
|
||||
:MulAX
|
||||
stx :MulA
|
||||
cmp :MulA ; Put the smaller value in MulA (less shifts on average)
|
||||
bcc :swap
|
||||
sta :MulB
|
||||
bra :entry
|
||||
:swap stx :MulB
|
||||
sta :MulA
|
||||
|
||||
:entry
|
||||
lda #0
|
||||
|
||||
; Start shifting and adding. We actually do an extra
|
||||
; shift if MulA is zero, but a zero value does not
|
||||
; change the result and it allows us to eliminate a
|
||||
; branch on the inner loop
|
||||
|
||||
:loop
|
||||
lsr :MulA ; shift out the LSB
|
||||
bcc :skip ; zero is no multiply
|
||||
clc
|
||||
adc :MulB
|
||||
|
||||
:skip
|
||||
asl :MulB ; double the multplicand
|
||||
ldx :MulA
|
||||
bne :loop
|
||||
|
||||
rts
|
@ -609,61 +609,3 @@ ApplyBG1OffsetValues
|
||||
:none rts
|
||||
|
||||
BG1YCache ds 32
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -1,87 +1,81 @@
|
||||
; Direct page locations used by the engine
|
||||
ScreenHeight equ 0 ; Height of the playfield in scan lines
|
||||
ScreenWidth equ 2 ; Width of the playfield in bytes
|
||||
ScreenY0 equ 4 ; First vertical line on the physical screen of the playfield
|
||||
ScreenY1 equ 6 ; End of playfield on the physical screen. If the height is 20 and Y0 is
|
||||
ScreenX0 equ 8 ; 100, then ScreenY1 = 120.
|
||||
ScreenX1 equ 10
|
||||
ScreenTileHeight equ 12 ; Height of the playfield in 8x8 blocks
|
||||
ScreenTileWidth equ 14 ; Width of the playfield in 8x8 blocks
|
||||
|
||||
StartX equ 16 ; Which code buffer byte is the left edge of the screen. Range = 0 to 167
|
||||
StartY equ 18 ; Which code buffer line is the top of the screen. Range = 0 to 207
|
||||
EngineMode equ 20 ; Defined the mode/capabilities that are enabled
|
||||
; bit 0: 0 = Single Background, 1 = Parallax
|
||||
DirtyBits equ 22 ; Identify values that have changed between frames
|
||||
|
||||
BG1DataBank equ 24 ; Data bank that holds BG1 layer data
|
||||
BG1AltBank equ 26 ; Alternate BG1 bank
|
||||
|
||||
BlitterDP equ 28 ; Direct page address the holder blitter data
|
||||
|
||||
OldStartX equ 30
|
||||
OldStartY equ 32
|
||||
|
||||
LastPatchOffset equ 34 ; Offset into code field that was patched with BRA instructions
|
||||
StartXMod164 equ 36
|
||||
StartYMod208 equ 38
|
||||
|
||||
BG1StartX equ 40 ; Logical offset of the second background
|
||||
BG1StartXMod164 equ 42
|
||||
|
||||
BG1StartY equ 44
|
||||
BG1StartYMod208 equ 46
|
||||
|
||||
OldBG1StartX equ 48
|
||||
OldBG1StartY equ 50
|
||||
|
||||
BG1OffsetIndex equ 52
|
||||
|
||||
BankLoad equ 128
|
||||
|
||||
bstk equ 208 ; 16-byte stack to push bank addresses
|
||||
|
||||
tmp8 equ 224
|
||||
tmp9 equ 226
|
||||
tmp10 equ 228
|
||||
|
||||
tmp0 equ 240 ; 16 bytes of temporary space to be used as scratch
|
||||
tmp1 equ 242
|
||||
tmp2 equ 244
|
||||
tmp3 equ 246
|
||||
tmp4 equ 248
|
||||
tmp5 equ 250
|
||||
tmp6 equ 252
|
||||
tmp7 equ 254
|
||||
|
||||
DIRTY_BIT_BG0_X equ $0001
|
||||
DIRTY_BIT_BG0_Y equ $0002
|
||||
DIRTY_BIT_BG1_X equ $0004
|
||||
DIRTY_BIT_BG1_Y equ $0008
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
ScreenHeight equ 0 ; Height of the playfield in scan lines
|
||||
ScreenWidth equ 2 ; Width of the playfield in bytes
|
||||
ScreenY0 equ 4 ; First vertical line on the physical screen of the playfield
|
||||
ScreenY1 equ 6 ; End of playfield on the physical screen. If the height is 20 and Y0 is
|
||||
ScreenX0 equ 8 ; 100, then ScreenY1 = 120.
|
||||
ScreenX1 equ 10
|
||||
ScreenTileHeight equ 12 ; Height of the playfield in 8x8 blocks
|
||||
ScreenTileWidth equ 14 ; Width of the playfield in 8x8 blocks
|
||||
|
||||
StartX equ 16 ; Which code buffer byte is the left edge of the screen. Range = 0 to 167
|
||||
StartY equ 18 ; Which code buffer line is the top of the screen. Range = 0 to 207
|
||||
EngineMode equ 20 ; Defined the mode/capabilities that are enabled
|
||||
; bit 0: 0 = Single Background, 1 = Parallax
|
||||
DirtyBits equ 22 ; Identify values that have changed between frames
|
||||
|
||||
BG1DataBank equ 24 ; Data bank that holds BG1 layer data
|
||||
BG1AltBank equ 26 ; Alternate BG1 bank
|
||||
|
||||
BlitterDP equ 28 ; Direct page address the holder blitter data
|
||||
|
||||
OldStartX equ 30
|
||||
OldStartY equ 32
|
||||
|
||||
LastPatchOffset equ 34 ; Offset into code field that was patched with BRA instructions
|
||||
StartXMod164 equ 36
|
||||
StartYMod208 equ 38
|
||||
|
||||
BG1StartX equ 40 ; Logical offset of the second background
|
||||
BG1StartXMod164 equ 42
|
||||
|
||||
BG1StartY equ 44
|
||||
BG1StartYMod208 equ 46
|
||||
|
||||
OldBG1StartX equ 48
|
||||
OldBG1StartY equ 50
|
||||
|
||||
BG1OffsetIndex equ 52
|
||||
|
||||
BG0TileOriginX equ 54 ; Coordinate in the tile map that corresponds to the top-left corner
|
||||
BG0TileOriginY equ 56
|
||||
OldBG0TileOriginX equ 58
|
||||
OldBG0TileOriginY equ 60
|
||||
|
||||
BG1TileOriginX equ 62 ; Coordinate in the tile map that corresponds to the top-left corner
|
||||
BG1TileOriginY equ 64
|
||||
OldBG1TileOriginX equ 66
|
||||
OldBG1TileOriginY equ 68
|
||||
|
||||
TileMapWidth equ 70
|
||||
TileMapHeight equ 72
|
||||
TileMapPtr equ 74
|
||||
|
||||
Next equ 78
|
||||
|
||||
BankLoad equ 128
|
||||
|
||||
blttmp equ 192 ; 32 bytes of local cache/scratch space
|
||||
|
||||
tmp8 equ 224
|
||||
tmp9 equ 226
|
||||
tmp10 equ 228
|
||||
tmp11 equ 230
|
||||
tmp12 equ 232
|
||||
tmp13 equ 234
|
||||
tmp14 equ 236
|
||||
tmp15 equ 238
|
||||
|
||||
tmp0 equ 240 ; 16 bytes of temporary space to be used as scratch
|
||||
tmp1 equ 242
|
||||
tmp2 equ 244
|
||||
tmp3 equ 246
|
||||
tmp4 equ 248
|
||||
tmp5 equ 250
|
||||
tmp6 equ 252
|
||||
tmp7 equ 254
|
||||
|
||||
DIRTY_BIT_BG0_X equ $0001
|
||||
DIRTY_BIT_BG0_Y equ $0002
|
||||
DIRTY_BIT_BG1_X equ $0004
|
||||
DIRTY_BIT_BG1_Y equ $0008
|
||||
|
@ -235,19 +235,3 @@ CopyTile
|
||||
sta $7003,y
|
||||
rep #$20
|
||||
rts
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -189,5 +189,3 @@ CopyRTableToStkAddr
|
||||
:x01 ldal RTable+00,x
|
||||
sta: STK_ADDR+$0000,y
|
||||
:none rts
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user