;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 inx stx OffscreenPage ; $00 = currently showing HGR page 2 jsr Home ; clear screen (switches to text mode) jsr OnInputChanged ; draw UI on HGR page 1 jsr HGRMode ; show HGR screen 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 jmp MaybeAnimateTitle ;------------------------------------------------------------------------------ ; 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 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