4cade/src/ui.search.mode.a
2019-10-03 16:20:18 -04:00

259 lines
8.0 KiB
Plaintext

;license:MIT
;(c) 2018-9 by 4am
;
; Search Mode - main UI
;
; Public functions
; - SearchMode
; - IsSearchKey
;
.noKeyMatch
jsr IsSearchKey
beq .foundSearchKey
ldx #kInputError
+HIDE_NEXT_2_BYTES
.foundSearchKey
ldx #kInputSearch
; execution falls through here
.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 ; $FF = no game selected
jsr Home ; clear screen (switches to text mode)
jsr OnInputChanged ; draw UI offscreen
jsr HGRMode ; show HGR screen
jsr ResyncPage
lda KBD
jsr IsSearchKey
beq .SearchModeInputLoop
bit CLEARKBD
.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.
jsr IsUpDownOrRightArrow
bne @notArrow
ldx #kInputBrowse
bne .InputDispatch ; always branches
@notArrow
bit CLEARKBD
ldy #kNumBrowseKeys
- dey
bmi .noKeyMatch
cmp InputKeys,y
bne -
ldx InputKeyDispatch,y
bne .InputDispatch ; always branches
OnClear
ldx InputLength
bne +
jmp CoverFade ; Esc with no input transitions to
; mega attract mode
OnBack
ldx InputLength
beq OnError
+HIDE_NEXT_2_BYTES
+ ldx #1 ; Esc with input clears the input
dex
stx InputLength
bpl OnInputChanged ; always branches
OnTab
ldx gGameToLaunch
cpx #$FF
beq OnError
jsr MiniAttractMode
cmp #$8D ; if we exited mini attract mode
bne .req_redraw ; by pressing Enter, launch the game
OnLaunch
ldx gGameToLaunch
cpx #$FF
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
OnInputChanged
lda InputLength
bne @findMatchingTitle
; no input, reset params and UI
ldx #$FF
stx gGameToLaunch ; no game selected
jsr LoadTitleOffscreen
jsr DrawUIWithoutDots
clc
rts
@findMatchingTitle
jsr ResetTextRank
jsr okvs_iter_values ; iterate through all game titles
!word gGamesListStore ; 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
jmp SoftBell ; Beep on invalid input and start over.
+
ldx BestMatchIndex ; check if the new best match is the same
cpx gGameToLaunch ; as the current best match
stx gGameToLaunch
bne +
jsr ToggleOffscreenPage ; Since we're not loading a new screenshot
; we fake switching the 'offscreen' page
; in order to draw on the visible page.
bpl @noload ; (always branches)
+ jsr LoadGameTitleOffscreen
@noload jsr DrawUI
jsr MaybeAnimateTitle
clc
rts
;------------------------------------------------------------------------------
; IsSearchKey
; test whether accumulator contains a key that might trigger a new textrank
; search
;
; in: A = key
; out: A &= 0x7F
; Y preserved
; X clobbered
; Z = 1 if this is a search key
; Z = 0 if this is not a search key
;------------------------------------------------------------------------------
IsSearchKey
and #$7F ; strip high bit for search characters
cmp #$30 ; control keys and punctuation ignored
bcc @badkey
cmp #$3A ; numbers are good input
bcc @goodkey
cmp #$41 ; more punctuation (also ignored)
bcc @badkey
cmp #$5B ; uppercase letters are good input
bcs +
ora #$20 ; convert uppercase letters to lowercase
@goodkey
ldx #0
rts
+ cmp #$61 ; more punctuation (also ignored)
bcc @badkey
cmp #$7B ; lowercase letters are good input
bcc @goodkey
@badkey
ldx #1
rts
IsUpDownOrRightArrow
cmp #$8B ; up arrow
beq @done
cmp #$95 ; right arrow
beq @done
cmp #$8A ; down arrow
@done rts
; 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 $A6 ; '&' = credits
!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