;license:MIT ;(c) 2018-9 by 4am ; ; Functions to launch games and self-running demos ; ; Public functions ; - GetGameDisplayName ; - PlayGameFromSearch ; - PlayGameFromBrowse ; - PlayGameFromAttract ; - Prelaunch ; - Launch ; ; Public variables ; - gCurrentAttractIndex ; [byte] numeric index in gAttractModeStore of current Mega-Attract Module ; - gCurrentlyVisibleSlideshowIndex ; [byte] numeric index in gSlideshowStore of currently visible slideshow picture ; (only valid during slideshows, not updated once a key is pressed) !zone { 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) ; 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 clc @exit rts PlayGameFromSearch PlayGameFromBrowse ; in: X = game index stx + jsr okvs_nth !word gGamesListStore + !byte $FD ; SMC ; A/Y = address of game filename jmp .Go PlayGameFromAttract ; in: none jsr LoadAndParseAttractModeConf jsr okvs_nth ; get filename of current attract-mode module !word gAttractModeStore gCurrentAttractIndex !byte $FD ; set in MegaAttractMode +STAY @key jsr okvs_get !word gAttractModeStore @key !word $FDFD ; SMC ; A/Y = address of attract mode value (module type) +STAY PTR ldy #1 lda (PTR),y and #$0F bne @playFromSlideshow ; we reached here by pressing during a self-running demo, ; which means that @key points to the filename of the game we want to play, +LDAY @key jmp .Go @playFromSlideshow ; we reached here by pressing during a slideshow ; gSlideshowStore is still in memory, and gCurrentlyVisibleSlideshowIndex ; is the index into gSlideshowStore of the picture that is being displayed jsr okvs_nth !word gSlideshowStore gCurrentlyVisibleSlideshowIndex !byte $FD ; set in HGRTitleCallback, HGRActionCallback, DHGRTitleCallback +STAY @sskey +STAY @sskey2 jsr okvs_get !word gGamesListStore @sskey !word $FDFD ; SMC bcs + +LDAY @sskey ; the slideshow key was a game filename, so use that jmp .Go + ; if the key is not found, get the value of the current record ; from gSlideshowStore instead (some games have multiple action screenshots, so ; the key is just a unique filename for that screenshot and the value is the ; actual game filename) jsr okvs_get !word gSlideshowStore @sskey2 !word $FDFD ; SMC ; execution falls through here .Go ; in: A/Y = lo/hi address of filename +STAY SAVE +STAY + +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 iny bne @clear inc @clear+2 dex bne @clear bit gCheatsEnabled ; are cheats enabled? bpl @noCheats jsr okvs_get ; need to get game index from filename to determine !word gGamesListStore ; whether there are any cheats for this game + !word $FDFD ; SMC ; X = game index 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 ldx #$F1 - lda $100,x sta $DF00,x ; back up stack inx 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 - jmp $106 ; jump to pre-launch code }