mirror of
https://github.com/lscharen/iigs-game-engine.git
synced 2025-01-29 15:33:52 +00:00
Refactor to support building a tool and new demo to try and use it [not working]
This commit is contained in:
parent
8bb17895a9
commit
e2710ace85
18
build-image.bat
Normal file
18
build-image.bat
Normal file
@ -0,0 +1,18 @@
|
||||
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/Toolbox"
|
||||
|
||||
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% .\src\GTETool
|
||||
|
||||
REM Copy in the image assets
|
83
demos/tool/App.Main.s
Normal file
83
demos/tool/App.Main.s
Normal file
@ -0,0 +1,83 @@
|
||||
REL
|
||||
DSK MAINSEG
|
||||
|
||||
use Locator.Macs
|
||||
use Load.Macs
|
||||
use Mem.Macs
|
||||
use Misc.Macs
|
||||
use Util.Macs
|
||||
use EDS.GSOS.Macs
|
||||
|
||||
_GTEStartUp MAC
|
||||
UserTool $02A0
|
||||
<<<
|
||||
|
||||
; Typical init
|
||||
phk
|
||||
plb
|
||||
|
||||
jsr ToolStartUp ; Start up the basic tools: Locator, Memory Manager, Misc
|
||||
jsr GTEStartUp
|
||||
|
||||
_QuitGS qtRec
|
||||
|
||||
bcs Fatal
|
||||
Fatal brk $00
|
||||
qtRec adrl $0000
|
||||
da $00
|
||||
|
||||
ToolStartUp
|
||||
_TLStartUp ; normal tool initialization
|
||||
pha
|
||||
_MMStartUp
|
||||
pla
|
||||
sta MasterId ; our master handle references the memory allocated to us
|
||||
ora #$0100 ; set auxID = $01 (valid values $01-0f)
|
||||
sta UserId ; any memory we request must use our own id
|
||||
|
||||
_MTStartUp
|
||||
rts
|
||||
|
||||
; Load the GTE User Tool and register it
|
||||
GTEStartUp
|
||||
pea $0000
|
||||
pea $0000
|
||||
pea $0000
|
||||
pea $0000
|
||||
pea $0000 ; result space
|
||||
|
||||
lda UserId
|
||||
pha
|
||||
|
||||
pea #^ToolPath
|
||||
pea #ToolPath
|
||||
pea $0001 ; do not load into special memory
|
||||
pea $0001 ; GS/OS string for the argument
|
||||
_InitialLoad2
|
||||
|
||||
ply
|
||||
pla ; Address of the loaded tool
|
||||
plx
|
||||
ply
|
||||
ply
|
||||
|
||||
pea $8000 ; User toolset
|
||||
pea $00A0 ; Set the tool set number
|
||||
phx
|
||||
pha ; Address of function pointer table
|
||||
_SetTSPtr
|
||||
|
||||
clc ; Give GTE a page of direct page memory
|
||||
tdc
|
||||
adc #$0100
|
||||
pha
|
||||
lda UserId
|
||||
pha
|
||||
_GTEStartUp
|
||||
|
||||
rts
|
||||
|
||||
|
||||
MasterId ds 2
|
||||
UserId ds 2
|
||||
ToolPath strl '9:GTETool'
|
10
demos/tool/App.s
Normal file
10
demos/tool/App.s
Normal file
@ -0,0 +1,10 @@
|
||||
; IIgs Sprite Testbed
|
||||
|
||||
TYP $B3 ; S16 file
|
||||
DSK GTEToolDemo
|
||||
XPL
|
||||
|
||||
; Segment #1 -- Main execution block
|
||||
|
||||
ASM App.Main.s
|
||||
SNA Main
|
BIN
demos/tool/GTEToolDemo
Normal file
BIN
demos/tool/GTEToolDemo
Normal file
Binary file not shown.
1
demos/tool/_FileInformation.txt
Normal file
1
demos/tool/_FileInformation.txt
Normal file
@ -0,0 +1 @@
|
||||
GTEToolDemo=Type(B3),AuxType(0000),VersionCreate(70),MinVersion(BE),Access(E3),FolderInfo1(000000000000000000000000000000000000),FolderInfo2(000000000000000000000000000000000000)
|
19
demos/tool/build-image.bat
Normal file
19
demos/tool/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/Tool"
|
||||
|
||||
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% .\GTEToolDemo
|
||||
%CADIUS% ADDFILE %IMAGE% %FOLDER% ..\..\src\GTETool
|
||||
|
||||
REM Copy in the image assets
|
30
demos/tool/package.json
Normal file
30
demos/tool/package.json
Normal file
@ -0,0 +1,30 @@
|
||||
{
|
||||
"name": "gte-toolbox-demo",
|
||||
"version": "1.0.0",
|
||||
"description": "A testbed for developing a toolbox wrapper around the GTE library",
|
||||
"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% GTEToolTest -Source GTEToolTest_S02_MAINSEG_Output.txt -Debug -CompatibilityLayer",
|
||||
"build": "%npm_package_config_merlin32% -V %npm_package_config_macros% App.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": {
|
||||
}
|
||||
}
|
29
package.json
Normal file
29
package.json
Normal file
@ -0,0 +1,29 @@
|
||||
{
|
||||
"name": "generic-tile-engine",
|
||||
"version": "1.0.0",
|
||||
"description": "A tile-base game engine for the Apple IIgs",
|
||||
"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%",
|
||||
"build": "%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": {
|
||||
}
|
||||
}
|
408
src/Core.s
408
src/Core.s
@ -8,94 +8,6 @@
|
||||
|
||||
use .\Defs.s
|
||||
|
||||
; Feature flags
|
||||
NO_INTERRUPTS equ 1 ; turn off for crossrunner debugging
|
||||
NO_MUSIC equ 1 ; turn music + tool loading off
|
||||
|
||||
; External data space provided by the main program segment
|
||||
tiledata EXT
|
||||
TileStore EXT
|
||||
|
||||
; Sprite plane data and mask banks are provided as an exteral segment
|
||||
;
|
||||
; The sprite data holds a set of pre-rendered sprites that are optimized to support the rendering pipeline. There
|
||||
; are four copies of each sprite, along with the cooresponding mask laid out into 4x4 tile regions where the
|
||||
; empty row and column is shared between adjacent blocks.
|
||||
;
|
||||
; Logically, the memory is laid out as 4 columns of sprites and 4 rows.
|
||||
;
|
||||
; +---+---+---+---+---+---+---+---+---+---+---+---+-...
|
||||
; | | | | | | | | | | | | | ...
|
||||
; +---+---+---+---+---+---+---+---+---+---+---+---+-...
|
||||
; | | 0 | 0 | | 1 | 1 | | 2 | 2 | | 3 | 3 | ...
|
||||
; +---+---+---+---+---+---+---+---+---+---+---+---+-...
|
||||
; | | 0 | 0 | | 1 | 1 | | 2 | 2 | | 3 | 3 | ...
|
||||
; +---+---+---+---+---+---+---+---+---+---+---+---+-...
|
||||
; | | | | | | | | | | | | | ...
|
||||
; +---+---+---+---+---+---+---+---+---+---+---+---+-...
|
||||
; | | 4 | 4 | | 5 | 5 | | 6 | 6 | | 7 | 7 | ...
|
||||
; +---+---+---+---+---+---+---+---+---+---+---+---+-...
|
||||
; | | 4 | 4 | | 5 | 5 | | 6 | 6 | | 7 | 7 | ...
|
||||
; +---+---+---+---+---+---+---+---+---+---+---+---+-...
|
||||
; | | | | | | | | | | | | | ...
|
||||
; +---+---+---+---+---+---+---+---+---+---+---+---+-...
|
||||
;
|
||||
; For each sprite, when it needs to be copied into an on-screen tile, it could exist at any offset compared to its
|
||||
; natural alignment. By having a buffer around the sprite data, an address pointer can be set to a different origin
|
||||
; and a simple 8x8 block copy can cut out the appropriate bit of the sprite. For example, here is a zoomed-in look
|
||||
; at a sprite with an offset, O, at (-2,-3). As shown, by selecting an appropriate origin, just the top corner
|
||||
; of the sprite data will be copied.
|
||||
;
|
||||
; +---+---+---+---++---+---+---+---++---+---+---+---++---+---+---+---+..
|
||||
; | | || | || | | | || | | | |
|
||||
; +---+-- O----------------+ --+---++---+---+---+---++---+---+---+---+..
|
||||
; | | | | | || | | | || | | | |
|
||||
; +---+-- | | --+---++---+---+---+---++---+---+---+---+..
|
||||
; | | | | | || | | | || | | | |
|
||||
; +---+-- | | --+---++---+---+---+---++---+---+---+---+..
|
||||
; | | | | | || | | | || | | | |
|
||||
; +===+== | ++===+== | ==+===++===+===+===+===++===+===+===+===+..
|
||||
; | | | || | S | S | S || S | S | S | || | | | |
|
||||
; +---+-- +----------------+ --+---++---+---+---+---++---+---+---+---+..
|
||||
; | | || S | S S | S || S | S | S | S || | | | |
|
||||
; +---+---+---+---++---+---+---+---++---+---+---+---++---+---+---+---+..
|
||||
; | | | | || S | S | S | S || S | S | S | S || | | | |
|
||||
; +---+---+---+---++---+---+---+---++---+---+---+---++---+---+---+---+..
|
||||
; | | | | || S | S | S | S || S | S | S | S || | | | |
|
||||
; +===+===+===+===++===+===+===+===++===+===+===+===++===+===+===+===+..
|
||||
; | | | | || S | S | S | S || S | S | S | S || | | | |
|
||||
; +---+---+---+---++---+---+---+---++---+---+---+---++---+---+---+---+..
|
||||
; | | | | || S | S | S | S || S | S | S | S || | | | |
|
||||
; +---+---+---+---++---+---+---+---++---+---+---+---++---+---+---+---+..
|
||||
; | | | | || S | S | S | S || S | S | S | S || | | | |
|
||||
; +---+---+---+---++---+---+---+---++---+---+---+---++---+---+---+---+..
|
||||
; | | | | || | S | S | S || S | S | S | || | | | |
|
||||
; +---+---+---+---++---+---+---+---++---+---+---+---++---+---+---+---+..
|
||||
; . . . . . . . . . . . . . . . . .
|
||||
;
|
||||
; Each sprite will take up, effectively 9 tiles of storage space per
|
||||
; instance (plus edges) and there are 4 instances for the H/V bits
|
||||
; and 4 more for the masks. This results in a need for 43,264 bytes
|
||||
; for all 16 sprites.
|
||||
|
||||
spritedata EXT
|
||||
spritemask EXT
|
||||
|
||||
; If there are overlays, they are provided as an external
|
||||
Overlay EXT
|
||||
|
||||
; Core engine functionality. The idea is that that source file can be PUT into
|
||||
; a main source file and all of the functionality will be available.
|
||||
;
|
||||
; There are some constancts that must be externally defined that can affect how
|
||||
; the GTE runtime works
|
||||
;
|
||||
; NO_MUSIC : Set to non-zero to avoid using any source
|
||||
; NO_INTERRUPTS : Set to non-zero to avoid installing custom interrupt handlers
|
||||
|
||||
mx %00
|
||||
|
||||
; High-Level StartUp and ShutDown functions
|
||||
EngineStartUp ENT
|
||||
phb
|
||||
phk
|
||||
@ -103,41 +15,23 @@ EngineStartUp ENT
|
||||
|
||||
jsr ToolStartUp ; Start up the toolbox tools we rely on
|
||||
jsr _CoreStartUp
|
||||
jsr SoundStartUp ; Start up any sound/music tools
|
||||
|
||||
plb
|
||||
rtl
|
||||
|
||||
_CoreStartUp
|
||||
jsr SoundStartUp ; Start up any sound/music tools
|
||||
jsr IntStartUp ; Enable certain iterrupts
|
||||
|
||||
jsr InitMemory ; Allocate and initialize memory for the engine
|
||||
jsr EngineReset ; All of the resources are allocated, put the engine in a known state
|
||||
|
||||
jsr InitGraphics ; Initialize all of the graphics-related data
|
||||
nop
|
||||
jsr InitSprites ; Initialize the sprite subsystem
|
||||
jsr InitTiles ; Initialize the tile subsystem
|
||||
|
||||
jsr InitTimers ; Initialize the timer subsystem
|
||||
rts
|
||||
|
||||
EngineShutDown ENT
|
||||
phb
|
||||
phk
|
||||
plb
|
||||
|
||||
jsr SoundShutDown
|
||||
jsr _CoreShutDown
|
||||
jsr ToolShutDown
|
||||
|
||||
plb
|
||||
rtl
|
||||
|
||||
_CoreShutDown
|
||||
jsr IntShutDown
|
||||
jsr SoundShutDown
|
||||
rts
|
||||
|
||||
ToolStartUp
|
||||
_TLStartUp ; normal tool initialization
|
||||
pha
|
||||
@ -152,7 +46,7 @@ ToolStartUp
|
||||
rts
|
||||
|
||||
MasterId ds 2
|
||||
UserId ds 2
|
||||
;UserId ds 2
|
||||
|
||||
; Fatal error handler invoked by the _Err macro
|
||||
PgmDeath tax
|
||||
@ -168,9 +62,6 @@ PgmDeath0 pha
|
||||
ContDeath ldx #$1503
|
||||
jsl $E10000
|
||||
|
||||
ToolShutDown
|
||||
rts
|
||||
|
||||
; Use Tool222 (NinjaTrackerPlus) for music playback
|
||||
SoundStartUp
|
||||
lda #NO_MUSIC
|
||||
@ -194,299 +85,10 @@ SoundShutDown
|
||||
:no_music
|
||||
rts
|
||||
|
||||
; Install interrupt handlers. We use the VBL interrupt to keep animations
|
||||
; moving at a consistent rate, regarless of the rendered frame rate. The
|
||||
; one-second timer is generally just used for counters and as a handy
|
||||
; frames-per-second trigger.
|
||||
IntStartUp
|
||||
lda #NO_INTERRUPTS
|
||||
bne :no_interrupts
|
||||
PushLong #0
|
||||
pea $0015 ; Get the existing 1-second interrupt handler and save
|
||||
_GetVector
|
||||
PullLong OldOneSecVec
|
||||
|
||||
pea $0015 ; Set the new handler and enable interrupts
|
||||
PushLong #OneSecHandler
|
||||
_SetVector
|
||||
|
||||
pea $0006
|
||||
_IntSource
|
||||
|
||||
PushLong #VBLTASK ; Also register a Heart Beat Task
|
||||
_SetHeartBeat
|
||||
|
||||
:no_interrupts
|
||||
rts
|
||||
|
||||
IntShutDown
|
||||
lda #NO_INTERRUPTS
|
||||
bne :no_interrupts
|
||||
|
||||
pea $0007 ; disable 1-second interrupts
|
||||
_IntSource
|
||||
|
||||
PushLong #VBLTASK ; Remove our heartbeat task
|
||||
_DelHeartBeat
|
||||
|
||||
pea $0015
|
||||
PushLong OldOneSecVec ; Reset the interrupt vector
|
||||
_SetVector
|
||||
|
||||
:no_interrupts
|
||||
rts
|
||||
|
||||
|
||||
; Interrupt handlers. We install a heartbeat (1/60th second and a 1-second timer)
|
||||
OneSecHandler mx %11
|
||||
phb
|
||||
pha
|
||||
phk
|
||||
plb
|
||||
|
||||
rep #$20
|
||||
inc OneSecondCounter
|
||||
sep #$20
|
||||
|
||||
ldal $E0C032
|
||||
and #%10111111 ;clear IRQ source
|
||||
stal $E0C032
|
||||
|
||||
pla
|
||||
plb
|
||||
clc
|
||||
rtl
|
||||
mx %00
|
||||
|
||||
OneSecondCounter ENT
|
||||
dw 0
|
||||
OldOneSecVec ds 4
|
||||
|
||||
VBLTASK hex 00000000
|
||||
dw 0
|
||||
hex 5AA5
|
||||
|
||||
; Reset the engine to a known state
|
||||
; Blitter initialization
|
||||
EngineReset
|
||||
stz ScreenHeight
|
||||
stz ScreenWidth
|
||||
stz ScreenY0
|
||||
stz ScreenY1
|
||||
stz ScreenX0
|
||||
stz ScreenX1
|
||||
stz ScreenTileHeight
|
||||
stz ScreenTileWidth
|
||||
stz StartX
|
||||
stz OldStartX
|
||||
stz StartXMod164
|
||||
|
||||
stz StartY
|
||||
stz OldStartY
|
||||
stz StartYMod208
|
||||
|
||||
stz EngineMode
|
||||
stz DirtyBits
|
||||
stz LastRender
|
||||
stz LastPatchOffset
|
||||
stz BG1StartX
|
||||
stz BG1StartXMod164
|
||||
stz BG1StartY
|
||||
stz BG1StartYMod208
|
||||
stz BG1OffsetIndex
|
||||
|
||||
stz BG0TileOriginX
|
||||
stz BG0TileOriginY
|
||||
stz OldBG0TileOriginX
|
||||
stz OldBG0TileOriginY
|
||||
|
||||
stz BG1TileOriginX
|
||||
stz BG1TileOriginY
|
||||
stz OldBG1TileOriginX
|
||||
stz OldBG1TileOriginY
|
||||
|
||||
stz TileMapWidth
|
||||
stz TileMapHeight
|
||||
stz TileMapPtr
|
||||
stz TileMapPtr+2
|
||||
stz FringeMapPtr
|
||||
stz FringeMapPtr+2
|
||||
|
||||
stz BG1TileMapWidth
|
||||
stz BG1TileMapHeight
|
||||
stz BG1TileMapPtr
|
||||
stz BG1TileMapPtr+2
|
||||
|
||||
stz SCBArrayPtr
|
||||
stz SCBArrayPtr+2
|
||||
|
||||
stz SpriteBanks
|
||||
stz SpriteMap
|
||||
stz ActiveSpriteCount
|
||||
|
||||
stz OneSecondCounter
|
||||
|
||||
lda #13
|
||||
sta tmp15
|
||||
stz tmp14
|
||||
|
||||
:loop
|
||||
ldx #BlitBuff
|
||||
lda #^BlitBuff
|
||||
ldy tmp14
|
||||
jsr BuildBank
|
||||
|
||||
lda tmp14
|
||||
clc
|
||||
adc #4
|
||||
sta tmp14
|
||||
|
||||
dec tmp15
|
||||
bne :loop
|
||||
|
||||
rts
|
||||
|
||||
; Allow the user to dynamically select one of the pre-configured screen sizes, or pass
|
||||
; in a specific width and height. The screen is automatically centered. If this is
|
||||
; not desired, then SetScreenRect should be used directly
|
||||
;
|
||||
; 0. Full Screen : 40 x 25 320 x 200 (32,000 bytes (100.0%))
|
||||
; 1. Sword of Sodan : 34 x 24 272 x 192 (26,112 bytes ( 81.6%))
|
||||
; 2. ~NES : 32 x 25 256 x 200 (25,600 bytes ( 80.0%))
|
||||
; 3. Task Force : 32 x 22 256 x 176 (22,528 bytes ( 70.4%))
|
||||
; 4. Defender of the World : 35 x 20 280 x 160 (22,400 bytes ( 70.0%))
|
||||
; 5. Rastan : 32 x 20 256 x 160 (20,480 bytes ( 64.0%))
|
||||
; 6. Game Boy Advanced : 30 x 20 240 x 160 (19,200 bytes ( 60.0%))
|
||||
; 7. Ancient Land of Y's : 36 x 16 288 x 128 (18,432 bytes ( 57.6%))
|
||||
; 8. Game Boy Color : 20 x 18 160 x 144 (11,520 bytes ( 36.0%))
|
||||
; 9. Agony (Amiga) : 36 x 24 288 x 192 (27,648 bytes ( 86.4%))
|
||||
; 10. Atari Lynx : 20 x 13 160 x 102 (8,160 bytes ( 25.5%))
|
||||
;
|
||||
; X = mode number OR width in pixels (must be multiple of 2)
|
||||
; Y = height in pixels (if X > 8)
|
||||
|
||||
ScreenModeWidth dw 320,272,256,256,280,256,240,288,160,288,160,320
|
||||
ScreenModeHeight dw 200,192,200,176,160,160,160,128,144,192,102,1
|
||||
|
||||
SetScreenMode ENT
|
||||
phb
|
||||
phk
|
||||
plb
|
||||
jsr _SetScreenMode
|
||||
plb
|
||||
rtl
|
||||
|
||||
_SetScreenMode
|
||||
cpx #11
|
||||
bcs :direct ; if x > 10, then assume X and Y are the dimensions
|
||||
|
||||
txa
|
||||
asl
|
||||
tax
|
||||
|
||||
ldy ScreenModeHeight,x
|
||||
lda ScreenModeWidth,x
|
||||
tax
|
||||
|
||||
:direct cpy #201
|
||||
bcs :exit
|
||||
|
||||
cpx #321
|
||||
bcs :exit
|
||||
|
||||
txa
|
||||
lsr
|
||||
pha ; Save X (width / 2) and Y (height)
|
||||
phy
|
||||
|
||||
lda #160 ; Center the screen
|
||||
sec
|
||||
sbc 3,s
|
||||
lsr
|
||||
xba
|
||||
pha ; Save half the origin coordinate
|
||||
|
||||
lda #200
|
||||
sec
|
||||
sbc 3,s ; This is now Y because of the PHA above
|
||||
lsr
|
||||
ora 1,s
|
||||
|
||||
plx ; Throw-away to pop the stack
|
||||
ply
|
||||
plx
|
||||
|
||||
jsr SetScreenRect
|
||||
jmp FillScreen ; tail return
|
||||
:exit
|
||||
rts
|
||||
|
||||
|
||||
WaitForKey sep #$20
|
||||
stal KBD_STROBE_REG ; clear the strobe
|
||||
:WFK ldal KBD_REG
|
||||
bpl :WFK
|
||||
rep #$20
|
||||
and #$007F
|
||||
rts
|
||||
|
||||
ClearKbdStrobe sep #$20
|
||||
stal KBD_STROBE_REG
|
||||
rep #$20
|
||||
rts
|
||||
|
||||
; Read the keyboard and paddle controls and return in a game-controller-like format
|
||||
LastKey db 0
|
||||
ReadControl ENT
|
||||
jsr _ReadControl
|
||||
rtl
|
||||
|
||||
_ReadControl
|
||||
pea $0000 ; low byte = key code, high byte = %------AB
|
||||
|
||||
sep #$20
|
||||
ldal OPTION_KEY_REG ; 'B' button
|
||||
and #$80
|
||||
beq :BNotDown
|
||||
|
||||
lda #PAD_BUTTON_B
|
||||
ora 2,s
|
||||
sta 2,s
|
||||
|
||||
:BNotDown
|
||||
ldal COMMAND_KEY_REG
|
||||
and #$80
|
||||
beq :ANotDown
|
||||
|
||||
lda #PAD_BUTTON_A
|
||||
ora 2,s
|
||||
sta 2,s
|
||||
|
||||
:ANotDown
|
||||
ldal KBD_STROBE_REG ; read the keyboard
|
||||
bit #$80
|
||||
beq :KbdNotDwn ; check the key-down status
|
||||
and #$7f
|
||||
ora 1,s
|
||||
sta 1,s
|
||||
|
||||
cmpl LastKey
|
||||
beq :KbdDown
|
||||
stal LastKey
|
||||
|
||||
lda #PAD_KEY_DOWN ; set the keydown flag
|
||||
ora 2,s
|
||||
sta 2,s
|
||||
bra :KbdDown
|
||||
|
||||
:KbdNotDwn
|
||||
lda #0
|
||||
stal LastKey
|
||||
:KbdDown
|
||||
rep #$20
|
||||
pla
|
||||
ToolShutDown
|
||||
rts
|
||||
|
||||
put CoreImpl.s
|
||||
put blitter/Template.s
|
||||
|
||||
put Memory.s
|
||||
|
369
src/CoreImpl.s
Normal file
369
src/CoreImpl.s
Normal file
@ -0,0 +1,369 @@
|
||||
; Feature flags
|
||||
NO_INTERRUPTS equ 1 ; turn off for crossrunner debugging
|
||||
NO_MUSIC equ 1 ; turn music + tool loading off
|
||||
|
||||
; External data space provided by the main program segment
|
||||
tiledata EXT
|
||||
TileStore EXT
|
||||
|
||||
; Sprite plane data and mask banks are provided as an external segment
|
||||
;
|
||||
; The sprite data holds a set of pre-rendered sprites that are optimized to support the rendering pipeline. There
|
||||
; are four copies of each sprite, along with the cooresponding mask laid out into 4x4 tile regions where the
|
||||
; empty row and column is shared between adjacent blocks.
|
||||
;
|
||||
; Logically, the memory is laid out as 4 columns of sprites and 4 rows.
|
||||
;
|
||||
; +---+---+---+---+---+---+---+---+---+---+---+---+-...
|
||||
; | | | | | | | | | | | | | ...
|
||||
; +---+---+---+---+---+---+---+---+---+---+---+---+-...
|
||||
; | | 0 | 0 | | 1 | 1 | | 2 | 2 | | 3 | 3 | ...
|
||||
; +---+---+---+---+---+---+---+---+---+---+---+---+-...
|
||||
; | | 0 | 0 | | 1 | 1 | | 2 | 2 | | 3 | 3 | ...
|
||||
; +---+---+---+---+---+---+---+---+---+---+---+---+-...
|
||||
; | | | | | | | | | | | | | ...
|
||||
; +---+---+---+---+---+---+---+---+---+---+---+---+-...
|
||||
; | | 4 | 4 | | 5 | 5 | | 6 | 6 | | 7 | 7 | ...
|
||||
; +---+---+---+---+---+---+---+---+---+---+---+---+-...
|
||||
; | | 4 | 4 | | 5 | 5 | | 6 | 6 | | 7 | 7 | ...
|
||||
; +---+---+---+---+---+---+---+---+---+---+---+---+-...
|
||||
; | | | | | | | | | | | | | ...
|
||||
; +---+---+---+---+---+---+---+---+---+---+---+---+-...
|
||||
;
|
||||
; For each sprite, when it needs to be copied into an on-screen tile, it could exist at any offset compared to its
|
||||
; natural alignment. By having a buffer around the sprite data, an address pointer can be set to a different origin
|
||||
; and a simple 8x8 block copy can cut out the appropriate bit of the sprite. For example, here is a zoomed-in look
|
||||
; at a sprite with an offset, O, at (-2,-3). As shown, by selecting an appropriate origin, just the top corner
|
||||
; of the sprite data will be copied.
|
||||
;
|
||||
; +---+---+---+---++---+---+---+---++---+---+---+---++---+---+---+---+..
|
||||
; | | || | || | | | || | | | |
|
||||
; +---+-- O----------------+ --+---++---+---+---+---++---+---+---+---+..
|
||||
; | | | | | || | | | || | | | |
|
||||
; +---+-- | | --+---++---+---+---+---++---+---+---+---+..
|
||||
; | | | | | || | | | || | | | |
|
||||
; +---+-- | | --+---++---+---+---+---++---+---+---+---+..
|
||||
; | | | | | || | | | || | | | |
|
||||
; +===+== | ++===+== | ==+===++===+===+===+===++===+===+===+===+..
|
||||
; | | | || | S | S | S || S | S | S | || | | | |
|
||||
; +---+-- +----------------+ --+---++---+---+---+---++---+---+---+---+..
|
||||
; | | || S | S S | S || S | S | S | S || | | | |
|
||||
; +---+---+---+---++---+---+---+---++---+---+---+---++---+---+---+---+..
|
||||
; | | | | || S | S | S | S || S | S | S | S || | | | |
|
||||
; +---+---+---+---++---+---+---+---++---+---+---+---++---+---+---+---+..
|
||||
; | | | | || S | S | S | S || S | S | S | S || | | | |
|
||||
; +===+===+===+===++===+===+===+===++===+===+===+===++===+===+===+===+..
|
||||
; | | | | || S | S | S | S || S | S | S | S || | | | |
|
||||
; +---+---+---+---++---+---+---+---++---+---+---+---++---+---+---+---+..
|
||||
; | | | | || S | S | S | S || S | S | S | S || | | | |
|
||||
; +---+---+---+---++---+---+---+---++---+---+---+---++---+---+---+---+..
|
||||
; | | | | || S | S | S | S || S | S | S | S || | | | |
|
||||
; +---+---+---+---++---+---+---+---++---+---+---+---++---+---+---+---+..
|
||||
; | | | | || | S | S | S || S | S | S | || | | | |
|
||||
; +---+---+---+---++---+---+---+---++---+---+---+---++---+---+---+---+..
|
||||
; . . . . . . . . . . . . . . . . .
|
||||
;
|
||||
; Each sprite will take up, effectively 9 tiles of storage space per
|
||||
; instance (plus edges) and there are 4 instances for the H/V bits
|
||||
; and 4 more for the masks. This results in a need for 43,264 bytes
|
||||
; for all 16 sprites.
|
||||
|
||||
spritedata EXT
|
||||
spritemask EXT
|
||||
|
||||
; If there are overlays, they are provided as an external
|
||||
Overlay EXT
|
||||
|
||||
; Core engine functionality. The idea is that that source file can be PUT into
|
||||
; a main source file and all of the functionality will be available.
|
||||
;
|
||||
; There are some constancts that must be externally defined that can affect how
|
||||
; the GTE runtime works
|
||||
;
|
||||
; NO_MUSIC : Set to non-zero to avoid using any source
|
||||
; NO_INTERRUPTS : Set to non-zero to avoid installing custom interrupt handlers
|
||||
|
||||
mx %00
|
||||
|
||||
; A = memory manager userId
|
||||
; X = tool number
|
||||
_CoreStartUp
|
||||
sta UserId ; This is the first thing to do
|
||||
stx ToolNum
|
||||
|
||||
jsr IntStartUp ; Enable certain iterrupts
|
||||
|
||||
jsr InitMemory ; Allocate and initialize memory for the engine
|
||||
jsr EngineReset ; All of the resources are allocated, put the engine in a known state
|
||||
|
||||
; jsr InitGraphics ; Initialize all of the graphics-related data
|
||||
; jsr InitSprites ; Initialize the sprite subsystem
|
||||
; jsr InitTiles ; Initialize the tile subsystem
|
||||
|
||||
jsr InitTimers ; Initialize the timer subsystem
|
||||
|
||||
_CoreShutDown
|
||||
jsr IntShutDown
|
||||
rts
|
||||
|
||||
; Install interrupt handlers. We use the VBL interrupt to keep animations
|
||||
; moving at a consistent rate, regarless of the rendered frame rate. The
|
||||
; one-second timer is generally just used for counters and as a handy
|
||||
; frames-per-second trigger.
|
||||
IntStartUp
|
||||
lda #NO_INTERRUPTS
|
||||
bne :no_interrupts
|
||||
PushLong #0
|
||||
pea $0015 ; Get the existing 1-second interrupt handler and save
|
||||
_GetVector
|
||||
PullLong OldOneSecVec
|
||||
|
||||
pea $0015 ; Set the new handler and enable interrupts
|
||||
PushLong #OneSecHandler
|
||||
_SetVector
|
||||
|
||||
pea $0006
|
||||
_IntSource
|
||||
|
||||
PushLong #VBLTASK ; Also register a Heart Beat Task
|
||||
_SetHeartBeat
|
||||
|
||||
:no_interrupts
|
||||
rts
|
||||
|
||||
IntShutDown
|
||||
lda #NO_INTERRUPTS
|
||||
bne :no_interrupts
|
||||
|
||||
pea $0007 ; disable 1-second interrupts
|
||||
_IntSource
|
||||
|
||||
PushLong #VBLTASK ; Remove our heartbeat task
|
||||
_DelHeartBeat
|
||||
|
||||
pea $0015
|
||||
PushLong OldOneSecVec ; Reset the interrupt vector
|
||||
_SetVector
|
||||
|
||||
:no_interrupts
|
||||
rts
|
||||
|
||||
|
||||
; Interrupt handlers. We install a heartbeat (1/60th second and a 1-second timer)
|
||||
OneSecHandler mx %11
|
||||
phb
|
||||
pha
|
||||
phk
|
||||
plb
|
||||
|
||||
rep #$20
|
||||
inc OneSecondCounter
|
||||
sep #$20
|
||||
|
||||
ldal $E0C032
|
||||
and #%10111111 ;clear IRQ source
|
||||
stal $E0C032
|
||||
|
||||
pla
|
||||
plb
|
||||
clc
|
||||
rtl
|
||||
mx %00
|
||||
|
||||
OneSecondCounter ENT
|
||||
dw 0
|
||||
OldOneSecVec ds 4
|
||||
|
||||
VBLTASK hex 00000000
|
||||
dw 0
|
||||
hex 5AA5
|
||||
|
||||
; Reset the engine to a known state
|
||||
; Blitter initialization
|
||||
EngineReset
|
||||
stz ScreenHeight
|
||||
stz ScreenWidth
|
||||
stz ScreenY0
|
||||
stz ScreenY1
|
||||
stz ScreenX0
|
||||
stz ScreenX1
|
||||
stz ScreenTileHeight
|
||||
stz ScreenTileWidth
|
||||
stz StartX
|
||||
stz OldStartX
|
||||
stz StartXMod164
|
||||
|
||||
stz StartY
|
||||
stz OldStartY
|
||||
stz StartYMod208
|
||||
|
||||
stz EngineMode
|
||||
stz DirtyBits
|
||||
stz LastRender
|
||||
stz LastPatchOffset
|
||||
stz BG1StartX
|
||||
stz BG1StartXMod164
|
||||
stz BG1StartY
|
||||
stz BG1StartYMod208
|
||||
stz BG1OffsetIndex
|
||||
|
||||
stz BG0TileOriginX
|
||||
stz BG0TileOriginY
|
||||
stz OldBG0TileOriginX
|
||||
stz OldBG0TileOriginY
|
||||
|
||||
stz BG1TileOriginX
|
||||
stz BG1TileOriginY
|
||||
stz OldBG1TileOriginX
|
||||
stz OldBG1TileOriginY
|
||||
|
||||
stz TileMapWidth
|
||||
stz TileMapHeight
|
||||
stz TileMapPtr
|
||||
stz TileMapPtr+2
|
||||
stz FringeMapPtr
|
||||
stz FringeMapPtr+2
|
||||
|
||||
stz BG1TileMapWidth
|
||||
stz BG1TileMapHeight
|
||||
stz BG1TileMapPtr
|
||||
stz BG1TileMapPtr+2
|
||||
|
||||
stz SCBArrayPtr
|
||||
stz SCBArrayPtr+2
|
||||
|
||||
stz SpriteBanks
|
||||
stz SpriteMap
|
||||
stz ActiveSpriteCount
|
||||
|
||||
stz OneSecondCounter
|
||||
|
||||
lda #13
|
||||
sta tmp15
|
||||
stz tmp14
|
||||
|
||||
:loop
|
||||
ldx #BlitBuff
|
||||
lda #^BlitBuff
|
||||
ldy tmp14
|
||||
; jsr BuildBank
|
||||
|
||||
lda tmp14
|
||||
clc
|
||||
adc #4
|
||||
sta tmp14
|
||||
|
||||
dec tmp15
|
||||
bne :loop
|
||||
|
||||
rts
|
||||
|
||||
|
||||
WaitForKey sep #$20
|
||||
stal KBD_STROBE_REG ; clear the strobe
|
||||
:WFK ldal KBD_REG
|
||||
bpl :WFK
|
||||
rep #$20
|
||||
and #$007F
|
||||
rts
|
||||
|
||||
ClearKbdStrobe sep #$20
|
||||
stal KBD_STROBE_REG
|
||||
rep #$20
|
||||
rts
|
||||
|
||||
; Read the keyboard and paddle controls and return in a game-controller-like format
|
||||
LastKey db 0
|
||||
ReadControl ENT
|
||||
jsr _ReadControl
|
||||
rtl
|
||||
|
||||
_ReadControl
|
||||
pea $0000 ; low byte = key code, high byte = %------AB
|
||||
|
||||
sep #$20
|
||||
ldal OPTION_KEY_REG ; 'B' button
|
||||
and #$80
|
||||
beq :BNotDown
|
||||
|
||||
lda #PAD_BUTTON_B
|
||||
ora 2,s
|
||||
sta 2,s
|
||||
|
||||
:BNotDown
|
||||
ldal COMMAND_KEY_REG
|
||||
and #$80
|
||||
beq :ANotDown
|
||||
|
||||
lda #PAD_BUTTON_A
|
||||
ora 2,s
|
||||
sta 2,s
|
||||
|
||||
:ANotDown
|
||||
ldal KBD_STROBE_REG ; read the keyboard
|
||||
bit #$80
|
||||
beq :KbdNotDwn ; check the key-down status
|
||||
and #$7f
|
||||
ora 1,s
|
||||
sta 1,s
|
||||
|
||||
cmpl LastKey
|
||||
beq :KbdDown
|
||||
stal LastKey
|
||||
|
||||
lda #PAD_KEY_DOWN ; set the keydown flag
|
||||
ora 2,s
|
||||
sta 2,s
|
||||
bra :KbdDown
|
||||
|
||||
:KbdNotDwn
|
||||
lda #0
|
||||
stal LastKey
|
||||
:KbdDown
|
||||
rep #$20
|
||||
pla
|
||||
rts
|
||||
|
||||
|
||||
; Helper function to take a local pixel coordinate [0, ScreenWidth-1],[0, ScreenHeight-1] and return the
|
||||
; row and column in the tile store that is corresponds to. This takes into consideration the StartX and
|
||||
; StartY offsets.
|
||||
;
|
||||
; This is more specialized than the code in the _MarkDirtySprite routine below since it does not deal with
|
||||
; negative or off-screen values.
|
||||
_OriginToTileStore
|
||||
lda StartYMod208
|
||||
lsr
|
||||
lsr
|
||||
and #$FFFE ; Store the pre-multiplied by 2 for indexing
|
||||
tay
|
||||
lda StartXMod164
|
||||
lsr
|
||||
and #$FFFE ; Same pre-multiply by 2 for later
|
||||
tax
|
||||
rts
|
||||
|
||||
; X = local x-coordinate (0, playfield width)
|
||||
; Y = local y-coordinate (0, playfield height)
|
||||
_LocalToTileStore
|
||||
clc
|
||||
tya
|
||||
adc StartYMod208 ; Adjust for the scroll offset
|
||||
cmp #208 ; check if we went too far positive
|
||||
bcc *+5
|
||||
sbc #208
|
||||
lsr
|
||||
lsr
|
||||
and #$FFFE ; Store the pre-multiplied by 2 for indexing
|
||||
tay
|
||||
|
||||
clc
|
||||
txa
|
||||
adc StartXMod164
|
||||
cmp #164
|
||||
bcc *+5
|
||||
sbc #164
|
||||
lsr
|
||||
and #$FFFE ; Same pre-multiply by 2 for later
|
||||
tax
|
||||
rts
|
@ -88,7 +88,9 @@ BankLoad equ 104
|
||||
TileStoreBankAndBank01 equ 106
|
||||
TileStoreBankAndTileDataBank equ 108
|
||||
TileStoreBankDoubled equ 110
|
||||
Next equ 112
|
||||
UserId equ 112 ; Memory manager user Id to use
|
||||
ToolNum equ 114 ; Tool number assigned to us
|
||||
Next equ 116
|
||||
|
||||
activeSpriteList equ 128 ; 32 bytes for the active sprite list (can persist across frames)
|
||||
; tiletmp equ 178 ; 16 bytes of temp storage for the tile renderers
|
||||
|
@ -24,6 +24,82 @@ DefaultPalette dw $0000,$007F,$0090,$0FF0
|
||||
dw $0fa9,$0ff0,$00e0,$04DF
|
||||
dw $0d00,$078f,$0ccc,$0FFF
|
||||
|
||||
|
||||
; Allow the user to dynamically select one of the pre-configured screen sizes, or pass
|
||||
; in a specific width and height. The screen is automatically centered. If this is
|
||||
; not desired, then SetScreenRect should be used directly
|
||||
;
|
||||
; 0. Full Screen : 40 x 25 320 x 200 (32,000 bytes (100.0%))
|
||||
; 1. Sword of Sodan : 34 x 24 272 x 192 (26,112 bytes ( 81.6%))
|
||||
; 2. ~NES : 32 x 25 256 x 200 (25,600 bytes ( 80.0%))
|
||||
; 3. Task Force : 32 x 22 256 x 176 (22,528 bytes ( 70.4%))
|
||||
; 4. Defender of the World : 35 x 20 280 x 160 (22,400 bytes ( 70.0%))
|
||||
; 5. Rastan : 32 x 20 256 x 160 (20,480 bytes ( 64.0%))
|
||||
; 6. Game Boy Advanced : 30 x 20 240 x 160 (19,200 bytes ( 60.0%))
|
||||
; 7. Ancient Land of Y's : 36 x 16 288 x 128 (18,432 bytes ( 57.6%))
|
||||
; 8. Game Boy Color : 20 x 18 160 x 144 (11,520 bytes ( 36.0%))
|
||||
; 9. Agony (Amiga) : 36 x 24 288 x 192 (27,648 bytes ( 86.4%))
|
||||
; 10. Atari Lynx : 20 x 13 160 x 102 (8,160 bytes ( 25.5%))
|
||||
;
|
||||
; X = mode number OR width in pixels (must be multiple of 2)
|
||||
; Y = height in pixels (if X > 8)
|
||||
|
||||
ScreenModeWidth dw 320,272,256,256,280,256,240,288,160,288,160,320
|
||||
ScreenModeHeight dw 200,192,200,176,160,160,160,128,144,192,102,1
|
||||
|
||||
SetScreenMode ENT
|
||||
phb
|
||||
phk
|
||||
plb
|
||||
jsr _SetScreenMode
|
||||
plb
|
||||
rtl
|
||||
|
||||
_SetScreenMode
|
||||
cpx #11
|
||||
bcs :direct ; if x > 10, then assume X and Y are the dimensions
|
||||
|
||||
txa
|
||||
asl
|
||||
tax
|
||||
|
||||
ldy ScreenModeHeight,x
|
||||
lda ScreenModeWidth,x
|
||||
tax
|
||||
|
||||
:direct cpy #201
|
||||
bcs :exit
|
||||
|
||||
cpx #321
|
||||
bcs :exit
|
||||
|
||||
txa
|
||||
lsr
|
||||
pha ; Save X (width / 2) and Y (height)
|
||||
phy
|
||||
|
||||
lda #160 ; Center the screen
|
||||
sec
|
||||
sbc 3,s
|
||||
lsr
|
||||
xba
|
||||
pha ; Save half the origin coordinate
|
||||
|
||||
lda #200
|
||||
sec
|
||||
sbc 3,s ; This is now Y because of the PHA above
|
||||
lsr
|
||||
ora 1,s
|
||||
|
||||
plx ; Throw-away to pop the stack
|
||||
ply
|
||||
plx
|
||||
|
||||
jsr SetScreenRect
|
||||
jmp FillScreen ; tail return
|
||||
:exit
|
||||
rts
|
||||
|
||||
; Return the current border color ($0 - $F) in the accumulator
|
||||
_GetBorderColor lda #0000
|
||||
sep #$20
|
||||
|
34
src/Master.s
Normal file
34
src/Master.s
Normal file
@ -0,0 +1,34 @@
|
||||
; IIgs Generic Tile Engine User Toolset
|
||||
|
||||
TYP $BA ; TOL file
|
||||
DSK GTETool
|
||||
XPL
|
||||
|
||||
; Main toolbox interface and code
|
||||
|
||||
ASM Tool.s
|
||||
SNA Main
|
||||
|
||||
; 64KB Tile Memory
|
||||
|
||||
ASM static\TileData.s
|
||||
KND #$1001 ; Type and Attributes ($10=Static,$01=Data)
|
||||
SNA TDATA
|
||||
|
||||
; 64KB Sprite Plane Data
|
||||
|
||||
ASM static\SprData.s
|
||||
KND #$1001 ; Type and Attributes ($11=Static+Bank Relative,$01=Data)
|
||||
SNA SDATA
|
||||
|
||||
;64KB Sprite Mask Data
|
||||
|
||||
ASM static\SprMask.s
|
||||
KND #$1001 ; Type and Attributes ($11=Static+Bank Relative,$01=Data)
|
||||
SNA SMASK
|
||||
|
||||
; 64KB Tile Store
|
||||
|
||||
ASM static\TileStore.s
|
||||
KND #$1001 ; Type and Attributes ($11=Static+Bank Relative,$01=Data)
|
||||
SNA TSTORE
|
@ -62,9 +62,9 @@ InitSprites
|
||||
; covering the exact same tiles.
|
||||
|
||||
|
||||
; Render a sprite stamp into the sprite buffer. Stamps exits independent of the sprites
|
||||
; Render a sprite stamp into the sprite buffer. Stamps exist independent of the sprites
|
||||
; and sprite reference a specific stamp. This is necessary because it's common for a
|
||||
; spite to change its graphic as its animating, but it is too costly to have to set up
|
||||
; sprite to change its graphic as its animating, but it is too costly to have to set up
|
||||
; the stamp every time. So this allows users to create stamps in advance and then
|
||||
; assign them to the sprites as needed.
|
||||
;
|
||||
|
@ -16,49 +16,6 @@ ColLeft equ tmp9
|
||||
SpriteBit equ tmp10 ; set the bit of the value that if the current sprite index
|
||||
VBuffOrigin equ tmp11
|
||||
|
||||
; Helper function to take a local pixel coordinate [0, ScreenWidth-1],[0, ScreenHeight-1] and return the
|
||||
; row and column in the tile store that is corresponds to. This takes into consideration the StartX and
|
||||
; StartY offsets.
|
||||
;
|
||||
; This is more specialized than the code in the _MarkDirtySprite routine below since it does not deal with
|
||||
; negative or off-screen values.
|
||||
_OriginToTileStore
|
||||
lda StartYMod208
|
||||
lsr
|
||||
lsr
|
||||
and #$FFFE ; Store the pre-multiplied by 2 for indexing
|
||||
tay
|
||||
lda StartXMod164
|
||||
lsr
|
||||
and #$FFFE ; Same pre-multiply by 2 for later
|
||||
tax
|
||||
rts
|
||||
|
||||
; X = local x-coordinate (0, playfield width)
|
||||
; Y = local y-coordinate (0, playfield height)
|
||||
_LocalToTileStore
|
||||
clc
|
||||
tya
|
||||
adc StartYMod208 ; Adjust for the scroll offset
|
||||
cmp #208 ; check if we went too far positive
|
||||
bcc *+5
|
||||
sbc #208
|
||||
lsr
|
||||
lsr
|
||||
and #$FFFE ; Store the pre-multiplied by 2 for indexing
|
||||
tay
|
||||
|
||||
clc
|
||||
txa
|
||||
adc StartXMod164
|
||||
cmp #164
|
||||
bcc *+5
|
||||
sbc #164
|
||||
lsr
|
||||
and #$FFFE ; Same pre-multiply by 2 for later
|
||||
tax
|
||||
rts
|
||||
|
||||
; Marks a sprite as dirty. The work here is mapping from local screen coordinates to the
|
||||
; tile store indices. The first step is to adjust the sprite coordinates based on the current
|
||||
; code field offsets and then cache variations of this value needed in the rest of the subroutine
|
||||
|
101
src/Tool.s
101
src/Tool.s
@ -3,10 +3,19 @@
|
||||
; Ref: Toolbox Reference, Volume 2, Appendix A
|
||||
; Ref: IIgs Tech Note #73
|
||||
|
||||
; use Load.Macs.s
|
||||
use Mem.Macs.s
|
||||
use Misc.Macs.s
|
||||
use Util.Macs
|
||||
use Locator.Macs
|
||||
use Core.MACS.s
|
||||
|
||||
use Defs.s
|
||||
|
||||
ToStrip equ $E10184
|
||||
|
||||
_CallTable
|
||||
dw {_CTEnd-_CallTable}/4,0
|
||||
adrl {_CTEnd-_CallTable}/4
|
||||
adrl _TSBootInit-1
|
||||
adrl _TSStartUp-1
|
||||
adrl _TSShutDown-1
|
||||
@ -25,40 +34,58 @@ _TSBootInit
|
||||
clc
|
||||
rtl
|
||||
|
||||
; Call the regular GTE startup function after setting the Work Area Point (WAP). The caller much provide
|
||||
; one page of Bank 0 memory for the tool set's private use
|
||||
; Call the regular GTE startup function after setting the Work Area Pointer (WAP). The caller must provide
|
||||
; one page of Bank 0 memory for the tool set's private use and a userId to use for allocating memory
|
||||
;
|
||||
; X =
|
||||
; X = tool set number in low byte and function umber in high byte
|
||||
;
|
||||
; StartUp(dPageAddr, userId)
|
||||
_TSStartUp
|
||||
:zpToUse equ 7
|
||||
|
||||
pea #$8000
|
||||
rtll = 1
|
||||
rtl2 = rtl1+3
|
||||
userId = 7
|
||||
zpToUse = userId+2
|
||||
|
||||
txa
|
||||
and #$00FF
|
||||
pha
|
||||
and #$00FF ; Get just the tool number
|
||||
tax
|
||||
|
||||
pea $0000
|
||||
lda :zpToUse+6,s
|
||||
pha
|
||||
lda userId,s ; Get the userId for memory allocations
|
||||
tay
|
||||
lda zpToUse,s ; Get the direct page address
|
||||
|
||||
phd ; Save the current direct page
|
||||
tcd ; Set to our working direct page space
|
||||
|
||||
tya ; A = memory manager user Id, X = tool number
|
||||
jsr _CoreStartUp ; Initialize the library
|
||||
|
||||
; SetWAP(userOrSystem, tsNum, waptPtr)
|
||||
|
||||
pea #$8000 ; $8000 = user tool set
|
||||
pei ToolNum ; Push the tool number from the direct page
|
||||
pea $0000 ; High word of WAP is zero (bank 0)
|
||||
phd ; Low word of WAP is the direct page
|
||||
_SetWAP
|
||||
|
||||
jsr _CoreStartUp
|
||||
pld ; Restore the caller's direct page
|
||||
|
||||
lda #0
|
||||
clc
|
||||
rtl
|
||||
|
||||
_TSShutDown
|
||||
cmp #0 ; Acc is low word of the WAP (direct page)
|
||||
beq :inactive
|
||||
|
||||
phd
|
||||
pha
|
||||
pld ; Set the direct page for the toolset
|
||||
tcd ; Set the direct page for the toolset
|
||||
|
||||
phx ; Preserve the X register
|
||||
jsr _CoreShutDown ; Shut down GTE
|
||||
pla
|
||||
jsr _CoreShutDown ; Shut down the library
|
||||
|
||||
pea $8000
|
||||
and #$00FF
|
||||
pha
|
||||
pei ToolNum
|
||||
pea $0000 ; Set WAP to null
|
||||
pea $0000
|
||||
_SetWAP
|
||||
@ -71,7 +98,7 @@ _TSShutDown
|
||||
rtl
|
||||
|
||||
_TSVersion
|
||||
lda #$0100 ; Version 1
|
||||
lda #$0100 ; Version 1
|
||||
sta 7,s
|
||||
|
||||
lda #0
|
||||
@ -101,31 +128,45 @@ _TSReserved
|
||||
sec
|
||||
rtl
|
||||
|
||||
; SetScreenMode(width, height)
|
||||
_TSSetScreenMode
|
||||
phd ; Preserve the direct page
|
||||
pha
|
||||
pld
|
||||
:height equ 9
|
||||
:width equ 11
|
||||
|
||||
lda 9,s
|
||||
phd ; Preserve the direct page
|
||||
tcd ; Set the tool set direct pafe from WAP
|
||||
|
||||
lda :height,s
|
||||
tay
|
||||
lda 9,s
|
||||
lda :width,s
|
||||
tax
|
||||
jsr _SetScreenMode
|
||||
pld
|
||||
; jsr _SetScreenMode ; Not implemented yet
|
||||
|
||||
pld ; Restore direct page
|
||||
|
||||
ldx #0 ; No error
|
||||
ldy #4 ; Remove the 4 input bytes
|
||||
jml ToStrip
|
||||
|
||||
_TSReadControl
|
||||
:output equ 9
|
||||
|
||||
phd ; Preserve the direct page
|
||||
pha
|
||||
pld
|
||||
tcd
|
||||
|
||||
jsr _ReadControl
|
||||
sta 9,s
|
||||
sta :output,s
|
||||
|
||||
pld
|
||||
ldx #0 ; No error
|
||||
ldy #0 ; Remove zero input bytes
|
||||
jml ToStrip
|
||||
|
||||
; Insert the core GTE functions
|
||||
|
||||
put CoreImpl.s
|
||||
put Memory.s
|
||||
put Timer.s
|
||||
; put Graphics.s
|
||||
; put blitter/Template.s
|
||||
put blitter/Tables.s
|
||||
|
2
src/_FileInformation.txt
Normal file
2
src/_FileInformation.txt
Normal file
@ -0,0 +1,2 @@
|
||||
Tool=Type(00),AuxType(0000),VersionCreate(70),MinVersion(BE),Access(E3),FolderInfo1(000000000000000000000000000000000000),FolderInfo2(000000000000000000000000000000000000)
|
||||
GTETool=Type(BA),AuxType(0000),VersionCreate(70),MinVersion(BE),Access(E3),FolderInfo1(000000000000000000000000000000000000),FolderInfo2(000000000000000000000000000000000000)
|
@ -19,25 +19,26 @@
|
||||
;
|
||||
; 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.
|
||||
PER_TILE_SIZE equ 3
|
||||
]step equ 0
|
||||
|
||||
dw CODE_TOP ; There is a spot where we load Col2CodeOffet-2,x
|
||||
Col2CodeOffset lup 82
|
||||
dw CODE_TOP+{{81-]step}*PER_TILE_SIZE}
|
||||
]step equ ]step+1
|
||||
--^
|
||||
dw CODE_TOP+{81*PER_TILE_SIZE}
|
||||
;PER_TILE_SIZE equ 3
|
||||
;]step equ 0
|
||||
|
||||
; dw CODE_TOP ; There is a spot where we load Col2CodeOffet-2,x
|
||||
;Col2CodeOffset lup 82
|
||||
; dw CODE_TOP+{{81-]step}*PER_TILE_SIZE}
|
||||
;]step equ ]step+1
|
||||
; --^
|
||||
; dw CODE_TOP+{81*PER_TILE_SIZE}
|
||||
|
||||
; A parallel table to Col2CodeOffset that holds the offset to the exception handler address for each column
|
||||
SNIPPET_SIZE equ 32
|
||||
]step equ 0
|
||||
dw SNIPPET_BASE
|
||||
JTableOffset lup 82
|
||||
dw SNIPPET_BASE+{{81-]step}*SNIPPET_SIZE}
|
||||
]step equ ]step+1
|
||||
--^
|
||||
dw SNIPPET_BASE+{81*SNIPPET_SIZE}
|
||||
;SNIPPET_SIZE equ 32
|
||||
;]step equ 0
|
||||
; dw SNIPPET_BASE
|
||||
;JTableOffset lup 82
|
||||
; dw SNIPPET_BASE+{{81-]step}*SNIPPET_SIZE}
|
||||
;]step equ ]step+1
|
||||
; --^
|
||||
; dw SNIPPET_BASE+{81*SNIPPET_SIZE}
|
||||
|
||||
; Table of BRA instructions that are used to exit the code field. Separate tables for
|
||||
; even and odd aligned cases.
|
||||
|
@ -155,7 +155,6 @@ SetScreenRect sty ScreenHeight ; Save the screen height and
|
||||
cpx #TILE_STORE_SIZE-2
|
||||
bcc :tsloop
|
||||
|
||||
; Return
|
||||
rts
|
||||
|
||||
; Generalized routine that calculates the on-screen address of the tiles and takes the
|
||||
|
@ -74,7 +74,7 @@ _GetBaseTileAddr
|
||||
asl ; x64
|
||||
asl ; x128
|
||||
rts
|
||||
|
||||
|
||||
; On entry
|
||||
;
|
||||
; B is set to the correct BG1 data bank
|
||||
@ -102,9 +102,14 @@ _RenderTileBG1
|
||||
; Given an address to a Tile Store record, dispatch to the appropriate tile renderer. The Tile
|
||||
; Store record contains all of the low-level information that's needed to call the renderer.
|
||||
;
|
||||
; There are two execution paths that are handled here. First, if there is no sprite, then
|
||||
; the tile data is read directly and written into the code field in a single pass. If there
|
||||
; are sprites that overlap the tile, then the sprite data is combined with the tile data
|
||||
; and written to a temporary direct page buffer. If
|
||||
;
|
||||
; This routine sets the direct page register to the second page since we use that space to
|
||||
; build and cache tile and sprite data, when necessary
|
||||
; Y = address of tile
|
||||
|
||||
_RenderTile2
|
||||
lda TileStore+TS_SPRITE_FLAG,x ; This is a bitfield of all the sprites that intersect this tile, only care if non-zero or not
|
||||
bne do_dirty_sprite
|
||||
@ -159,10 +164,19 @@ do_dirty_sprite
|
||||
pei TileStoreBankAndTileDataBank ; Special value that has the TileStore bank in LSB and TileData bank in MSB
|
||||
plb
|
||||
|
||||
; Cache a couple of values into the direct page, but preserve the Accumulator
|
||||
; Cache a couple of values into the direct page that are used across all copy routines
|
||||
|
||||
ldy TileStore+TS_TILE_ADDR,x ; load the address of this tile's data (pre-calculated)
|
||||
sty tileAddr
|
||||
lda TileStore+TS_TILE_ADDR,y ; load the address of this tile's data (pre-calculated)
|
||||
sta tileAddr
|
||||
|
||||
ldx TileStore+TS_VBUFF_ADDR_COUNT,y
|
||||
jmp (dirty_sprite_dispatch,x)
|
||||
dirty_sprite_dispatch
|
||||
da CopyNoSprites
|
||||
da CopyOneSprite
|
||||
da CopyTwoSprites
|
||||
da CopyThreeSprites
|
||||
da CopyFourSprites ; MAX, don't bother with more than 4 sprites per tile
|
||||
|
||||
; This is very similar to the code in the dirty tile renderer, but we can't reuse
|
||||
; because that code draws directly to the graphics screen, and this code draws
|
||||
@ -243,7 +257,15 @@ do_dirty_sprite
|
||||
|
||||
; We set up direct page pointers to the mask bank and use the bank register for the
|
||||
; data.
|
||||
CopyFourSpritesAbove
|
||||
CopyFourSprites
|
||||
lda TileStore+TS_VBUFF_ADDR_0,y
|
||||
sta spriteIdx
|
||||
lda TileStore+TS_VBUFF_ADDR_1,y
|
||||
sta spriteIdx+4
|
||||
lda TileStore+TS_VBUFF_ADDR_2,y
|
||||
sta spriteIdx+8
|
||||
lda TileStore+TS_VBUFF_ADDR_3,y
|
||||
sta spriteIdx+12
|
||||
|
||||
; Copy three sprites into a temporary direct page buffer
|
||||
LDA_IL equ $A7 ; lda [dp]
|
||||
@ -252,6 +274,13 @@ AND_IL equ $27 ; and [dp]
|
||||
AND_ILY equ $37 ; and [dp],y
|
||||
|
||||
CopyThreeSprites
|
||||
lda TileStore+TS_VBUFF_ADDR_0,y
|
||||
sta spriteIdx
|
||||
lda TileStore+TS_VBUFF_ADDR_1,y
|
||||
sta spriteIdx+4
|
||||
lda TileStore+TS_VBUFF_ADDR_2,y
|
||||
sta spriteIdx+8
|
||||
|
||||
]line equ 0
|
||||
lup 8
|
||||
ldy #]line*SPRITE_PLANE_SPAN
|
||||
@ -285,6 +314,11 @@ CopyThreeSprites
|
||||
|
||||
; Copy two sprites into a temporary direct page buffer
|
||||
CopyTwoSprites
|
||||
lda TileStore+TS_VBUFF_ADDR_0,y
|
||||
sta spriteIdx
|
||||
lda TileStore+TS_VBUFF_ADDR_1,y
|
||||
sta spriteIdx+4
|
||||
|
||||
]line equ 0
|
||||
lup 8
|
||||
ldy #]line*SPRITE_PLANE_SPAN
|
||||
@ -311,9 +345,56 @@ CopyTwoSprites
|
||||
; jmp FinishTile
|
||||
|
||||
; Copy a single piece of sprite data into a temporary direct page . X = spriteIdx
|
||||
;
|
||||
; X register is the offset of the underlying tile data
|
||||
; Y register is the line offset into the sprite data and mask buffers
|
||||
; There is a pointer for each sprite on the direct page that can be used
|
||||
; to access both the data and mask components of a sprite
|
||||
; The Data Bank reigster points to the sprite data
|
||||
;
|
||||
; ldal tiledata,x
|
||||
; and [spriteIdx],y
|
||||
; ora (spriteIdx),y
|
||||
; sta tmp_sprite_data
|
||||
;
|
||||
; For multiple sprites, we can chain together the and/ora instructions to stack the sprites
|
||||
;
|
||||
; ldal tiledata,x
|
||||
; and [spriteIdx],y
|
||||
; ora (spriteIdx),y
|
||||
; and [spriteIdx+4],y
|
||||
; ora (spriteIdx+4),y
|
||||
; and [spriteIdx+8],y
|
||||
; ora (spriteIdx+8),y
|
||||
; sta tmp_sprite_data
|
||||
;
|
||||
; When the sprites need to be drawn on top of the background, then change the order of operations
|
||||
;
|
||||
; lda (spriteIdx),y
|
||||
; and [spriteIdx+4],y
|
||||
; ora (spriteIdx+4),y
|
||||
; and [spriteIdx+8],y
|
||||
; ora (spriteIdx+8),y
|
||||
; sta tmp_sprite_data
|
||||
; andl tiledata+32,x
|
||||
; oral tiledata,x
|
||||
;
|
||||
CopyOneSprite
|
||||
clc
|
||||
lda TileStore+TS_VBUFF_ADDR_0,y
|
||||
sta spriteIdx
|
||||
adc #2
|
||||
sta spriteIdx+4
|
||||
|
||||
]line equ 0
|
||||
lup 8
|
||||
ldal tiledata,x
|
||||
and [spriteIdx]
|
||||
ora (spriteIdx)
|
||||
sta tmp_sprite_data+{]line*4}
|
||||
|
||||
|
||||
|
||||
ldal spritedata+{]line*SPRITE_PLANE_SPAN},x
|
||||
sta tmp_sprite_data+{]line*4}
|
||||
ldal spritedata+{]line*SPRITE_PLANE_SPAN}+2,x
|
||||
|
3
src/static/SprData.s
Normal file
3
src/static/SprData.s
Normal file
@ -0,0 +1,3 @@
|
||||
; sprite stamp pixel data
|
||||
spritedata ENT
|
||||
ds 65536
|
3
src/static/SprMask.s
Normal file
3
src/static/SprMask.s
Normal file
@ -0,0 +1,3 @@
|
||||
; sprite stamp masks
|
||||
spritemask ENT
|
||||
ds 65536
|
3
src/static/TileData.s
Normal file
3
src/static/TileData.s
Normal file
@ -0,0 +1,3 @@
|
||||
; Bank of memory that holds the 8x8 tile data
|
||||
tiledata ENT
|
||||
ds 65536
|
3
src/static/TileStore.s
Normal file
3
src/static/TileStore.s
Normal file
@ -0,0 +1,3 @@
|
||||
; Bank of memory that holds the core sprite and tile store data structures
|
||||
TileStore ENT
|
||||
ds 65536
|
Loading…
x
Reference in New Issue
Block a user