WIP search mode

This commit is contained in:
4am 2019-06-18 14:56:05 -04:00
parent 007c25bd44
commit cd689703a6
87 changed files with 401 additions and 85 deletions

View File

@ -101,9 +101,9 @@ dsk: md asm
rsync -aP res/fx/* build/FX >>build/log rsync -aP res/fx/* build/FX >>build/log
$(CADIUS) ADDFOLDER build/"$(DISK)" "/${VOLUME}/FX" "build/FX" >>build/log $(CADIUS) ADDFOLDER build/"$(DISK)" "/${VOLUME}/FX" "build/FX" >>build/log
$(CADIUS) CREATEFOLDER build/"$(DISK)" "/${VOLUME}/X/" >>build/log $(CADIUS) CREATEFOLDER build/"$(DISK)" "/${VOLUME}/X/" >>build/log
bin/do2po.py res/dsk/ build/po/ # bin/do2po.py res/dsk/ build/po/
rsync -a res/dsk/*.po build/po/ # rsync -a res/dsk/*.po build/po/
bin/extract.py build/po/ | sh >>build/log # bin/extract.py build/po/ | sh >>build/log
rm -f build/X/**/.DS_Store rm -f build/X/**/.DS_Store
rm -f build/X/**/PRODOS rm -f build/X/**/PRODOS
rm -f build/X/**/LOADER.SYSTEM rm -f build/X/**/LOADER.SYSTEM

Binary file not shown.

View File

@ -45,7 +45,8 @@ Main
jsr Play jsr Play
+ +
bit $C010 bit $C010
jsr AttractMode ; jsr AttractMode
jsr SearchMode
jmp @loop jmp @loop
; these routines will only be called after relocating to language card ; these routines will only be called after relocating to language card
@ -59,6 +60,7 @@ Main
!source "src/glue.prorwts2.a" !source "src/glue.prorwts2.a"
!source "src/okvs.a" !source "src/okvs.a"
!source "src/wait.a" !source "src/wait.a"
!source "src/textrank.a"
!source "src/parse.common.a" !source "src/parse.common.a"
!source "src/parse.prefs.a" !source "src/parse.prefs.a"
!source "src/parse.games.a" !source "src/parse.games.a"

View File

@ -108,3 +108,12 @@
jsr LoadFile jsr LoadFile
!word gPathname !word gPathname
} }
!macro LOW_ASCII_TO_LOWER {
cmp #$41
bcc +
cmp #$5B
bcs +
ora #$20
+
}

181
src/textrank.a Normal file
View File

