mirror of
https://github.com/lscharen/iigs-game-engine.git
synced 2024-11-24 09:31:22 +00:00
Checkpoint
This commit is contained in:
parent
135a7384b9
commit
94dafd2093
1
demos/lite/.gitignore
vendored
Normal file
1
demos/lite/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
GTEToolDemo
|
333
demos/lite/App.Main.s
Normal file
333
demos/lite/App.Main.s
Normal file
@ -0,0 +1,333 @@
|
||||
REL
|
||||
DSK MAINSEG
|
||||
|
||||
use Locator.Macs
|
||||
use Load.Macs
|
||||
use Mem.Macs
|
||||
use Misc.Macs
|
||||
use Util.Macs
|
||||
use EDS.GSOS.Macs
|
||||
use GTE.Macs
|
||||
|
||||
mx %00
|
||||
|
||||
TSZelda EXT ; tileset buffer
|
||||
|
||||
ScreenX equ 0
|
||||
ScreenY equ 2
|
||||
Tmp0 equ 4
|
||||
Tmp1 equ 6
|
||||
KeyState equ 8
|
||||
Selected equ 10
|
||||
Flips equ 12
|
||||
DTile equ 14
|
||||
Tmp2 equ 16
|
||||
ScreenWidth equ 18
|
||||
ScreenHeight equ 20
|
||||
SpriteFlags equ 22
|
||||
frameCount equ 24
|
||||
OldOneSecondCounter equ 26
|
||||
SpriteAddr equ 28
|
||||
RenderMode equ 30
|
||||
|
||||
; Control modes
|
||||
DefaultMode equ RENDER_WITH_SHADOWING
|
||||
SlowSprites equ 0
|
||||
|
||||
; Typical init
|
||||
phk
|
||||
plb
|
||||
|
||||
sta MyUserId ; GS/OS passes the memory manager user ID for the application into the program
|
||||
tdc
|
||||
sta MyDirectPage ; Keep a copy for the overlay callback
|
||||
|
||||
_MTStartUp ; GTE requires the miscellaneous toolset to be running
|
||||
|
||||
lda #ENGINE_MODE_USER_TOOL
|
||||
jsr GTEStartUp ; Load and install the GTE User Tool
|
||||
|
||||
; Init local variables
|
||||
|
||||
stz frameCount
|
||||
|
||||
; Initialize the graphics screen to a 256x160 playfield
|
||||
|
||||
pea #160
|
||||
pea #200
|
||||
_GTESetScreenMode
|
||||
|
||||
; Load a tileset
|
||||
|
||||
pea 0
|
||||
pea 360
|
||||
pea #^TSZelda
|
||||
pea #TSZelda
|
||||
_GTELoadTileSet
|
||||
|
||||
; Set the palette
|
||||
pea $0000
|
||||
pea #^palette
|
||||
pea #palette
|
||||
_GTESetPalette
|
||||
|
||||
jsr SetLimits
|
||||
|
||||
pha
|
||||
_GTEGetSeconds
|
||||
pla
|
||||
sta OldOneSecondCounter
|
||||
|
||||
; Manually fill in the 41x26 tiles of the TileStore with a test pattern of trees
|
||||
|
||||
jsr _fillTileStore
|
||||
|
||||
pha
|
||||
pha
|
||||
pea liteBlitter
|
||||
_GTEGetAddress
|
||||
pla
|
||||
plx
|
||||
|
||||
; Set the screen coordinates
|
||||
|
||||
lda #0
|
||||
sta ScreenX
|
||||
lda #0
|
||||
sta ScreenY
|
||||
|
||||
stz Selected
|
||||
stz Flips
|
||||
|
||||
; Very simple actions
|
||||
:evt_loop
|
||||
pha ; space for result, with pattern
|
||||
_GTEReadControl
|
||||
pla
|
||||
|
||||
jsr HandleKeys ; Do the generic key handlers
|
||||
bcs :do_more
|
||||
brl :do_render
|
||||
:do_more
|
||||
and #$007F
|
||||
|
||||
:do_render jsr :next_frame
|
||||
brl :evt_loop
|
||||
|
||||
:next_frame
|
||||
; inc ScreenX
|
||||
; inc ScreenY
|
||||
; pei ScreenX
|
||||
; pei ScreenY
|
||||
; _GTESetBG0Origin
|
||||
|
||||
pea $FFFE
|
||||
_GTERender
|
||||
|
||||
; Update the performance counters
|
||||
|
||||
inc frameCount
|
||||
pha
|
||||
_GTEGetSeconds
|
||||
pla
|
||||
cmp OldOneSecondCounter
|
||||
beq :noudt
|
||||
sta OldOneSecondCounter
|
||||
jsr UdtOverlay
|
||||
stz frameCount
|
||||
:noudt
|
||||
rts
|
||||
|
||||
; Shut down everything
|
||||
Exit
|
||||
_GTEShutDown
|
||||
_QuitGS qtRec
|
||||
qtRec adrl $0000
|
||||
da $00
|
||||
|
||||
; Called by StartUp function callbacks when the screen size changes
|
||||
SetLimits
|
||||
pha ; Allocate space for x, y, width, height
|
||||
pha
|
||||
pha
|
||||
pha
|
||||
_GTEGetScreenInfo
|
||||
pla
|
||||
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
|
||||
sta Tmp2
|
||||
stz Tmp0
|
||||
:oloop
|
||||
stz Tmp1
|
||||
:iloop
|
||||
ldx Tmp1
|
||||
ldy Tmp0
|
||||
jsr _drawTree
|
||||
|
||||
lda Tmp1
|
||||
clc
|
||||
adc #2
|
||||
sta Tmp1
|
||||
cmp #40
|
||||
bcc :iloop
|
||||
|
||||
lda Tmp0
|
||||
clc
|
||||
adc #2
|
||||
sta Tmp0
|
||||
cmp #25
|
||||
bcc :oloop
|
||||
rts
|
||||
|
||||
; Tile 65 Tile 66
|
||||
; Tile 97 Tile 98
|
||||
|
||||
_drawTreeFront
|
||||
phx
|
||||
phy
|
||||
pea #65+TILE_PRIORITY_BIT
|
||||
|
||||
inx
|
||||
phx
|
||||
phy
|
||||
pea #66+TILE_PRIORITY_BIT
|
||||
|
||||
iny
|
||||
phx
|
||||
phy
|
||||
pea #98+TILE_PRIORITY_BIT
|
||||
|
||||
dex
|
||||
phx
|
||||
phy
|
||||
pea #97+TILE_PRIORITY_BIT
|
||||
|
||||
_GTESetTile
|
||||
_GTESetTile
|
||||
_GTESetTile
|
||||
_GTESetTile
|
||||
rts
|
||||
|
||||
_drawTree
|
||||
phx
|
||||
phy
|
||||
pea #65
|
||||
|
||||
inx
|
||||
phx
|
||||
phy
|
||||
pea #66
|
||||
|
||||
iny
|
||||
phx
|
||||
phy
|
||||
pea #98
|
||||
|
||||
dex
|
||||
phx
|
||||
phy
|
||||
pea #97
|
||||
|
||||
_GTESetTile
|
||||
_GTESetTile
|
||||
_GTESetTile
|
||||
_GTESetTile
|
||||
rts
|
||||
|
||||
_drawTreeH
|
||||
phx
|
||||
phy
|
||||
pea #66+TILE_HFLIP_BIT
|
||||
|
||||
inx
|
||||
phx
|
||||
phy
|
||||
pea #65+TILE_HFLIP_BIT
|
||||
|
||||
iny
|
||||
phx
|
||||
phy
|
||||
pea #97+TILE_HFLIP_BIT
|
||||
|
||||
dex
|
||||
phx
|
||||
phy
|
||||
pea #98+TILE_HFLIP_BIT
|
||||
|
||||
_GTESetTile
|
||||
_GTESetTile
|
||||
_GTESetTile
|
||||
_GTESetTile
|
||||
rts
|
||||
|
||||
_drawTreeV
|
||||
phx
|
||||
phy
|
||||
pea #97+TILE_VFLIP_BIT
|
||||
|
||||
inx
|
||||
phx
|
||||
phy
|
||||
pea #98+TILE_VFLIP_BIT
|
||||
|
||||
iny
|
||||
phx
|
||||
phy
|
||||
pea #66+TILE_VFLIP_BIT
|
||||
|
||||
dex
|
||||
phx
|
||||
phy
|
||||
pea #65+TILE_VFLIP_BIT
|
||||
|
||||
_GTESetTile
|
||||
_GTESetTile
|
||||
_GTESetTile
|
||||
_GTESetTile
|
||||
rts
|
||||
|
||||
_drawTreeHV
|
||||
phx
|
||||
phy
|
||||
pea #98+TILE_VFLIP_BIT+TILE_HFLIP_BIT
|
||||
|
||||
inx
|
||||
phx
|
||||
phy
|
||||
pea #97+TILE_VFLIP_BIT+TILE_HFLIP_BIT
|
||||
|
||||
iny
|
||||
phx
|
||||
phy
|
||||
pea #65+TILE_VFLIP_BIT+TILE_HFLIP_BIT
|
||||
|
||||
dex
|
||||
phx
|
||||
phy
|
||||
pea #66+TILE_VFLIP_BIT+TILE_HFLIP_BIT
|
||||
|
||||
_GTESetTile
|
||||
_GTESetTile
|
||||
_GTESetTile
|
||||
_GTESetTile
|
||||
rts
|
||||
|
||||
MyDirectPage ds 2
|
||||
MyUserId ds 2
|
||||
palette dw $0000,$08C1,$0C41,$0F93,$0777,$0FDA,$00A0,$0000,$0D20,$0FFF,$0FD7,$0F59,$0000,$01CE,$0EDA,$0EEE
|
||||
|
||||
PUT ../kfest-2022/StartUp.s
|
||||
PUT ../shell/Overlay.s
|
||||
|
||||
; PUT App.Msg.s
|
||||
; PUT font.s
|
105
demos/lite/App.Msg.s
Normal file
105
demos/lite/App.Msg.s
Normal file
@ -0,0 +1,105 @@
|
||||
HexToChar dfb '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'
|
||||
|
||||
; Convert a byte (Acc) into a string and store at (Y)
|
||||
ByteToString and #$00FF
|
||||
sep #$20
|
||||
pha
|
||||
lsr
|
||||
lsr
|
||||
lsr
|
||||
lsr
|
||||
and #$0F
|
||||
tax
|
||||
ldal HexToChar,x
|
||||
sta: $0000,y
|
||||
|
||||
pla
|
||||
and #$0F
|
||||
tax
|
||||
ldal HexToChar,x
|
||||
sta: $0001,y
|
||||
|
||||
rep #$20
|
||||
rts
|
||||
|
||||
; Convert a word (Acc) into a hexadecimal string and store at (Y)
|
||||
WordToString pha
|
||||
bra Addr2ToString
|
||||
|
||||
; Pass in Acc = High, X = low
|
||||
Addr3ToString phx
|
||||
jsr ByteToString
|
||||
iny
|
||||
iny
|
||||
lda 1,s
|
||||
Addr2ToString xba
|
||||
jsr ByteToString
|
||||
iny
|
||||
iny
|
||||
pla
|
||||
jsr ByteToString
|
||||
rts
|
||||
|
||||
; A=Value
|
||||
; X=Screen offset
|
||||
DrawWord phx ; Save register value
|
||||
phy
|
||||
ldy #WordBuff+1
|
||||
jsr WordToString
|
||||
ply
|
||||
plx
|
||||
lda #WordBuff
|
||||
jsr DrawString
|
||||
rts
|
||||
|
||||
WordBuff str '0000'
|
||||
Addr3Buff str '000000' ; str adds leading length byte
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
15
demos/lite/App.s
Normal file
15
demos/lite/App.s
Normal file
@ -0,0 +1,15 @@
|
||||
; IIgs GTE Lite rendering test
|
||||
|
||||
TYP $B3 ; S16 file
|
||||
DSK GTELiteDemo
|
||||
XPL
|
||||
|
||||
; Segment #1 -- Main execution block
|
||||
|
||||
ASM App.Main.s
|
||||
SNA Main
|
||||
|
||||
; Segment #2 -- Tileset
|
||||
|
||||
ASM Zelda.TileSet.s
|
||||
SNA TSET
|
13687
demos/lite/Zelda.TileSet.s
Normal file
13687
demos/lite/Zelda.TileSet.s
Normal file
File diff suppressed because it is too large
Load Diff
2
demos/lite/_FileInformation.txt
Normal file
2
demos/lite/_FileInformation.txt
Normal file
@ -0,0 +1,2 @@
|
||||
GTEToolDemo=Type(B3),AuxType(0000),VersionCreate(70),MinVersion(BE),Access(E3),FolderInfo1(000000000000000000000000000000000000),FolderInfo2(000000000000000000000000000000000000)
|
||||
GTELiteDemo=Type(B3),AuxType(0000),VersionCreate(70),MinVersion(BE),Access(E3),FolderInfo1(000000000000000000000000000000000000),FolderInfo2(000000000000000000000000000000000000)
|
19
demos/lite/build-image.bat
Normal file
19
demos/lite/build-image.bat
Normal file
@ -0,0 +1,19 @@
|
||||
echo off
|
||||
|
||||
REM Copy all of the assets into the ProDOS image for emulator testing
|
||||
REM
|
||||
REM Pass the path of the Cadius tool as the first argument (%1)
|
||||
|
||||
set CADIUS="%1"
|
||||
set IMAGE="..\\..\\emu\\Target.2mg"
|
||||
set FOLDER="/GTEDEV/Lite"
|
||||
|
||||
REM Cadius does not overwrite files, so clear the root folder first
|
||||
%CADIUS% DELETEFOLDER %IMAGE% %FOLDER%
|
||||
%CADIUS% CREATEFOLDER %IMAGE% %FOLDER%
|
||||
|
||||
REM Now copy files and folders as needed
|
||||
%CADIUS% ADDFILE %IMAGE% %FOLDER% .\GTELiteDemo
|
||||
%CADIUS% ADDFILE %IMAGE% %FOLDER% ..\..\src\Tool160
|
||||
|
||||
REM Copy in the image assets
|
668
demos/lite/font.s
Normal file
668
demos/lite/font.s
Normal file
@ -0,0 +1,668 @@
|
||||
****************************************
|
||||
* FONT ENGINE (v3?) *
|
||||
* *
|
||||
* Dagen Brock <dagenbrock@gmail.com> *
|
||||
* 2013-07-20 *
|
||||
****************************************
|
||||
* A= ptr to string preceded by length *
|
||||
* X= screen location *
|
||||
****************************************
|
||||
; each char:
|
||||
; draw char at loc
|
||||
; update loc
|
||||
; see if length hit - no? back to draw char
|
||||
rel
|
||||
mx %00
|
||||
]F_Length ds 2 ;length of string (only one byte currently used)
|
||||
]F_CharIdx ds 2 ;index of current character
|
||||
]F_CurrentPos ds 2 ;current top left char position
|
||||
]F_StrPtr equ $01 ;pointer to string (including length byte) / DP
|
||||
]F_StrClr equ $03
|
||||
|
||||
DrawString
|
||||
pha ; local variable space
|
||||
pha
|
||||
tsc
|
||||
phd
|
||||
tcd
|
||||
|
||||
; sta ]F_StrPtr ; (done in pha init above) store at dp 0 ($00) for indirect loads
|
||||
stx ]F_CurrentPos
|
||||
sty ]F_StrClr
|
||||
stz ]F_CharIdx
|
||||
lda (]F_StrPtr)
|
||||
and #$00ff ;strip off first char (len is only one byte)
|
||||
sta ]F_Length ;get our length byte
|
||||
|
||||
NextChar lda ]F_CharIdx
|
||||
cmp ]F_Length
|
||||
bne :notDone
|
||||
ldy ]F_StrClr ;restore the color pattern
|
||||
pld
|
||||
pla
|
||||
pla
|
||||
rts ;DONE! Return to caller
|
||||
|
||||
:notDone inc ]F_CharIdx
|
||||
ldy ]F_CharIdx
|
||||
lda (]F_StrPtr),y ;get next char!
|
||||
and #$00FF ;mask high byte
|
||||
sec
|
||||
sbc #' ' ;our table starts with space ' '
|
||||
asl ;*2
|
||||
tay
|
||||
ldx ]F_CurrentPos
|
||||
jsr :drawChar
|
||||
inc ]F_CurrentPos ;compare to addition time (?)
|
||||
inc ]F_CurrentPos
|
||||
inc ]F_CurrentPos
|
||||
inc ]F_CurrentPos ;update screen pos (2 words=8 pixels)
|
||||
bra NextChar
|
||||
|
||||
;x = TopLeft screen pos
|
||||
;y = char table offset
|
||||
:drawChar lda FontTable,y ;get real address of char data
|
||||
sec
|
||||
sbc #FontData ;pivot offset - now a is offset of fontdata
|
||||
tay ;so we'll index with that
|
||||
|
||||
lda FontData,y
|
||||
and ]F_StrClr
|
||||
stal $E12000,x
|
||||
|
||||
lda FontData+2,y
|
||||
and ]F_StrClr
|
||||
stal $E12000+2,x
|
||||
|
||||
lda FontData+4,y
|
||||
and ]F_StrClr
|
||||
stal $E12000+160,x
|
||||
|
||||
lda FontData+6,y
|
||||
and ]F_StrClr
|
||||
stal $E12000+160+2,x
|
||||
|
||||
lda FontData+8,y
|
||||
and ]F_StrClr
|
||||
stal {$E12000+160*2},x
|
||||
|
||||
lda FontData+10,y
|
||||
and ]F_StrClr
|
||||
stal {$E12000+160*2+2},x
|
||||
|
||||
lda FontData+12,y
|
||||
and ]F_StrClr
|
||||
stal {$E12000+160*3},x
|
||||
|
||||
lda FontData+14,y
|
||||
and ]F_StrClr
|
||||
stal {$E12000+160*3+2},x
|
||||
|
||||
lda FontData+16,y
|
||||
and ]F_StrClr
|
||||
stal {$E12000+160*4},x
|
||||
|
||||
lda FontData+18,y
|
||||
and ]F_StrClr
|
||||
stal {$E12000+160*4+2},x
|
||||
|
||||
lda FontData+20,y
|
||||
and ]F_StrClr
|
||||
stal {$E12000+160*5},x
|
||||
|
||||
lda FontData+22,y
|
||||
and ]F_StrClr
|
||||
stal {$E12000+160*5+2},x
|
||||
rts
|
||||
|
||||
FontTable dw s_Space
|
||||
dw s_Exclaim
|
||||
dw s_Quote
|
||||
dw s_Number
|
||||
dw s_Dollar
|
||||
dw s_Percent
|
||||
dw s_Amper
|
||||
dw s_Single
|
||||
dw s_OpenParen
|
||||
dw s_CloseParen
|
||||
dw s_Asterix
|
||||
dw s_Plus
|
||||
dw s_Comma
|
||||
dw s_Minus
|
||||
dw s_Period
|
||||
dw s_Slash
|
||||
dw s_N0
|
||||
dw s_N1
|
||||
dw s_N2
|
||||
dw s_N3
|
||||
dw s_N4
|
||||
dw s_N5
|
||||
dw s_N6
|
||||
dw s_N7
|
||||
dw s_N8
|
||||
dw s_N9
|
||||
dw s_Colon
|
||||
dw s_Semi
|
||||
dw s_LAngle
|
||||
dw s_Equal
|
||||
dw s_RAngle
|
||||
dw s_Question
|
||||
dw s_At
|
||||
dw s_A
|
||||
dw s_B
|
||||
dw s_C
|
||||
dw s_D
|
||||
dw s_E
|
||||
dw s_F
|
||||
dw s_G
|
||||
dw s_H
|
||||
dw s_I
|
||||
dw s_J
|
||||
dw s_K
|
||||
dw s_L
|
||||
dw s_M
|
||||
dw s_N
|
||||
dw s_O
|
||||
dw s_P
|
||||
dw s_Q
|
||||
dw s_R
|
||||
dw s_S
|
||||
dw s_T
|
||||
dw s_U
|
||||
dw s_V
|
||||
dw s_W
|
||||
dw s_X
|
||||
dw s_Y
|
||||
dw s_Z
|
||||
dw s_LBracket
|
||||
dw s_BackSlash
|
||||
dw s_RBracket
|
||||
dw s_Carot
|
||||
dw s_UnderLine
|
||||
|
||||
FontData = *
|
||||
s_Space hex 00000000
|
||||
hex 00000000
|
||||
hex 00000000
|
||||
hex 00000000
|
||||
hex 00000000
|
||||
hex 00000000
|
||||
|
||||
s_Exclaim hex 000FF000
|
||||
hex 000FF000
|
||||
hex 000FF000
|
||||
hex 000FF000
|
||||
hex 00000000
|
||||
hex 000FF000
|
||||
|
||||
s_Quote hex 0FF00FF0
|
||||
hex 00F000F0
|
||||
hex 00000000
|
||||
hex 00000000
|
||||
hex 00000000
|
||||
hex 00000000
|
||||
|
||||
s_Number hex 00000000
|
||||
hex 00F00F00
|
||||
hex 0FFFFFF0
|
||||
hex 00F00F00
|
||||
hex 0FFFFFF0
|
||||
hex 00F00F00
|
||||
|
||||
s_Dollar hex 000F0F00
|
||||
hex 00FFFFF0
|
||||
hex 0F0F0F00
|
||||
hex 00FFFF00
|
||||
hex 000F0FF0
|
||||
hex 0FFFFF00
|
||||
|
||||
s_Percent hex 0FF000F0
|
||||
hex 00000F00
|
||||
hex 0000F000
|
||||
hex 000F0000
|
||||
hex 00F00000
|
||||
hex 0F000FF0
|
||||
|
||||
s_Amper hex 000FF000
|
||||
hex 00F00F00
|
||||
hex 0F00F000
|
||||
hex 00F000F0
|
||||
hex 0F0FFF00
|
||||
hex 00F0F000
|
||||
|
||||
s_Single hex 000FF000
|
||||
hex 0000F000
|
||||
hex 00000000
|
||||
hex 00000000
|
||||
hex 00000000
|
||||
hex 00000000
|
||||
|
||||
s_OpenParen hex 000FF000
|
||||
hex 00FF0000
|
||||
hex 0FF00000
|
||||
hex 0FF00000
|
||||
hex 00FF0000
|
||||
hex 000FF000
|
||||
|
||||
s_CloseParen hex 000FF000
|
||||
hex 0000FF00
|
||||
hex 00000FF0
|
||||
hex 00000FF0
|
||||
hex 0000FF00
|
||||
hex 000FF000
|
||||
|
||||
|
||||
s_Asterix hex 00000000
|
||||
hex 00F0F0F0
|
||||
hex 000FFF00
|
||||
hex 00FFFFF0
|
||||
hex 000FFF00
|
||||
hex 00F0F0F0
|
||||
|
||||
s_Plus hex 000F0000
|
||||
hex 000F0000
|
||||
hex 0FFFFF00
|
||||
hex 000F0000
|
||||
hex 000F0000
|
||||
hex 00000000
|
||||
|
||||
s_Comma hex 00000000
|
||||
hex 00000000
|
||||
hex 00000000
|
||||
hex 00000000
|
||||
hex 0000FF00
|
||||
hex 0000F000
|
||||
|
||||
s_Minus hex 00000000
|
||||
hex 00000000
|
||||
hex 0FFFFF00
|
||||
hex 00000000
|
||||
hex 00000000
|
||||
hex 00000000
|
||||
|
||||
|
||||
s_Period hex 00000000
|
||||
hex 00000000
|
||||
hex 00000000
|
||||
hex 00000000
|
||||
hex 0000FF00
|
||||
hex 0000FF00
|
||||
|
||||
s_Slash hex 000000F0
|
||||
hex 00000F00
|
||||
hex 0000F000
|
||||
hex 000F0000
|
||||
hex 00F00000
|
||||
hex 0F000000
|
||||
|
||||
s_N0 hex 00FFFF00
|
||||
hex 0F000FF0
|
||||
hex 0F00F0F0
|
||||
hex 0F0F00F0
|
||||
hex 0FF000F0
|
||||
hex 00FFFF00
|
||||
|
||||
s_N1 hex 000F0000
|
||||
hex 00FF0000
|
||||
hex 000F0000
|
||||
hex 000F0000
|
||||
hex 000F0000
|
||||
hex 00FFF000
|
||||
|
||||
s_N2 hex 00FFFF00
|
||||
hex 0F0000F0
|
||||
hex 00000F00
|
||||
hex 000FF000
|
||||
hex 00F00000
|
||||
hex 0FFFFFF0
|
||||
|
||||
s_N3 hex 00FFFF00
|
||||
hex 000000F0
|
||||
hex 000FFF00
|
||||
hex 000000F0
|
||||
hex 000000F0
|
||||
hex 00FFFF00
|
||||
|
||||
s_N4 hex 0000FF00
|
||||
hex 000F0F00
|
||||
hex 00F00F00
|
||||
hex 0FFFFFF0
|
||||
hex 00000F00
|
||||
hex 00000F00
|
||||
|
||||
s_N5 hex 0FFFFFF0
|
||||
hex 0F000000
|
||||
hex 0FFFFF00
|
||||
hex 000000F0
|
||||
hex 0F0000F0
|
||||
hex 00FFFF00
|
||||
|
||||
s_N6 hex 000FFF00
|
||||
hex 00F00000
|
||||
hex 0F000000
|
||||
hex 0FFFFF00
|
||||
hex 0F0000F0
|
||||
hex 00FFFFF0
|
||||
|
||||
s_N7 hex 0FFFFFF0
|
||||
hex 000000F0
|
||||
hex 00000F00
|
||||
hex 0000F000
|
||||
hex 000F0000
|
||||
hex 000F0000
|
||||
|
||||
s_N8 hex 00FFFF00
|
||||
hex 0F0000F0
|
||||
hex 00FFFF00
|
||||
hex 0F0000F0
|
||||
hex 0F0000F0
|
||||
hex 00FFFF00
|
||||
|
||||
s_N9 hex 00FFFF00
|
||||
hex 0F0000F0
|
||||
hex 00FFFF00
|
||||
hex 0000F000
|
||||
hex 000F0000
|
||||
hex 00F00000
|
||||
|
||||
s_Colon hex 000FF000
|
||||
hex 000FF000
|
||||
hex 00000000
|
||||
hex 000FF000
|
||||
hex 000FF000
|
||||
hex 00000000
|
||||
|
||||
s_Semi hex 00000000
|
||||
hex 000FF000
|
||||
hex 000FF000
|
||||
hex 00000000
|
||||
hex 000FF000
|
||||
hex 000F0000
|
||||
|
||||
s_LAngle hex 0000F000
|
||||
hex 000F0000
|
||||
hex 00F00000
|
||||
hex 000F0000
|
||||
hex 0000F000
|
||||
hex 00000000
|
||||
|
||||
s_Equal hex 00000000
|
||||
hex 00000000
|
||||
hex 0FFFFF00
|
||||
hex 00000000
|
||||
hex 0FFFFF00
|
||||
hex 00000000
|
||||
|
||||
s_RAngle hex 0000F000
|
||||
hex 00000F00
|
||||
hex 000000F0
|
||||
hex 00000F00
|
||||
hex 0000F000
|
||||
hex 00000000
|
||||
|
||||
s_Question hex 00FFF000
|
||||
hex 0F000F00
|
||||
hex 00000F00
|
||||
hex 000FF000
|
||||
hex 00000000
|
||||
hex 000FF000
|
||||
|
||||
s_At hex 00FFFF00
|
||||
hex 0F0000F0
|
||||
hex 0F00F0F0
|
||||
hex 0FFFF0F0
|
||||
hex 000000F0
|
||||
hex 0FFFFF00
|
||||
|
||||
s_A hex 000FF000
|
||||
hex 00F00F00
|
||||
hex 0F0000F0
|
||||
hex 0FFFFFF0
|
||||
hex 0F0000F0
|
||||
hex 0F0000F0
|
||||
|
||||
s_B hex 0FFFFF00
|
||||
hex 0F0000F0
|
||||
hex 0FFFFF00
|
||||
hex 0F0000F0
|
||||
hex 0F0000F0
|
||||
hex 0FFFFF00
|
||||
|
||||
s_C hex 00FFFFF0
|
||||
hex 0F000000
|
||||
hex 0F000000
|
||||
hex 0F000000
|
||||
hex 0F000000
|
||||
hex 00FFFFF0
|
||||
|
||||
s_D hex 0FFFFF00
|
||||
hex 0F0000F0
|
||||
hex 0F0000F0
|
||||
hex 0F0000F0
|
||||
hex 0F0000F0
|
||||
hex 0FFFFF00
|
||||
|
||||
s_E hex 0FFFFFF0
|
||||
hex 0F000000
|
||||
hex 0FFFF000
|
||||
hex 0F000000
|
||||
hex 0F000000
|
||||
hex 0FFFFFF0
|
||||
|
||||
s_F hex 0FFFFFF0
|
||||
hex 0F000000
|
||||
hex 0FFFF000
|
||||
hex 0F000000
|
||||
hex 0F000000
|
||||
hex 0F000000
|
||||
|
||||
s_G hex 00FFFFF0
|
||||
hex 0F000000
|
||||
hex 0F000000
|
||||
hex 0F00FFF0
|
||||
hex 0F0000F0
|
||||
hex 00FFFF00
|
||||
|
||||
s_H hex 0F0000F0
|
||||
hex 0F0000F0
|
||||
hex 0FFFFFF0
|
||||
hex 0F0000F0
|
||||
hex 0F0000F0
|
||||
hex 0F0000F0
|
||||
|
||||
s_I hex 0FFFFF00
|
||||
hex 000F0000
|
||||
hex 000F0000
|
||||
hex 000F0000
|
||||
hex 000F0000
|
||||
hex 0FFFFF00
|
||||
|
||||
s_J hex 000000F0
|
||||
hex 000000F0
|
||||
hex 000000F0
|
||||
hex 0F0000F0
|
||||
hex 0F0000F0
|
||||
hex 00FFFF00
|
||||
|
||||
s_K hex 0F000F00
|
||||
hex 0F00F000
|
||||
hex 0FFF0000
|
||||
hex 0F00F000
|
||||
hex 0F000F00
|
||||
hex 0F000F00
|
||||
|
||||
s_L hex 0F000000
|
||||
hex 0F000000
|
||||
hex 0F000000
|
||||
hex 0F000000
|
||||
hex 0F000000
|
||||
hex 0FFFFFF0
|
||||
|
||||
s_M hex 0F0000F0
|
||||
hex 0FF00FF0
|
||||
hex 0F0FF0F0
|
||||
hex 0F0000F0
|
||||
hex 0F0000F0
|
||||
hex 0F0000F0
|
||||
|
||||
s_N hex 0F0000F0
|
||||
hex 0FF000F0
|
||||
hex 0F0F00F0
|
||||
hex 0F00F0F0
|
||||
hex 0F000FF0
|
||||
hex 0F0000F0
|
||||
|
||||
s_O hex 00FFFF00
|
||||
hex 0F0000F0
|
||||
hex 0F0000F0
|
||||
hex 0F0000F0
|
||||
hex 0F0000F0
|
||||
hex 00FFFF00
|
||||
|
||||
s_P hex 0FFFFF00
|
||||
hex 0F0000F0
|
||||
hex 0FFFFF00
|
||||
hex 0F000000
|
||||
hex 0F000000
|
||||
hex 0F000000
|
||||
|
||||
s_Q hex 00FFFF00
|
||||
hex 0F0000F0
|
||||
hex 0F0000F0
|
||||
hex 0F00F0F0
|
||||
hex 0F000FF0
|
||||
hex 00FFFFF0
|
||||
|
||||
s_R hex 0FFFFF00
|
||||
hex 0F0000F0
|
||||
hex 0FFFFF00
|
||||
hex 0F000F00
|
||||
hex 0F0000F0
|
||||
hex 0F0000F0
|
||||
|
||||
s_S hex 00FFFFF0
|
||||
hex 0F000000
|
||||
hex 00FFFF00
|
||||
hex 000000F0
|
||||
hex 000000F0
|
||||
hex 0FFFFF00
|
||||
|
||||
s_T hex 0FFFFF00
|
||||
hex 000F0000
|
||||
hex 000F0000
|
||||
hex 000F0000
|
||||
hex 000F0000
|
||||
hex 000F0000
|
||||
|
||||
s_U hex 0F0000F0
|
||||
hex 0F0000F0
|
||||
hex 0F0000F0
|
||||
hex 0F0000F0
|
||||
hex 0F0000F0
|
||||
hex 00FFFF00
|
||||
|
||||
s_V hex 0F0000F0
|
||||
hex 0F0000F0
|
||||
hex 0F0000F0
|
||||
hex 0F0000F0
|
||||
hex 00F00F00
|
||||
hex 000FF000
|
||||
|
||||
s_W hex 0F0000F0
|
||||
hex 0F0000F0
|
||||
hex 0F0000F0
|
||||
hex 0F0FF0F0
|
||||
hex 0FF00FF0
|
||||
hex 0F0000F0
|
||||
|
||||
s_X hex 0F0000F0
|
||||
hex 00F00F00
|
||||
hex 000FF000
|
||||
hex 000FF000
|
||||
hex 00F00F00
|
||||
hex 0F0000F0
|
||||
|
||||
s_Y hex F00000F0
|
||||
hex 0F000F00
|
||||
hex 00F0F000
|
||||
hex 000F0000
|
||||
hex 000F0000
|
||||
hex 000F0000
|
||||
|
||||
s_Z hex 0FFFFFF0
|
||||
hex 00000F00
|
||||
hex 0000F000
|
||||
hex 000F0000
|
||||
hex 00F00000
|
||||
hex 0FFFFFF0
|
||||
|
||||
s_LBracket hex 000FFF00
|
||||
hex 000F0000
|
||||
hex 000F0000
|
||||
hex 000F0000
|
||||
hex 000F0000
|
||||
hex 000FFF00
|
||||
|
||||
s_BackSlash hex 0F000000
|
||||
hex 00F00000
|
||||
hex 000F0000
|
||||
hex 0000F000
|
||||
hex 00000F00
|
||||
hex 000000F0
|
||||
|
||||
s_RBracket hex 00FFF000
|
||||
hex 0000F000
|
||||
hex 0000F000
|
||||
hex 0000F000
|
||||
hex 0000F000
|
||||
hex 00FFF000
|
||||
|
||||
s_Carot hex 0000F000
|
||||
hex 000F0F00
|
||||
hex 00F000F0
|
||||
hex 00000000
|
||||
hex 00000000
|
||||
hex 00000000
|
||||
|
||||
s_UnderLine hex 00000000
|
||||
hex 00000000
|
||||
hex 00000000
|
||||
hex 00000000
|
||||
hex 00000000
|
||||
hex FFFFFFF0
|
||||
|
||||
s_Template hex 00000000
|
||||
hex 00000000
|
||||
hex 00000000
|
||||
hex 00000000
|
||||
hex 00000000
|
||||
hex 00000000
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
32
demos/lite/package.json
Normal file
32
demos/lite/package.json
Normal file
@ -0,0 +1,32 @@
|
||||
{
|
||||
"name": "gte-lite-demo",
|
||||
"version": "1.0.0",
|
||||
"description": "A testbed for testing hte GTE lite rendering mode",
|
||||
"main": "index.js",
|
||||
"config": {
|
||||
"merlin32": "C:\\Programs\\IIgsXDev\\bin\\Merlin32-1.1.10.exe",
|
||||
"cadius": "C:\\Programs\\IIgsXDev\\bin\\Cadius.exe",
|
||||
"gsport": "C:\\Programs\\gsport\\gsport_0.31\\GSPort.exe",
|
||||
"macros": "../../macros",
|
||||
"crossrunner": "C:\\Programs\\Crossrunner\\Crossrunner.exe"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "npm run build && build-image.bat %npm_package_config_cadius% && %npm_package_config_gsport%",
|
||||
"debug": "%npm_package_config_crossrunner% GTELiteDemo -Source MAINSEG_Output.txt -Debug -CompatibilityLayer -Map App.s",
|
||||
"build": "npm run build:tool && npm run build:sys16",
|
||||
"build:sys16": "%npm_package_config_merlin32% -V %npm_package_config_macros% App.s",
|
||||
"build:tool": "%npm_package_config_merlin32% -V %npm_package_config_macros% ../../src/Master.s"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/lscharen/iigs-game-engine.git"
|
||||
},
|
||||
"author": "Lucas Scharenbroich",
|
||||
"license": "Apache-2.0",
|
||||
"bugs": {
|
||||
"url": "https://github.com/lscharen/iigs-game-engine/issues"
|
||||
},
|
||||
"homepage": "https://github.com/lscharen/iigs-game-engine#readme",
|
||||
"devDependencies": {
|
||||
}
|
||||
}
|
@ -190,6 +190,7 @@ extSpriteRenderer equ $0005
|
||||
rawDrawTile equ $0006
|
||||
extBG0TileUpdate equ $0007
|
||||
userTileCallback equ $0008
|
||||
liteBlitter equ $0009
|
||||
|
||||
; CopyPicToBG1 flags
|
||||
COPY_PIC_NORMAL equ $0000 ; Copy into BG1 buffer in "normal mode"
|
||||
|
@ -18,7 +18,8 @@
|
||||
"test": "npm run build && build-image.bat %npm_package_config_cadius% && %npm_package_config_gsport%",
|
||||
"build": "%npm_package_config_merlin32% -V %npm_package_config_macros% ./src/Master.s",
|
||||
"build:debug": "%npm_package_config_merlin32% -V %npm_package_config_macros% ./src/Debug.s",
|
||||
"debug": "%npm_package_config_crossrunner% ./src/Debug160 -Source ./src/Debug160_S02__Output.txt -Debug -CompatibilityLayer"
|
||||
"debug": "%npm_package_config_crossrunner% ./src/Debug160 -Source ./src/Debug160_S02__Output.txt -Debug -CompatibilityLayer",
|
||||
"install:header": "copy .\\ORCACDefs\\gte.h C:\\ProgramData\\GoldenGate\\Libraries\\ORCACDefs\\gte.h"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
@ -238,6 +238,16 @@ EngineReset
|
||||
|
||||
stz OneSecondCounter
|
||||
|
||||
; Fill in the state register values
|
||||
|
||||
sep #$20
|
||||
ldal STATE_REG
|
||||
and #$CF
|
||||
sta STATE_REG_OFF ; Put this value in to return to "normal" blitter
|
||||
ora #$10
|
||||
sta STATE_REG_BLIT ; Running the blitter, this is the mode to put us into
|
||||
rep #$20
|
||||
|
||||
lda #13
|
||||
sta tmp15
|
||||
stz tmp14
|
||||
|
17
src/Defs.s
17
src/Defs.s
@ -105,6 +105,9 @@ BG1Scaling equ 126
|
||||
activeSpriteList equ 128 ; 32 bytes for the active sprite list (can persist across frames)
|
||||
|
||||
; Free space from 160 to 192
|
||||
STATE_REG_OFF equ 160
|
||||
STATE_REG_BLIT equ 161
|
||||
STK_SAVE equ 162 ; Only used by the lite renderer
|
||||
|
||||
blttmp equ 192 ; 32 bytes of local cache/scratch space for blitter
|
||||
|
||||
@ -206,6 +209,7 @@ extSpriteRenderer equ $0005
|
||||
rawDrawTile equ $0006
|
||||
extBG0TileUpdate equ $0007
|
||||
userTileCallback equ $0008
|
||||
liteBlitter equ $0009
|
||||
|
||||
; CopyPicToBG1 flags
|
||||
COPY_PIC_NORMAL equ $0000 ; Copy into BG1 buffer in "normal mode" treating the buffer as a 164x208 pixmap with stride of 256
|
||||
@ -329,3 +333,16 @@ ExtUpdateBG0Tiles EXT
|
||||
|
||||
; Tool error codes
|
||||
NO_TIMERS_AVAILABLE equ 10
|
||||
|
||||
; Offsets for the Lite blitter
|
||||
_ENTRY_1 equ 0
|
||||
_ENTRY_JMP equ 4
|
||||
_ENTRY_ODD equ 11
|
||||
_LOOP equ 38
|
||||
_EXIT_ODD equ 290
|
||||
_EXIT_EVEN equ 293
|
||||
_LOW_SAVE equ 296
|
||||
|
||||
_LINE_BASE equ 4 ; header size
|
||||
_LINE_SIZE equ 298 ; number of bytes for each blitter line
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
TYP $BA ; Tool set file
|
||||
DSK Tool160
|
||||
XPL
|
||||
XPL
|
||||
|
||||
; Main toolbox interface and code
|
||||
|
||||
@ -44,6 +44,12 @@
|
||||
ALI BANK
|
||||
SNA ROTDATA
|
||||
|
||||
; GTE "Lite" blitter. One bank of static code, no relocation needed.
|
||||
|
||||
ASM blitter/TemplateLite.s
|
||||
ALI BANK
|
||||
SNA BLTLITE
|
||||
|
||||
; Additional code
|
||||
|
||||
; ASM FastCopies.s
|
||||
|
73
src/Memory.s
73
src/Memory.s
@ -74,6 +74,15 @@ InitMemory lda EngineMode
|
||||
sta CompileBank
|
||||
stz CompileBank0
|
||||
|
||||
; If ENGINE_MODE_TWO_LAYER and ENGINE_MODE_DYN_TILES are turned off, then
|
||||
; we are in "GTE lite" mode and use a blitter template that only requires
|
||||
; one bank of memory
|
||||
lda EngineMode
|
||||
bit #ENGINE_MODE_DYN_TILES+ENGINE_MODE_TWO_LAYER
|
||||
bne InitFullBlitter
|
||||
brl InitLiteBlitter
|
||||
|
||||
InitFullBlitter
|
||||
; Allocate the 13 banks of memory we need and store in double-length array
|
||||
]step equ 0
|
||||
lup 13
|
||||
@ -155,6 +164,70 @@ InitMemory lda EngineMode
|
||||
:exit
|
||||
rts
|
||||
|
||||
InitLiteBlitter
|
||||
lite_base EXT
|
||||
|
||||
; Overwrite the Col2CodeOffset tables. This array needs to hold the offset from the start of the line (BTableLow),
|
||||
; to each of the PEA words *in logical order*. This means the actual addresses are reversed.
|
||||
|
||||
lda #_LOOP
|
||||
sta Col2CodeOffset-2
|
||||
|
||||
ldx #0
|
||||
lda #_LOOP+{81*PER_TILE_SIZE}
|
||||
sta Col2CodeOffset+{4*82} ; Store a copy one off the end
|
||||
|
||||
:loop0 sta Col2CodeOffset,x
|
||||
sta Col2CodeOffset+{2*82},x
|
||||
sec
|
||||
sbc #PER_TILE_SIZE
|
||||
inx
|
||||
inx
|
||||
cpx #82*2
|
||||
bcc :loop0
|
||||
|
||||
; Fill in the BTable and BRowTable values
|
||||
|
||||
ldx #0
|
||||
ldy #lite_base
|
||||
|
||||
:loop1
|
||||
tya
|
||||
sta BTableLow,x
|
||||
sta BTableLow+{208*2},x
|
||||
clc
|
||||
adc #_LINE_SIZE
|
||||
tay
|
||||
|
||||
lda #^lite_base
|
||||
sta BTableHigh,x
|
||||
sta BTableHigh+{208*2},x
|
||||
|
||||
inx
|
||||
inx
|
||||
cpx #208*2
|
||||
bcc :loop1
|
||||
|
||||
ldx #0
|
||||
ldy #lite_base
|
||||
:loop2
|
||||
lda BTableHigh ; This is the same value for the lite blitter
|
||||
sta BRowTableHigh+2,x
|
||||
sta BRowTableHigh+{26*2}+2,x
|
||||
|
||||
tya
|
||||
sta BRowTableLow,x
|
||||
sta BRowTableLow+{26*2},x
|
||||
clc
|
||||
adc #{8*_LINE_SIZE}
|
||||
tay
|
||||
|
||||
inx
|
||||
inx
|
||||
cpx #26*2
|
||||
bcc :loop2
|
||||
rts
|
||||
|
||||
; Bank allocator (for one full, fixed bank of memory. Can be immediately deferenced)
|
||||
|
||||
AllocOneBank PushLong #0
|
||||
|
58
src/Render.s
58
src/Render.s
@ -626,6 +626,64 @@ _RenderWithShadowing
|
||||
:no_removal
|
||||
rts
|
||||
|
||||
; Specail mode for rendering in GTE-lite mode. No secondary background is possible
|
||||
_RenderLite
|
||||
sta RenderFlags
|
||||
jsr _DoTimers ; Run any pending timer tasks
|
||||
|
||||
; brk $65
|
||||
jsr _ApplyBG0YPosLite ; Set stack addresses for the virtual lines to the physical screen
|
||||
; brk $66
|
||||
jsr _ApplyBG0XPosPre ; Lock in certain rendering variables (not lite/non-lite specific)
|
||||
; brk $67
|
||||
|
||||
|
||||
jsr _UpdateBG0TileMap ; and the tile maps. These subroutines build up a list of tiles
|
||||
jsr _ApplyTiles ; This function actually draws the new tiles into the code field
|
||||
|
||||
jsr _ApplyBG0XPosLite ; Patch the code field instructions with exit BRA opcode
|
||||
|
||||
; At this point, everything in the background has been rendered into the code field. Next, we need
|
||||
; to create priority lists of scanline ranges.
|
||||
|
||||
; jsr _FilterObjectList ; Walk the sorted list and create an array of objects that need to be rendered
|
||||
;
|
||||
; jsr _ShadowOff ; Turn off shadowing and draw all the scanlines with sprites on them
|
||||
; jsr _DrawObjShadow ; Draw the background
|
||||
; jsr _DrawDirectSprites ; Draw the sprites directly to the Bank $01 graphics buffer (skipping the render-to-tile step)
|
||||
;
|
||||
; jsr _ShadowOn ; Turn shadowing back on
|
||||
;
|
||||
; jsr _DrawFinalPass
|
||||
|
||||
ldx #0
|
||||
lda ScreenHeight
|
||||
jsr _BltRange
|
||||
|
||||
lda StartYMod208 ; Restore the fields back to their original state
|
||||
ldx ScreenHeight
|
||||
jsr _RestoreBG0OpcodesLite
|
||||
|
||||
lda StartY
|
||||
sta OldStartY
|
||||
lda StartX
|
||||
sta OldStartX
|
||||
|
||||
lda BG1StartY
|
||||
sta OldBG1StartY
|
||||
lda BG1StartX
|
||||
sta OldBG1StartX
|
||||
|
||||
stz DirtyBits
|
||||
stz LastRender ; Mark that a full render was just performed
|
||||
|
||||
lda SpriteRemovedFlag ; If any sprite was removed, set the rebuild flag
|
||||
beq :no_removal
|
||||
lda #DIRTY_BIT_SPRITE_ARRAY
|
||||
sta DirtyBits
|
||||
:no_removal
|
||||
rts
|
||||
|
||||
; Run through the list of sprites that are not OFFSCREEN and not OVERLAYS and draw them directly to the graphics screen. We can use
|
||||
; compiled sprites here, with limitations.
|
||||
_DrawDirectSprites
|
||||
|
21
src/Tool.s
21
src/Tool.s
@ -305,6 +305,8 @@ _TSRender
|
||||
lda :flags,s
|
||||
cmp #$FFFF ; Hack! Special mode...
|
||||
beq :nes
|
||||
cmp #$FFFE ; Experimental gte-lite mode
|
||||
beq :lite
|
||||
|
||||
bit #RENDER_WITH_SHADOWING
|
||||
beq :no_shadowing
|
||||
@ -323,6 +325,10 @@ _TSRender
|
||||
|
||||
:nes
|
||||
jsr _RenderNES
|
||||
bra :done
|
||||
|
||||
:lite
|
||||
jsr _RenderLite
|
||||
|
||||
:done
|
||||
_TSExit #0;#2
|
||||
@ -945,7 +951,17 @@ _TSGetAddress
|
||||
lda #^_DrawTileToScreen
|
||||
sta :output+2,s
|
||||
bra :out
|
||||
:next_3
|
||||
|
||||
:next_3 cmp #liteBlitter
|
||||
bne :next_4
|
||||
|
||||
lda #lite_base
|
||||
sta :output,s
|
||||
lda #^lite_base
|
||||
sta :output+2,s
|
||||
bra :out
|
||||
|
||||
:next_4
|
||||
:out
|
||||
_TSExit #0;#2
|
||||
|
||||
@ -1114,11 +1130,14 @@ _TSEnableBackground
|
||||
put tiles/DirtyTileQueue.s
|
||||
put blitter/SCB.s
|
||||
put blitter/Horz.s
|
||||
put blitter/HorzLite.s
|
||||
put blitter/Vert.s
|
||||
put blitter/VertLite.s
|
||||
put blitter/BG0.s
|
||||
put blitter/BG1.s
|
||||
put blitter/Rotation.s
|
||||
put blitter/Template.s
|
||||
put blitter/TemplateUtils.s
|
||||
put blitter/Blitter.s
|
||||
put blitter/BlitterLite.s
|
||||
put blitter/PEISlammer.s
|
||||
|
@ -26,8 +26,15 @@ _BltRange
|
||||
brl DisabledBG
|
||||
:normal
|
||||
|
||||
; If we are in "lite" mode, defer to that implementation
|
||||
lda EngineMode
|
||||
bit #ENGINE_MODE_TWO_LAYER+ENGINE_MODE_DYN_TILES
|
||||
bne :dark
|
||||
jmp _BltRangeLite
|
||||
|
||||
:dark
|
||||
phb ; preserve the bank register
|
||||
clc`
|
||||
clc
|
||||
|
||||
dey
|
||||
tya ; Get the address of the line that we want to return from
|
||||
@ -98,6 +105,9 @@ stk_save lda #0000 ; load the stack
|
||||
plp ; re-enable interrupts (maybe, if interrupts disabled when we are called, they are not re-endabled)
|
||||
pld ; restore the direct page
|
||||
|
||||
:exit_ptr equ tmp0
|
||||
:jmp_low_save equ tmp2
|
||||
|
||||
sep #$20
|
||||
ldy #CODE_EXIT+1
|
||||
lda :jmp_low_save
|
||||
@ -164,15 +174,13 @@ DisabledBG
|
||||
|
||||
lda tmp15 ; restore the stack
|
||||
tcs
|
||||
|
||||
sep #$30 ; 8-bit mode
|
||||
ldal STATE_REG
|
||||
tax ; Save the value
|
||||
and #$CF ; Read Bank 0 / Write Bank 0
|
||||
lda STATE_REG_OFF ; Could be on the direct page....
|
||||
stal STATE_REG
|
||||
cli
|
||||
nop ; Give a couple of cycles
|
||||
sei
|
||||
txa ; Restore the state
|
||||
lda STATE_REG_BLIT ; External values
|
||||
stal STATE_REG
|
||||
rep #$30
|
||||
bra :next
|
||||
|
75
src/blitter/BlitterLite.s
Normal file
75
src/blitter/BlitterLite.s
Normal file
@ -0,0 +1,75 @@
|
||||
; This is the method that is most useful from the high-level code. We want the
|
||||
; freedom to blit a range of lines. This subroutine can assume that all of the
|
||||
; data in the code fields is set up properly.
|
||||
;
|
||||
; X = first line (inclusive), valid range of 0 to 199
|
||||
; Y = last line (exclusive), valid range >X up to 200
|
||||
;
|
||||
; The lines are based on the appearance of lines in the play field, so blitting lines 0 through
|
||||
; 19 will draw the first 20 lines on the play field, regardless of where the playfield is physically
|
||||
; on the SHR screen or the current value of StartY
|
||||
lite_base EXT
|
||||
lite_full_return EXT
|
||||
|
||||
; This should only be called from _Render when it is determined to be safe
|
||||
_BltRangeLite
|
||||
|
||||
:exit_ptr equ tmp0
|
||||
:jmp_low_save equ tmp2
|
||||
|
||||
clc
|
||||
dey
|
||||
tya ; Get the address of the line that we want to return from
|
||||
adc StartYMod208 ; and create a pointer to it
|
||||
asl
|
||||
tay
|
||||
lda BTableLow,y
|
||||
sta :exit_ptr
|
||||
lda BTableHigh,y
|
||||
sta :exit_ptr+2
|
||||
|
||||
txa ; get the first line (0 - 199)
|
||||
adc StartYMod208 ; add in the virtual offset (0, 207) -- max value of 406
|
||||
asl
|
||||
tax ; this is the offset into the blitter table
|
||||
|
||||
lda BTableLow,x ; patch in the address
|
||||
sta blt_entry_lite+1
|
||||
|
||||
; 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
|
||||
; executed.
|
||||
;
|
||||
; The trick we use is to patch the low byte to force the code to jump to a special return
|
||||
; function (jml blt_return) in the *next* code field line.
|
||||
|
||||
ldy #_EXIT_EVEN+1 ; this is a JMP instruction that points to the next line.
|
||||
lda [:exit_ptr],y ; we have to save because not every line points to the same
|
||||
sta :jmp_low_save ; position in the next code line
|
||||
|
||||
lda #lite_full_return ; this is the address of the return code
|
||||
sta [:exit_ptr],y ; patch out the address of the JMP
|
||||
|
||||
php ; save the current processor flags
|
||||
sep #$20 ; run the lite blitter in 8-bit accumulator mode
|
||||
brk $99
|
||||
sei ; disable interrupts
|
||||
_R0W1
|
||||
tsx ; save the stack pointer in Y
|
||||
txy
|
||||
blt_entry_lite jml lite_base ; Jump into the blitter code $ZZ/YYXX (Does not modify Y or X)
|
||||
|
||||
blt_return_lite ENT
|
||||
_R0W0
|
||||
tyx
|
||||
txs ; restore the stack
|
||||
plp ; re-enable interrupts (maybe, if interrupts disabled when we are called, they are not re-endabled)
|
||||
|
||||
:exit_ptr equ tmp0
|
||||
:jmp_low_save equ tmp2
|
||||
mx %00
|
||||
|
||||
ldy #_EXIT_EVEN+1
|
||||
lda :jmp_low_save
|
||||
sta [:exit_ptr],y
|
||||
rts
|
651
src/blitter/HorzLite.s
Normal file
651
src/blitter/HorzLite.s
Normal file
@ -0,0 +1,651 @@
|
||||
; Subroutines that deal with the horizontal scrolling in the "lite" blitter. The
|
||||
; advantage of the lite blitter is that the entire code field is in one bank, so
|
||||
; there is no need to chunk up the updates into 16-line pieces. The entire height
|
||||
; of the playfield can be done with a single unrolled loop.
|
||||
;
|
||||
; A = starting virtual line in the code field (0 - 207)
|
||||
; X = number of lines to render (0 - 200)
|
||||
|
||||
_RestoreBG0OpcodesLite
|
||||
:virt_line_x2 equ tmp1
|
||||
:lines_left_x2 equ tmp2
|
||||
:exit_offset equ tmp4
|
||||
|
||||
asl
|
||||
sta :virt_line_x2 ; Keep track of it
|
||||
|
||||
txa
|
||||
asl
|
||||
sta :lines_left_x2
|
||||
|
||||
lda LastPatchOffset ; If zero, there are no saved opcodes
|
||||
sta :exit_offset
|
||||
|
||||
|
||||
_RestoreBG0OpcodesAltLite
|
||||
:virt_line_x2 equ tmp1
|
||||
:lines_left_x2 equ tmp2
|
||||
:draw_count_x2 equ tmp3
|
||||
:exit_offset equ tmp4
|
||||
:base_address equ tmp5
|
||||
:exit_address equ tmp6
|
||||
:draw_count_x6 equ blttmp+10
|
||||
|
||||
; We do need to split the update into two parts so that we can handle the wrap-around portion
|
||||
|
||||
ldx :lines_left_x2
|
||||
lda #208*2
|
||||
sec
|
||||
sbc :virt_line_x2 ; calculate number of lines to the end of the buffer
|
||||
cmp :lines_left_x2
|
||||
bcs :one_pass ; if there's room, do it in one shot
|
||||
|
||||
; If the virtual screen wraps around the bank, then we need to split the update up
|
||||
; into two pieces to efficiently restore the values without having to do the
|
||||
; virtual_line -> physical_line conversion each time.
|
||||
|
||||
tax
|
||||
jsr :one_pass ; Go through with this draw count
|
||||
|
||||
stz :virt_line_x2
|
||||
|
||||
lda :lines_left_x2
|
||||
sec
|
||||
sbc :draw_count_x2 ; this many left to draw. Fall through to finish up
|
||||
tax
|
||||
|
||||
:one_pass
|
||||
txa
|
||||
sta :draw_count_x2 ; this is the number of lines we will do right now
|
||||
asl
|
||||
adc :draw_count_x2
|
||||
sta :draw_count_x6
|
||||
|
||||
phb
|
||||
|
||||
sep #$20 ; Set the data bank to the code field
|
||||
lda BTableHigh
|
||||
pha
|
||||
plb
|
||||
rep #$21 ; clear the carry while we're here...
|
||||
|
||||
ldx :virt_line_x2
|
||||
ldal BTableLow,x ; Get the address of the first code field line
|
||||
sta :base_address
|
||||
|
||||
adc #_LOW_SAVE
|
||||
sta :low_save_addr
|
||||
|
||||
lda :base_address
|
||||
adc :exit_offset ; Add some offsets to get the base address in the code field line
|
||||
sta :exit_address
|
||||
|
||||
sec
|
||||
CopyXToYPrep :do_restore
|
||||
|
||||
ldx :low_save_addr
|
||||
ldy :exit_address
|
||||
:do_restore jsr $0000 ; Jump in to do SCREEN_HEIGHT lines
|
||||
|
||||
stz LastPatchOffset ; Clear the value once completed
|
||||
plb
|
||||
rts
|
||||
|
||||
; Based on the current value of StartX in the direct page, patch up the code fields
|
||||
; to render the correct data. Note that we do *not* do the OpcodeRestore in this
|
||||
; routine. The reason is that the restore *must* be applied using the (StartX, StartY)
|
||||
; values from the previous frame, which requires logic that is not relevant to setting
|
||||
; up the code field.
|
||||
;
|
||||
; This function is where the reverse-mapping aspect of the code field is compensated
|
||||
; for. In the initialize case where X = 0, the exit point is at the *end* of
|
||||
; the code buffer line
|
||||
;
|
||||
; +----+----+ ... +----+----+----+
|
||||
; | 82 | 80 | | 04 | 02 | 00 |
|
||||
; +----+----+ ... +----+----+----+
|
||||
; ^ x=0
|
||||
;
|
||||
; As the screen scrolls right-to-left, the exit position moves to earlier memory
|
||||
; locations until wrapping around from 163 to 0.
|
||||
;
|
||||
; The net calculation are
|
||||
;
|
||||
; x_exit = (164 - x) % 164
|
||||
; x_enter = (164 - x - width) % 164
|
||||
;
|
||||
|
||||
_ApplyBG0XPosLite
|
||||
:virt_line_x2 equ tmp1
|
||||
:lines_left_x2 equ tmp2
|
||||
|
||||
; If there are saved opcodes that have not been restored, do not run this routine
|
||||
lda LastPatchOffset
|
||||
beq *+3
|
||||
rts
|
||||
|
||||
; This code is fairly succinct. See the corresponding code in Vert.s for more detailed comments.
|
||||
|
||||
lda StartYMod208 ; This is the base line of the virtual screen
|
||||
asl
|
||||
sta :virt_line_x2 ; Keep track of it
|
||||
|
||||
lda ScreenHeight
|
||||
asl
|
||||
sta :lines_left_x2
|
||||
|
||||
; Calculate the exit and entry offsets into the code fields. This is a bit tricky, because odd-aligned
|
||||
; rendering causes the left and right edges to move in a staggered fashion.
|
||||
;
|
||||
; ... +----+----+----+----+----+- ... -+----+----+----+----+----+
|
||||
; | 04 | 06 | 08 | 0A | 0C | | 44 | 46 | 48 | 4A |
|
||||
; ... +----+----+----+----+----+- ... -+----+----+----+----+----+
|
||||
; | |
|
||||
; +---- screen width --------------+
|
||||
; entry | | exit
|
||||
;
|
||||
; Here is an example of a screen 64 bytes wide. When everything is aligned to an even offset
|
||||
; then the entry point is column $08 and the exit point is column $48
|
||||
;
|
||||
; If we move the screen forward one byte (which means the pointers move backwards) then the low-byte
|
||||
; of column $06 will be on the right edge of the screen and the high-byte of column $46 will left-edge
|
||||
; of the screen. Since the one-byte edges are handled specially, the exit point shifts one column, but
|
||||
; the entry point does not.
|
||||
;
|
||||
; ... +----+----+----+----+----+- ... -+----+----+----+----+----+
|
||||
; | 04 | 06 | 08 | 0A | 0C | | 44 | 46 | 48 | 4A |
|
||||
; ... +----+----+----+----+----+- ... -+----+----+----+----+----+
|
||||
; | | | |
|
||||
; +--|------ screen width -------|--+
|
||||
; entry | | exit
|
||||
;
|
||||
; When the screen is moved one more byte forward, then the entry point will move to the
|
||||
; next column.
|
||||
;
|
||||
; ... +----+----+----+----+----+- ... -+----+----+----+----+----+
|
||||
; | 04 | 06 | 08 | 0A | 0C | | 44 | 46 | 48 | 4A |
|
||||
; ... +----+----+----+----+----+- ... -+----+----+----+----+----+
|
||||
; | |
|
||||
; +------ screen width ------------+
|
||||
; entry | | exit
|
||||
;
|
||||
; So, in short, the entry tile position is rounded up from the x-position and the exit
|
||||
; tile position is rounded down.
|
||||
;
|
||||
; Now, the left edge of the screen is pushed last, so we need to exit one instruction *after*
|
||||
; the location (163 - StartX % 164)
|
||||
;
|
||||
; x = 0
|
||||
;
|
||||
; | PEA $0000 |
|
||||
; +-----------+
|
||||
; | PEA $0000 |
|
||||
; +-----------+
|
||||
; | JMP loop | <-- Exit here
|
||||
; +-----------+
|
||||
;
|
||||
; x = 1 and 2
|
||||
;
|
||||
; | PEA $0000 |
|
||||
; +-----------+
|
||||
; | PEA $0000 | <-- Exit Here
|
||||
; +-----------+
|
||||
; | JMP loop |
|
||||
; +-----------+
|
||||
|
||||
lda StartXMod164
|
||||
|
||||
; Alternate entry point if the virt_line_x2 and lines_left_x2 and XMod164 values are passed in externally
|
||||
|
||||
_ApplyBG0XPosAltLite
|
||||
;:stk_save equ tmp0
|
||||
:virt_line_x2 equ tmp1
|
||||
:lines_left_x2 equ tmp2
|
||||
:draw_count_x2 equ tmp3
|
||||
:exit_offset equ tmp4
|
||||
:entry_offset equ tmp5
|
||||
:exit_bra equ tmp6
|
||||
:exit_address equ tmp7
|
||||
:base_address equ tmp8
|
||||
:opcode equ tmp9
|
||||
:odd_entry_offset equ tmp10
|
||||
:draw_count_x3 equ blttmp ; steal even mode direct page temp space...
|
||||
:draw_count_x6 equ blttmp+2
|
||||
:entry_jmp_addr equ blttmp+4
|
||||
:low_save_addr equ blttmp+6
|
||||
:draw_count_x3 equ blttmp+8
|
||||
:draw_count_x6 equ blttmp+10
|
||||
:entry_odd_addr equ blttmp+12
|
||||
:exit_odd_addr equ blttmp+14
|
||||
|
||||
bit #$0001
|
||||
jne :odd_case ; Specialized routines for even/odd cases
|
||||
|
||||
; If the exit byte is even, then the left edge is odd-aligned and we exit at this word.
|
||||
|
||||
tax
|
||||
lda CodeFieldEvenBRA-2,x
|
||||
sta :exit_bra
|
||||
|
||||
lda Col2CodeOffset-2,x ; offset from :base that is the exit location
|
||||
sta :exit_offset
|
||||
sta LastPatchOffset ; Cache as a flag for later
|
||||
|
||||
; Calculate the entry point into the code field by calculating the right edge
|
||||
|
||||
txa ; lda StartXMod164
|
||||
clc
|
||||
adc ScreenWidth ; move to the right edge
|
||||
|
||||
cmp #164 ; Keep the value in range
|
||||
bcc *+5
|
||||
sbc #164
|
||||
|
||||
; Lookup the relative offset that we will be entering the code field. Need to adjust the Col2CodeOffset
|
||||
; to account for the position of the BRL instruction
|
||||
|
||||
tax
|
||||
lda Col2CodeOffset-2,x ; offset from _LOOP (0 to 249 step 3)
|
||||
clc
|
||||
adc #-_ENTRY_JMP+3
|
||||
sta :opcode
|
||||
|
||||
; Now update the code field to get ready to execute. We set the bank register to the code
|
||||
; field to make updates faster. The primary actions to do are.
|
||||
;
|
||||
; 1. Saves the low operand byte in the code field (opcode is always $F4)
|
||||
; 2. Writes the BRA instruction to exit the code field
|
||||
; 3. Writes the JMP entry point to enter the code field
|
||||
;
|
||||
; We do need to split the update into two parts so that we can handle the wrap-around portion
|
||||
|
||||
ldx :lines_left_x2
|
||||
lda #208*2
|
||||
sec
|
||||
sbc :virt_line_x2 ; calculate number of lines to the end of the buffer
|
||||
cmp :lines_left_x2
|
||||
bcs :one_pass_even ; if there's room, do it in one shot
|
||||
|
||||
; Since the screen height can be up to 200 lines and the virtual buffer size is 208, the common
|
||||
; case will be that the blit will wrap around the end of the code field
|
||||
|
||||
tax
|
||||
jsr :one_pass_even ; Go through with this draw count
|
||||
|
||||
stz :virt_line_x2
|
||||
|
||||
lda :lines_left_x2
|
||||
sec
|
||||
sbc :draw_count_x2 ; this many left to draw. Fall through to finish up
|
||||
tax
|
||||
|
||||
:one_pass_even
|
||||
txa
|
||||
sta :draw_count_x2 ; this is the number of lines we will do right now
|
||||
asl
|
||||
adc :draw_count_x2
|
||||
sta :draw_count_x6
|
||||
lsr
|
||||
sta :draw_count_x3
|
||||
|
||||
phb ; Save the existing bank
|
||||
|
||||
sep #$20 ; Set the data bank to the code field
|
||||
lda BTableHigh
|
||||
pha
|
||||
plb
|
||||
rep #$21 ; clear the carry while we're here...
|
||||
|
||||
ldx :virt_line_x2
|
||||
ldal BTableLow,x ; Get the address of the code field line
|
||||
sta :base_address ; Will use this address a few times
|
||||
|
||||
adc #_ENTRY_JMP ; Add the offsets in order to get absolaute addresses
|
||||
sta :entry_jmp_addr
|
||||
adc #{_LOW_SAVE-_ENTRY_JMP}
|
||||
sta :low_save_addr
|
||||
|
||||
lda :base_address
|
||||
adc :exit_offset ; Add the offset to get the absolute address in the code field line
|
||||
sta :exit_address
|
||||
|
||||
; First step is to set the BRA instruction to exit the code field at the proper location. There
|
||||
; are two sub-steps to do here; we need to save the 8-bit value that exists at the location+1 and
|
||||
; then overwrite it with the branch instruction.
|
||||
|
||||
sec ; These macros preform subtractions that do not underflow
|
||||
CopyXToYPrep :do_save_entry_e
|
||||
LiteSetConstPrep :do_set_bra_e
|
||||
stal :do_setopcode_e+1
|
||||
stal :do_set_rel_e+1
|
||||
|
||||
sep #$20
|
||||
ldy :entry_jmp_addr
|
||||
lda #$82
|
||||
:do_setopcode_e jsr $0000 ; Copy in the BRL opcode into the entry point
|
||||
rep #$20
|
||||
|
||||
ldx :exit_address
|
||||
ldy :low_save_addr
|
||||
:do_save_entry_e jsr $0000 ; Copy a word from offset x to y
|
||||
|
||||
ldy :exit_address
|
||||
lda :exit_bra
|
||||
:do_set_bra_e jsr $0000 ; Set the BRA instruction in the code field to exit
|
||||
|
||||
ldy :entry_jmp_addr
|
||||
iny
|
||||
lda :opcode
|
||||
:do_set_rel_e jsr $0000 ; Set the relative offset for all BRL instructions
|
||||
|
||||
plb
|
||||
rts
|
||||
|
||||
; Odd case if very close to the even case, except that the code is entered a word later. It is still
|
||||
; exited at the same word. There is extra work done because we have to save the third byte of the
|
||||
; exit location to fill in the left edge and we have to patch a different BRL to enter the code field
|
||||
; afte the right-edge byte is pushed onto the screen
|
||||
:odd_case
|
||||
dec
|
||||
tax
|
||||
lda CodeFieldOddBRA,x
|
||||
sta :exit_bra
|
||||
|
||||
lda Col2CodeOffset,x
|
||||
sta :exit_offset
|
||||
sta LastPatchOffset ; Cache as a flag for later
|
||||
|
||||
txa ; StartXMod164 - 1
|
||||
clc
|
||||
adc ScreenWidth
|
||||
cmp #164 ; Keep the value in range
|
||||
bcc *+5
|
||||
sbc #164
|
||||
|
||||
tax
|
||||
lda Col2CodeOffset,x
|
||||
clc
|
||||
adc #-_ENTRY_JMP+3 ; In this case it gets loaded in the X-register
|
||||
sta :opcode
|
||||
|
||||
lda Col2CodeOffset-2,x
|
||||
clc
|
||||
adc #-_ENTRY_ODD+3
|
||||
sta :odd_entry_offset
|
||||
|
||||
; Main loop
|
||||
|
||||
ldx :lines_left_x2
|
||||
lda #208*2
|
||||
sec
|
||||
sbc :virt_line_x2 ; calculate number of lines to the end of the buffer
|
||||
cmp :lines_left_x2
|
||||
bcs :one_pass_odd ; if there's room, do it in one shot
|
||||
|
||||
tax
|
||||
jsr :one_pass_odd
|
||||
|
||||
stz :virt_line_x2
|
||||
|
||||
lda :lines_left_x2
|
||||
sec
|
||||
sbc :draw_count_x2 ; this many left to draw. Fall through to finish up
|
||||
tax
|
||||
|
||||
:one_pass_odd
|
||||
txa
|
||||
sta :draw_count_x2 ; this is the number of lines we will do right now
|
||||
asl
|
||||
adc :draw_count_x2
|
||||
sta :draw_count_x6
|
||||
lsr
|
||||
sta :draw_count_x3
|
||||
|
||||
phb ; Save the existing bank
|
||||
|
||||
sep #$20
|
||||
lda BTableHigh ; Get the bank
|
||||
pha
|
||||
plb
|
||||
rep #$21
|
||||
|
||||
ldx :virt_line_x2
|
||||
ldal BTableLow,x ; Get the address of the first code field line
|
||||
sta :base_address ; Save it to use as the base address
|
||||
|
||||
adc #_ENTRY_JMP ; Add the offsets in order to get absolute addresses
|
||||
sta :entry_jmp_addr
|
||||
adc #{_ENTRY_ODD-_ENTRY_JMP}
|
||||
sta :entry_odd_addr
|
||||
adc #{_EXIT_ODD-_ENTRY_ODD}
|
||||
sta :exit_odd_addr
|
||||
adc #{_LOW_SAVE-_EXIT_ODD}
|
||||
sta :low_save_addr
|
||||
|
||||
lda :base_address
|
||||
adc :exit_offset ; Add some offsets to get the base address in the code field line
|
||||
sta :exit_address
|
||||
|
||||
; Setup the jumps into the unrolled loops
|
||||
|
||||
sec
|
||||
CopyXToYPrep :do_save_entry_o
|
||||
stal :do_save_high_byte+1
|
||||
LiteSetConstPrep :do_set_bra_o
|
||||
stal :do_setopcode_o+1
|
||||
stal :do_set_rel_o+1
|
||||
stal :do_odd_code_entry+1
|
||||
|
||||
sep #$20
|
||||
ldy :entry_jmp_addr
|
||||
lda #$A2
|
||||
:do_setopcode_o jsr $0000 ; Copy in the LDX opcode into the entry point
|
||||
|
||||
ldx :exit_address
|
||||
inx
|
||||
inx
|
||||
ldy :exit_odd_addr
|
||||
iny
|
||||
:do_save_high_byte jsr $0000 ; Copy high byte of the exit location into the odd handling path
|
||||
rep #$20
|
||||
|
||||
ldx :exit_address
|
||||
ldy :low_save_addr
|
||||
:do_save_entry_o jsr $0000 ; Save the low word of the exit into a save location for restore later
|
||||
|
||||
ldx :exit_address
|
||||
lda :exit_bra
|
||||
:do_set_bra_o jsr $0000 ; Insert a BRA instruction over the saved word
|
||||
|
||||
ldy :entry_jmp_addr
|
||||
iny
|
||||
lda :opcode ; Store the same relative address to use for loading the entry word data
|
||||
:do_set_rel_o jsr $0000
|
||||
|
||||
; The odd case need to do a bit of extra work
|
||||
|
||||
ldy :entry_odd_addr
|
||||
iny
|
||||
lda :odd_entry_offset
|
||||
:do_odd_code_entry jsr $0000 ; Fill in the BRL argument for the odd entry
|
||||
|
||||
plb
|
||||
rts
|
||||
|
||||
_RestoreScanlineBG0OpcodesLite
|
||||
:virt_line_x2 equ tmp1
|
||||
:lines_left_x2 equ tmp2
|
||||
:exit_offset equ tmp4
|
||||
|
||||
; Avoid local var collisions
|
||||
:virt_line_pos_x2 equ tmp11
|
||||
:total_left_x2 equ tmp12
|
||||
:current_count_x2 equ tmp13
|
||||
:ptr equ tmp14
|
||||
|
||||
asl
|
||||
sta :virt_line_pos_x2
|
||||
tay
|
||||
|
||||
txa
|
||||
asl
|
||||
sta :total_left_x2
|
||||
|
||||
lda StartXMod164Tbl
|
||||
sta :ptr
|
||||
lda StartXMod164Tbl+2
|
||||
sta :ptr+2
|
||||
|
||||
; Patch our the ranges from the StartXMod164Tbl array starting at the first virtual line
|
||||
:loop
|
||||
lda [:ptr],y
|
||||
and #$FF00 ; Determine how many sequential lines to restore
|
||||
xba
|
||||
inc
|
||||
asl
|
||||
min :total_left_x2 ; Don't draw more than the number of lines that are left to process
|
||||
sta :current_count_x2 ; Save a copy for later
|
||||
|
||||
sta :lines_left_x2 ; Set the parameter
|
||||
sty :virt_line_x2 ; Set the parameter
|
||||
lda LastOffsetTbl,y
|
||||
sta :exit_offset
|
||||
jsr _RestoreBG0OpcodesAltLite
|
||||
|
||||
clc
|
||||
lda :virt_line_pos_x2
|
||||
adc :current_count_x2
|
||||
cmp #208*2 ; Do the modulo check in this loop
|
||||
bcc *+5
|
||||
sbc #208*2
|
||||
sta :virt_line_pos_x2
|
||||
tay
|
||||
|
||||
lda :total_left_x2
|
||||
sec
|
||||
sbc :current_count_x2
|
||||
sta :total_left_x2
|
||||
bne :loop
|
||||
|
||||
rts
|
||||
|
||||
; This is a variant of the above routine that allows each x-position to be set independently from a table of value. This is
|
||||
; quite a bit slower than the other routine since we cannot store constant values for each line.
|
||||
;
|
||||
; This routine operates at a higher level and does not try to be super optimized for the case where every line has a different
|
||||
; set of parameters. Instead, we optimize for the case where there are a few large ranges of the screen moving at different
|
||||
; rates, e.g. a fixed status bar area on top, a slow-scrolling area in the middle and a fast are in the foreground.
|
||||
;
|
||||
; The table that drives this is dense and has the following format for each word
|
||||
;
|
||||
; Bits 0 - 7: X mod 164 value
|
||||
; Bits 8 - 15: Number of scanline to persist this mod value
|
||||
;
|
||||
; So, if the first 10 entries has a mod value of 5, they would look like: $0905, $0805, $0705, ... $0105, $0005
|
||||
;
|
||||
; This allows the code to start an an arbitrary location and immeditely sync up with the modulo list. It also allows
|
||||
; the code to easily skip ranges of constant values using the existing _ApplyBG0XPos function as a subroutine.
|
||||
;
|
||||
; NOTE: This function is *exactly* the same as _ApplyScanlineBG0XPos with the exception that it calls
|
||||
; _ApplyBG0XPosAltLite instead of _ApplyBG0XPosAlt. Should unify with an subroutine selector
|
||||
_ApplyScanlineBG0XPosLite
|
||||
|
||||
; Copies of the local variables in _ApplyBG0XPos
|
||||
:virt_line_x2 equ tmp1
|
||||
:lines_left_x2 equ tmp2
|
||||
:exit_offset equ tmp4
|
||||
|
||||
; Avoid local var collision with _ApplyBG0XPos
|
||||
:virt_line_pos_x2 equ tmp11
|
||||
:total_left_x2 equ tmp12
|
||||
:current_count_x2 equ tmp13
|
||||
:ptr equ tmp14
|
||||
|
||||
lda StartXMod164Tbl
|
||||
sta :ptr
|
||||
lda StartXMod164Tbl+2
|
||||
sta :ptr+2
|
||||
ora :ptr
|
||||
bne *+3 ; null pointer check
|
||||
rts
|
||||
|
||||
lda StartYMod208 ; This is the base line of the virtual screen
|
||||
asl
|
||||
sta :virt_line_pos_x2
|
||||
tay
|
||||
|
||||
lda ScreenHeight
|
||||
asl
|
||||
sta :total_left_x2
|
||||
|
||||
; Patch our the ranges from the StartXMod164Tbl array starting at the first virtual line
|
||||
:loop
|
||||
lda [:ptr],y
|
||||
tax
|
||||
|
||||
and #$FF00 ; Determine how many sequential lines have this mod value
|
||||
xba
|
||||
inc
|
||||
asl
|
||||
min :total_left_x2 ; Don't draw more than the number of lines that are left to process
|
||||
sta :current_count_x2 ; Save a copy for later
|
||||
|
||||
sta :lines_left_x2 ; Set the parameter
|
||||
sty :virt_line_x2 ; Set the parameter
|
||||
txa ; Put the X mod 164 value in the accumulator
|
||||
and #$00FF
|
||||
jsr _ApplyBG0XPosAltLite
|
||||
|
||||
lda :exit_offset ; Get the direct address in the code field that was overwritten
|
||||
ldy :virt_line_pos_x2
|
||||
sta LastOffsetTbl,y ; Stash it for use by the per-scanline resotre function
|
||||
|
||||
tya
|
||||
clc
|
||||
adc :current_count_x2
|
||||
cmp #208*2 ; Do the modulo check in this loop
|
||||
bcc *+5
|
||||
sbc #208*2
|
||||
sta :virt_line_pos_x2
|
||||
tay
|
||||
|
||||
lda :total_left_x2
|
||||
sec
|
||||
sbc :current_count_x2
|
||||
sta :total_left_x2
|
||||
bne :loop
|
||||
|
||||
rts
|
||||
|
||||
; Copy from the offset at X to the offset at Y
|
||||
;
|
||||
; Y = code field offset
|
||||
; X = value
|
||||
CopyXToYPrep mac
|
||||
lda #x2y_bottom
|
||||
sbc blttmp+10 ; Copy from above, :draw_count_x6 equ blttmp+10
|
||||
stal ]1+1 ; A jmp/jsr instruction
|
||||
<<<
|
||||
]line equ 199
|
||||
lup 200
|
||||
lda {]line*_LINE_SIZE},x
|
||||
sta {]line*_LINE_SIZE},y
|
||||
]line equ ]line-1
|
||||
--^
|
||||
x2y_bottom rts
|
||||
|
||||
; Set a constant 8-bit value across the code field
|
||||
;
|
||||
; Y = code field offset
|
||||
LiteSetConstPrep mac
|
||||
lda #lsc_bottom
|
||||
sbc blttmp+8 ; Copy from above, :draw_count_x3 equ blttmp+8
|
||||
stal ]1+1 ; A jmp/jsr instruction
|
||||
<<<
|
||||
|
||||
]line equ 199
|
||||
lup 200
|
||||
sta {]line*_LINE_SIZE},y
|
||||
]line equ ]line-1
|
||||
--^
|
||||
lsc_bottom rts
|
@ -38,7 +38,7 @@ PagePatches da {long_0-base+2}
|
||||
da {long_2-base+2}
|
||||
da {long_3-base+2}
|
||||
; da {long_4-base+2}
|
||||
da {long_5-base+2}
|
||||
; da {long_5-base+2}
|
||||
da {long_6-base+2}
|
||||
da {odd_entry-base+2}
|
||||
da {loop_exit_1-base+2}
|
||||
@ -63,7 +63,7 @@ BankPatches da {long_0-base+3}
|
||||
da {long_2-base+3}
|
||||
da {long_3-base+3}
|
||||
; da {long_4-base+3}
|
||||
da {long_5-base+3}
|
||||
; da {long_5-base+3}
|
||||
da {long_6-base+3}
|
||||
BankPatchNum equ *-BankPatches
|
||||
|
||||
@ -94,13 +94,13 @@ entry_jmp jmp $0100
|
||||
; update the low-byte of the address, the means it takes only
|
||||
; an amortized 4-cycles per line to set the entry point break
|
||||
|
||||
bit #$000B ; Check the bottom nibble to quickly identify a PEA instruction
|
||||
bne r_is_not_pea ; This costs 5 cycles in the fast-path
|
||||
; bit #$000B ; Check the bottom nibble to quickly identify a PEA instruction
|
||||
; bne r_is_not_pea ; This costs 5 cycles in the fast-path
|
||||
|
||||
xba ; fast code for PEA
|
||||
r_jmp_rtn sep #$20 ; shared return code path by all methods
|
||||
two_byte_rtn pha
|
||||
rep #$61 ; Clear Carry, Overflow and M bits #$20
|
||||
; rep #$61 ; Clear Carry, Overflow and M bits #$20
|
||||
odd_entry jmp $0100 ; unconditionally jump into the "next" instruction in the
|
||||
; code field. This is OK, even if the entry point was the
|
||||
; last instruction, because there is a JMP at the end of
|
||||
@ -179,9 +179,9 @@ loop_back jmp loop-base ; +252 Ensure execution cont
|
||||
loop_exit_3 jmp even_exit-base ; +255
|
||||
|
||||
odd_exit sep #$21 ; 8-bit mode and set the carry just in case we get to a snippet JMP
|
||||
long_5 ldal OPCODE_SAVE ; Load the opcode that was saved
|
||||
bit #$0B
|
||||
bne :chk_jmp
|
||||
;long_5 ldal OPCODE_SAVE ; Load the opcode that was saved
|
||||
; bit #$0B
|
||||
; bne :chk_jmp
|
||||
long_6 ldal OPCODE_HIGH_SAVE+1 ; get the high byte of the PEA operand
|
||||
|
||||
; Fall-through when we have to push a byte on the left edge. Must be 8-bit on entry. Optimized
|
||||
|
239
src/blitter/TemplateLite.s
Normal file
239
src/blitter/TemplateLite.s
Normal file
@ -0,0 +1,239 @@
|
||||
; Template and equates for GTE blitter
|
||||
blt_return_lite EXT
|
||||
|
||||
use ../Defs.s ; this causes merlin32 to terminate early with no error output
|
||||
|
||||
mx %00
|
||||
|
||||
LITE_STK_ADDR equ lite_entry_1-lite_base+1 ; offset to patch in the stack (SHR) right edge address
|
||||
LITE_LYR_ENTRY equ lite_entry_1-lite_base
|
||||
|
||||
LITE_CODE_ENTRY_OPCODE equ lite_entry_jmp-lite_base
|
||||
LITE_CODE_ENTRY equ lite_entry_jmp-lite_base+1 ; low byte of the page-aligned jump address
|
||||
LITE_ODD_ENTRY equ lite_odd_entry-lite_base+1
|
||||
LITE_CODE_LEN equ lite_top-lite_base
|
||||
LITE_CODE_EXIT equ lite_even_exit-lite_base
|
||||
LITE_OPCODE_SAVE equ lite_odd_low_save-lite_base ; spot to save the code field opcode when patching exit BRA
|
||||
LITE_OPCODE_HIGH_SAVE equ lite_odd_high_save-lite_base ; save the third byte only
|
||||
|
||||
LITE_ENABLE_INT equ lite_enable_int-lite_base ; offset that re-enable interrupts and continues
|
||||
|
||||
; Return to caller -- this is the target address to patch in the JMP instruction on the last rendered line. We
|
||||
; put it at the beginning so the rest of the bank can be replicated line templates.
|
||||
lite_full_return ENT
|
||||
jml blt_return_lite ; Full exit
|
||||
|
||||
; Start of the template code. This code is replicated 208 times in the code field
|
||||
; bank, which is what is required to render 26 tiles to cover the full screen vertical
|
||||
; scrolling. The lite blitter is crafted to allow the accumulator to be in 8-bit
|
||||
; mode and avoid any need for rep/sep instructions to handle the odd-aligned case
|
||||
lite_base ENT
|
||||
lite_entry_1 ldx #0000 ; Sets screen address (right edge)
|
||||
txs
|
||||
|
||||
lite_entry_jmp brl $0000 ; If the screen is odd-aligned, then the opcode is set to
|
||||
; $A2 to convert to a LDX #imm instruction. This puts the
|
||||
; relative offset of the instruction field in the register
|
||||
; and falls through to the next instruction.
|
||||
|
||||
lda: $0001,x ; Get the low byte and push onto the stack
|
||||
pha
|
||||
lite_odd_entry brl $0000 ; unconditionally jump into the "next" instruction in the
|
||||
; code field. This is OK, even if the entry point was the
|
||||
; last instruction, because there is a JMP at the end of
|
||||
; the code field, so the code will simply jump to that
|
||||
; instruction directly.
|
||||
;
|
||||
; As with the original entry point, because all of the
|
||||
; code field is page-aligned, only the low byte needs to
|
||||
; be updated when the scroll position changes
|
||||
|
||||
|
||||
|
||||
; Re-enable interrupts and continue -- the even_exit JMP from the previous line will jump here every
|
||||
; 8 or 16 lines in order to give the system time to handle interrupts.
|
||||
lite_enable_int tyx
|
||||
txs ; restore the stack. No 2-layer support, so B and D are set to GTE data bank
|
||||
lda STATE_REG_OFF ; we are in 8-bit mode the whole time...
|
||||
stal STATE_REG
|
||||
cli
|
||||
sei
|
||||
lda STATE_REG_BLIT ; External values
|
||||
stal STATE_REG
|
||||
bra lite_entry_1
|
||||
|
||||
lite_loop_exit_1 jmp lite_odd_exit ; +0 Alternate exit point depending on whether the left edge is
|
||||
lite_loop_exit_2 jmp lite_even_exit ; +3 odd-aligned
|
||||
|
||||
lite_loop lup 82 ; +6 Set up 82 PEA instructions, which is 328 pixels and consumes 246 bytes
|
||||
pea $0000 ; This is 41 8x8 tiles in width. Need to have N+1 tiles for screen overlap
|
||||
--^
|
||||
lite_loop_back jmp lite_loop ; +252 Ensure execution continues to loop around
|
||||
lite_loop_exit_3 jmp lite_even_exit ; +255
|
||||
|
||||
mx %10
|
||||
lite_odd_exit lda #0 ; get the high byte of the saved PEA operand (odd-case is already in 8-bit mode)
|
||||
pha
|
||||
lite_even_exit jmp $0000 ; Jump to the next line.
|
||||
dfb $F4,$00 ; low-word of the saved PEA instruction
|
||||
|
||||
; Now repeat the code above 207 more times. Loop 206 times and then manually do the last one
|
||||
]line equ 1 ; start at line 1 (line zero was just done above)
|
||||
lup 206
|
||||
ldx #0000
|
||||
txs
|
||||
dfb $82,$00,$00
|
||||
lda: 1,x
|
||||
pha
|
||||
dfb $82,$00,$00
|
||||
|
||||
tyx
|
||||
txs
|
||||
lda STATE_REG_OFF
|
||||
stal STATE_REG
|
||||
cli
|
||||
sei
|
||||
lda STATE_REG_BLIT
|
||||
stal STATE_REG
|
||||
; bra *-34
|
||||
dfb $80,$E0
|
||||
|
||||
jmp _LINE_BASE+{_LINE_SIZE*]line}+_EXIT_EVEN
|
||||
jmp _LINE_BASE+{_LINE_SIZE*]line}+_EXIT_ODD
|
||||
|
||||
pea $0000
|
||||
pea $0000
|
||||
pea $0000
|
||||
pea $0000
|
||||
pea $0000
|
||||
pea $0000
|
||||
pea $0000
|
||||
pea $0000
|
||||
pea $0000
|
||||
pea $0000
|
||||
|
||||
pea $0000
|
||||
pea $0000
|
||||
pea $0000
|
||||
pea $0000
|
||||
pea $0000
|
||||
pea $0000
|
||||
pea $0000
|
||||
pea $0000
|
||||
pea $0000
|
||||
pea $0000
|
||||
|
||||
pea $0000
|
||||
pea $0000
|
||||
pea $0000
|
||||
pea $0000
|
||||
pea $0000
|
||||
pea $0000
|
||||
pea $0000
|
||||
pea $0000
|
||||
pea $0000
|
||||
pea $0000
|
||||
|
||||
pea $0000
|
||||
pea $0000
|
||||
pea $0000
|
||||
pea $0000
|
||||
pea $0000
|
||||
pea $0000
|
||||
pea $0000
|
||||
pea $0000
|
||||
pea $0000
|
||||
pea $0000
|
||||
|
||||
pea $0000
|
||||
pea $0000
|
||||
pea $0000
|
||||
pea $0000
|
||||
pea $0000
|
||||
pea $0000
|
||||
pea $0000
|
||||
pea $0000
|
||||
pea $0000
|
||||
pea $0000
|
||||
|
||||
pea $0000
|
||||
pea $0000
|
||||
pea $0000
|
||||
pea $0000
|
||||
pea $0000
|
||||
pea $0000
|
||||
pea $0000
|
||||
pea $0000
|
||||
pea $0000
|
||||
pea $0000
|
||||
|
||||
pea $0000
|
||||
pea $0000
|
||||
pea $0000
|
||||
pea $0000
|
||||
pea $0000
|
||||
pea $0000
|
||||
pea $0000
|
||||
pea $0000
|
||||
pea $0000
|
||||
pea $0000
|
||||
|
||||
pea $0000
|
||||
pea $0000
|
||||
pea $0000
|
||||
pea $0000
|
||||
pea $0000
|
||||
pea $0000
|
||||
pea $0000
|
||||
pea $0000
|
||||
pea $0000
|
||||
pea $0000
|
||||
|
||||
pea $0000
|
||||
pea $0000
|
||||
|
||||
jmp _LINE_BASE+{_LINE_SIZE*]line}+_LOOP
|
||||
jmp _LINE_BASE+{_LINE_SIZE*]line}+_EXIT_EVEN
|
||||
|
||||
mx %10
|
||||
lda #0
|
||||
pha
|
||||
jmp $0000
|
||||
dfb $F4,$00
|
||||
]line equ ]line+1
|
||||
--^
|
||||
|
||||
:entry_207 ldx #0000
|
||||
txs
|
||||
dfb $82,$00,$00 ; brl $0000 starts at the next instruction
|
||||
lda: 1,x
|
||||
sep #$20
|
||||
pha
|
||||
dfb $82,$00,$00
|
||||
|
||||
tyx
|
||||
txs
|
||||
lda STATE_REG_OFF
|
||||
stal STATE_REG
|
||||
cli
|
||||
sei
|
||||
lda STATE_REG_BLIT
|
||||
stal STATE_REG
|
||||
bra :entry_207
|
||||
|
||||
jmp :odd_out_207
|
||||
jmp :exit_207
|
||||
:loop_207
|
||||
lup 82
|
||||
pea $0000
|
||||
--^
|
||||
jmp :loop_207
|
||||
jmp :exit_207
|
||||
|
||||
mx %10
|
||||
:odd_out_207 lda #0
|
||||
pha
|
||||
:exit_207 jmp lite_entry_1
|
||||
dfb $F4,$00
|
||||
|
||||
ds 3546 ; pad to the end of the bank to make sure we start at address $0000
|
@ -5,92 +5,6 @@
|
||||
; Based on the current value of StartY in the direct page. Set up the dispatch
|
||||
; information so that the BltRange driver will render the correct code field
|
||||
; lines in the correct order
|
||||
_ApplyBG0YPosOld
|
||||
|
||||
:rtbl_idx_x2 equ tmp0
|
||||
:virt_line_x2 equ tmp1
|
||||
:lines_left_x2 equ tmp2
|
||||
:draw_count_x2 equ tmp3
|
||||
:stk_save equ tmp4
|
||||
|
||||
; First task is to fill in the STK_ADDR values by copying them from the RTable array. We
|
||||
; copy from RTable[i] into BlitField[StartY+i]. As with all of this code, the difficult part
|
||||
; is decomposing the update across banks
|
||||
|
||||
stz :rtbl_idx_x2 ; Start copying from the first entry in the table
|
||||
|
||||
lda StartY ; This is the base line of the virtual screen
|
||||
jsr Mod208
|
||||
sta StartYMod208
|
||||
|
||||
asl
|
||||
sta :virt_line_x2 ; Keep track of it
|
||||
|
||||
phb ; Save the current bank
|
||||
tsc ; we intentionally leak one byte of stack in each loop
|
||||
sta :stk_save ; iteration, so save the stack to repair at the end
|
||||
|
||||
; copy a range of address from the table into the destination bank. If we restrict ourselves to
|
||||
; rectangular playfields, this can be optimized to just subtracting a constant value. See the
|
||||
; Templates::SetScreenAddrs subroutine.
|
||||
|
||||
lda ScreenHeight
|
||||
asl
|
||||
sta :lines_left_x2
|
||||
|
||||
; This is the verbose part -- figure out how many lines to draw. We don't want to artificially limit
|
||||
; the height of the visible screen (for example, doing an animated wipe while scrolling), so the screen
|
||||
; height could be anything from 1 to 200.
|
||||
;
|
||||
; For larger values, we want to break things up on 16-line boundaries based on the virt_line value. So,
|
||||
;
|
||||
; draw_count = min(lines_left, (16 - (virt_line % 16))
|
||||
|
||||
:loop
|
||||
ldx :virt_line_x2
|
||||
ldal BTableLow,x ; Get the address of the first code field line
|
||||
tay
|
||||
|
||||
ldal BTableHigh,x ; Target bank in low byte
|
||||
pha
|
||||
|
||||
txa
|
||||
and #$001E
|
||||
eor #$FFFF
|
||||
sec
|
||||
adc #32
|
||||
min :lines_left_x2
|
||||
|
||||
sta :draw_count_x2 ; Do this many lines
|
||||
tax
|
||||
|
||||
clc ; pre-advance virt_line_2 because we have the value
|
||||
adc :virt_line_x2
|
||||
sta :virt_line_x2
|
||||
|
||||
plb
|
||||
jsr _CopyRTableToStkAddr
|
||||
; CopyRTableToStkAddr :rtbl_idx_x2 ; X = rtbl_idx_x2 on return
|
||||
|
||||
txa ; carry flag is unchanged
|
||||
adc :draw_count_x2 ; advance the index into the RTable
|
||||
sta :rtbl_idx_x2
|
||||
|
||||
lda :lines_left_x2 ; subtract the number of lines we just completed
|
||||
sec
|
||||
sbc :draw_count_x2
|
||||
sta :lines_left_x2
|
||||
|
||||
jne :loop
|
||||
|
||||
lda :stk_save
|
||||
tcs
|
||||
plb
|
||||
rts
|
||||
|
||||
; This is an optimized version of _ApplyBG0YPos. We pre-compute the breakdown across the bank
|
||||
; boundries in order to eliminate the the minimum calculation and some loop variable updates
|
||||
; from the inner loop.
|
||||
|
||||
_ApplyBG0YPos
|
||||
|
||||
|
93
src/blitter/VertLite.s
Normal file
93
src/blitter/VertLite.s
Normal file
@ -0,0 +1,93 @@
|
||||
; Subroutines that deal with the vertical scrolling and rendering. The primary function
|
||||
; of these routines are to adjust tables and patch in new values into the code field
|
||||
; when the virtual Y-position of the play field changes.
|
||||
|
||||
_ApplyBG0YPosLite
|
||||
|
||||
:rtbl_idx_x2 equ tmp0
|
||||
:virt_line_x2 equ tmp1
|
||||
:lines_left_x2 equ tmp2
|
||||
:draw_count_x2 equ tmp3
|
||||
:stk_save equ tmp4
|
||||
:line_count equ tmp5
|
||||
|
||||
; First task is to fill in the STK_ADDR values by copying them from the RTable array. We
|
||||
; copy from RTable[i] into BlitField[StartY+i].
|
||||
|
||||
stz :rtbl_idx_x2 ; Start copying from the first entry in the table
|
||||
|
||||
lda StartY ; This is the base line of the virtual screen
|
||||
jsr Mod208
|
||||
sta StartYMod208
|
||||
|
||||
asl
|
||||
sta :virt_line_x2 ; Keep track of it
|
||||
|
||||
; copy a range of address from the table into the destination bank. If we restrict ourselves to
|
||||
; rectangular playfields, this can be optimized to just subtracting a constant value. See the
|
||||
; Templates::SetScreenAddrs subroutine.
|
||||
|
||||
lda ScreenHeight
|
||||
asl
|
||||
sta :lines_left_x2
|
||||
|
||||
; Check to see if we need to split the update into two parts, e.g. do we wrap around the end
|
||||
; of the code field?
|
||||
|
||||
ldx :lines_left_x2
|
||||
lda #208*2
|
||||
sec
|
||||
sbc :virt_line_x2 ; calculate number of lines to the end of the buffer
|
||||
cmp :lines_left_x2
|
||||
bcs :one_pass ; if there's room, do it in one shot
|
||||
|
||||
tax ; Only do this many lines right now (saved to draw_count_x2)
|
||||
jsr :one_pass ; Go through with this draw count
|
||||
|
||||
stz :virt_line_x2 ; virtual line is at the top (by construction)
|
||||
|
||||
lda :lines_left_x2
|
||||
sec
|
||||
sbc :draw_count_x2 ; this many left to draw. Fall through to finish up
|
||||
tax
|
||||
|
||||
; Set up the addresses for filling in the code field
|
||||
:one_pass
|
||||
stx :draw_count_x2
|
||||
|
||||
phb ; Save the current bank
|
||||
|
||||
ldx :virt_line_x2
|
||||
lda BTableLow,x ; Get the address of the first code field line
|
||||
tay
|
||||
iny ; Fill in the first byte (_ENTRY_1 = 0)
|
||||
|
||||
sep #$20 ; Set the data bank to the code field
|
||||
lda BTableHigh
|
||||
pha
|
||||
plb
|
||||
rep #$21 ; clear the carry while we're here...
|
||||
|
||||
lda :draw_count_x2 ; Do this many lines
|
||||
asl ; x4
|
||||
asl ; x8
|
||||
asl ; x16
|
||||
sec
|
||||
sbc :draw_count_x2 ; x14
|
||||
lsr ; x7
|
||||
eor #$FFFF
|
||||
sec
|
||||
adc #:bottom
|
||||
stal :entry+1 ; patch in the dispatch address
|
||||
|
||||
; This is an inline, unrolled version of CopyRTableToStkAddr
|
||||
:entry jmp $0000
|
||||
]line equ 199
|
||||
lup 200
|
||||
ldal RTable+{]line*2},x
|
||||
sta {]line*_LINE_SIZE},y
|
||||
]line equ ]line-1
|
||||
--^
|
||||
:bottom
|
||||
plb
|
||||
rts
|
@ -102,9 +102,11 @@ TileStoreLookup ENT
|
||||
;
|
||||
; Remember, because the data is pushed on to the stack, the last instruction, which is
|
||||
; in the highest memory location, pushed data that apepars on the left edge of the screen.
|
||||
|
||||
;
|
||||
; This table is overwritten by the "Lite" engine intialization code to provide a different set
|
||||
; of offsets since the lite blitter has a different offset than the normal one.
|
||||
]step equ 0
|
||||
dw CODE_TOP ; There is a spot where we load Col2CodeOffet-2,x
|
||||
dw CODE_TOP ; There is a spot where we load Col2CodeOffset-2,x
|
||||
Col2CodeOffset ENT
|
||||
lup 82
|
||||
dw CODE_TOP+{{81-]step}*PER_TILE_SIZE}
|
||||
|
Loading…
Reference in New Issue
Block a user