;license:MIT ;(c) 2018-9 by 4am ; ; Functions to launch games and self-running demos ; ; Public functions ; - GetGameDisplayName ; - PlayGame ; - Launch ; GetGameDisplayName ; in: A/Y points to game filename ; X = #$60 if we should only look in gGamesListStore for a match ; X = #$EA if we should also look in gSlideshowStore ; out: C clear if game exists in gGamesListStore, and ; A/Y points to game display name (but see hack notes below) ; X = game index, or #$FF if the game doesn't really exist but ; we want to return a successful result anyway (really, read the ; hack notes, they're important) ; C set if game does not exist (this can happen because slideshows ; list games that require a joystick, but the games list parser ; filters out joystick-only games if the machine doesn't have a ; joystick) stx @maybeExit +STAY @key +STAY @slideshowKey jsr okvs_get !word gGamesListStore @key !word $FDFD ; SMC bcc @exit ; Hack to allow self-running demos that don't correspond to a game ; filename. If the name ends in a '.', accept it unconditionally. ; The filename is its own display name. Launching this fake game ; will of course fail, so don't do that. +LDAY @key +STAY PARAM ldy #0 lda (PARAM),y tay lda (PARAM),y cmp #"." beq @forceGoodResult sec @maybeExit !byte $00 ; SMC ; if the key is still not found, AND the caller said to try this, then try ; getting the value of the current record from gSlideshowStore ; (some games have multiple action screenshots, in which case the filename of ; the action screenshot is not the game name, but the value is) jsr okvs_get !word gSlideshowStore @slideshowKey !word $FDFD ; SMC +STAY @key3 jsr okvs_get !word gGamesListStore @key3 !word $FDFD ; SMC ; note that the game might still not be found (C will be set by okvs_get), ; which can happen if the game can't be played due to memory or joystick ; requirements rts @forceGoodResult +LDAY @key ldx #$FF clc @exit rts PlayGame gGameToLaunch=*+1 ldx #$FF ; SMC +LDADDR gGamesListStore jsr okvs_nth ; A/Y = address of game filename +STAY SAVE +STAY @pfile jsr Home ; clear screen (clobbers $106, must do now before loading prelaunch code) lda #$20 ; clear both hi-res pages sta @clear+2 ; (in case game loader shows them, we don't want ldx #$40 ; to flash previous bits of the launcher UI) ldy #$00 tya @clear sta $FD00,y ; SMC iny bne @clear inc @clear+2 dex bne @clear bit gCheatsEnabled ; are cheats enabled? bpl @noCheats ldx gGameToLaunch ldy gCheatsAvailable,x ; are there any cheats for this game? beq @noCheats jsr LoadFile ; cheats are enabled and this game has a prelaunch !word kPrelaunchDirectory ; file that will set up the cheats, so load that @pfile !word $FDFD ; SMC !word $0106 jmp @loadedPrelaunch @noCheats jsr LoadFile ; no game-specific prelaunch file, so !word kPrelaunchDirectory ; load standard prelaunch file instead !word kStandardPrelaunch !word $0106 @loadedPrelaunch ldx #1 ; construct path to game's startup file sec ; which is always /X/game/game !byte $2c -- pha clc php ldy #0 lda (SAVE), y tay iny sty @runlength+1 ldy #0 lda #'X' sta ProDOS_prefix+1 lda #'/' - inx sta ProDOS_prefix, x iny lda (SAVE), y @runlength cpy #$D1 ; SMC bne - txa plp bcs -- stx ProDOS_prefix jsr LoadFile ; load the game startup file !word kRootDirectory !word ProDOS_prefix !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 jsr SaveOrRestoreScreenHoles ; save screen hole contents ldy #$F1 - lda $100,y sta $DF00,y ; back up stack iny bne - tsx ; back up stack pointer stx $DFF0 lda #$38 ; 'sec' opcode to tell |Reenter| to sta RestoreStackNextTime ; restore the stack and stack pointer ldx #(end_promote-promote-1) - lda promote,x ; copy ProDOS shim to main memory sta $bf00,x dex bpl - tya ldy #$18 - sta $bf57,y dey bne - jmp $106 ; jump to pre-launch code