mirror of
https://github.com/lscharen/iigs-game-engine.git
synced 2024-11-01 10:05:50 +00:00
608 lines
17 KiB
ArmAsm
608 lines
17 KiB
ArmAsm
; Test driver to exercise graphics routines.
|
|
|
|
REL
|
|
DSK MAINSEG
|
|
|
|
use Locator.Macs
|
|
use Load.Macs
|
|
use Mem.Macs
|
|
use Misc.Macs
|
|
use Tool222.Macs.s
|
|
use Util.Macs
|
|
use EDS.GSOS.Macs
|
|
use GTE.Macs
|
|
|
|
mx %00
|
|
|
|
; Feature flags
|
|
NO_INTERRUPTS equ 0 ; turn off for crossrunner debugging
|
|
NO_MUSIC equ 1 ; turn music + tool loading off
|
|
|
|
; Keycodes
|
|
LEFT_ARROW equ $08
|
|
RIGHT_ARROW equ $15
|
|
UP_ARROW equ $0B
|
|
DOWN_ARROW equ $0A
|
|
|
|
StartX equ 4
|
|
StartY equ 6
|
|
tmp0 equ 8
|
|
|
|
TSet EXT
|
|
; Typical init
|
|
phk
|
|
plb
|
|
|
|
stz StartX
|
|
stz StartY
|
|
|
|
|
|
sta MyUserId ; GS/OS passes the memory manager user ID for the application into the program
|
|
_MTStartUp ; GTE requires the miscellaneous toolset to be running
|
|
|
|
jsr GTEStartUp ; Load and install the GTE User Tool
|
|
|
|
; Load a tileset
|
|
|
|
pea #^TSet
|
|
pea #TSet
|
|
_GTELoadTileSet
|
|
|
|
|
|
pea $0000
|
|
pea #^MyPalette
|
|
pea #MyPalette
|
|
_GTESetPalette
|
|
|
|
pea #256
|
|
pea #176
|
|
_GTESetScreenMode
|
|
|
|
; Set up our level data
|
|
jsr BG0SetUp
|
|
|
|
; Initialize the sprite's global position (this is tracked outside of the tile engine)
|
|
lda #64
|
|
sta PlayerX
|
|
sta PlayerY
|
|
stz MapScreenX
|
|
stz MapScreenY
|
|
|
|
; Add a sprite to the engine and save its sprite
|
|
HERO_DOWN_ID equ {SPRITE_16X16+1}
|
|
HERO_DOWN_VBUFF equ VBUFF_SPRITE_START+0*VBUFF_SPRITE_STEP
|
|
HERO_SIDE_ID equ {SPRITE_16X16+5}
|
|
HERO_SIDE_VBUFF equ VBUFF_SPRITE_START+1*VBUFF_SPRITE_STEP
|
|
HERO_UP_ID equ {SPRITE_16X16+9}
|
|
HERO_UP_VBUFF equ VBUFF_SPRITE_START+2*VBUFF_SPRITE_STEP
|
|
|
|
HERO_SLOT equ 0
|
|
OKTOROK_ID equ {SPRITE_16X16+79}
|
|
OKTOROK_VBUFF equ VBUFF_SPRITE_START+3*VBUFF_SPRITE_STEP
|
|
OKTOROK_SLOT_1 equ 1
|
|
OKTOROK_SLOT_2 equ 2
|
|
OKTOROK_SLOT_3 equ 3
|
|
OKTOROK_SLOT_4 equ 4
|
|
|
|
; Create the sprite stamps for this scene
|
|
|
|
pea HERO_DOWN_ID ; sprint id
|
|
pea HERO_DOWN_VBUFF ; vbuff address
|
|
_GTECreateSpriteStamp
|
|
|
|
pea HERO_SIDE_ID ; sprint id
|
|
pea HERO_SIDE_VBUFF ; vbuff address
|
|
_GTECreateSpriteStamp
|
|
|
|
pea HERO_UP_ID ; sprint id
|
|
pea HERO_UP_VBUFF ; vbuff address
|
|
_GTECreateSpriteStamp
|
|
|
|
pea OKTOROK_ID ; sprint id
|
|
pea OKTOROK_VBUFF ; vbuff address
|
|
_GTECreateSpriteStamp
|
|
|
|
pea HERO_DOWN_ID
|
|
lda PlayerX
|
|
pha
|
|
lda PlayerY
|
|
pha
|
|
pea HERO_SLOT
|
|
_GTEAddSprite
|
|
|
|
pea HERO_SLOT
|
|
pea $0000 ; with these flags (h/v flip)
|
|
pea HERO_DOWN_VBUFF ; and use this stamp
|
|
_GTEUpdateSprite
|
|
|
|
; Add 4 octoroks
|
|
ldx #0
|
|
:oktorok_loop
|
|
phx ; save the index
|
|
|
|
txa ; calculate the SLOT ID
|
|
lsr
|
|
inc
|
|
tay
|
|
|
|
; _GTEUpdateSprite parameters
|
|
|
|
phy
|
|
pea $0000 ; with these flags (h/v flip)
|
|
pea OKTOROK_VBUFF ; and use this stamp
|
|
|
|
; _GTEAddSprite parameters
|
|
|
|
pea OKTOROK_ID
|
|
lda OktorokX,x
|
|
pha
|
|
lda OktorokY,x
|
|
pha
|
|
phy
|
|
|
|
_GTEAddSprite
|
|
_GTEUpdateSprite
|
|
|
|
plx
|
|
dex
|
|
dex
|
|
bpl :oktorok_loop
|
|
|
|
; Draw the initial screen
|
|
|
|
pea $0000
|
|
_GTERender
|
|
|
|
; Set up a very specific test. First, we draw a sprite into the sprite plane, and then
|
|
; leave it alone. We are just testing the ability to merge sprite plane data into
|
|
; the play field tiles.
|
|
EvtLoop
|
|
lda #2
|
|
jsr _SetBorderColor
|
|
|
|
pha
|
|
_GTEReadControl
|
|
pla
|
|
|
|
; Check the buttons first
|
|
pha
|
|
|
|
bit #$0100
|
|
beq :no_sword
|
|
:no_sword
|
|
|
|
; Enable/disable v-sync
|
|
lda 1,s
|
|
bit #PAD_KEY_DOWN
|
|
beq :no_key_down
|
|
and #$007F
|
|
cmp #'v'
|
|
bne :not_v
|
|
lda #$0001
|
|
eor vsync
|
|
sta vsync
|
|
:not_v
|
|
:no_key_down
|
|
pla
|
|
and #$007F ; Ignore the buttons for now
|
|
|
|
cmp #'q'
|
|
bne :not_q
|
|
brl Exit
|
|
:not_q
|
|
|
|
cmp #'d'
|
|
bne :not_d
|
|
inc PlayerX
|
|
lda PlayerX
|
|
cmp #128-8
|
|
bcc *+5
|
|
jsr TransitionRight
|
|
|
|
pea HERO_SLOT
|
|
pea $0000 ; no flags
|
|
pea HERO_SIDE_VBUFF ; and use this stamp
|
|
_GTEUpdateSprite
|
|
|
|
bra :do_render
|
|
:not_d
|
|
|
|
cmp #'a'
|
|
bne :not_a
|
|
dec PlayerX
|
|
bpl *+5
|
|
jsr TransitionLeft
|
|
|
|
pea HERO_SLOT
|
|
pea SPRITE_HFLIP
|
|
pea HERO_SIDE_VBUFF
|
|
_GTEUpdateSprite
|
|
|
|
bra :do_render
|
|
:not_a
|
|
|
|
cmp #'s'
|
|
bne :not_s
|
|
inc PlayerY
|
|
|
|
pea HERO_SLOT
|
|
pea $0000
|
|
pea HERO_DOWN_VBUFF
|
|
_GTEUpdateSprite
|
|
bra :do_render
|
|
:not_s
|
|
|
|
cmp #'w'
|
|
bne :not_w
|
|
dec PlayerY
|
|
pea HERO_SLOT
|
|
pea $0000
|
|
pea HERO_UP_VBUFF
|
|
_GTEUpdateSprite
|
|
bra :do_render
|
|
:not_w
|
|
|
|
:do_render
|
|
lda #3
|
|
jsr _SetBorderColor
|
|
|
|
pea HERO_SLOT
|
|
lda PlayerX
|
|
pha
|
|
lda PlayerY
|
|
pha
|
|
_GTEMoveSprite
|
|
|
|
; Based on the frame count, move an oktorok
|
|
|
|
jsr _GetVBLTicks
|
|
pha
|
|
|
|
; pha ; save the vbl value for a second
|
|
; and #$0003 ; pick which oktorok to move
|
|
lda #4
|
|
jsr _SetBorderColor
|
|
|
|
plx
|
|
phx
|
|
lda #0
|
|
jsr MoveEnemy
|
|
|
|
plx
|
|
phx
|
|
lda #1
|
|
; jsr MoveEnemy
|
|
|
|
plx
|
|
phx
|
|
lda #2
|
|
; jsr MoveEnemy
|
|
|
|
plx
|
|
lda #3
|
|
; jsr MoveEnemy
|
|
|
|
|
|
; Let's see what it looks like!
|
|
|
|
; lda vsync
|
|
; beq :no_vsync
|
|
|
|
;:vsyncloop jsr _GetVBL ; 8-bit value
|
|
; cmp #12
|
|
; bcc :vsyncloop
|
|
; cmp #16
|
|
; bcs :vsyncloop ; Wait until we're within the top 4 scanlines
|
|
|
|
lda #0
|
|
jsr _SetBorderColor
|
|
|
|
ldx #8
|
|
jsr _WaitForScanline
|
|
|
|
lda #1
|
|
jsr _SetBorderColor
|
|
:no_vsync
|
|
pea $0000
|
|
_GTERenderDirty
|
|
; brk $03
|
|
|
|
; lda vsync
|
|
; beq :no_vsync2
|
|
; lda #0
|
|
; jsr _SetBorderColor
|
|
|
|
:no_vsync2
|
|
brl EvtLoop
|
|
|
|
; Exit code
|
|
Exit
|
|
_GTEShutDown
|
|
|
|
_QuitGS qtRec
|
|
|
|
bcs Fatal
|
|
Fatal brk $00
|
|
|
|
TransitionRight
|
|
lda MapScreenX ; Only two screens
|
|
cmp #1
|
|
bcs :done
|
|
|
|
lda StartX ; Scroll 128 bytes to the right
|
|
clc
|
|
adc #128
|
|
sta TransitionX
|
|
|
|
jsr HideEnemies
|
|
|
|
:loop lda StartX
|
|
cmp TransitionX
|
|
bcs :out
|
|
clc
|
|
adc #4
|
|
sta StartX
|
|
pha
|
|
pei StartY
|
|
_GTESetBG0Origin
|
|
|
|
lda PlayerX
|
|
sec
|
|
sbc #4
|
|
bmi :nosprite
|
|
sta PlayerX
|
|
|
|
pea HERO_SLOT
|
|
lda PlayerX
|
|
pha
|
|
lda PlayerY
|
|
pha
|
|
_GTEMoveSprite
|
|
:nosprite
|
|
pea $0000
|
|
_GTERender ; Do full renders since the playfield is scrolling
|
|
bra :loop
|
|
:out
|
|
jsr ShowEnemies
|
|
inc MapScreenX ; Move the index to the next screen
|
|
:done
|
|
rts
|
|
|
|
|
|
TransitionLeft
|
|
lda MapScreenX
|
|
cmp #0
|
|
beq :done
|
|
|
|
jsr HideEnemies
|
|
|
|
lda StartX ; Scroll 128 bytes to the left
|
|
sec
|
|
sbc #128
|
|
sta TransitionX
|
|
|
|
:loop lda StartX
|
|
cmp TransitionX
|
|
beq :out
|
|
sec
|
|
sbc #4
|
|
sta StartX
|
|
pha
|
|
pei StartY
|
|
_GTESetBG0Origin
|
|
|
|
lda PlayerX
|
|
clc
|
|
adc #4
|
|
cmp #128-8+1
|
|
bcs :nosprite
|
|
sta PlayerX
|
|
|
|
pea HERO_SLOT
|
|
lda PlayerX
|
|
pha
|
|
lda PlayerY
|
|
pha
|
|
_GTEMoveSprite
|
|
:nosprite
|
|
pea $0000
|
|
_GTERender
|
|
bra :loop
|
|
:out
|
|
jsr ShowEnemies
|
|
dec MapScreenX ; Move the index to the next screen
|
|
:done
|
|
rts
|
|
|
|
; Move an oktorok. A = 0 - 3, X = animation frame
|
|
MoveEnemy
|
|
phx
|
|
|
|
tay
|
|
iny ; Oktoroks are in slots 1 - 4
|
|
|
|
asl
|
|
tax ; Update this oktorok
|
|
|
|
pla ; Pop the VBL value
|
|
and #$007C
|
|
lsr
|
|
|
|
phy ; push the SLOT ID
|
|
tay
|
|
|
|
lda OktorokX,x
|
|
clc
|
|
adc OktorokDelta,y
|
|
pha ; Push the X position
|
|
|
|
lda OktorokY,x
|
|
pha
|
|
_GTEMoveSprite
|
|
rts
|
|
|
|
; Set the hidden flag on the enemy sprites during the screen transition
|
|
HideEnemies
|
|
ldx #6
|
|
:loop
|
|
phx
|
|
|
|
txa
|
|
lsr
|
|
inc
|
|
pha
|
|
pea SPRITE_HIDE
|
|
pea OKTOROK_VBUFF
|
|
_GTEUpdateSprite
|
|
|
|
plx
|
|
dex
|
|
dex
|
|
bpl :loop
|
|
rts
|
|
|
|
ShowEnemies
|
|
ldx #6
|
|
:loop
|
|
phx
|
|
|
|
txa
|
|
lsr
|
|
inc
|
|
pha
|
|
pea $0000
|
|
pea OKTOROK_VBUFF
|
|
_GTEUpdateSprite
|
|
|
|
plx
|
|
dex
|
|
dex
|
|
bpl :loop
|
|
rts
|
|
|
|
ToolPath str '1/Tool160'
|
|
MyUserId ds 2
|
|
; Color palette
|
|
MyPalette dw $0FDA,$08C1,$0C41,$0F93,$0777,$0FDA,$00A0,$0000,$0D20,$0FFF,$023E,$01CE,$02E3,$0870,$0F93,$0FD7
|
|
|
|
MapScreenX ds 2
|
|
MapScreenY ds 2
|
|
|
|
PlayerID ds 2
|
|
PlayerX ds 2
|
|
PlayerY ds 2
|
|
|
|
OktorokX dw 32,32,96,96
|
|
OktorokY dw 64,96,56,72
|
|
OktorokDelta dw 0,1,2,3,4,5,6,7,6,5,4,3,2,1,0,-1,-2,-3,-4,-5,-6,-7,-8,-7,-6,-5,-4,-3,-2,-1,0,0,0
|
|
TransitionX ds 2
|
|
TransitionY ds 2
|
|
|
|
oldOneSecondCounter ds 2
|
|
frameCount ds 2
|
|
|
|
qtRec adrl $0000
|
|
da $00
|
|
|
|
vsync dw $8000
|
|
|
|
_GetVBLTicks
|
|
PushLong #0
|
|
_GetTick
|
|
pla
|
|
plx
|
|
rts
|
|
|
|
; Load the GTE User Tool and install it
|
|
GTEStartUp
|
|
pea $0000
|
|
_LoaderStatus
|
|
pla
|
|
|
|
pea $0000
|
|
pea $0000
|
|
pea $0000
|
|
pea $0000
|
|
pea $0000 ; result space
|
|
|
|
lda MyUserId
|
|
pha
|
|
|
|
pea #^ToolPath
|
|
pea #ToolPath
|
|
pea $0001 ; do not load into special memory
|
|
_InitialLoad
|
|
bcc :ok1
|
|
brk $01
|
|
|
|
:ok1
|
|
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
|
|
bcc :ok2
|
|
brk $02
|
|
|
|
:ok2
|
|
clc ; Give GTE a page of direct page memory
|
|
tdc
|
|
adc #$0100
|
|
pha
|
|
pea #0 ; Fast Mode
|
|
lda MyUserId ; Pass the userId for memory allocation
|
|
pha
|
|
_GTEStartUp
|
|
bcc :ok3
|
|
brk $03
|
|
|
|
:ok3
|
|
rts
|
|
|
|
BORDER_REG equ $E0C034 ; 0-3 = border, 4-7 Text color
|
|
VBL_VERT_REG equ $E0C02E
|
|
VBL_HORZ_REG equ $E0C02F
|
|
VBL_STATE_REG equ $E0C019
|
|
|
|
_WaitForVBL
|
|
sep #$20
|
|
:wait1 ldal VBL_STATE_REG ; If we are already in VBL, then wait
|
|
bmi :wait1
|
|
:wait2 ldal VBL_STATE_REG
|
|
bpl :wait2 ; spin until transition into VBL
|
|
rep #$20
|
|
rts
|
|
|
|
_WaitForScanline
|
|
jsr _GetVBL
|
|
and #$FFFE
|
|
sta tmp0
|
|
cpx tmp0
|
|
bne _WaitForScanline
|
|
rts
|
|
|
|
_GetVBL
|
|
sep #$20
|
|
ldal VBL_HORZ_REG
|
|
asl
|
|
ldal VBL_VERT_REG
|
|
rol ; put V5 into carry bit, if needed. See TN #39 for details.
|
|
rep #$20
|
|
and #$00FF
|
|
rts
|
|
|
|
_SetBorderColor sep #$20 ; ACC = $X_Y, REG = $W_Z
|
|
eorl BORDER_REG ; ACC = $(X^Y)_(Y^Z)
|
|
and #$0F ; ACC = $0_(Y^Z)
|
|
eorl BORDER_REG ; ACC = $W_(Y^Z^Z) = $W_Y
|
|
stal BORDER_REG
|
|
rep #$20
|
|
rts
|
|
PUT gen/App.TileMapBG0.s
|