diff --git a/src/4cade.a b/src/4cade.a index 0258cfe73..99c9d29d5 100644 --- a/src/4cade.a +++ b/src/4cade.a @@ -12,56 +12,56 @@ RELBASE=$2000 !source "src/constants.a" !source "src/macros.a" - ; first-run initialization, relocates code to language card and continues from Main + ; first-run initialization, relocates code to language card and jumps + ; to |Reenter| !source "src/4cade.init.a" FirstMover !pseudopc RELBASE { -Reenter ; self-running demos should call this to exit back to 4cade +;------------------------------------------------------------------------------ +; Reenter +; This is the primary entry point for returning to the launcher from anywhere. +; - Self-running demos call this when the user presses a key or when the demo +; cycles ends naturally. +; - It is set as the reset vector, so the user can play a game then press +; Ctrl-Reset to return to the launcher and choose another. +; - It also functions as a reset vector while the launcher is running. +; - It is also called on program startup, after the first-run initialization. +; +; When execution reaches this point, we may have previously backed up the stack +; and stack pointer, in which case it is now our job to restore it and return +; to the caller. This allows magic like 'JSR PlayGame' then continuing once the +; JSR returns. +; +; If there is no stack to restore, this exits via SearchMode. +; +; in: no parameters +; out: see above +;------------------------------------------------------------------------------ +Reenter cld cli +READ_RAM2_WRITE_RAM2 - jsr CloseHandles ; close any open handles to restore ProRWTS state to original + jsr CloseHandles ; close any open handles to restore ProRWTS ; (also switches to LC RAM bank 1) - jsr SaveScreenHoles ; restore screen hole contents from saved copy -Main - ldx #$FF - txs - ldx #5 -- lda Prelaunch,x ; copy reset vector code (switches to LC RAM and jumps to |Reenter|) + jsr SaveOrRestoreScreenHoles ; restore original screen hole contents +RestoreStackNextTime + clc ; SMC + bcc SearchMode ; not an unconditional branch because code + ; might change the 'clc' just before it + ; If we fall through to here, it's because we backed up the stack and + ; stack pointer and wanted this routine to restore it and return to + ; caller. + lda #$18 ; reset to 'clc' opcode so we don't try to + sta RestoreStackNextTime ; restore the same stack twice + ldx #1 +- lda $DF00,x ; restore stack sta $100,x - dex - bpl - inx - stx $3F2 ; set up reset vectors - inx - stx $3F3 - txa - eor #$A5 - sta $3F4 - - jsr BlankHGR -@loop - lda $C000 - cmp #$8D - bne + - jsr Play -+ cmp #$9B - bne + - lda Mode - eor #$80 - sta Mode -+ - bit $C010 - bit Mode - bpl + - jsr MegaAttractMode - jmp @loop -+ - jsr SearchMode - jmp @loop -Mode - !byte $00 + bne - + ldx $DF00 ; restore stack pointer + txs + rts ; these routines will only be called after relocating to language card !source "src/ui.search.mode.a" @@ -80,6 +80,7 @@ Mode !source "src/parse.games.a" !source "src/ui.sound.a" !source "src/ui.font.a" +Mode !byte $00 gGlobalPrefsStore !word $D000 ; address of first okvs store !word Reenter ; NMI vector ($FFFA-B) diff --git a/src/4cade.init.a b/src/4cade.init.a index 77320dae6..18d965254 100644 --- a/src/4cade.init.a +++ b/src/4cade.init.a @@ -76,7 +76,7 @@ ProRWTSBuffer OneTimeSetup lda MachineStatus sta oldstatus - jsr SaveScreenHoles ; save initial copy of screen hole content + jsr SaveOrRestoreScreenHoles ; save initial copy of screen hole content lda #$91 sta holepatch ; enable restoring of copy from now on lda hddopendir+1 ; save current directory as 'root' @@ -107,10 +107,55 @@ OneTimeSetup !word gGamesListStore !word ldrlo2 ; (ldrlo2) points to last load address, so $8000 + jsr okvs_len + !word gGamesListStore + sta SAVE + ; calculate and update visible game count (3-digit decimal number as ASCII string) + ldy #0 +@outer + lda #0 + pha +@inner + lda SAVE + cmp kPowersOfTen,y + bcc @digitDone + sbc kPowersOfTen,y + sta SAVE + lda SAVE+1 + sbc #0 + sta SAVE+1 + pla + adc #0 + pha + jmp @inner +@digitDone + pla + ora #$30 + sta UILine2_GameCount,y + iny + cpy #$03 + bcc @outer + bit $C010 ; clear keyboard strobe so we don't mistakenly think we just tried to run something - jmp Main ; continue execution from LC RAM bank + ldx #5 +- lda Prelaunch,x ; copy reentry wrapper to bottom of stack + sta $100,x ; (many self-running demos use this) + dex + bpl - + inx + stx $3F2 ; page 3 reset vector to ($100) + inx + stx $3F3 + ldx #$A4 + stx $3F4 + jmp $100 ; continue execution from LC RAM bank kGameListConfFile !byte 10 !text "GAMES.CONF" + +kPowersOfTen + !byte 100 + !byte 10 + !byte 1 diff --git a/src/constants.a b/src/constants.a index 8cd71d899..9c0adc2d2 100644 --- a/src/constants.a +++ b/src/constants.a @@ -14,7 +14,8 @@ ; D000..D3FF - ProRWTS data ; D400..D5FF - ProRWTS code ; D600..D9FF - HGR font data -; DA00..DFFF - unused +; DA00..DEFF - unused +; DF00..DFFF - backup of stack during self-running demos ;------------------------------------------------------------------------------ ; soft switches diff --git a/src/glue.launch.a b/src/glue.launch.a index 1e2b9d8b2..8247f1d0f 100644 --- a/src/glue.launch.a +++ b/src/glue.launch.a @@ -4,26 +4,23 @@ ; Functions to launch games and self-running demos ; ; Public functions -; - Launch +; - PlayGameFromSearch +; - PlayGameFromAttract ; ; Public variables +; - SelectedIndex ; [byte] numeric index in gGamesStore of currently selected game in search mode ; - 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) -Play - lda Mode - bmi @playFromAttract -@playFromSearch - lda SelectedIndex - sta @selectedIndex +PlayGameFromSearch jsr okvs_nth !word gGamesListStore -@selectedIndex +SelectedIndex !byte $FD ; SMC jmp Go -@playFromAttract +PlayGameFromAttract +LDADDR kAttractModeConfFile jsr SetPath jsr LoadFile ; load attract-mode configuration file at $8000 @@ -114,6 +111,17 @@ Go sta ProDOS_prefix copy_prelaunch + +READ_RAM2_WRITE_RAM2 + ldx #1 +- lda $100,x + sta $DF00,x ; backup stack + inx + bne - + tsx ; backup stack pointer + stx $DF00 + lda #$38 ; 'sec' opcode + sta RestoreStackNextTime ; tell |Reenter| to restore stack + ldx #(End_Prelaunch-Prelaunch-1) - lda Prelaunch,x ; copy pre-launch code to main memory sta $100,x @@ -136,7 +144,7 @@ copy_prelaunch ; in: none ; out: exits via JMP (ldrlo2), which is expected to exit via JMP |Prelaunch| ; (not here, but wherever it was copied to in main memory) or by -; manually enabling LC RAM bank 1 then JMP |Reenter| +; manually enabling LC RAM then JMP |Reenter| ;------------------------------------------------------------------------------ Prelaunch ; this runs from main memory ; entry point used by some self-running demos diff --git a/src/glue.prorwts2.a b/src/glue.prorwts2.a index f350ab1e7..666c1fe4a 100644 --- a/src/glue.prorwts2.a +++ b/src/glue.prorwts2.a @@ -355,7 +355,7 @@ ProDOS_prefix=$bfd0 end_promote ;------------------------------------------------------------------------------ -; SaveScreenHoles +; SaveOrRestoreScreenHoles ; preserve screen hole contents across demo execution ; to avoid crashing later on disk access ; @@ -364,7 +364,7 @@ end_promote ; all registers clobbered ;------------------------------------------------------------------------------ -SaveScreenHoles +SaveOrRestoreScreenHoles lda #4 sta namhi ldx #0 diff --git a/src/textrank.a b/src/textrank.a index fe1a6deeb..f98e6fd9a 100644 --- a/src/textrank.a +++ b/src/textrank.a @@ -9,7 +9,6 @@ ; Public variables ; - InputLength ; - InputBuffer -; - SelectedIndex ; - MatchCount ; - BestMatchScore ; - BestMatchIndex @@ -28,8 +27,6 @@ InputLength !byte 0 InputBuffer !text " " -SelectedIndex - !byte $FF MatchCount !byte 0 BestMatchScore diff --git a/src/ui.attract.mode.a b/src/ui.attract.mode.a index 6aa6668d3..9c15bb995 100644 --- a/src/ui.attract.mode.a +++ b/src/ui.attract.mode.a @@ -26,6 +26,8 @@ ; memory, unused portions of the stack page, all registers, all flags) ;------------------------------------------------------------------------------ MegaAttractMode + jsr BlankHGR + +LDADDR kAttractModeConfFile jsr SetPath jsr LoadFile ; load attract-mode configuration file at $8000 @@ -86,10 +88,15 @@ gAttractIndex jsr @RunNextAttractModule lda $C000 - bmi + + bpl @jmpattract + cmp #$8D + bne @jmpsearch + jsr PlayGameFromAttract + ; execution falls through here +@jmpattract jmp MegaAttractMode -+ - rts +@jmpsearch + jmp SearchMode @RunNextAttractModule ldy #1 @@ -127,7 +134,7 @@ gAttractIndex +LOAD_FILE_IMM @key - jsr SaveScreenHoles ; save screen hole contents in case game changes them + jsr SaveOrRestoreScreenHoles ; save screen hole contents in case game changes them jmp copy_prelaunch @NotDemo ; slideshow module or screenshot diff --git a/src/ui.search.mode.a b/src/ui.search.mode.a index c8c408351..289e2126d 100644 --- a/src/ui.search.mode.a +++ b/src/ui.search.mode.a @@ -1,7 +1,7 @@ ;license:MIT ;(c) 2018 by 4am ; -; Search Mode - incrementally search game catalog +; Search Mode - UI to search game catalog, see game assets, and launch games ; ; Public functions ; - SearchMode @@ -20,14 +20,14 @@ InputDispatchTable !word OnLaunch SearchMode - jsr Home - - lda #0 - sta OffscreenPage - sta InputLength - jsr _UpdateGameCount - - jsr OnInputChanged ; draw default UI on HGR page 1 + ldx #0 + stx OffscreenPage + dex + stx SelectedIndex ; no game selected + txs + jsr Home ; clear screen + lda #$FF + jsr OnInputChanged ; draw UI on HGR page 1, set $C054 bit $C052 bit $C057 bit $C050 @@ -110,18 +110,18 @@ InputDispatch sta @j+2 pla ; restore key pressed @j jsr $FDFD ; SMC - jmp _SearchModeInputLoop + bcc + + jmp SearchMode ++ jmp _SearchModeInputLoop OnClear + bit $C010 ldx InputLength bne + - jsr _CoverFade - pla ; Esc with no input exits search mode - pla ; and switches to attract mode - rts -+ ldx #0 + jsr _CoverFade ; Esc with no input switches to + jmp MegaAttractMode ; mega-attract mode ++ ldx #0 ; Esc with input clears the input stx InputLength - bit $C010 jmp OnInputChanged OnBack @@ -137,9 +137,11 @@ OnLaunch ldx SelectedIndex cpx #$FF beq + - pla ; Return exits search mode - pla ; and launches game -+ rts + jsr PlayGameFromSearch + sec ; tell caller to redraw UI + rts ++ clc + rts OnSearch ldx InputLength @@ -172,7 +174,9 @@ OnInputChanged jsr _LoadCoverOffscreen jsr _DrawSearchBarOffscreen - jmp _ShowOtherPage + jsr _ShowOtherPage + clc + rts @findMatchingTitle jsr ResetTextRank @@ -304,41 +308,6 @@ _ShowOtherPage + bit $C054 ; show page 1 rts -_UpdateGameCount - jsr okvs_len - !word gGamesListStore - sta SAVE - ldy #0 -@outer - lda #0 - pha -@inner - lda SAVE - cmp @powersOfTen,y - bcc @digitDone - sbc @powersOfTen,y - sta SAVE - lda SAVE+1 - sbc #0 - sta SAVE+1 - pla - adc #0 - pha - jmp @inner -@digitDone - pla - ora #$30 - sta UILine2_GameCount,y - iny - cpy #$03 - bcc @outer - rts - -@powersOfTen - !byte 100 - !byte 10 - !byte 1 - _ResetInputTimeout ; clobbers X, preserves A/Y ldx #$16