;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 gGamesListStore (word) ; gGameToLaunch !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 ;------------------------------------------------------------------------------ ; FindGame ; check if an arbitrary game exists, for some definition of 'exists' ; ; in: A/Y points to game filename ; out: C clear if game exists in gGamesListStore, and ; $WINDEX = game index, or #$FFFF if the game doesn't really ; exist but we want to return a successful result anyway ; C set if game does not exist (this can happen because slideshows ; list games that require a joystick, but the games list parser ; filters them out if the machine doesn't have a joystick) ; all registers clobbered ;------------------------------------------------------------------------------ FindGame +ST16 @key jsr okvs_find !word gGamesListStore @key !word $FDFD ; SMC bcc GlueLaunchRTS ; Hack to allow self-running demos that don't correspond to a game ; filename. If the name ends in a '.', accept it unconditionally. ldx #$FF stx WINDEX stx WINDEX+1 +LD16 @key +ST16 PARAM ldy #0 lda (PARAM),y tay lda (PARAM),y cmp #"." beq ForceGoodResult sec GlueLaunchRTS 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 ; $WINDEX = game index, and ; A/Y points to game display name ; C set if game can't be found by any means ;------------------------------------------------------------------------------ FindGameInActionSlideshow +ST16 @slideshowKey jsr FindGame bcc @GetGameDisplayName ; if the game was not found, try getting the value of the current record from ; gSlideshowStore (some games have multiple action screenshots, in which case ; the key is only the screenshot filename, and the value is the actual game ; filename) jsr okvs_get !word gSlideshowStore @slideshowKey !word $FDFD ; SMC jsr FindGame bcs GlueLaunchRTS @GetGameDisplayName +LD16 @slideshowKey jsr okvs_get_current jsr okvs_get_current_PTR_is_already_set +LD16 PTR 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 +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 68