;license:MIT ;(c) 2018-9 by 4am ; ; Attract Mode - cycle through slideshows and self-running demos ; ; Public functions ; - MegaAttractMode ; - MiniAttractMode ; - RunAttractModule ;------------------------------------------------------------------------------ ; MegaAttractMode ; main entry point for Mega Attract Mode, which endlessly cycles through ; modules listed in ATTRACT.CONF to display title pages, action screenshots, ; super hi-res box art (on supporting platforms), and self-running game demos ; ; in: gGlobalPrefsStore must be initialized ; out: never returns to caller (may JMP to other major modes) ;------------------------------------------------------------------------------ MegaAttractMode jsr SwitchToBank1 ldx #$FF txs jsr BlankHGR ; switch to HGR page 1 (once cleared) jsr LoadFile ; load attract-mode configuration file into $8000 !word kRootDirectory !word kAttractModeConfFile - !word $8000 jsr ParseKeyValueList ; parse attract-mode configuration into OKVS data structure at $6000 !word gAttractModeStore !word - !byte 0 jsr pref_get ; get attract mode module from prefs !word kNextAttract !word gAttractModeStore +STAY @mname ; A/Y = module name ; X = index of module in attract store +LDADDR gAttractModeStore jsr okvs_next ; get module after this one +STAY + jsr pref_set ; update prefs store and save to disk !word kNextAttract + !word $FDFD ; SMC jsr okvs_get !word gAttractModeStore @mname !word $FDFD ; SMC +STAY PTR ldy #1 lda (PTR),y tax ; X = module type +LDAY @mname ; A/Y = address of module name jsr RunAttractModule lda KBD bpl @jmpattract cmp #$8D ; Enter plays the game shown on screen. bne @jmpsearch ; Any other key switches to Search Mode. jsr PlayGame ; (might return if user hits Ctrl-Reset) @jmpattract jmp MegaAttractMode @jmpsearch jmp SearchMode ;------------------------------------------------------------------------------ ; MiniAttractMode ; run attract modules related to one game ; ; in: X = index in gGamesListStore ; gGlobalPrefsStore must be initialized ; out: all flags and registers clobbered ; assume all of main memory has been clobbered ;------------------------------------------------------------------------------ MiniAttractMode +LDADDR gGamesListStore jsr okvs_nth +STAY @fname jsr BlankHGR lda #0 sta @MiniAttractIndex @loop jsr LoadFile ; load mini attract mode configuration file into $8000 !word kMiniAttractDirectory @fname !word $FDFD ; SMC - !word $8000 jsr ParseKeyValueList ; parse configuration into OKVS data structure at $6000 !word gAttractModeStore !word - !byte 0 +LDADDR gAttractModeStore jsr okvs_len cmp @MiniAttractIndex beq @exit ; we've run through all modules, so exit to caller @MiniAttractIndex=*+1 ldx #$FD ; SMC +LDADDR gAttractModeStore jsr okvs_nth ; get the next module on the list +STAY SAVE jsr okvs_get_current ; get module type ldy #1 lda (PTR),y tax ; X = module type +LDAY SAVE ; A/Y = address of module name jsr RunAttractModule ; execute the module inc @MiniAttractIndex lda KBD bpl @loop @exit rts ;------------------------------------------------------------------------------ ; RunAttractModule ; run a single attract module of any type and return to caller ; ; in: X = module type as ASCII char (1-6,A-C, see attract.conf) ; A/Y = address of module name ; for demos, this is the filename of an executable in /demo/ ; for slideshows, this is the filename of a .conf file in /ss/ ; for singles, this is a pathname of the graphic to load ; gGlobalPrefsStore must be initialized (if we load a transition effect ; of any kind, we will update the global prefs with the next one) ; out: all flags and registers clobbered ; assume all of main memory has been clobbered ;------------------------------------------------------------------------------ RunAttractModule +STAY @key +STAY @key2 cpx #$30 bne @NotDemo ; Self-running demos are loaded into main memory and executed. ; Each binary has been patched to quit on any key and jump back ; to the |Reenter| entry point. ; All demos are strictly 48K / main memory. No demo uses the ; language card or auxiliary memory. +LDAY @key jsr GetGameDisplayName bcc + ; if game doesn't exist, skip the demo rts + cpx #$FF beq + stx gGameToLaunch + jsr Home ; avoid seeing code load into the HGR page jsr LoadFile ; load standard prelaunch code (|Launch| will call it) !word kPrelaunchDirectory !word kStandardPrelaunch !word $0106 ldy kDemoDirectory sty ProDOS_prefix ; temporarily set 'root' directory to - lda kDemoDirectory, y ; /demos/ directory so demos can can load sta ProDOS_prefix, y ; other resources in the same directory dey bne - jsr LoadFile ; load self-running demo into its default address (varies) !word kDemoDirectory @key !word $FDFD !word 0 jmp Launch ; will return to caller via |Reenter| ; not a demo, so maybe a slideshow or single screenshot @NotDemo txa cmp #$41 ; numbers are slideshow modules, bcs @dispatchSingle ; letters are single files ; it's a slideshow, so load and parse slideshow configuration file pha ; save module type jsr LoadFile ; load slideshow configuration file into $4000 !word kAttractModeSlideshowDirectory @key2 !word $FDFD ; SMC - !word $4000 jsr ParseKeyValueList ; parse into an OKVS data structure at $0800 !word gSlideshowStore !word - !byte 0 pla ; restore module type - and #$0F ; convert ASCII digit to int tax lda @slideshowslo-1,x sta @jmp+1 lda @slideshowshi-1,x sta @jmp+2 +LDAY @key ; pass in module name @jmp jmp $FDFD ; SMC @dispatchSingle adc #(@singleslo-@slideshowslo)-1 bne - ; always branches @slideshowslo !byte HGRTitleSlideshow !byte >HGRActionSlideshow !byte >DHGRTitleSlideshow !byte >DHGRActionSlideshow !byte >SHRSlideshow !byte >GRActionSlideshow @singleshi !byte >HGRSingle !byte >DHGRSingle !byte >SHRSingle !byte >GRSingle