4cade/src/ui.search.mode.a
2020-03-24 16:30:14 -04:00

253 lines
7.7 KiB
Plaintext

;license:MIT
;(c) 2018-2020 by 4am
;
; Search Mode - main UI
;
; Public functions
; - SearchMode
; - SoftBell
;
; indices into InputDispatchTable
kInputSearch = 0
kInputClear = 1
kInputBack = 2
kInputBrowse = 3
kInputTab = 4
kInputLaunch = 5
kInputHelp = 6
kInputCredits = 7
kInputCheat = 8
kInputError = 9
InputDispatchTableLo
!byte <OnSearch
!byte <OnClear
!byte <OnBack
!byte <BrowseMode
!byte <OnTab
!byte <OnLaunch
!byte <Help
!byte <Credits
!byte <OnCheat
!byte <OnError
InputDispatchTableHi
!byte >OnSearch
!byte >OnClear
!byte >OnBack
!byte >BrowseMode
!byte >OnTab
!byte >OnLaunch
!byte >Help
!byte >Credits
!byte >OnCheat
!byte >OnError
kNumInputKeys = 10 ; number of entries in next 2 tables (each)
InputKeys
!byte $83 ; Ctrl-C = toggle cheat mode
!byte $81 ; Ctrl-A = about
!byte $AF ; '/' = help
!byte $BF ; '?' = help
!byte $A0 ; Space = mini attract mode
!byte $89 ; TAB = mini attract mode
!byte $88 ; left arrow = delete (may as well, since
; popular emulators remap this anyway)
!byte $FF ; backspace = delete
!byte $8D ; ENTER = launch current game (if any)
!byte $9B ; Esc = clear input buffer (if any)
; or switch to mega attract mode
InputKeyDispatch
!byte kInputCheat
!byte kInputCredits
!byte kInputHelp
!byte kInputHelp
!byte kInputTab
!byte kInputTab
!byte kInputBack
!byte kInputBack
!byte kInputLaunch
!byte kInputClear
.noKeyMatch
jsr IsSearchKey
!if kInputSearch > 0 {
+HIDE_NEXT_2_BYTES
.foundSearchKey
ldx #kInputSearch
} else {
.foundSearchKey
}
; execution falls through here to .InputDispatch
.InputDispatch
ldy InputDispatchTableLo,x
sty .j+1
ldy InputDispatchTableHi,x
sty .j+2
.j jsr $FDFD ; SMC
bcc .SearchModeInputLoop ; if carry is clear, we're done
; fall through to force full redraw
;------------------------------------------------------------------------------
; SearchMode
; main entry point for Search Mode, which allows the user to search the game
; catalog and launch games
;
; in: none
; out: never returns to caller (may JMP to other major modes)
;------------------------------------------------------------------------------
SearchMode
ldx #$FF
txs
stx gGameToLaunch ; $FFFF = no game selected
stx gGameToLaunch+1
jsr BuildSearchStore
jsr Home ; clear screen (switches to text mode)
stx OffscreenPage ; don't show text page 2 by accident
jsr OnInputChanged ; draw UI offscreen
jsr HGRMode ; show HGR screen
jsr ResyncPage
lda KBD
jsr IsSearchKey
lda CLEARKBD - kInputError,X
; clear strobe if key was bad
.SearchModeInputLoop
jsr WaitForKeyFor30Seconds
; Don't clear keyboard strobe yet. If the user pressed an arrow key,
; we want to switch to Browse Mode with the keyboard still hot so
; that mode finds and dispatches the arrow key.
ldx #kInputBrowse
jsr IsUpDownOrRightArrow
beq .InputDispatch
bit CLEARKBD
ldy #kNumBrowseKeys
- dey
bmi .noKeyMatch
cmp InputKeys,y
bne -
ldx InputKeyDispatch,y
bne .InputDispatch ; always branches
OnClear
ldx #1 ; Esc with input clears the input
ldy InputLength
bne +
jmp CoverFade ; Esc with no input transitions to
; mega attract mode
OnBack
ldx InputLength
beq OnError
+ dex
stx InputLength
bpl OnInputChanged ; always branches
OnTab
jsr AnyGameSelected
bcs OnError
jsr MiniAttractMode
cmp #$8D ; if we exited mini attract mode
bne .req_redraw ; by pressing Enter, launch the game
OnLaunch
ldx gGameToLaunch+1
inx
beq OnError
jsr PlayGame
.req_redraw
sec ; tell caller to redraw UI
rts
OnCheat
dec gGameToLaunch ; force reload (will be reset to correct value in OnInputChanged)
jsr ToggleCheat
beq OnInputChanged ; always branches because Z=1 on exit from ToggleCheat
OnSearch
ldx InputLength
cpx #MaxInputLength
beq OnError
sta InputBuffer,x
inc InputLength
; execution falls through here to OnInputChanged
OnInputChanged
ldx InputLength
bne FindMatchingTitle
; no input, reset params and UI
dex
stx gGameToLaunch ; $FFFF = no game selected
stx gGameToLaunch+1
jsr LoadTitleOffscreen
jmp DrawUIWithoutDots
FindMatchingTitle
jsr SwitchToBank2
jsr EnableAcceleratorAndSwitchToBank1
jsr ResetTextRank
jsr okvs_iter_values ; iterate through all game display names
!word gSearchStore ; and rank them for the best match
!word TextRankCallback ; to the current input buffer
lda MatchCount ; any matches at all?
bne +
; no matches for this input buffer
dec InputLength ; ignore the last key typed
OnError
jsr SwitchToBank2
jsr DisableAcceleratorAndSwitchToBank1
; /!\ execution falls through to SoftBell
;------------------------------------------------------------------------------
; SoftBell
; yell at the user, but, like, gently
;
; in: none
; out: C clear
; Y preserved
; A=0
; X=0
; all flags preserved
;------------------------------------------------------------------------------
SoftBell
ldx #32
- lda #2
jsr WaitForKeyWithTimeout
bit SPEAKER
lda #33
jsr WaitForKeyWithTimeout
bit SPEAKER
dex
bne -
clc
rts
+
lda BestMatchIndex ; check if the new best match is the same
cmp gGameToLaunch ; as the current best match
bne @load
lda BestMatchIndex+1
cmp gGameToLaunch+1
bne @load
jsr ToggleOffscreenPage ; Since we're not loading a new screenshot
; we fake switching the 'offscreen' page
; in order to draw on the visible page.
lda #1
bne @noload ; always branches
@load
+LD16 BestMatchIndex
+ST16 gGameToLaunch
jsr LoadGameTitleOffscreen
lda #0
@noload
sta gDrawingOnscreen ; will minimize flicker in case we're
jsr DrawUI ; drawing directly onscreen
; /!\ execution falls through to ui.animation/MaybeAnimateTitle