iigs-game-engine/demos/kfest-2022/demo-5/App.Main.s
2023-01-02 20:40:09 -06:00

538 lines
13 KiB
ArmAsm

; Test driver to exercise graphics routines.
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
use Tool222.Macs.s
mx %00
tiledata EXT ; tileset buffer
TileSetPalette EXT
; Keycodes
LEFT_ARROW equ $08
RIGHT_ARROW equ $15
UP_ARROW equ $0B
DOWN_ARROW equ $0A
; Direct page space
MyUserId equ 0
BankLoad equ 2
StartX equ 4
StartY equ 6
TileMapWidth equ 8
TileMapHeight equ 10
ScreenWidth equ 12
ScreenHeight equ 14
MaxGlobalX equ 16
MaxGlobalY equ 18
MaxBG0X equ 20
MaxBG0Y equ 22
OldOneSecondCounter equ 26
appTmp0 equ 28
PlayerX equ 30
PlayerY equ 32
PlayerXVel equ 34
PlayerYVel equ 36
PlayerStanding equ 38
PlayerGlobalX equ 40
PlayerGlobalY equ 42
LastHFlip equ 44
SpriteFrame equ 46
SpriteToggle equ 48
SpriteCount equ 50
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 ; Engine in Fast Mode
jsr GTEStartUp ; Load and install the GTE User Tool
jsr SoundStartUp
jsr StartMusic
; Initialize local variables
stz StartX
stz StartY
stz frameCount
stz LastHFlip
stz SpriteCount
stz SpriteToggle
; Initialize the graphics screen playfield
pea #160 ; width in bytes
pea #200 ; height in lines
_GTESetScreenMode
; Load a tileset
pea #0
pea #512
pea #^tiledata
pea #tiledata
_GTELoadTileSet
pea $0000
pea #^TileSetPalette
pea #TileSetPalette
_GTESetPalette
; Set up our level data
jsr BG0SetUp
jsr SetLimits
lda #193 ; Tile ID of '0'
jsr InitOverlay ; Initialize the status bar
pha
_GTEGetSeconds
pla
sta OldOneSecondCounter
jsr UdtOverlay
; Initialize the sprite's global position (this is tracked outside of the tile engine)
lda #16
sta PlayerGlobalX
sta PlayerX
lda MaxGlobalY
sec
sbc #48 ; 32 for tiles, 16 for sprite
sta PlayerGlobalY
sta PlayerY
stz PlayerXVel
stz PlayerYVel
; Create the sprites
HERO_SIZE equ {SPRITE_16X16}
HERO_FLAGS equ HERO_SIZE ; no extra H/V bits for now
HERO_FRAME_1 equ HERO_SIZE+145
HERO_VBUFF_1 equ VBUFF_SPRITE_START+0*VBUFF_SPRITE_STEP
HERO_FRAME_2 equ HERO_SIZE+147
HERO_VBUFF_2 equ VBUFF_SPRITE_START+1*VBUFF_SPRITE_STEP
HERO_FRAME_3 equ HERO_SIZE+149
HERO_VBUFF_3 equ VBUFF_SPRITE_START+2*VBUFF_SPRITE_STEP
HERO_FRAME_4 equ HERO_SIZE+151
HERO_VBUFF_4 equ VBUFF_SPRITE_START+3*VBUFF_SPRITE_STEP
HERO_SLOT equ 1
pea HERO_FRAME_1
pea HERO_VBUFF_1
_GTECreateSpriteStamp
pea HERO_FRAME_2
pea HERO_VBUFF_2
_GTECreateSpriteStamp
pea HERO_FRAME_3
pea HERO_VBUFF_3
_GTECreateSpriteStamp
pea HERO_FRAME_4
pea HERO_VBUFF_4
_GTECreateSpriteStamp
pea HERO_SLOT ; Put the player in slot 1
pea HERO_FLAGS
pea HERO_VBUFF_1 ; and use this stamp
pei PlayerX
pei PlayerY
_GTEAddSprite
EvtLoop
pha
_GTEReadControl
pla
jsr HandleKeys ; Do the generic key handlers
bcs :do_more
brl do_render
:do_more
bit #PAD_BUTTON_A
beq :no_a
pha
jsr handle_a
pla
:no_a
bit #PAD_KEY_DOWN
beq :other_keys
and #$007F
cmp #'p'
bne :not_p
pea $0001
_NTPPlayMusic
bra EvtLoop
:not_p cmp #'['
bne do_render
_NTPStopMusic
bra EvtLoop
:other_keys
and #$007F
cmp #LEFT_ARROW
bne *+5
jmp handle_left
cmp #RIGHT_ARROW
bne *+5
jmp handle_right
cmp #' '
bne do_render
stz PlayerXVel
do_render
jsr UpdatePlayerPos ; Apply forces
jsr ApplyCollisions ; Check if we run into things
jsr UpdateCameraPos ; Moves the screen
pea HERO_SLOT
pei PlayerX
pei PlayerY
_GTEMoveSprite ; Move the sprite to this local position
pea $0000
_GTERender
; Update the performance counters
inc frameCount
pha
_GTEGetSeconds
pla
cmp OldOneSecondCounter
beq :noudt
sta OldOneSecondCounter
jsr UdtOverlay
stz frameCount
:noudt
brl EvtLoop
; Exit code
Exit
jsr SoundShutDown
_GTEShutDown
Quit
_QuitGS qtRec
bcs Fatal
Fatal brk $00
qtRec adrl $0000
da $00
handle_a
lda PlayerStanding
beq :no_jump
lda #-9
sta PlayerYVel
:no_jump rts
handle_left
lda PlayerXVel
bpl :ok
cmp #-4
bcc :out
:ok
dec PlayerXVel
:out
jmp do_render
handle_right lda PlayerXVel
bmi :ok
cmp #6
bcs :out
:ok
inc PlayerXVel
:out
jmp do_render
; Color palette
MyDirectPage ds 2
SetLimits
pha ; Allocate space for width (in tiles), height (in tiles), pointer
pha
pha
pha
_GTEGetBG0TileMapInfo
pla
sta TileMapWidth
pla
sta TileMapHeight
pla
pla ; discard the pointer
pha ; Allocate space for x, y, width, height
pha
pha
pha
_GTEGetScreenInfo
pla
pla ; Discard screen corner
pla
sta ScreenWidth
pla
sta ScreenHeight
lda TileMapWidth
asl
asl
sta MaxGlobalX
sec
sbc ScreenWidth
sta MaxBG0X
lda TileMapHeight
asl
asl
asl
sta MaxGlobalY
sec
sbc ScreenHeight
sta MaxBG0Y
; Check if the current StartX and StartY are out of bounds
lda StartX
cmp MaxBG0X
bcc :x_ok
lda MaxBG0X
:x_ok pha
lda StartY
cmp MaxBG0Y
bcc :y_ok
lda MaxBG0Y
:y_ok pha
_GTESetBG0Origin
rts
; Use Tool222 (NinjaTrackerPlus) for music playback
SoundStartUp
pea $00DE
pea $0000
_LoadOneTool
bcc *+4
brk $02
lda MyUserId
pha
_NTPStartUp
bcc *+4
brk $04
:out
rts
SoundShutDown
_NTPShutDown
rts
StartMusic
pea #^MusicFile
pea #MusicFile
_NTPLoadOneMusic
bcc *+4
brk $06
rts
; Simple updates with gravity and collisions. It's important that eveything in this
; subroutine be done against the VBL tick count
UpdatePlayerPos
lda PlayerGlobalY
clc
adc PlayerYVel
bpl :not_neg_y
lda #0
:not_neg_y
cmp MaxGlobalY
bcc *+4
lda MaxGlobalY
sta PlayerGlobalY
lda PlayerGlobalX
clc
adc PlayerXVel
bpl :not_neg
lda #0
:not_neg
cmp MaxGlobalX
bcc *+4
lda MaxGlobalX
sta PlayerGlobalX
rts
ApplyCollisions
; Convert global to local coordinates
lda PlayerGlobalX
sec
sbc StartX
sta PlayerX
lda PlayerGlobalY
sec
sbc StartY
sta PlayerY
; Collision testing
inc PlayerYVel
stz PlayerStanding
; Check if the player is standing on the ground at their current local position
pha ; space for result
pei PlayerX
lda PlayerY
clc
adc #16
pha
_GTEGetTileAt
pla
; Decide if mario's feet are on a "ground" tile (blocks, pipes, etc.)
and #TILE_ID_MASK
cmp #0
beq :not_ground
cmp #32
bcs :not_ground
lda PlayerYVel
bmi :not_ground
lda PlayerGlobalY
and #$fff8
sta PlayerGlobalY
stz PlayerYVel ; Stop falling when we hit the ground
lda #1
sta PlayerStanding
bra :y_ok
:not_ground
lda PlayerYVel
bmi :y_ok
cmp #8
bcc :y_ok
lda #7
sta PlayerYVel
:y_ok
ldx LastHFlip ; Update sprite frame based on actions
lda PlayerXVel
beq :no_dxv
bpl :pos_dxv
ldx #SPRITE_HFLIP
bra :no_dxv
:pos_dxv
ldx #0
:no_dxv
sta PlayerXVel
stx LastHFlip
lda SpriteCount
eor SpriteToggle
sta SpriteCount
; If the player is standing and XVel != 0, pick a frame
ldx #HERO_VBUFF_1
lda PlayerXVel
beq :frame
jsr _GetVBLTicks
and #$0003
asl
tax
lda HeroFrames,x
tax
:frame
pea HERO_SLOT
pei LastHFlip
phx
_GTEUpdateSprite
rts
HeroFrames dw HERO_VBUFF_2,HERO_VBUFF_3,HERO_VBUFF_4,HERO_VBUFF_3
; Set the scroll position based on the global coordinates of the player
; Try to center the player on the screen
UpdateCameraPos
lda ScreenWidth
lsr
sta appTmp0
lda PlayerGlobalX
sec
sbc appTmp0
bpl :x_pos
lda #0
:x_pos cmp MaxBG0X
bcc :x_ok
lda MaxBG0X
:x_ok sta StartX
lda ScreenHeight
lsr
sta appTmp0
lda PlayerGlobalY
sec
sbc appTmp0
bpl :y_pos
lda #0
:y_pos cmp MaxBG0Y
bcc :y_ok
lda MaxBG0Y
:y_ok sta StartY
pei StartX
pei StartY
_GTESetBG0Origin
; pea $0000
; lda StartY
; lsr
; pha
; _GTESetBG1Origin
rts
_GetVBLTicks
PushLong #0
_GetTick
pla
plx
rts
frameCount equ 24
MusicFile str '1/overworld.ntp'
PUT ../StartUp.s
PUT ../../shell/Overlay.s
PUT gen/App.TileMapBG0.s