4cade/src/glue.launch.a
2021-11-02 21:49:41 -04:00

223 lines
6.8 KiB
Plaintext

;license:MIT
;(c) 2018-9 by 4am
;
; Functions to launch games and self-running demos
;
; Public functions
; - AnyGameSelected
; - GetGameToLaunch
; - FindGame
; - FindGameInActionSlideshow
; - PlayGame
; - Launch
;
; Public variables:
; - gGameToLaunch - 0-based index into gSearchStore (word)
;
gGameToLaunch
!word $FFFF
gLastMegaAttractGame
!word $FFFF
;------------------------------------------------------------------------------
; AnyGameSelected
; get index of game that is currently selected in the UI (if any)
;
; in: none
; out: A/Y = gGameToLaunch (word)
; C clear if gGameToLaunch is not #$FFFF
; C set if gGameToLaunch is #$FFFF
; X preserved
;------------------------------------------------------------------------------
AnyGameSelected
+LD16 gGameToLaunch
+CMP16_NE $FFFF, ForceGoodResult
rts ; CMP sets carry when equal
;------------------------------------------------------------------------------
; GetGameToLaunch
; get filename of game that is currently selected in the UI (if any)
;
; in: gGameToLaunch = index into gSearchStore (word) or #$FFFF if no game selected
; gSearchStore populated
; out: C clear if a game is selected, and
; A/Y points to game filename
; C set if no game is selected
;------------------------------------------------------------------------------
GetGameToLaunch
jsr AnyGameSelected
bcs _gameToLaunchExit
+ST16 WINDEX
+LDADDR gSearchStore
jsr okvs_nth
ForceGoodResult
clc
_gameToLaunchExit
rts
;------------------------------------------------------------------------------
; FindGameInActionSlideshow
; check if an arbitrary game exists, for some definition of 'exists', while
; in the middle of a slideshow
;
; in: A/Y points to a key in gSlideshowStore
; out: C clear if game exists and is playable on current machine, and
; (SAVE) -> game display name, and
; (gLastMegaAttractGame) -> game filename
; C set otherwise
; clobbers $FF, PTR
; all registers clobbered
;------------------------------------------------------------------------------
FindGameInActionSlideshow
+ST16 gLastMegaAttractGame
jsr okvs_get_current ; (PTR) -> OKVS value (filename or empty string)
; Y=0
lda (PTR), y
beq +
+LD16 PTR
+ST16 gLastMegaAttractGame
+ jsr okvs_get_current_PTR_is_already_set ; (PTR) -> game display name
+LD16 PTR ; A/Y -> game display name
+ST16 SAVE ; (SAVE) -> game display name
FindGame
jsr okvs_get_current ; (PTR) -> game requirements bitfield
; Y=0
; check if game requires joystick
lda (PTR), y
sta $FF
bpl @check128K
lda MachineStatus
and #HAS_JOYSTICK
beq @failedCheck ; machine doesn't have joystick but game requires it
@check128K
; check if game requires 128K
bit $FF
bvc @passedAllChecks
lda MachineStatus
and #HAS_128K
beq @failedCheck ; machine doesn't have 128K but game requires it
@passedAllChecks
clc
rts
@failedCheck
sec
rts
;------------------------------------------------------------------------------
; PlayGame
;
; in: gGameToLaunch != #$FFFF
; out: exits via the game, but also backs up the stack, which may get
; restored in |Reenter|... what I'm saying is that we might actually
; 'return' from this after the user is done playing the game, which is
; a neat trick
;------------------------------------------------------------------------------
PlayGame
jsr GetGameToLaunch
; A/Y = address of game filename
PlayGameInAY
+ST16 SAVE
+ST16 @pfile
jsr ClearScreens ; avoid seeing code load into the HGR page
; (clobbers $106, must do now before loading prelaunch code)
jsr LoadFile ; load prelaunch index file into $6000
!word kRootDirectory
!word kPrelaunchIndexFile
- !word $6000
jsr okvs_find
!word -
@pfile !word $FDFD ; SMC
+ST16 @indexRecordPtr
jsr LoadIndexedFile
!word kPrelaunchFulFile
!word $0106
@indexRecordPtr
!word $FDFD ; SMC
; we start by placing the subdirectory name at gPathname+kGameDirectoryLen
; to leave room for the GameDirectory name as the parent
lda #kGameDirectoryLen
sta gPathname
+LD16 SAVE
jsr AddToPath
; attach the separator
inc gPathname
lda #'/'
sta gPathname+1,x
; then we save the length of the resulting string without the count byte
dex
txa
pha
; then attach the game name
+LD16 SAVE
jsr AddToPath
; don't look while I do this
; we "place" a string at gPathname+kGameDirectoryLen
; whose length is the subdirectory name and game name
; then we load it
; the load sets the path to the GameDirectory
; and then finds the subdirectory name and game name right after it
; and attaches it to the path by overwriting the count byte
;;sec ; carry set by AddToPath
lda gPathname
sbc #kGameDirectoryLen
sta gPathname+kGameDirectoryLen
jsr LoadFile ; load the game startup file
!word kGameDirectory
!word gPathname+kGameDirectoryLen
!word 0 ; use file's default address
pla
sta ProDOS_prefix ; set 'root' directory to the path part
; of the game startup file we just loaded
; so games can load other files without
; knowing which directory they're in
; execution falls through here
Launch
jsr SwitchToBank2
lda #$BD
sta launchpatch
jsr saveslot ; set proper slot information
lda #$9D
sta launchpatch
jmp LaunchInternal
Joystick
jsr LoadStandardPrelaunch
jsr LoadFile
!word kRootDirectory
!word kJoystickFile
!word 0
jmp Launch
LoadStandardPrelaunch
jsr LoadIndexedFile ; load standard prelaunch code at $0106
!word kPrelaunchFulFile
!word $0106
!word +
rts
+ !byte 0
!be24 0
!le16 PRELAUNCH_STANDARD_SIZE