-
Notifications
You must be signed in to change notification settings - Fork 2
/
textrank.a
239 lines (230 loc) · 6.17 KB
/
textrank.a
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
;license:MIT
;(c) 2018-2020 by 4am & qkumba
;
; text rank - an implementation of the Quicksilver search rank algorithm
;
; Public functions
; - ReloadSearchIndex
; - ResetTextRank
; - FindTitleInCache
; - 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
;
; Zero page variables
; - 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 " "
;------------------------------------------------------------------------------
; ReloadSearchIndex
;
; Load indexes to support search UI
;
; in: none
; out: gSearchStore populated
;------------------------------------------------------------------------------
ReloadSearchIndex
jsr LoadIndexedFile ; load appropriate search cache into $B000
!word gSearchCache
!word kSearchCacheRecord
ReloadSearchIndexOnly
jsr LoadIndexedFile ; load appropriate search index into $6000
SearchIndexHandle
!word gSearchIndex
!word kSearchIndexRecord
rts
FindTitleInCache
ldx InputLength
cpx #5
bcs @nomatch
lda #$20
sta InputBuffer, x
+LDADDR gSearchCache
+ST16 PTR
ldx #$FF
-- inx
ldy #0
- lda (PTR), y
beq @nomatch
cmp InputBuffer, x
beq @matchchar
iny
iny
iny
bne - ; always branches
@matchchar
iny
lda (PTR), y
pha
iny
lda (PTR), y
bpl @foundindex
sta PTR+1
pla
sta PTR
cpx InputLength
bcc --
@nomatch
sec
rts
@foundindex
sta BestMatchIndex+1
pla
sta BestMatchIndex
clc
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
tax
dex
cpx InputLength
bcc ++
sta gamelength
sty runningscore
sty runningscore+1
iny
sty startat
- sty i
lda (zpword),y
jsr tolower
sta tmp
ldy startat
-- lda (zpstring),y
jsr tolower
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
adc #0 ; round fractions up
pha
ldy #1
lda (zpstring),y
jsr tolower
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
tolower
cmp #$41
bcc +
cmp #$5B
bcs +
ora #$20
+ rts