-
Notifications
You must be signed in to change notification settings - Fork 2
/
QBOOT.S
422 lines (391 loc) · 9.17 KB
/
QBOOT.S
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
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
;fast seek/multi-read
;copyright (c) Peter Ferrie 2015-16
;assemble using ACME
!cpu 6502
!to "qboot",plain
*=$800
sectors = $d1 ;user-defined
firsttrk = $d1 ;user-defined, first track to read
firstsec = $d1 ;user-defined, first sector to read
address = $d1 ;user-defined
entry = $d1d1 ;user-defined
zpread = 0 ;set to 1 to allow reading into zero page
;relies on memory wraparound, not supported on IIGS
;also precludes reading to page $FF
stkread = 0 ;set to 1 to allow reading into stack page
;but remember about the 6 bytes of stack
seekback = 0 ;set to 1 to enable seek backwards
version = 1
;memory usage:
;256 bytes ($bd00-bdff) static table
grouped = $bd00
;106 bytes ($xx00-xx69) static table
preshift = code_end
zvalue = $fd ;only during init
znibble = $fe ;only during init
zmask = $ff ;only during init
!byte 1 ;we'll read the other two ourselves
lsr ;check sector number
;the following TAY is a workaround for a CFFA bug
;the bug is that Y isn't zero on entry
;the workaround sets it to two instead
;it's not zero, but it's better than #$10
tay
adc #$bd
sta $27 ;set or update address as needed
asl
bmi + ;branch if not 3
inc $3d ;increment sector (faster to find)
txa
lsr
lsr
lsr
lsr
ora #$c0 ;slot to PROM base
pha
lda #$5b ;read-1
pha
rts
+ txa
ora #$8c ;slot to Q6L
- iny
ldx patchtbl-3, y
sta code_begin, x ;replace placeholders with Q6L
bne -
and #$f8 ;MOTOROFF
sta slotpatch7+1
eor #8 ;PHASEOFF
sta slotpatch8+1
ldx #$3f
stx zmask
inx
ldy #$7f
bne + ;branch always
*=$839
lda #>(entry-1)
pha
lda #<(entry-1)
pha
jsr preread
jmp $bf00 ;DOS 3.3 launcher entrypoint
patchtbl
!byte <(slotpatch1+1), <(slotpatch2+1), <(slotpatch3+1), <(slotpatch4+1), <(slotpatch5+1), <(slotpatch6+1)
indextbl ;the 0 also terminates the patchtbl list!
!byte 0, 2, 1, 3
;construct denibbilisation table
;pre-shifted for interleave read
+
-- sty znibble
tya
asl
bit znibble
beq +
ora znibble
eor #$ff
and #$7e
- bcs +
lsr
bne -
dex
txa
asl
asl
sta preshift-$16, y
+ dey
bne --
;construct 2-bit group table
sty zvalue
-- lsr zmask
lsr zmask
- lda indextbl, x
sta grouped, y
inc zvalue
lda zvalue
and zmask
bne +
inx
txa
and #3
tax
+ iny
iny
iny
iny
cpy #3
bcs -
iny
cpy #3
bcc --
lda #>(entry-1)
pha
lda #<(entry-1)
pha
jsr preread
!if seekback { ;no room to do this in the routine
sty startsec+1
sta tmpadr+1
stx total+1
}
jmp seekread
preread
;copy post-read if necessary
;push post-read address here
; pla
; tax
; pla
; tay
; lda #>(postread-1)
; pha
; lda #<(postread-1)
; pha
; tya
; pha
; txa
; pha
lda #<(firsttrk*2)
sta phase+1
ldx #sectors
lda #address
ldy #firstsec
rts
*=$8fe
!byte $be, 1
;the following lives on sectors $0E and $0D
!pseudopc $be00 {
code_begin
!byte version
readnib
slotpatch1
- lda $c0d1
bpl -
rts
;fill address array for one track
seekread
!if seekback=0 {
sty startsec+1
sta tmpadr+1
stx total+1
}
inittrk
sec
lda #$10
sbc startsec+1
cmp total+1
bcs +
tax
+ stx partial1
stx partial2
jsr seek
startsec
ldy #$d1
!if zpread {
inc tmpadr+1
}
tmpadr
- lda #$d1
sta addrtbl, y
!if !zpread {
inc tmpadr+1
}
iny
dec partial1
bne -
read
-- jsr readnib
- cmp #$d5
bne --
jsr readnib
cmp #$aa
bne -
tay ;we need Y=#$AA later
jsr readnib
eor #$ad ;zero A if match
beq check_mode
;if not #$AD, then #$96 is assumed
ldy #2 ;volume, track, sector
- jsr readnib
rol ;set carry
sta sector+1
jsr readnib
and sector+1
dey
bpl -
tay
ldx addrtbl, y ;fetch corresponding address
beq read
sta sector+1 ;store index for later
!if zpread {
stx adrpatch9+2
dex
}
stx adrpatch1+2
stx adrpatch8+2
stx adrpatch2+2
stx adrpatch3+2
stx adrpatch5+2
stx adrpatch7+2
!if !zpread {
inx
stx adrpatch9+2
dex
}
dex
stx adrpatch4+2
stx adrpatch6+2
!if stkread {
inx
!if zpread {
inx
}
}
ldy #$fe
adrpatch1
- lda $d102, y
pha
iny
bne -
branch_read
bcs read ;branch always
check_mode
cpx #0
beq read ;loop if not expecting #$AD
-- sta tmpval+1 ;zero rolling checksum
slotpatch2
- ldx $c0d1
bpl -
lda preshift-$96, x
adrpatch2
sta $d102, y ;store 2-bit array
tmpval
eor #$d1
iny
bne --
ldy #$aa
slotpatch3
- ldx $c0d1
bpl -
eor preshift-$96, x
adrpatch3
ldx $d102, y ;bit2tbl
eor grouped+2, x ;first 86 nibbles use group bits 0-1
adrpatch4
sta $d156, y
iny
bne -
and #$fc
ldy #$aa
slotpatch4
- ldx $c0d1
bpl -
eor preshift-$96, x
adrpatch5
ldx $d102, y ;bit2tbl
eor grouped+1, x ;second 86 nibbles use group bits 2-3
adrpatch6
sta $d1ac, y
iny
bne -
and #$fc
ldx #$ac
slotpatch5
- ldy $c0d1
bpl -
eor preshift-$96, y
adrpatch7
ldy $d100, x ;bit2tbl
eor grouped, y ;last 84 nibbles use group bits 4-5
adrpatch8
sta $d100, x
inx
bne -
and #$fc
slotpatch6
- ldy $c0d1
bpl -
eor preshift-$96, y
cmp #1 ;carry = !zero
ldy #1
- pla
adrpatch9
sta $d100, y
dey
bpl -
branch_read2
bcs branch_read ;branch if checksum failure
sector
ldy #$d1
txa
sta addrtbl, y ;zero corresponding address
dec total+1
dec partial2 ;adjust remaining count (faster than looping over array)
sec
bne branch_read2 ;read all requested sectors in one track
total
ldx #$d1
beq driveoff
inc phase+1
inc phase+1 ;update current track
jmp inittrk
driveoff
slotpatch7
lda $c0d1
seekret
rts
seek
lda #0
sta step+1
copy_cur
curtrk
lda #0
sta tmpval+1
sec
phase
sbc #$d1
beq seekret
!if seekback {
bcs +
}
eor #$ff
inc curtrk+1
!if seekback {
bcc ++
+ adc #$fe
dec curtrk+1
++
}
cmp step+1
bcc +
step
lda #$d1
+ cmp #8
bcs +
tay
sec
+ lda curtrk+1
ldx step1, y
bne +
--- clc
lda tmpval+1
ldx step2, y
+ stx sector+1
and #3
rol
tax
slotpatch8
sta $c0d1, x
-- ldx #$13
- dex
bne -
dec sector+1
bne --
lsr
bcs ---
inc step+1
bne copy_cur
step1 !byte 1, $30, $28, $24, $20, $1e, $1d, $1c
step2 !byte $70, $2c, $26, $22, $1f, $1e, $1d, $1c
addrtbl !fill 16
partial1 = *
partial2 = partial1+1
code_end=partial2+1
}