;license:MIT ;(c) 2018-9 by 4am & qkumba ; ; text rank - an implementation of the Quicksilver search rank algorithm ; ; Public functions ; - BuildSearchStore ; - ResetTextRank ; - TextRankCallback (as okvs_iter_values callback) ; ; Public variables ; - InputLength ; [byte] number of characters typed in search mode ; - InputBuffer ; [25 bytes] characters typed in search mode ; - SelectedIndex ; [byte] index in gSearchStore of currently selected game in search mode ; - MatchCount ; [byte] number of games that match InputBuffer ; - BestMatchScore ; [byte] raw ranking score (0-100) of current best match (updated during TextRankCallback) ; - BestMatchIndex ; [byte] index in gSearchStore of current best match (updated during TextRankCallback) MaxInputLength = 26 InputLength !byte 0 InputBuffer !text " " BuildSearchStore jsr SwitchToBank2 jsr EnableAcceleratorAndSwitchToBank1 +LDADDR gSearchStore jsr okvs_init jsr okvs_iter !word gGamesListStore !word @callback jsr SwitchToBank2 jmp DisableAcceleratorAndSwitchToBank1 @callback ; callback called by okvs_iter on gGamesListStore ; in: A/Y contains address of filename ; $WINDEX contains 0-based index of the current record in gGamesListStore (word) ; out: all registers and flags clobbered +ST16 @key jsr GetGameDisplayName +ST16 @value @append jsr okvs_append !word gSearchStore @key !word $FDFD ; SMC @value !word $FDFD ; SMC !byte 0 rts ;------------------------------------------------------------------------------ ; ResetTextRank ; reset the Match variables to allow re-scanning (e.g. because of backspace) ; in: nothing ; out: X, MatchCount, BestMatchScore, BestMatchIndex zeroed ;------------------------------------------------------------------------------ ResetTextRank ldx #0 stx MatchCount stx BestMatchScore dex stx BestMatchIndex stx BestMatchIndex+1 rts ;------------------------------------------------------------------------------ ; TextRankCallback ; callback called by okvs_iter_values on gSearchStore ; to calculate a ranking score for a single game display name ; against the current InputBuffer ; in: A/Y contains address of game display name ; $WINDEX contains 0-based index of the current record in gSearchStore (word) ; out: all registers and flags clobbered ; MatchCount possibly incremented (if this game was a match at all) ; BestMatchScore and BestMatchIndex possibly updated (if this game ; was the best match so far) ;------------------------------------------------------------------------------ TextRankCallback +ST16 zpstring ; A/Y = address of this game display name +LDADDR InputLength +ST16 zpword ldy #0 lda (zpstring),y sec sbc #1 cmp InputLength bcc ++ sta gamelength sty runningscore sty runningscore+1 iny 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 + tya ldy i cpy InputLength bcs + iny sta startat inc startat cmp gamelength bcc - rts ; no match :( + 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 +LOW_ASCII_TO_LOWER sta firstletter pla ldx InputBuffer cpx firstletter bne + cmp #85 bcs + adc #15 + cmp BestMatchScore bcc + beq + sta BestMatchScore lda WINDEX sta BestMatchIndex lda WINDEX+1 sta BestMatchIndex+1 inc MatchCount + rts @div sta num1 stx num1+1 sty num2 lda #0 sta remainder sta remainder+1 ldx #16 - asl num1 rol num1+1 rol remainder rol remainder+1 lda remainder sec sbc num2 bcc + sta remainder dec remainder+1 inc num1 + dex bne - lda num1 rts