@ -0,0 +1,181 @@
;license:MIT
;(c) 2018 by 4am
;
; text rank - an implementation of the Quicksilver search rank algorithm
;
; Public functions
; - TextRankCallback (as okvs_iter_values callback)
;
; Public variables
; - InputLength
; - InputBuffer
; - SelectedIndex
; - MatchCount
; - BestMatchScore
; - BestMatchIndex
zpword = $F0 ; word
zpstring = $F2 ; word
runningscore= $F4 ; word
startat = $F6 ; byte
i = $F7 ; byte
tmp = $F8 ; byte
gamelength= $F9 ; byte
firstletter= $FA ; byte
MaxInputLength = 24
InputLength
!byte 0
InputBuffer
!text " "
SelectedIndex
!byte $FF
MatchCount
!byte 0
BestMatchScore
!byte 0
BestMatchIndex
!byte 0
;------------------------------------------------------------------------------
; TextRankCallback
; callback called by okvs_iter_values on gGamesListStore
; to calculate a ranking score for a single game title
; against the current InputBuffer
; in: A/Y contains address of game title
; X contains 0-based index of the current record in gGamesListStore
; out: all registers and flags clobbered
; MatchCount possibly incremented (if this title was a match at all)
; BestMatchScore and BestMatchIndex possibly updated (if this title
; was the best match so far)
;------------------------------------------------------------------------------
TextRankCallback
stx @tmpx ; X = OKVS index of this title
+STAY zpstring ; A/Y = address of this title
+LDADDR InputLength
+STAY zpword
; ldy #0 ; first we'll check for an exact match
; lda (zpstring),y ; check length of this title against the input buffer
; sta gamelength
; cmp InputLength
; bne + ; not equal, so can't be an exact match
; tay ; check for exact match
;- lda (zpword),y
; cmp (zpstring),y
; bne + ; nope, not an exact match
; dey
; bne -
; inc MatchCount
; lda #100 ; maximum possible score
; sta BestMatchScore
; ldx @tmpx ; save this game as the best match
; stx BestMatchIndex
; rts
;+
lda #0
sta runningscore
sta runningscore+1
ldy #1
sty startat
- sty i
lda (zpword),y
+LOW_ASCII_TO_LOWER
sta tmp
ldy startat
-- lda (zpstring),y
+LOW_ASCII_TO_LOWER
cmp tmp
beq +
cpy gamelength
iny
bcc --
rts ; no match :(
+
ldx #80
cpy startat
beq +
ldx #10
cpy #1
beq +
dey
lda (zpstring),y
iny
cmp #' '
bne +
ldx #90
+ txa
clc
adc runningscore
sta runningscore
bcc +
inc runningscore+1
+ iny
sty startat
ldy i
cpy InputLength
iny
bcc -
lda runningscore
ldx runningscore+1
ldy gamelength
jsr @div
sta tmp
lda runningscore
ldx runningscore+1
ldy InputLength
jsr @div
clc
adc tmp
lsr
pha
ldy #1
lda (zpstring),y
sta firstletter
pla
ldx InputBuffer
cpx firstletter
bne +
cmp #85
bcs +
adc #15
+
cmp BestMatchScore
bcc +
sta BestMatchScore
ldx @tmpx
stx BestMatchIndex
inc MatchCount
+
rts
@div
sta @num1
stx @num1+1
sty @num2
lda #0
sta @rem
sta @rem+1
ldx #16
- asl @num1
rol @num1+1
rol @rem
rol @rem+1
lda @rem
sec
sbc @num2
bcc +
sta @rem
dec @rem+1
inc @num1
+ dex
bne -
lda @num1
rts
@rem !word 0
@num1 !word 0
@num2 !byte 0
@tmpx !byte $FD

View File

@ -7,61 +7,157 @@
; - SearchMode ; - SearchMode
; ;
MaxInputLength = 24 ; indices into InputDispatchTable
kInputBackspace= 1
kInputEnter = 2
kInputSearchKey= 3
InputDispatchTable
!word 0
!word OnBackspace
!word OnEnter
!word OnKey
SearchMode SearchMode
jsr Home ; switches to text mode jsr Home ; switches to text mode
jsr LoadFile ; load initial background at $2000 lda #0
sta InputLength
jsr OnInputChanged
bit $C054 ; show it
bit $C052
bit $C057
bit $C050
bit $C010
InputLoop
- lda $C000
bpl -
bit $C010
and #$7F
cmp #$7F ; delete key
bne +
- ldx #kInputBackspace
bne InputDispatch ; always branches
+ cmp #$08 ; left arrow = delete
beq -
cmp #$0D ; ENTER launches the current game (if any)
bne +
ldx #kInputEnter
bne InputDispatch ; always branches
+
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
bne @goodkey ; always branches
+ cmp #$61 ; more punctuation (also ignored)
bcc @badkey
cmp #$7B ; lowercase letters are good input
bcc @goodkey
; execution falls through here
@badkey
jsr SoftBell ; beep on invalid input
jmp InputLoop ; and start over
@goodkey
ldx #kInputSearchKey
; execution falls through here
InputDispatch
pha ; save key pressed
txa
asl
tax
lda InputDispatchTable,x
sta @j+1
lda InputDispatchTable+1,x
sta @j+2
pla ; restore key pressed
@j jsr $FDFD ; SMC
jmp InputLoop
OnBackspace
ldx InputLength
bne +
jsr SoftBell
rts
+ dec InputLength
jmp OnInputChanged
OnEnter
; TODO
jmp $ff59
OnKey
ldx InputLength
cpx #MaxInputLength
bne +
jsr SoftBell
rts
+ sta InputBuffer,x
inc InputLength
; execution falls through here
OnInputChanged
lda InputLength
bne @findMatchingTitle
; no input, reset params and UI
lda #$FF
sta SelectedIndex ; reset selected index
ldy #MaxInputLength ; clear visible search bar
lda #" "
- sta UILine2+1,y
dey
bne -
lda #$7F
sta UILine2+1
jsr LoadFile ; load default background at $2000
!word Cover !word Cover
lda #22 ; draw search UI on top of background lda #22 ; draw visible search bar
sta VTAB sta VTAB
clc ; draw on page 1 clc ; on page 1
+LDADDR UILine1 +LDADDR UILine1
jsr Draw40Chars jsr Draw40Chars
clc clc
+LDADDR UILine2 +LDADDR UILine2
jsr Draw40Chars jmp Draw40Chars
bit $c054 ; show it @findMatchingTitle
bit $c052 lda #0 ; reset match count
bit $c057 sta MatchCount ; TextRankCallback will increment this if
bit $c050 ; there are any matches
@loop
bit $c010
- lda $c000
bpl -
ldx InputLength
cpx MaxInputLength
beq @loop
sta InputBuffer,x
inc InputLength
jsr OnInputChanged
jmp @loop
OnInputChanged
lda #0
sta MatchCount
jsr okvs_iter_values jsr okvs_iter_values
!word gGamesListStore !word gGamesListStore
!word RankSearchResult !word TextRankCallback
lda MatchCount
beq @nomatches
lda MatchCount ; check match count
bne @yeschange
jsr SoftBell ; no matches for this input buffer, beep
dec InputLength ; and ignore the last key typed
@nochange
rts
@yeschange
lda BestMatchIndex lda BestMatchIndex
cmp SelectedIndex cmp SelectedIndex ; we found a 'new' best match but it's the
beq @nochange beq @nochange ; same as the current match, so we're done
; TODO re-highlight here
sta SelectedIndex sta SelectedIndex ; we have a new best match, so load the
sta @index sta @index ; new title screenshot and display the
jsr okvs_nth jsr okvs_nth ; new game title in the search bar
!word gGamesListStore !word gGamesListStore
@index !byte $FD @index !byte $FD
+STAY @key +STAY @key
@ -72,58 +168,88 @@ OnInputChanged
jsr okvs_get jsr okvs_get
!word gGamesListStore !word gGamesListStore
@key !word $FDFD @key !word $FDFD
; TODO A/Y points to visible title string now +STAY SRC ; A/Y points to game title (in OKVS)
ldy #0 ; copy game title into search bar buffer
lda (SRC),y
sta SAVE ; game title length
inc SAVE
- iny
cpy SAVE
bcc +
lda #" "
+HIDE_NEXT_2_BYTES
+ lda (SRC),y
sta UILine2,y
cpy #MaxInputLength+1
bcc -
@nochange lda #22 ; draw search bar
; TODO sta VTAB
clc sec ; on page 2, not currently visible
rts +LDADDR UILine1
@nomatches jsr Draw40Chars
; TODO
sec sec
+LDADDR UILine2
jsr Draw40Chars
bit $C055 ; show page 2
ldx #$20 ; copy back to page 1
stx @b+2 ; TODO delete this and use LoadFileAt
lda #$40 ; to load title screenshots on different
sta @a+2 ; pages
ldy #0
@a lda $4000,y
@b sta $2000,y
iny
bne @a
inc @a+2
inc @b+2
dex
bne @a
bit $C054 ; show page 1
rts rts
RankSearchResult ;------------------------------------------------------------------------------
zpword = $0 ; SoftBell
zpstring = $2 ;
runningscore = $4 ; in: none
startat = $6 ; out: all registers and flags preserved
i = $7 ;------------------------------------------------------------------------------
tmp = $8 SoftBell
stx @tmpx php
+STAY zpstring pha
+LDADDR InputLength txa
+STAY zpword pha
ldy #0 ldx #32
lda (zpstring),y - lda #2
cmp InputLength jsr Wait
bne + bit $C030
- lda (zpword),y lda #33
cmp (zpstring),y jsr Wait
bne + bit $C030
dey dex
bne - bne -
lda #100 pla
tax
pla
plp
rts rts
+
@tmpx !byte $FD Wait ; identical to $FCA8 ROM routine, but ROM is switched out when we need it
sec
-- pha
- sbc #1
bne -
pla
sbc #1
bne --
rts
;------------------------------------------------------------------------------
Cover !byte 5 Cover !byte 5
!text "COVER" !text "COVER"
InputLength
!byte 0
InputBuffer
!text " "
SelectedIndex ; only valid if InputLength > 0
!byte $FF
MatchCount ; only valid during OnInputChanged
!byte 0
BestMatchScore ; only valid during OnInputChanged
!byte 0
BestMatchIndex ; only valid during OnInputChanged, and only if MatchCount > 0
!byte 0
UILine1 UILine1
!byte 0,0,0,0,0,0,0,0,0,0 !byte 0,0,0,0,0,0,0,0,0,0
!byte 0,0,0,0,0,0,0,0,0,0 !byte 0,0,0,0,0,0,0,0,0,0
@ -131,9 +257,7 @@ UILine1
!byte 0,0,0,0,0,0,0,0,0,0 !byte 0,0,0,0,0,0,0,0,0,0
UILine2 UILine2
; !text "0123456789012345678901234567890123456789"
!text "[" !text "["
!byte $7F !byte $7F
; !text "Championship Lode Runner_"
!text " " !text " "
!text "] 000 games" !text "] 000 games"