;license:MIT ;(c) 2018-9 by 4am ; ; Functions to launch games and self-running demos ; ; Public functions ; - AnyGameSelected ; - GetGameToLaunch ; - FindGame ; - PlayGame ; - Launch ; - Joystick ; - LoadXSingle ; - LoadStandardPrelaunch ; ; 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 ;------------------------------------------------------------------------------ ; FindGame ; 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 ;------------------------------------------------------------------------------ FindGame +ST16 gLastMegaAttractGame jsr okvs_next_field ; (PTR) -> OKVS value (filename or empty string) ; Y=0 lda (PTR), y beq + +LD16 PTR +ST16 gLastMegaAttractGame + jsr okvs_next_field_PTR_is_already_set ; (PTR) -> game display name +LD16 PTR ; A/Y -> game display name +ST16 SAVE ; (SAVE) -> game display name jsr okvs_next_field ; (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 in gSearchIndex PlayGameInAY +ST16 SAVE +ST16 @pfile +ST16 xfile jsr okvs_next_field jsr okvs_next_field_PTR_is_already_set ; (PTR) -> length-prefixed game info bitfield ; Y = 0 iny ; Y = 1 lda (PTR), y ; A = game info bitfield and #IS_SINGLE_LOAD php jsr ClearScreens ; avoid seeing code load into the HGR page ; (clobbers $106, must do now before loading prelaunch code) jsr LoadIndexedFile ; load prelaunch index file - !word gSearchCache ; clobber gSearchCache which we no longer need !word kPrelaunchIndexRecord jsr okvs_find ; find this game's prelaunch index record !word - @pfile !word $FDFD ; SMC +ST16 @prelaunchIndexRecordPtr jsr LoadIndexedFile ; load this game's prelaunch code into $0106 !word $0106 @prelaunchIndexRecordPtr !word $FDFD ; SMC plp beq @loadFromSubdirectory jsr LoadXSingle_NameIsAlreadySet jmp Launch @loadFromSubdirectory +LD16 SAVE +ST16 @p jsr LoadFile ; load the game startup file !word kGameDirectory @p !word $FDFD !word 0 ; use file's default address lda #1 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 ;------------------------------------------------------------------------------ ; LoadXSingle/LoadXSingle_NameIsAlreadySet/LoadXFile ; load an indexed file via an extended index record that also contains starting ; address information ; ; in: A/Y points to game filename (must be listed in xsingle OKVS) ; out: all flags & registers clobbered ;------------------------------------------------------------------------------ LoadXSingle ; entry point used by demos to load additional resources +ST16 xfile LoadXSingle_NameIsAlreadySet ; entry point used by PlayGame jsr LoadIndexedFile ; load xsingle index file (contains pointers to game binaries) - !word gSearchCache ; clobber search cache which we no longer need !word kXSingleRecord LoadXFile ; entry point used by attract mode to load self-running demo jsr okvs_find ; find this game's extended index record !word - xfile !word $FDFD ; SMC +ST16 @xsingleIndexRecordPtr jsr okvs_next_field ldy #5 lda (PTR), y ; get game load address (stored immediately after index record) sta @xsingleAddr iny lda (PTR), y sta @xsingleAddr+1 jsr LoadIndexedFile ; load this game binary @xsingleAddr !word $FDFD ; SMC @xsingleIndexRecordPtr !word $FDFD ; SMC rts ;------------------------------------------------------------------------------ ; Joystick ; launch joystick calibration program ; ; in: none ; out: exits via Launch ;------------------------------------------------------------------------------ Joystick jsr LoadStandardPrelaunch jsr LoadIndexedFile !word $800 !word kJoystickRecord jmp Launch LoadStandardPrelaunch jsr LoadIndexedFile ; load standard prelaunch code at $0106 !word $0106 !word kStandardPrelaunchRecord rts