-
Notifications
You must be signed in to change notification settings - Fork 13
/
Copy pathhi-scores.asm
310 lines (268 loc) · 6.78 KB
/
hi-scores.asm
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
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
.const TABLE_ENTRIES = 3 // # entries in the table
.const TABLE_NAMELENGTH = 7 // # characters for the name
.const TABLE_SCORELENGTH = 3 // 3 bytes, up to 999999. hardcoded!!
// do NOT change the number of bytes in a score.
.const ENTRY_LENGTH = TABLE_NAMELENGTH + TABLE_SCORELENGTH
// you can have 255 characters in the table. depending on the length of the
// names there is a max to entries. // example: 3+8=11, 255/11= 23 entries
// Entry point.
// this function will look at the score located in new_score
// it will insert a new entry if a hiscore is detected and leave the
// offset to the name inentry_offset
PROCESS_NEW_SCORE:
// start with no hiscore
lda #0
sta new_hiscore
// reset entries counter
lda #1
sta current_entry
// reset table data offset
ldy #0
entry_compare:
// reset byte compare flags for this entry
lda #0
sta compare_flags
sta compare_flags+1
sta compare_flags+2
//reset the compare flag counter
ldx #0
byte_compare_loop:
// check each byte in the new_score with current entry
// set compare flag accordingly
lda new_score,x
cmp hiscore_table_start,y
beq byte_compared // score is same. skip
bpl byte_is_higher // score is higher
dec compare_flags,x // score is lower
jmp byte_compared
byte_is_higher:
inc compare_flags,x
byte_compared:
iny // inc data counter
inx // inc byte counter
cpx #TABLE_SCORELENGTH
bne byte_compare_loop
// lets see if new_score was higher than the table entry
// this is fixed to a score length of 3 bytes !!
lda compare_flags
beq !skip+ // this byte was the same, check next
bpl found_hiscore // higher! :)
jmp no_hiscore // lower :(
!skip:
lda compare_flags+1
beq !skip+ // same, check 3rd byte
bpl found_hiscore // :)
jmp no_hiscore // :(
!skip:
lda compare_flags+2
bmi no_hiscore // last byte is lower. so no new hi
jmp found_hiscore // all 3 digits the same or last higher. new hiscore!
no_hiscore:
// new_score was lower than this entry.
// check the rest of the entries if not yet all done.
inc current_entry
ldx current_entry
cpx #TABLE_ENTRIES+1
beq all_entries_compared // all entries compared
// so no hiscore at all! exit
// goto start of next table entry
// ldx current_entry
jsr GET_ENTRY_OFFSET // this uses X register.
ldy entry_offset // get offset to beginnig of next entry
jmp entry_compare // do the next entry
all_entries_compared:
rts
found_hiscore:
// hiscore found and its position is in current_entry
// lda current_entry
// save this so input routine can use it for name entry
ldx current_entry
jsr GET_ENTRY_OFFSET
jsr INSERT_HISCORE_ENTRY
// add the score to the entry
ldy entry_offset
lda new_score
sta hiscore_table_start,y
lda new_score+1
sta hiscore_table_start+1,y
lda new_score+2
sta hiscore_table_start+2,y
// clear the name. add dots
ldx #TABLE_NAMELENGTH
lda #$2e
!loop:
sta hiscore_table_start+3,y
iny
dex
bne !loop-
// mark that a new hiscore has been detected at this entry.
lda current_entry
sta new_hiscore
rts
// Entry point.
// set X register to index where you want to insert an entry.
// entries below will be moved down.
// this function will then insert the value in new_score
// into the cleared position and clear the name.
INSERT_HISCORE_ENTRY:
// first we need to move the data down.
// point memory offset to end of table.
ldy #hiscore_table_end - hiscore_table_start
!loop:
// move data until we're on the wanted offset.
lda hiscore_table_start - ENTRY_LENGTH,y
sta hiscore_table_start,y
dey
cpy entry_offset
bpl !loop- // keep going
clear_entry:
ldy entry_offset
lda #$01
ldx #0
!loop:
sta hiscore_table_start,y
iny
inx
cpx #ENTRY_LENGTH
bne !loop-
!exit:
rts
// ------------------------------------------
// calculate the offset to required entry.
// X register must be set to the entry #.
// new offset is stored in entry_offset
GET_ENTRY_OFFSET:
lda #0
!loop:
dex
beq !done+
clc
adc #ENTRY_LENGTH
jmp !loop-
!done:
sta entry_offset
rts
// ------------------------------------------
// set x and y to the position you want to draw the table
// x register : yposition
// y register: xposition
PRINT_HISCORE_TABLE:
// save coordinates
stx hiscore_table_position
sty hiscore_table_position+1
// place cursor
clc
jsr PLOT
// reset the entries done counter
lda #1
sta current_entry
// reset data offset
ldy #0
print_table_entry:
ldx #TABLE_SCORELENGTH // this amount of bytes in score
!loop:
lda hiscore_table_start, y
pha // store value
lsr // shift right 4 times
lsr
lsr
lsr
clc
adc #$30 // add $30 to get a screen code
jsr PRINT // print it
pla // retrieve original value
and #%00001111 // get rid of leftmost bits
clc
adc #$30
jsr PRINT
iny
dex // dec number counter
bne !loop-
// add a space
lda #$20
jsr PRINT
// print the name
ldx #TABLE_NAMELENGTH
!loop:
lda hiscore_table_start,y
jsr PRINT
iny
dex
bne !loop-
// all entries done?
lda current_entry
cmp #TABLE_ENTRIES
beq !exit+
// get ready for next entry
inc current_entry
// save memory pointer. we need the y register
tya
pha
// go one line down
inc hiscore_table_position
// position cursor
ldx hiscore_table_position
ldy hiscore_table_position+1
clc
jsr PLOT
// restore memory pointer
pla
tay
jmp print_table_entry
!exit:
rts
// -------------------------------------------
// resets the hiscore table with the default entries
RESET_HISCORE_TABLE:
lda #TABLE_ENTRIES
sta current_entry
ldx #0
start_entry_reset:
ldy #0
!loop:
lda default_table_entry,y
sta hiscore_table_start,x
inx
iny
cpy #ENTRY_LENGTH
bne !loop-
dec current_entry
bne start_entry_reset
!exit:
rts
// ------ data -------------------------------------------------------------
// flags for each byte in the score
// 0 means the byte in new score is the same as the checked hiscore
// 1 means the byte in new score is higher than the checked hiscore
// -1 means the byte in new score is lower than the checked hiscore
compare_flags:
.fill TABLE_SCORELENGTH, 0
// new score needs to stored here, msB first.
new_score:
.fill TABLE_SCORELENGTH, 0
// new score needs to be inserted on this position in the list
// is also used as a flag to indicate if a hiscore has been found
new_hiscore:
.byte 0
// offset pointer, used by INSERT_ENTRY
// offset is counted from hiscore_table_start
entry_offset:
.byte 0
// counter for RESET_HISCORES_TABLE and PRINT_HISCORE_TABLE
current_entry:
.byte 0
// x and y positions for PRINT_HISCORE_TABLE
hiscore_table_position:
.byte 0,0
// the default entry.
default_table_entry:
.byte $00,$00,$00 // ,$12,$06
.text "WDWBEST"
// -------- 8 chars
// the hiscore table itself
// labels can be used to load and save memory from/to disk
hiscore_table_start:
.fill ENTRY_LENGTH*TABLE_ENTRIES, 0
hiscore_table_end:
// buffer area for moving data.
.fill ENTRY_LENGTH, 0