OXYGENHUB
◆ main openmsx / Contrib / dmk / READ-DMK.Z80
60.0 KiB · last changed chore(): initial commit 1 month ago source blame history raw
e8555c89 Andy McCall 1
		org	#0100
2
3
		ld	hl,debug_buffer	; circular buffer for debug output
4
		ld	(debug_ptr),hl
5
6
; TODO simplify commandline parsing
7
; parse commandline
8
		ld	hl,#0081
9
parse_loop	ld	a,(hl)
10
		inc	hl
11
		or	a
12
		jp	z,parse_end
13
		cp	13
14
		jp	z,parse_end
15
		cp	' '
16
		jr	z,parse_loop	; skip space
17
		cp	9
18
		jr	z,parse_loop	; skip tab
19
		ld	c,a
20
		and	#df		; to upper case
21
		cp	'D'
22
		jp	z,check_debug
23
		cp	'S'
24
		jp	z,check_s
25
		cp	'T'
26
		jp	nz,unknown_option
27
check_t		ld	a,(hl)
28
		inc	hl
29
		and	#df
30
		cp	'Y'
31
		jp	nz,unknown_option
32
		ld	a,(hl)
33
		inc	hl
34
		and	#df
35
		cp	'P'
36
		jp	nz,unknown_option
37
		ld	a,(hl)
38
		inc	hl
39
		and	#df
40
		cp	'E'
41
		jp	nz,unknown_option
42
		ld	a,(hl)
43
		inc	hl
44
		cp	'='
45
		jp	nz,unknown_option
46
check_type	ld	a,(hl)
47
		inc	hl
48
		and	#df
49
		cp	'P'
50
		jp	z,check_philips
51
		cp	'M'
52
		jr	z,check_microsol
53
		cp	'N'
54
		jp	nz,unknown_option
55
56
check_national	ld	a,(hl)
57
		inc	hl
58
		and	#df
59
		cp	'A'
60
		jp	nz,unknown_option
61
		ld	a,(hl)
62
		inc	hl
63
		and	#df
64
		cp	'T'
65
		jp	nz,unknown_option
66
		ld	a,(hl)
67
		inc	hl
68
		and	#df
69
		cp	'I'
70
		jp	nz,unknown_option
71
		ld	a,(hl)
72
		inc	hl
73
		and	#df
74
		cp	'O'
75
		jp	nz,unknown_option
76
		ld	a,(hl)
77
		inc	hl
78
		and	#df
79
		cp	'N'
80
		jp	nz,unknown_option
81
		ld	a,(hl)
82
		inc	hl
83
		and	#df
84
		cp	'A'
85
		jp	nz,unknown_option
86
		ld	a,(hl)
87
		inc	hl
88
		and	#df
89
		cp	'L'
90
		jp	nz,unknown_option
91
		ld	de,natl_driver
92
		ld	(driver),de
93
		jp	parse_loop
94
95
check_microsol	ld	a,(hl)
96
		inc	hl
97
		and	#df
98
		cp	'I'
99
		jp	nz,unknown_option
100
		ld	a,(hl)
101
		inc	hl
102
		and	#df
103
		cp	'C'
104
		jp	nz,unknown_option
105
		ld	a,(hl)
106
		inc	hl
107
		and	#df
108
		cp	'R'
109
		jp	nz,unknown_option
110
		ld	a,(hl)
111
		inc	hl
112
		and	#df
113
		cp	'O'
114
		jp	nz,unknown_option
115
		ld	a,(hl)
116
		inc	hl
117
		and	#df
118
		cp	'S'
119
		jp	nz,unknown_option
120
		ld	a,(hl)
121
		inc	hl
122
		and	#df
123
		cp	'O'
124
		jp	nz,unknown_option
125
		ld	a,(hl)
126
		inc	hl
127
		and	#df
128
		cp	'L'
129
		jp	nz,unknown_option
130
		ld	de,mics_driver
131
		ld	(driver),de
132
		jp	parse_loop
133
134
check_philips	ld	a,(hl)
135
		inc	hl
136
		and	#df
137
		cp	'H'
138
		jp	nz,unknown_option
139
		ld	a,(hl)
140
		inc	hl
141
		and	#df
142
		cp	'I'
143
		jp	nz,unknown_option
144
		ld	a,(hl)
145
		inc	hl
146
		and	#df
147
		cp	'L'
148
		jp	nz,unknown_option
149
		ld	a,(hl)
150
		inc	hl
151
		and	#df
152
		cp	'I'
153
		jp	nz,unknown_option
154
		ld	a,(hl)
155
		inc	hl
156
		and	#df
157
		cp	'P'
158
		jp	nz,unknown_option
159
		ld	a,(hl)
160
		inc	hl
161
		and	#df
162
		cp	'S'
163
		jp	nz,unknown_option
164
		ld	de,phil_driver
165
		ld	(driver),de
166
		jp	parse_loop
167
168
check_s		ld	a,(hl)
169
		inc	hl
170
		and	#df
171
		cp	'T'
172
		jp	nz,unknown_option
173
		ld	a,(hl)
174
		inc	hl
175
		and	#df
176
		cp	'A'
177
		jr	z,check_start
178
		cp	'O'
179
		jp	nz,unknown_option
180
check_stop	ld	a,(hl)
181
		inc	hl
182
		and	#df
183
		cp	'P'
184
		jp	nz,unknown_option
185
		ld	a,(hl)
186
		inc	hl
187
		cp	'='
188
		jp	nz,unknown_option
189
stop_option	call	parse_dec
190
		ld	(stop_track),a
191
		ld	a,1
192
		ld	(stop_set),a
193
		jp	parse_loop
194
195
check_start	ld	a,(hl)
196
		inc	hl
197
		and	#df
198
		cp	'R'
199
		jp	nz,unknown_option
200
		ld	a,(hl)
201
		inc	hl
202
		and	#df
203
		cp	'T'
204
		jp	nz,unknown_option
205
		ld	a,(hl)
206
		inc	hl
207
		cp	'='
208
		jp	nz,unknown_option
209
start_option	call	parse_dec
210
		ld	(start_track),a
211
		jp	parse_loop
212
213
check_debug	ld	a,(hl)
214
		inc	hl
215
		and	#df
216
		cp	'E'
217
		jp	nz,unknown_option
218
		ld	a,(hl)
219
		inc	hl
220
		and	#df
221
		cp	'B'
222
		jp	nz,unknown_option
223
		ld	a,(hl)
224
		inc	hl
225
		and	#df
226
		cp	'U'
227
		jp	nz,unknown_option
228
		ld	a,(hl)
229
		inc	hl
230
		and	#df
231
		cp	'G'
232
		jp	nz,unknown_option
233
		ld	a,(hl)
234
		inc	hl
235
		cp	'='
236
		jp	nz,unknown_option
237
debug_option	call	parse_dec
238
		ld	(debug),a
239
		jp	parse_loop
240
241
parse_end
242
		; TODO check start_track <= stop_track
243
		;       and both <= 85
244
245
; Select the correct driver routines
246
; For now we only have a driver for Philps machines
247
		ld	hl,(driver)
248
		ld	de,driver_routines
249
		ld	bc,driver_size
250
		ldir
251
252
		ld	a,'S'
253
		call	debug_log
254
		call	print_pc
255
		db	"Read-DMK version 0.42",13,10
256
		db	13,10
257
		db	"Insert source      disk in drive A",13,10
258
		db      "Insert destination disk in drive B",13,10
259
		db      "Press any key to continue ...",0
260
		ld	ix,#009f
261
		ld	iy,(#fcc0)
262
		call	#001c
263
		call	print_pc
264
		db	13,10,13,10,0
265
266
; loop over all cylinders and both sides
267
		ld	a,(start_track)
268
cylinder_loop	ld	(cylinder),a
269
		xor	a
270
side_loop	ld	(side),a	; start at side 0
271
272
; delete debug file, so that we never by accident end up with a leftover
273
; old debug file
274
		ld	de,fcb_debug
275
		ld	c,#13		; delete file
276
		call	#0005
277
278
; Prepare drive:
279
; - select drive, turn motor on
280
; - select side
281
; - seek to correct track
282
		ld	a,'L'
283
		call	debug_log
284
		call	select_fdc
285
		call	seek
286
287
;; TODO currently we always restore the head to track 0 followed by a seek to
288
;; the destination track. I tried to use a 'step-in' command instead, but I
289
;; couldn't get this to work correctly. I suspect it's because I'm using the
290
;; BDOS routines to save a file (although to the B drive) and that interferes
291
;; with the state of the A drive. A possible improvement would be to buffer as
292
;; much data in (v)ram before writing it out to disk. So minimize the number
293
;; of switches between the A and B drives.
294
295
		call	print_pc
296
		db	13,10
297
		db	"Cylinder: ",0
298
		ld	a,(cylinder)
299
		call	print_dec_a
300
		call	print_pc
301
		db	" side: ",0
302
		ld	a,(side)
303
		call	print_dec_a
304
305
		call	select_fdc	; TODO is/was this call still/ever needed?
306
307
308
; Use the "read address" WD2793 command in a loop to read all address marks
309
; on this track. We start this loop right after the index pulse. During the
310
; wait-for-next-byte-loop we also increase a counter, and the value of this
311
; counter is stored together with the read-address-data. This counter value
312
; will later be used to estimate the location of the address mark in the raw
313
; track data.
314
;
315
; We also use this counter to make sure we have read all address marks of the
316
; whole track. Experiments on a real MSX have shown that the counter has
317
; approximately the value 0x38E0 after one revolution (though rotation speed
318
; can vary). We stop the loop after the counter has reached value 0xc000. So
319
; this makes sure we have read each address mark at least 3 times (see below
320
; why this is needed).
321
322
		ld	a,'R'
323
		call	debug_log
324
		xor	a		; for reasons explained below, we
325
		ld	(retries),a	; sometimes need to retry
326
retry		call	print_pc
327
		db	"   (attempt ",0
328
		ld	a,(retries)
329
		inc	a
330
		call	print_dec_a
331
		call	print_pc
332
		db	")",13,10,0
333
334
		xor	a
335
		ld	(addr_retries),a
336
337
do_addr_retry
338
		ld	a,'r'
339
		call	debug_log
340
		call	print_pc
341
		db	"Read addresses ...",0
342
343
		ld	iy,(driver_rd_addr)
344
		jp	(iy)
345
346
addr_error	; 'Record not found' status bit was set. This means there
347
		; wasn't any address mark in this track. This e.g. happens
348
		; if you read the 81th track on a normal disk.
349
		; don't retry on this
350
		jr	skip_addr
351
352
read_addr_err	call	print_pc
353
		db	"Read address command didn't return 6 bytes.",13,10,0
354
355
addr_retry	ld	a,(addr_retries)
356
		inc	a
357
		ld	(addr_retries),a
358
		cp	20
359
		jp	c,do_addr_retry
360
361
		call	print_pc
362
		db	"Couldn't reliably read address marks ... skipped",13,10,0
363
364
skip_addr	ld	de,addr_buffer+1	; as long as it's > addr_buffer
365
		ld	(addr_buf_end),de
366
		ld	hl,0
367
		jr	addr_found
368
369
addr_done	ld	(addr_buf_end),de
370
371
372
; Now each address mark is read for at least 3 full revolutions. Analyze this
373
; data to detect the number of address marks in one revolution. Note that it's
374
; possible a single track contains several identical address marks. So
375
; detecting the number of sectors in the track is not as simple as searching
376
; for the 2nd occurrence of the 1st read address mark.
377
;
378
; Some examples (the latters 'A'-'Z' each represent a unique address mark):
379
; * ABCDEFGHIABCDEFGHIABCDEFGHIABCD
380
;   -> 'normal' track with 9 unique address marks
381
; * ABCDABEABCDABEABCDABEABC
382
;   -> 8 unique address marks, the marks A and B appear twice
383
; * ABCABCABCABCABCABCABCA
384
;   -> the current algorithm detects a track with 3 unique address marks
385
;      so it cannot distinguish the track 'ABC' from 'ABCABC'
386
;      TODO fix this by taking the timing into account
387
;
388
; Note that the detection can fail if we did not read at least 2 full
389
; revolutions. For example, suppose the actual track contains these marks:
390
; 'AAAAAAABAA' (10 unique marks, mark A is duplicated 9 times). Now suppose we
391
; only read 'AAAAAAABAAAAAAA'. Valid periods for this sequence could be 8, 9
392
; or 10. (The current algorithm would return 8). This ambiguity disappears if
393
; we read at least 2 full revolutions.
394
395
		ld	hl,0
396
next_period	ld	ix,(addr_buf_end)
397
		ld	a,ixl
398
		and	7
399
		jp	nz,read_addr_err
400
		ld	de,addr_buffer
401
		call	get_period
402
addr_found	ld	(nb_sectors),hl
403
		; TODO check not more than 64 (DMK cannot handle that)
404
		; if (nb_sectors > 64) error("not supported by dmk");
405
406
		call	print_pc
407
		db	" found ",0
408
		ld	hl,(nb_sectors)
409
		call	print_dec_hl	; TODO print_dec_a
410
		call	print_pc
411
		db	" sectors",13,10,0
412
413
; We now know the period after which the address marks start repeating.
414
; Take the difference of the counter value that was stored at the 1st
415
; and address mark and the 1st replica of this mark.
416
;
417
; This difference should be around 0x38E0 (tested on real machine).
418
; TODO if measured value is far below 0x38E0, try doubling, tripling, ...
419
; until it gets in range.
420
421
		ld	hl,(nb_sectors)
422
		ld	a,h
423
		or	l
424
		jp	z,read_track	; skip ticks-check
425
		add	hl,hl
426
		add	hl,hl
427
		add	hl,hl
428
		ld	de,addr_buffer
429
		add	hl,de
430
		ld	de,(addr_buf_end)
431
		or	a
432
		sbc	hl,de
433
		jr	c,ok_periodic
434
435
		; period is whole buffer -> not periodic
436
		call	print_pc
437
		db	"Not periodic (read noise?)",13,10,0
438
		jp	addr_retry
439
440
ok_periodic	add	hl,de
441
		ld	de,ofst_amark_tick
442
		add	hl,de
443
		ld	a,(hl)
444
		inc	hl
445
		ld	h,(hl)
446
		ld	l,a
447
		ld	de,(addr_buffer+ofst_amark_tick)
448
		or	a
449
		sbc	hl,de
450
		ld	(ticks),hl
451
452
		ld	a,(debug)
453
		or	a
454
		jr	z,debug_2
455
		call	print_pc
456
		db	", ticks: ",0
457
		ld	hl,(ticks)
458
		call	print_dec_hl	; is this info useful?
459
		call	print_pc
460
		db	13,10,0
461
debug_2
462
463
; If there were read errors during the 'read address' command, then it's
464
; possible the detected period is larger than one disk revolution. This for
465
; example happened for the disks of 'New Vision Benelux'.
466
; We read the address marks for about 3 revolutions, but if there was a read
467
; error for e.g. an address mark in the 2nd revolution (so the read address
468
; command didn't return the exact same 6 bytes than for revolution 1 and 3),
469
; then the get_period routine won't detect the true period, but instead it
470
; returns the full 3 revolutions as the period (without internal repetition).
471
; We can detect this error by looking at the detected number of ticks for
472
; the period. If the detected period is for a single revolution, it should
473
; be in range [13834, 15290]. But if it's higher we've probably estimated
474
; more than one revolution.
475
476
; TODO also check for lower than 13834.
477
		ld	hl,(ticks)
478
		ld	de,(ticks_min)	; depends on driver
479
		or	a
480
		sbc	hl,de
481
		jr	c,too_short
482
		add	hl,de
483
		ld	de,(ticks_max)	; depends on driver
484
		or	a
485
		sbc	hl,de
486
		jp	nc,addr_retry	; maybe it works in the next attempt
487
		jr	read_track
488
489
too_short	ld	hl,(nb_sectors)
490
		jp	next_period
491
492
493
; Use the WD2793 "read track" command to get the raw track data.
494
; Also store the number of read bytes. This is the track length.
495
; The 'normal' track length is 6250 bytes, but this can also vary.
496
497
read_track
498
		ld	a,'t'
499
		call	debug_log
500
		call	print_pc
501
		db	"Read track ...",0
502
503
		;; TODO is this call required?
504
		;; Quibus reported a hang during 'Read track' at one point.
505
		;; The LED of drive B was turned on when that happened.
506
		;; The only way I can see how that's possible is that the
507
		;; slot in page was somehow changed. Any other explanations???
508
track_retry	call	select_fdc
509
510
		ld	iy,(driver_rd_trck)
511
		jp	(iy)
512
513
514
track_too_much	call	print_pc
515
		db	"Read track returned too much data",13,10,0
516
		jr	read_track
517
518
track_err	call	print_pc
519
		db	"Read track error",13,10,0
520
		jp	debug_exit
521
track_no_start	call	print_pc
522
		db	"Read track command failed to start!",13,10,0
523
		jp	debug_exit
524
525
track_end
526
		ex	de,hl
527
		ld	(track_stop),hl	; store for later
528
		ld	de,trck_buffer
529
		or	a
530
		sbc	hl,de
531
		ld	(track_len),hl
532
		; TODO check in range [5938, 6562]?
533
		call	print_pc
534
		db	" length: ",0
535
		ld	hl,(track_len)
536
		call	print_dec_hl
537
		call	print_pc
538
		db	13,10,0
539
540
; Quibus reported a hang after the tool printed  "Read track .. length=12438"
541
; So it seemed the FDC somehow missed the index pulse and read the track data
542
; twice. This causes a buffer overflow later in the tool. To workaround this
543
; hardware quirk, we check that the tracklength in in range [5800..6700].
544
; That's +/-5% of the nominal track length.
545
		ld	hl,(track_len)
546
		ld	bc,6700+1
547
		or	a
548
		sbc	hl,bc
549
		jr	nc,wrong_length
550
		ld	hl,(track_len)
551
		ld	bc,5800
552
		or	a
553
		sbc	hl,bc
554
		jr	nc,length_ok
555
556
wrong_length	call	print_pc
557
		db	"Unexpected track length .. retrying ...",0
558
		jp	track_retry
559
560
length_ok
561
562
563
; Calculate the ratio between the number of ticks (the difference in counter
564
; value) and the track length. A typical value for the former is around 14560,
565
; for the latter it's around 6250. So the ratio between the two is smaller
566
; than 1. We calculate this ration as a 0.16-bit fractional number.
567
; Later this ratio will be used to estimate the position of the address marks
568
; in the raw track.
569
570
		ld	hl,(track_len)
571
		ld	bc,(ticks)
572
		call	frac_div
573
		ld	(ratio),de
574
575
576
577
; Copy the track data so that it is twice directly after each other in memory.
578
; This is a cheap way to implement 'circular-reads': on a real disk, if you
579
; read past the end of a track, you simply wrap around to the beginning of the
580
; track. With the copy reads (that only wrap once!) now behave the same.
581
;
582
; Note that the first dozen or so bytes returned by the read track command are
583
; totally unreliable. This is because the FDC has not yet seen any
584
; synchronization marks, so it has no idea which bit in the stream is the first
585
; bit of a byte. For us this is not a big problem because in the code below we
586
; only scan for these synchronization marks.
587
588
		ld	bc,(track_len)
589
		ld	hl,trck_buffer
590
		ld	d,h
591
		ld	e,l
592
		add	hl,bc
593
		ex	de,hl
594
		ldir
595
596
597
; Clear the DMK header. There is room for 64 IDAM entries. Unused position
598
; should contain the value 0x0000.
599
600
		ld	hl,dmk_header
601
		ld	de,dmk_header+1
602
		ld	bc,sizeof_dmk_h-1
603
		ld	(hl),0
604
		ldir
605
606
607
; Later we fill search the position of address and data marks in the raw track
608
; data. Clear that table now. Note that this table partly overlaps with the
609
; addr_buffer (where we stored the result of the "read address" commands).
610
; That's OK, from this point on we only need the first 64 entries from the
611
; that table anymore.
612
613
		ld	hl,offset_buffer
614
		ld	de,offset_buffer+1
615
		ld	bc,sizeof_off_buf-1
616
		ld	(hl),0
617
		ldir
618
619
620
; Now, for each data adress mark (returned by the "read address" command), try
621
; to locate it in the raw track data. For this we use the recorded counter
622
; value for that address mark and the earlier calculated ratio.
623
624
		ld	a,(nb_sectors)
625
		or	a		; if there are no address marks on
626
		jp	z,no_sectors	; this track we're done
627
628
		ld	a,'A'
629
		call	debug_log
630
		ld	a,(debug)
631
		or	a
632
		jr	z,skip_ana_prt
633
		call	print_pc
634
		db	"Analyze raw track ... ",0
635
skip_ana_prt
636
637
		ld	a,(nb_sectors)
638
		ld	hl,offset_buffer  ; store results in this table
639
		ld	(ofst_buf_ptr),hl
640
		ld	hl,addr_buffer
641
642
addr_mark_loop	ld	(sector_cntr),a
643
		ld	(addr_buf_ptr),hl
644
645
		ld	a,(debug)
646
		or	a
647
		jr	z,skip_ana_prt2
648
		push	hl
649
		ld	a,(sector_cntr)
650
		call	print_dec_a
651
		call	print_pc
652
		db	" ",0
653
		pop	hl
654
skip_ana_prt2
655
		ld	a,'a'
656
		call	debug_log
657
658
		ld	de,ofst_amark_tick
659
		add	hl,de
660
		ld	e,(hl)
661
		inc	hl
662
		ld	d,(hl)
663
		ld	bc,(ratio)
664
		call	mul_hi		; hl = (de * bc) >> 16
665
		ld	bc,trck_buffer
666
		add	hl,bc
667
		ld	(addr_estimate),hl
668
669
670
; We can only use this calculated position as a (fairly good) estimate of the
671
; position. The real position can be different for the following reasons:
672
;  - we recorded the counter at the end of the "read address" command, while
673
;    here we're looking for the start of the address mark
674
;  - the counter we've used does not 100% increase with a constant rate (e.g.
675
;    at the end of a command we have to do some extra stuff, and we don't
676
;    increase the counter during that time)
677
;  - the rotation speed (and maybe also the flux density?) is not 100%
678
;    constant
679
; To compensate for this we only use the calculated position as the starting
680
; point for the search. If we don't find the mark at exactly this position, we
681
; try the adjacent few bytes (both up and down). Tests on a real machine have
682
; shown that usually we find the mark withing 2 or 3 bytes from the calculated
683
; position (but here we try up to 5 bytes (up and down) from the calculated
684
; position).
685
; TODO more tests on Quibus machine indicated that (in rare cases?) 5 bytes is
686
; not enough. I've currently increased it up to 20 bytes. But that's most
687
; likely too much (searching too far from the initial position has a risk of
688
; finding a different mark in the wrong position)
689
;
690
; We look for the bytes 0xA1 0xA1 0xFE. The real address mark still has a 3rd
691
; byte 0xA1 in front of this sequence. But tests on a real WD2793 have shown
692
; that this byte is very often read wrong by the "read track" command. (Later
693
; we will correct this so that the data in the DMK file has the correct
694
; sequence A1 A1 A1 FE).
695
;
696
; The disk "Demo Kit Deluxe" has at the start of the track the sequence
697
; "A1 A1 A1 FC" (instead of the usual sequence C2 C2 C2 FC). When doing tests
698
; with this disk on a real machine, we found that the "read address" command
699
; also returns the 6 bytes following the "A1 A1 A1 FC" sequence (the expected
700
; sequence for an address mark is A1 A1 A1 FE). So it seems the WD2793 accepts
701
; both FC and FE in the address mark sequence.
702
703
		ld	de,ofst_tab
704
ofst_next	ld	hl,(addr_estimate) ; restore initial estimate
705
		ld	a,(de)
706
		inc	de
707
		cp	#80
708
		jp	z,ofst_err	; reached the end of the offset table
709
		ld	c,a
710
		ld	a,(de)
711
		inc	de
712
		ld	b,a		; 16-bit offset
713
714
		add	hl,bc		; add offset
715
		ld	a,(hl)
716
		cp	#A1
717
		jr	nz,ofst_next
718
		inc	hl
719
		ld	a,(hl)
720
		cp	#A1
721
		jr	nz,ofst_next
722
		inc	hl
723
		ld	a,(hl)
724
		cp	#FE
725
		jr	z,ofst_1
726
		cp	#FC		; see comments above
727
		jr	nz,ofst_next
728
ofst_1
729
		dec	hl
730
		dec	hl
731
		dec	hl		; points to start of A1 A1 A1 FE sequence
732
		ex	de,hl
733
		ld	hl,(ofst_buf_ptr)
734
		ld	(hl),e
735
		inc	hl
736
		ld	(hl),d		; store location in offset_buffer
737
738
		;;push	de
739
		;;call	print_pc
740
		;;db	" addr_mark=0x",0
741
		;;pop	hl
742
		;;call	print_hex_hl
743
744
; Now verify the CRC of the address mark. We use the data returned by the
745
; "read address" command (not the data in the raw track). If there is a CRC
746
; error we don't need to look for the data mark.
747
;
748
; Alternatively we could use the CRC-error-bit in the WD2793 status register
749
; to see if there was a CRC error. Though I prefered to not do that to keep
750
; the read-all-address-marks loop as fast as possible.
751
;
752
; The CRC value includes the 4 bytes of the address mark header (A1 A1 A1 FE)
753
; and the 4 actual "C H R N" bytes stored in the address.
754
755
		ld	hl,#B230	; precalculated CRC for A1 A1 A1 FE
756
		ld	de,(addr_buf_ptr)
757
		ld	a,(de)		; C
758
		call	crc_byte
759
		inc	de
760
		ld	a,(de)		; H
761
		call	crc_byte
762
		inc	de
763
		ld	a,(de)		; R
764
		call	crc_byte
765
		inc	de
766
		ld	a,(de)		; N
767
		call	crc_byte
768
		inc	de
769
		ld	a,(de)		; CRC (high byte)
770
		cp	h
771
		jr	nz,addr_crc_err
772
		inc	de
773
		ld	a,(de)		; CRC (low byte)
774
		cp	l
775
		jr	nz,addr_crc_err
776
777
		;;call	print_pc
778
		;;db	" CRC-OK",0
779
780
; We found the address mark and it has a valid CRC. Now search for the data
781
; mark. According to the WD2793 datasheet, the data mark should occur within
782
; 43 bytes from (the end of) the address mark.
783
;
784
; A data mark starts with the sequence "A1 A1 A1 FB" (normal data mark) or
785
; "A1 A1 A1 F8" (deleted data mark). But just as for the address mark, the
786
; WD2793 "read track" command cannot reliably read the first A1 byte of this
787
; sequence, so we ignore it while searching.
788
789
		ld	hl,(ofst_buf_ptr)
790
		ld	a,(hl)
791
		inc	hl
792
		ld	h,(hl)
793
		ld	l,a		; hl = start of address mark
794
		ld	de,10-1
795
		add	hl,de		; end of address mark
796
797
		ld	b,43+4		; should find data mark within 43 bytes
798
data_mark_1	dec	b
799
		jp	z,data_err
800
		inc	hl
801
		ld	a,(hl)
802
		cp	#A1
803
		jr	nz,data_mark_1
804
data_mark_2	dec	b
805
		jp	z,data_err
806
		inc	hl
807
		ld	a,(hl)
808
		cp	#A1
809
		jr	nz,data_mark_1
810
data_mark_3	dec	b
811
		jp	z,data_err
812
		inc	hl
813
		ld	a,(hl)		; data mark type (deleted or normal)
814
		cp	#A1
815
		jr	z,data_mark_3
816
		cp	#FB
817
		jr	z,data_mark_found
818
		cp	#F8
819
		jr	nz,data_mark_1
820
data_mark_found
821
		dec	hl
822
		dec	hl
823
		dec	hl		; points to start of A1 A1 A1 FB sequence
824
		ld	de,(track_stop)
825
		or	a
826
		sbc	hl,de
827
		jr	c,data_mark_4
828
		ld	de,trck_buffer
829
data_mark_4	add	hl,de
830
		ex	de,hl
831
		ld	hl,(ofst_buf_ptr)
832
		inc	hl
833
		inc	hl
834
		ld	(hl),e
835
		inc	hl
836
		ld	(hl),d		; data mark offset
837
		inc	hl
838
		ld	(hl),a		; data mark type
839
840
		;;push	af
841
		;;push	de
842
		;;call	print_pc
843
		;;db	" data_mark=0x",0
844
		;;pop	hl
845
		;;call	print_hex_hl
846
		;;call	print_pc
847
		;;db	" type=0x",0
848
		;;pop	af
849
		;;call	print_hex_a
850
851
		jr	next_addr_mark
852
853
addr_crc_err	; address mark had a CRC error (not an error for us)
854
		;;call	print_pc
855
		;;db	" CRC-ERR",0
856
		jr	next_addr_mark
857
858
data_err	; didn't find data mark in time (not an error for us)
859
		;;call	print_pc
860
		;;db	" data mark not found",0
861
		jr	next_addr_mark
862
863
864
; Also locate address and data marks for the other sectors in this track
865
866
next_addr_mark
867
		;;call	print_pc
868
		;;db	13,10,0
869
870
		ld	hl,(ofst_buf_ptr)
871
		ld	de,sizeof_offinfo
872
		add	hl,de
873
		ld	(ofst_buf_ptr),hl
874
		ld	hl,(addr_buf_ptr)
875
		ld	de,sizeof_amark
876
		add	hl,de
877
		ld	a,(sector_cntr)
878
		dec	a
879
		jp	nz,addr_mark_loop
880
881
		ld	a,(debug)
882
		or	a
883
		jr	z,skip_ana_prt3
884
		call	print_pc
885
		db	13,10,0
886
skip_ana_prt3
887
888
; We've located the address and data mark for each sector in the raw track
889
; data. Now start overwriting the sector data in the raw track data with
890
; data from an actual "read sector" command. Do this because tests on a real
891
; WD2793 have shown that the data returned by "read sector" is more reliable
892
; than the same data returned by "read track". This is especially true for a
893
; sector that wrap around the end of the track (so past the index point).
894
895
		ld	a,'S'
896
		call	debug_log
897
		call	print_pc
898
		db	"Read sectors ... ",0
899
900
		ld	hl,sector_buffer
901
		ld	(sector_buf_ptr),hl
902
903
; The appraoch below reads the correct sector data even if there are multiple
904
; sectors with the same ID present in the same track. It works well, but it's
905
; very slow (see below for details about the used approach). It can take 45
906
; minutes to dump a whole disk using this appraoch!
907
; In the majority of the cases the track does not have duplicate sectors IDs,
908
; in that case we can use a much faster approach.
909
910
		ld	hl,unique_buffer
911
		ld	de,unique_buffer+1
912
		ld	bc,256-1
913
		ld	(hl),#ff
914
		ldir				; fill unique_buffer with #ff
915
916
		ld	a,(nb_sectors)
917
		ld	bc,sizeof_amark
918
		ld	hl,addr_buffer+ofst_amark_R
919
		ld	d,unique_buffer/256
920
count_loop	ld	e,(hl)			; 'R'-value of address-mark
921
		ex	de,hl
922
		inc	(hl)
923
		jr	nz,read_slow		; if we increase #ff more than once
924
		ex	de,hl			; it's non-zero, in that case there's
925
		add	hl,bc			; a duplicate and we must use the
926
		dec	a			; slow approach
927
		jr	nz,count_loop
928
929
read_fast	ld	a,1
930
		jr	set_speed
931
read_slow	xor	a
932
set_speed	ld	(read_speed),a
933
934
		ld	hl,offset_buffer
935
		ld	(ofst_buf_ptr),hl
936
		ld	a,(nb_sectors)
937
		ld	hl,addr_buffer
938
939
sector_loop	ld	(sector_cntr),a
940
		ld	(addr_buf_ptr),hl
941
942
		call	print_dec_a
943
		call	print_pc
944
		db	" ",0
945
946
; Skip sectors for which we didn't find a data mark previously.
947
948
		ld	hl,(ofst_buf_ptr)
949
		inc	hl
950
		inc	hl
951
		ld	a,(hl)
952
		inc	hl
953
		or	(hl)
954
		jp	z,next_sector
955
956
957
; Reading a specific sector on some copy protected disks is not that simple
958
; because it can happen that a sector with the same identification header (so
959
; same address mark) appears multiple times on the same track. It's really
960
; important that we read the correct version.
961
;
962
; To solve this, we wait till the index pulse, then execute some delay loop
963
; (delay is based on the counter value we recorded during the "read address"
964
; phase above) and only then we execute the "read sector" command. For extra
965
; safety we measure the time between the start of the command and the moment
966
; we receive the first data from the command. If this difference is too big we
967
; adjust the delay value and try again.
968
969
		ld	a,'s'
970
		call	debug_log
971
		ld	hl,64
972
		ld	(adjust_ofst),hl
973
		ld	(adjust_scale),hl
974
975
try_read_sector	xor	a
976
retry_crc	ld	(crc_retries),a
977
978
		ld	hl,(addr_buf_ptr)
979
		ld	b,(hl)		; 'C' value from read address command
980
		inc	hl		; 'H'
981
		inc	hl
982
		ld	c,(hl)		; 'R'
983
		inc	hl		; 'N'
984
		inc	hl		; CRC1
985
		inc	hl		; CRC2
986
		inc	hl
987
		ld	a,(hl)
988
		inc	hl
989
		ld	h,(hl)
990
		ld	l,a		; hl = counter value
991
		ld	de,(adjust_ofst)
992
		or	a		; counter value was recorded at end of the
993
		sbc	hl,de		; "read address" command, we need to wait
994
		                        ; till the start of the address mark, so
995
		                        ; wait a bit less
996
997
		ld	de,(sector_buf_ptr)
998
		ld	iy,(driver_rd_sect)
999
		jp	(iy)
1000
sector_end
1001
		ex	de,hl
1002
		ld	de,(sector_buf_ptr)
1003
		or	a		; sector length, should be one of
1004
		sbc	hl,de		;    128, 256, 512 or 1024
1005
		ld	(sector_size),hl
1006
		ex	de,hl
1007
		ld	hl,(ofst_buf_ptr)
1008
		ld	bc,ofst_oi_size
1009
		add	hl,bc
1010
		ld	(hl),e
1011
		inc	hl
1012
		ld	(hl),d		; store sector size
1013
		inc	hl
1014
		ld	bc,(sector_buf_ptr)
1015
		ld	(hl),c
1016
		inc	hl
1017
		ld	(hl),b		; store pointer to sector data
1018
1019
		ld	b,a
1020
		and	8		; crc error?
1021
		jr	z,read_no_crc_err
1022
		ld	a,(crc_retries)	; Only when we have 5 crc errors, we
1023
		inc	a		; believe it's an intentional crc error
1024
		cp	5		; on the disk (and not some random read
1025
		jp	c,retry_crc	; error on an (old) disk).
1026
read_no_crc_err
1027
		ld	a,(read_speed)
1028
		or	a
1029
		jr	nz,sector_ok
1030
		ld	a,ixh
1031
		or	a
1032
		jr	nz,sector_retry
1033
		ld	a,ixl
1034
		cp	150
1035
		jr	c,sector_ok
1036
1037
sector_retry
1038
		ld	a,'t'
1039
		call	debug_log
1040
		ld	a,(debug)
1041
		or	a
1042
		jr	z,debug_1
1043
		push	ix
1044
		call	print_pc
1045
		db	13,10,"|",0
1046
		pop	hl
1047
		push	hl
1048
		call	print_hex_hl
1049
		call	print_pc
1050
		db	" ",0
1051
		ld	hl,(adjust_ofst)
1052
		call	print_hex_hl
1053
		call	print_pc
1054
		db	" ",0
1055
		ld	hl,(adjust_scale)
1056
		call	print_hex_hl
1057
		call	print_pc
1058
		db	"|",0
1059
		pop	ix
1060
debug_1
1061
		ld	hl,(adjust_scale)
1062
		ld	d,h
1063
		ld	e,l
1064
		srl	d
1065
		rr	e
1066
		srl	d
1067
		rr	e
1068
		srl	d
1069
		rr	e
1070
		or	a
1071
		sbc	hl,de
1072
		ld	(adjust_scale),hl	; scale = scale - scale/8
1073
		ex	de,hl
1074
		ld	hl,(adjust_ofst)
1075
		ld	a,ixh
1076
		cp	5
1077
		jr	c,sector_sub
1078
		add	hl,de
1079
		jr	sector_2
1080
sector_sub	or	a
1081
		sbc	hl,de
1082
sector_2:	ld	(adjust_ofst),hl
1083
		jp	try_read_sector
1084
1085
sector_ok	ld	a,'o'
1086
		call	debug_log
1087
		ld	hl,(ofst_buf_ptr)
1088
		ld	de,ofst_oi_status
1089
		add	hl,de
1090
		ld	(hl),b			; b = status register
1091
1092
1093
; We've read the sector, now copy it to the correct location in the raw track
1094
; buffer. We can't immediately read it in the correct place because we have
1095
; to perform a copy to a circular destination buffer (doing it inside the
1096
; read-sector loop might be too slow).
1097
1098
		ld	hl,(ofst_buf_ptr)
1099
		ld	bc,ofst_oi_ptr+1
1100
		add	hl,bc
1101
		ld	b,(hl)
1102
		dec	hl
1103
		ld	c,(hl)
1104
		dec	hl		; bc = pointer to sector data
1105
		push	bc
1106
		ld	b,(hl)
1107
		dec	hl
1108
		ld	c,(hl)		; bc = sector size
1109
1110
		dec	hl
1111
		dec	hl
1112
		dec	hl
1113
		dec	hl
1114
		ld	a,(hl)
1115
		inc	hl
1116
		ld	h,(hl)
1117
		ld	l,a		; hl = pos of data mark
1118
		inc	hl
1119
		inc	hl
1120
		inc	hl
1121
		inc	hl		; position of actual sector data
1122
		ld	de,(track_stop)
1123
		or	a
1124
		sbc	hl,de
1125
		jr	c,circular_1
1126
		ld	de,trck_buffer
1127
circular_1	add	hl,de
1128
		ex	de,hl
1129
1130
		pop	hl		; hl = pointer to sector data
1131
		call	circular_ldir
1132
		ld	(sector_stop),de
1133
1134
1135
; Did the "read sector" command return a CRC error? If so, we keep the CRC value
1136
; from the raw track data. But if there was no CRC error, we calculate the
1137
; correct CRC value and store that in the raw track data. Most of the time this
1138
; calculated value will be the same as the value that is already present in the
1139
; raw track data, though not in case the sector wrapped around the end of the
1140
; track.
1141
1142
		ld	hl,(ofst_buf_ptr)
1143
		ld	bc,ofst_oi_status
1144
		add	hl,bc
1145
		ld	a,(hl)			; sector status
1146
		and	8
1147
		jr	nz,sector_crc_err	; skip calculating CRC
1148
1149
		;;push	hl
1150
		;;call	print_pc
1151
		;;db	" CRC-OK",0
1152
		;;pop	hl
1153
1154
		dec	hl
1155
		ld	a,(hl)		; a = data mark type (is part of CRC)
1156
		inc	hl
1157
		inc	hl
1158
		ld	c,(hl)
1159
		inc	hl
1160
		ld	b,(hl)		; bc = sector size
1161
		inc	hl
1162
		ld	e,(hl)
1163
		inc	hl
1164
		ld	d,(hl)		; de = pointer to sector data
1165
1166
		ld	hl,#CDB4	; precalculated CRC for sequence "A1 A1 A1"
1167
		push	bc
1168
		call	crc_byte
1169
		pop	bc
1170
sector_crc_loop	ld	a,(de)
1171
		inc	de
1172
		push	bc
1173
		call	crc_byte
1174
		pop	bc
1175
		dec	bc
1176
		ld	a,b
1177
		or	c
1178
		jr	nz,sector_crc_loop
1179
1180
		ex	de,hl		; de = CRC value
1181
		ld	hl,(sector_stop)
1182
		ld	(hl),d		; CRC is stored big endian
1183
		inc	hl
1184
		ld	a,(track_stop)
1185
		cp	l
1186
		jr	nz,copy_crc_next
1187
		ld	a,(track_stop+1)
1188
		cp	h
1189
		jr	nz,copy_crc_next
1190
		ld	hl,trck_buffer
1191
copy_crc_next	ld	(hl),e
1192
1193
		jr	next_sector
1194
1195
sector_crc_err	;;call	print_pc
1196
		;;db	" CRC-ERR",0
1197
1198
1199
; Sector data (and possibly CRC value) is stored in raw track buffer.
1200
; Continue with the next sector.
1201
1202
next_sector
1203
		ld	hl,(sector_buf_ptr)
1204
		ld	bc,(sector_size)
1205
		add	hl,bc
1206
		ld	(sector_buf_ptr),hl
1207
		ld	a,h
1208
		cp	debug_buffer/256
1209
		jp	nc,buffer_overflow
1210
1211
		;;call	print_pc
1212
		;;db	13,10,0
1213
1214
		ld	hl,(ofst_buf_ptr)
1215
		ld	de,sizeof_offinfo
1216
		add	hl,de
1217
		ld	(ofst_buf_ptr),hl
1218
		ld	hl,(addr_buf_ptr)
1219
		ld	de,sizeof_amark
1220
		add	hl,de
1221
		ld	a,(sector_cntr)
1222
		dec	a
1223
		jp	nz,sector_loop
1224
1225
		call	print_pc
1226
		db	13,10,0
1227
1228
; At this point we've read the raw track data and overwritten it with data
1229
; from "read sector" commands. Though we still need to make some more
1230
; adjustments:
1231
;  - the read track command doesn't reliably read the first A1 byte in a
1232
;    address or data mark sequence.
1233
;  - I found that sometimes the "read sector" command had overwritten the
1234
;    address mark of another sector with different data (e.g. this happened
1235
;    while experimenting with the Pixess game disk which intentionally has
1236
;    overlapping sector)
1237
; To fix both problems we now restore the address and data marks.
1238
;
1239
; We also record the position of the address marks in the DMK track header.
1240
1241
		ld	a,'F'
1242
		call	debug_log
1243
		ld	a,(debug)
1244
		or	a
1245
		jr	z,skip_fix_prt
1246
		call	print_pc
1247
		db	"Fixup markers ...",13,10,0
1248
skip_fix_prt
1249
1250
		ld	hl,offset_buffer
1251
		ld	(ofst_buf_ptr),hl
1252
		ld	hl,dmk_header
1253
		ld	(dmk_ptr),hl
1254
		ld	a,(nb_sectors)
1255
		ld	hl,addr_buffer
1256
1257
fixup_loop	ld	(sector_cntr),a
1258
		ld	(addr_buf_ptr),hl
1259
		ld	a,'f'
1260
		call	debug_log
1261
1262
		ld	hl,(ofst_buf_ptr)
1263
		ld	e,(hl)
1264
		inc	hl
1265
		ld	d,(hl)		; de = pos of addr mark
1266
		inc	hl
1267
		push	hl
1268
		push	de
1269
1270
		ld	hl,addr_mark
1271
		ld	bc,4
1272
		call	circular_ldir
1273
		ld	hl,(addr_buf_ptr)
1274
		ld	bc,6
1275
		call	circular_ldir
1276
1277
		pop	hl		; pos of addr mark
1278
		ld	de,trck_buffer
1279
		or	a
1280
		sbc	hl,de
1281
		ld	de,#8083
1282
		add	hl,de
1283
		ex	de,hl
1284
		ld	hl,(dmk_ptr)
1285
		ld	(hl),e
1286
		inc	hl
1287
		ld	(hl),d
1288
		inc	hl
1289
		ld	(dmk_ptr),hl
1290
1291
		pop	hl
1292
		ld	e,(hl)
1293
		inc	hl
1294
		ld	d,(hl)
1295
		ld	a,e
1296
		or	d
1297
		jr	z,fixup_next	; no data mark
1298
		inc	hl
1299
		push	hl
1300
1301
		ld	hl,addr_mark
1302
		ld	bc,3
1303
		call	circular_ldir
1304
		pop	hl
1305
		ld	a,(hl)
1306
		ld	(de),a		; copy data mark type
1307
1308
fixup_next	ld	hl,(ofst_buf_ptr)
1309
		ld	de,sizeof_offinfo
1310
		add	hl,de
1311
		ld	(ofst_buf_ptr),hl
1312
		ld	hl,(addr_buf_ptr)
1313
		ld	de,sizeof_amark
1314
		add	hl,de
1315
		ld	a,(sector_cntr)
1316
		dec	a
1317
		jr	nz,fixup_loop
1318
1319
1320
; Done. ... Well, not quite ...
1321
; In theory everything should be done at this point. However tests on a real
1322
; machine have shown that for some disks we *sometimes* still get the wrong
1323
; data at this point. This happened for disks which have overlapping sectors
1324
; (e.g. sunrise disks). When I did a "read track" on such a disk, I found that
1325
; the distance in bytes between the start of the sectors is sometimes N but
1326
; sometimes N+1! Normally this doesn't matter (and this variation might be the
1327
; reason why there are gaps between sectors). Though in case of overlapping
1328
; sectors, if the relative start of the two sectors is shifted by a byte, then
1329
; the CRC of the sectors will be different (in case of the sunrise protection,
1330
; the CRC of the first sector is part of the data of the second sector). The
1331
; only way I found to detect/correct this problem is to verify the CRCs of the
1332
; sectors and if we find one that is not correct (while it should be) just try
1333
; again and hope we get the correct relative distance on the next attempt.
1334
; On a real machine I found that trying 3-4 times is enough to get the correct
1335
; data. Here we try up to 20 times.
1336
;
1337
; ... And it gets even more complicated. Compjoetania disks (e.g. Pixess or
1338
; NoiseDisk(?)) contain a track with a sector with the 'wrong' sectorsize. I
1339
; mean in the track layout that sector completely looks like a 512 byte sector
1340
; (so stuff like headers, gaps, CRC, ...). Only the sector size field has the
1341
; value 255 instead of 2. The WD2793 only looks at the lowest 2 bits of this
1342
; field, so for the WD2793 this is a 1024 byte sector. But with this larger
1343
; size the sector actually overlaps with the next sector. And because only the
1344
; size field was changed, the CRC of the sector is wrong (there's no correct
1345
; CRC 1024 bytes after the start of the sector). And to make it even more
1346
; complex: the distance between both sectors is not a multiple of 8 bits (I
1347
; think). At least if you read the 1024-byte sector, the last part of that data
1348
; does not show the sector headers etc of the next sector. The DMK file format
1349
; cannot represent non-integer byte offsets. But luckily the content of that
1350
; 1024 byte sector isn't checked by the software. That is the MSX software, but
1351
; it was checked in earlier versions of READ-DMK in this verify step. And
1352
; verification then failed.
1353
;
1354
; So what we do now is skip verification for overlapping sectors that have a
1355
; CRC error. So for sunrise disks we do verify the (overlapping) sector, but
1356
; for Compjoetania disks we don't. Non-overlapping sectors are always verified.
1357
1358
		ld	a,'V'
1359
		call	debug_log
1360
		call	print_pc
1361
		db	"Verifying ... ",0
1362
1363
		ld	hl,offset_buffer
1364
		ld	a,(nb_sectors)
1365
1366
verify_loop	ld	(sector_cntr),a
1367
		ld	(ofst_buf_ptr),hl
1368
1369
		ld	a,'v'
1370
		call	debug_log
1371
		;;push	hl
1372
		;;call	print_dec_a	; TODO print_dec
1373
		;;call	print_pc
1374
		;;db	": ",0
1375
		;;pop	hl
1376
1377
		inc	hl
1378
		inc	hl
1379
		ld	e,(hl)
1380
		inc	hl
1381
		ld	d,(hl)		; de = location of data mark
1382
		ld	a,e
1383
		or	d
1384
		jp	z,verify_next
1385
1386
		inc	hl
1387
		inc	hl
1388
		ld	a,(hl)		; a = read sector status
1389
		ld	(crc_status),a
1390
		inc	hl
1391
		ld	c,(hl)
1392
		inc	hl
1393
		ld	b,(hl)		; bc = sector length
1394
		inc	hl
1395
		push	bc
1396
		ld	c,(hl)
1397
		inc	hl
1398
		ld	b,(hl)		; bc = sector data
1399
		inc	hl
1400
		push	bc
1401
		pop	ix		; ix = sector data
1402
		ld	c,(hl)
1403
		inc	hl
1404
		ld	b,(hl)
1405
		push	bc
1406
		pop	iy		; iy = addr mark of next sector
1407
1408
verify_mark	ld	b,4		; length of data mark
1409
		ld	hl,#ffff	; initialize CRC
1410
circular_crc1	ld	a,(de)
1411
		inc	de
1412
		push	bc
1413
		call	crc_byte
1414
		pop	bc
1415
		ld	a,(track_stop)
1416
		cp	e
1417
		jr	nz,circ_crc_next1
1418
		ld	a,(track_stop+1)
1419
		cp	d
1420
		jr	nz,circ_crc_next1
1421
		ld	de,trck_buffer
1422
circ_crc_next1	djnz	circular_crc1
1423
1424
		ld	a,'w'
1425
		call	debug_log
1426
		pop	bc		; bc = sector length
1427
1428
check_overlap	push	hl
1429
		push	de
1430
		push	bc
1431
		push	iy
1432
		pop	hl		; hl = addr mark of next sector
1433
		or	a
1434
		sbc	hl,de		; hl = distance between this sector data and next sector header
1435
		jr	nc,check_overlap1
1436
		ld	de,(track_len)
1437
		add	hl,de		; handle wrapping
1438
check_overlap1	inc	bc
1439
		inc	bc		; 2 CRC bytes
1440
		or	a
1441
		sbc	hl,bc		; distance smaller than sector size?
1442
		pop	bc
1443
		pop	de
1444
		pop	hl
1445
		jr	nc,verify_content ; not smaller -> no overlap
1446
1447
overlap		ld	a,'0'
1448
		call	debug_log
1449
		ld	a,(crc_status)
1450
		and	8
1451
		jr	z,verify_content ; no CRC error -> verify sector content
1452
		ld	a,'C'
1453
		call	debug_log
1454
		jp	verify_next	; overlap with CRC error -> skip verify
1455
1456
verify_content
1457
circular_crc	ld	a,(de)
1458
		cp	(ix+0)
1459
		jr	nz,verify_data
1460
		inc	de
1461
		inc	ix
1462
		push	bc
1463
		call	crc_byte
1464
		pop	bc
1465
		ld	a,(track_stop)
1466
		cp	e
1467
		jr	nz,circ_crc_next
1468
		ld	a,(track_stop+1)
1469
		cp	d
1470
		jr	nz,circ_crc_next
1471
		ld	de,trck_buffer
1472
circ_crc_next	dec	bc
1473
		ld	a,b
1474
		or	c
1475
		jr	nz,circular_crc
1476
1477
		ld	a,'x'
1478
		call	debug_log
1479
		ex	de,hl
1480
		ld	b,(hl)
1481
		inc	hl
1482
		ld	c,(hl)		; bc = on-disk CRC  (stored big endian)
1483
		ex	de,hl		; hl = calculated CRC
1484
		or	a
1485
		sbc	hl,bc
1486
		jr	z,crc_match
1487
1488
		;;call	print_pc
1489
		;;db	" should have CRC error ... ", 0
1490
1491
crc_mismatch
1492
		ld	a,'m'
1493
		call	debug_log
1494
		ld	a,(crc_status)
1495
		and	8
1496
		jr	nz,verify_next	; ok, read sector command also returned CRC err
1497
		ld	a,'M'
1498
		jr	verify_retry
1499
1500
verify_data	ld	a,'D'
1501
verify_retry	call	debug_log
1502
		call	print_pc
1503
		db	"FAILED",13,10,0
1504
1505
maybe_retry	ld	a,(retries)
1506
		inc	a
1507
		ld	(retries),a
1508
		cp	20
1509
		jr	c,do_retry
1510
		jp	retry_error
1511
1512
do_retry	ld	a,(debug)
1513
		or	a
1514
		jr	z,no_debug_write
1515
		call	write_debug
1516
		call	select_fdc
1517
		call	seek
1518
no_debug_write	jp	retry
1519
1520
1521
crc_match
1522
		ld	a,'n'
1523
		call	debug_log
1524
		;;call	print_pc
1525
		;;db	" should not have CRC error ... ", 0
1526
		ld	a,(crc_status)
1527
		and	8
1528
		ld	a,'N'
1529
		jr	nz,verify_retry	; CRC did match, but it shouldn't have
1530
1531
verify_next	;;call	print_pc
1532
		;;db	"OK",13,10,0
1533
1534
		ld	hl,(ofst_buf_ptr)
1535
		ld	de,sizeof_offinfo
1536
		add	hl,de
1537
		ld	a,(sector_cntr)
1538
		dec	a
1539
		jp	nz,verify_loop
1540
verify_done
1541
1542
1543
; Really done.
1544
; Write the data to disk (the second drive).
1545
; TODO this tool should also be usuable on machines with only one disk drive.
1546
; So we should ask the user to swap disks. To make it more comfortable, we
1547
; should try to minimize the number of required swaps. So we should buffer the
1548
; data in (v)ram.
1549
1550
success		call	enable_irq
1551
1552
		call	print_pc
1553
		db	"Success!!!",13,10,0
1554
1555
		ld	a,(cylinder)
1556
		ld	hl,fcb+1+4
1557
		ld	b,'0'-1
1558
dec_loop	inc	b
1559
		sub	10
1560
		jr	nc,dec_loop
1561
		ld	(hl),b
1562
		add	a,'0'+10
1563
		inc	hl
1564
		ld	(hl),a
1565
		ld	a,(side)
1566
		add	a,'0'
1567
		inc	hl
1568
		inc	hl
1569
		ld	(hl),a
1570
1571
retry_open	ld	de,fcb
1572
		ld	c,#16		; create file
1573
		call	#0005
1574
		or	a
1575
		jp	nz,open_error
1576
1577
		ld	hl,1
1578
		ld	(fcb+14),hl	; set record size (1 byte)
1579
		ld	hl,0
1580
		ld	(fcb+33),hl
1581
		ld	(fcb+35),hl	; record number
1582
1583
		ld	de,dmk_header
1584
		ld	c,#1a		; set disk transfer address
1585
		call	#0005
1586
1587
		ld	hl,(track_len)
1588
		ld	bc,128
1589
		add	hl,bc		; hl = #bytes to write
1590
		ld	de,fcb
1591
		ld	c,#26		; random block write
1592
		call	#0005
1593
		or	a
1594
		jp	nz,write_error
1595
1596
		ld	de,fcb
1597
		ld	c,#10		; close file
1598
		call	#0005
1599
		or	a
1600
		jp	nz,close_error
1601
1602
1603
		ld	a,(side)
1604
		inc	a
1605
		cp	2
1606
		jp	nz,side_loop
1607
1608
		;; TODO use step-in
1609
1610
		ld	a,(stop_track)
1611
		inc	a
1612
		ld	b,a
1613
		ld	a,(cylinder)
1614
		inc	a
1615
		cp	b
1616
		jp	nz,cylinder_loop
1617
1618
1619
1620
1621
exit		call	deselect_fdc
1622
		call	enable_irq
1623
		ld	c,#00
1624
		jp	#0005		; exit program
1625
1626
1627
; We didn't find any sectors in this track. If we're already at cylinder 80 or
1628
; higher this means we're done. Though if the user explicitly set the
1629
; stop-cylinder, we continue until that cylinder.
1630
;
1631
; In case there's a 81th track on side 0, but not on side 1 we don't want to
1632
; stop dumping because the combine-dmk tool expects to see always track info
1633
; for both sides.
1634
1635
no_sectors	ld	a,(cylinder)
1636
		cp	80
1637
		jp	c,verify_done	; not yet at cylinder 80
1638
		ld	a,(stop_set)
1639
		or	a
1640
		jp	nz,verify_done	; user explicitly set end-cylinder
1641
		ld	a,(side)
1642
		or	a
1643
		jp	nz,verify_done	; if we're not on side 0, then continue
1644
1645
		call	print_pc
1646
		db	13,10
1647
		db	"End of disk detected.",13,10,0
1648
		jp	exit
1649
1650
1651
1652
1653
open_error	call	print_pc
1654
		db	"Error opening file",0
1655
err_retry	call	print_pc
1656
		db	" ... press key to retry ...",0
1657
		ld	ix,#009f
1658
		ld	iy,(#fcc0)
1659
		call	#001c
1660
		call	print_pc
1661
		db	13,10,0
1662
		jp	retry_open
1663
1664
write_error	call	print_pc
1665
		db	"Error writing file",13,10,0
1666
delete_file	ld	de,fcb
1667
		ld	c,#13		; delete file
1668
		call	#0005		; when the disk is full we get a write error
1669
					; but it also leaves a zero-sized file behind
1670
		jr	err_retry	; so here we delete it
1671
close_error	call	print_pc
1672
		db	"Error closing file",13,10,0
1673
		jr	delete_file
1674
1675
1676
ofst_err	call	print_pc
1677
		db	"Failed to find address mark in raw track data 0x",0
1678
		ld	hl,(addr_estimate)
1679
		call	print_hex_hl
1680
		call	print_pc
1681
		db	13,10,0
1682
		jp	maybe_retry
1683
1684
sector_err	call	print_pc
1685
		db	"Read sector command didn't find sector",0
1686
		jp	maybe_retry
1687
1688
retry_error	call	print_pc
1689
		db	"Unsuccessful after 20 retries :-(",13,10,0
1690
		jr	debug_exit
1691
1692
buffer_overflow	call	print_pc
1693
		db	"Sector buffer overflow",13,10,0
1694
debug_exit	call	write_debug
1695
		jp	exit
1696
1697
1698
1699
write_debug	call	print_pc
1700
		db	"Writing debug file ...",13,10,0
1701
1702
		ld	de,fcb_debug
1703
		ld	c,#16		; create file
1704
		call	#0005
1705
		or	a
1706
		jr	nz,debug_error
1707
1708
		ld	hl,1
1709
		ld	(fcb_debug+14),hl	; set record size (1 byte)
1710
		ld	hl,0
1711
		ld	(fcb_debug+33),hl
1712
		ld	(fcb_debug+35),hl	; record number
1713
1714
		ld	de,#8000
1715
		ld	c,#1a		; set disk transfer address
1716
		call	#0005
1717
1718
		ld	hl,#5000	; write #8000 .. #D000 (20kB)
1719
		ld	de,fcb_debug
1720
		ld	c,#26		; random block write
1721
		call	#0005
1722
		or	a
1723
		jr	nz,debug_error
1724
1725
		ld	de,fcb_debug
1726
		ld	c,#10		; close file
1727
		call	#0005
1728
		or	a
1729
		jr	nz,debug_error
1730
		ret
1731
1732
debug_error	call	print_pc
1733
		db	"Error while writing debug file",13,10,0
1734
		ret
1735
1736
unknown_option	call	print_pc
1737
		db	"Unknown command line option",13,10,0
1738
		jp	exit
1739
expected_int	call	print_pc
1740
		db	"Error parsing command line: expected integer",13,10,0
1741
		jp	exit
1742
1743
1744
; We disable VDP IRQs because the BIOS print routine enables interrupts (EI)
1745
; and that interferes with the low level drive settings we're doing (e.g. it
1746
; can turn the motor off) a better solution would be to make sure we only print
1747
; at non-critical places and/or restore all FDC state after a print. Or write
1748
; our own printing routine. And of course there could be other IRQ sources in
1749
; the MSX machine, so this is really only a hack (though would those other
1750
; sources also trigger the motor timeout mechanism??)
1751
1752
disable_irq	di
1753
		ld	a,(#f3e0)
1754
		and	#df
1755
		out	(#99),a
1756
		ld	(#f3e0),a
1757
		ld	a,1+128
1758
		out	(#99),a		; disable VDP IRQs
1759
		ret
1760
1761
enable_irq	di
1762
		ld	a,(#f3e0)
1763
		or	#20
1764
		out	(#99),a
1765
		ld	(#f3e0),a
1766
		ld	a,1+128
1767
		out	(#99),a
1768
		ei
1769
		ret
1770
1771
1772
select_fdc	call	disable_irq
1773
		ld	iy,(driver_select)
1774
		jp	(iy)
1775
1776
deselect_fdc	ld	iy,(driver_deselect)
1777
		jp	(iy)
1778
1779
seek		ld	iy,(driver_seek)
1780
		jp	(iy)
1781
1782
1783
1784
circular_ldir	ld	a,(hl)
1785
		ld	(de),a
1786
		inc	de
1787
		inc	hl
1788
		ld	a,(track_stop)
1789
		cp	e
1790
		jr	nz,ldir_next
1791
		ld	a,(track_stop+1)
1792
		cp	d
1793
		jr	nz,ldir_next
1794
		ld	de,trck_buffer
1795
ldir_next	dec	bc
1796
		ld	a,b
1797
		or	c
1798
		jr	nz,circular_ldir
1799
		ret
1800
1801
1802
1803
delay:		ld	hl,50000
1804
delay0		ex	(sp),hl
1805
		ex	(sp),hl
1806
		dec	hl
1807
		ld	a,h
1808
		or	l
1809
		jr	nz,delay0
1810
		ret
1811
1812
1813
; Input: [DE] = ptr to start of block
1814
;        [IX] = ptr to end of block (right after end)
1815
;        [HL] = previous result (or zero), now search for a longer period
1816
; Output [HL] = period
1817
1818
get_period:	inc	hl
1819
p_loop:		push	hl
1820
		push	de
1821
		call	test_period
1822
		pop	de
1823
		pop	hl
1824
		ret	z
1825
		inc	hl
1826
		jr	p_loop
1827
1828
; In: [de] = start
1829
;     [ix] = end
1830
;     [hl] = candidate period
1831
; Out:  Z -> period found
1832
;      NZ -> period not found
1833
test_period:	add	hl,hl
1834
		add	hl,hl
1835
		add	hl,hl
1836
		add	hl,de
1837
t_loop:		ld	a,l
1838
		cp	ixl
1839
		jr	nz,test_1
1840
		ld	a,h
1841
		cp	ixh
1842
		ret	z
1843
test_1:		ld	b,6
1844
c_loop		ld	a,(de)
1845
		cp	(hl)
1846
		ret	nz
1847
		inc	hl
1848
		inc	de
1849
		djnz	c_loop
1850
		inc	de
1851
		inc	de
1852
		inc	hl
1853
		inc	hl
1854
		jr	t_loop
1855
1856
1857
; Fractional division.
1858
; Requires that the divisor is strictly bigger than the dividend (BC > HL).
1859
; In: [HL] Dividend
1860
;     [BC] Divisor
1861
; Out: [DE] = fractional part of [HL]/[BC]
1862
frac_div:	ld	a,b
1863
		cpl
1864
		ld	b,a
1865
		ld	a,c
1866
		cpl
1867
		ld	c,a
1868
		inc	bc	; bc = -divider
1869
		ld	de,1	; stop after 16 iterations
1870
fdiv_loop	add	hl,hl	; hl <<= 1
1871
		add	hl,bc	; hl -= divider
1872
		jr	c,fdiv1	; hl.prev >= divider
1873
		sbc	hl,bc	; restore hl (carry flag remains clear)
1874
fdiv1		rl	e
1875
		rl	d	; adc de,de
1876
		jr	nc,fdiv_loop
1877
		ret
1878
1879
1880
; [HL] = mul-high([DE], [BC])
1881
mul_hi:		ld	hl,0
1882
		ld	a,16
1883
mul_loop	srl	d
1884
		rr	e
1885
		jr	nc,mul_skip
1886
		add	hl,bc
1887
mul_skip	rr	h
1888
		rr	l
1889
		dec	a
1890
		jr	nz,mul_loop
1891
		ret
1892
1893
1894
1895
; In: [HL] = current CRC value
1896
;     [A]  = input byte
1897
; Out [HL] = updated CRC Value
1898
crc_byte:	ld	c,a
1899
		ld	b,8
1900
crc_l:		add	hl,hl
1901
		jr	c,crc_1
1902
crc_0:		rlc	c
1903
		jr	c,crc_2
1904
		jr	crc_3
1905
crc_1:		rlc	c
1906
		jr	c,crc_3
1907
crc_2		ld	a,h
1908
		xor	#10
1909
		ld	h,a
1910
		ld	a,l
1911
		xor	#21
1912
		ld	l,a
1913
crc_3:		djnz	crc_l
1914
		ret
1915
1916
1917
1918
1919
parse_dec	ld	b,0
1920
		ld	a,(hl)
1921
parse_dec_loop	inc	hl
1922
		sub	'0'
1923
		jp	c,expected_int
1924
		cp	'9'+1
1925
		jp	nc,expected_int
1926
		ld	c,a
1927
		ld	a,b
1928
		add	a,a
1929
		add	a,a
1930
		add	a,a
1931
		add	a,b
1932
		add	a,b	; b*10
1933
		add	a,c
1934
		ld	b,a
1935
		ld	a,(hl)
1936
		or	a
1937
		jr	z,parse_dec_end
1938
		cp	13
1939
		jr	z,parse_dec_end
1940
		cp	' '
1941
		jr	z,parse_dec_end
1942
		cp	9
1943
		jr	nz,parse_dec_loop
1944
parse_dec_end	ld	a,b
1945
		ret
1946
1947
1948
1949
print_pc:	pop	hl
1950
		call	print_str
1951
		jp	(hl)
1952
1953
print_str:	ld	a,(hl)
1954
		or	a
1955
		ret	z
1956
		ld	ix,#00A2
1957
		ld	iy,(#fcc0)
1958
		call	#001c
1959
		inc	hl
1960
		jr	print_str
1961
1962
1963
print_hex_hl:	ld	a,h
1964
		call	print_hex_a
1965
		ld	a,l
1966
print_hex_a:	ld	b,a
1967
		rrca
1968
		rrca
1969
		rrca
1970
		rrca
1971
		call	print_hdig
1972
		ld	a,b
1973
print_hdig:	and	#0f
1974
		cp	10
1975
		jr	c,prt_1
1976
		add	a,'A'-'0'-10
1977
prt_1		add	a,'0'
1978
		ld	ix,#00A2
1979
		ld	iy,(#fcc0)
1980
		jp	#001c
1981
1982
1983
print_dec_hl	ld	e,0			; number of non-zero digits
1984
		ld	a,h
1985
		or	l
1986
		jr	z,print_dec_hl_3	; hl==0 -> print at least one 0-digit
1987
		ld	bc,-10000
1988
		call	print_dec_hl_1
1989
		ld	bc,-1000
1990
		call	print_dec_hl_1
1991
		ld	bc,-100
1992
		call	print_dec_hl_1
1993
		ld	c,-10
1994
		call	print_dec_hl_1
1995
		ld	c,-1
1996
print_dec_hl_1	ld	a,-1
1997
print_dec_hl_2	inc	a
1998
		add	hl,bc
1999
		jr	c,print_dec_hl_2
2000
		sbc	hl,bc
2001
		inc	e
2002
		or	a
2003
		jr	nz,print_dec_hl_3
2004
		dec	e
2005
		ret	z		; skip leading zeros
2006
print_dec_hl_3	add	a,'0'
2007
		ld	ix,#00A2
2008
		ld	iy,(#fcc0)
2009
		jp	#001c
2010
2011
print_dec_a	ld	e,0
2012
		or	a
2013
		jr	z,print_dec_a_3
2014
		ld	b,100
2015
		call	print_dec_a_1
2016
		ld	b,10
2017
		call	print_dec_a_1
2018
		ld	b,1
2019
print_dec_a_1	ld	c,-1
2020
print_dec_a_2	inc	c
2021
		sub	b
2022
		jr	nc,print_dec_a_2
2023
		add	a,b
2024
		ld	b,a
2025
		inc	e
2026
		ld	a,c
2027
		or	a
2028
		jr	nz,print_dec_a_3
2029
		dec	e
2030
		jr	z,print_dec_a_4
2031
print_dec_a_3	add	a,'0'
2032
		ld	ix,#00A2
2033
		ld	iy,(#fcc0)
2034
		call	#001c
2035
print_dec_a_4	ld	a,b
2036
		ret
2037
2038
2039
debug_log	push	hl
2040
		ld	hl,(debug_ptr)
2041
		ld	(hl),a
2042
		inc	l
2043
		ld	(debug_ptr),hl
2044
		pop	hl
2045
		ret
2046
2047
2048
2049
;---
2050
; Machine specific routines
2051
;  All these routine are still very much based on a WD2793 FDC. They only
2052
;  differ in how the WD2793 is connected to the MSX. Each 'driver' needs
2053
;  to implement 6 routines:
2054
2055
; 1) select
2056
;  input:
2057
;   'side' global variable
2058
;  output: -
2059
;  description:
2060
;    Needs to select the disk rom in page 1 (for memory mapped FDCs).
2061
;    Needs to select correct side, select drive A, turn motor on.
2062
2063
; 2) deselct
2064
;  input: -
2065
;  output: -
2066
;  description:
2067
;    Called right before program exit. Should e.g. turn drive motor off.
2068
2069
; 3) seek
2070
;  input: 'cylinder'
2071
;  output: -
2072
;  description:
2073
;   Should seek to the correct cylinder. E.g. by first seeking to track 0
2074
;   and then seek to the requested cylinder. It's not allowed to use the data
2075
;   in the track for this seek (e.g. verify the destination track).
2076
;   TODO in the future we may add a step-in command as well.
2077
2078
; 4) rd_addr
2079
;  input: -
2080
;  output:
2081
;   'addr_buffer' is filled in
2082
;   [DE] points to end of addr_buffer
2083
;  description:
2084
;   Executes 'read address' commands in a loop and put the result in a buffer.
2085
;   During this loop it keep a counter running and on each successful read
2086
;   address command, the value of this counter is also stored in the buffer.
2087
;  return:
2088
;   on success this routine jumps to 'addr_done'
2089
;   on error it jumps to 'addr_error'
2090
2091
; 5) rd_track
2092
;  input: -
2093
;  output:
2094
;   'trck_buffer' is filled in
2095
;   [DE] points to the end of trck_buffer
2096
;  description:
2097
;  return:
2098
;   on success this routine jumps to 'track_end'
2099
;   on error it jumps to 'track_err' or 'track_too_much'
2100
2101
; 6) rd_sector
2102
;  input:
2103
;   [B] = track number (number found in address mark, not physical track number)
2104
;   [C] = Sector number (found in address mark)
2105
;   [DE] = pointer to output buffer
2106
;   [HL] = delay value
2107
;   'read_speed' global variable
2108
;  output:
2109
;   buffer is filled in
2110
;   [A] = WD2793 status register after command has ended (e.g. contains CRC status)
2111
;   [DE] = points to end of buffer
2112
;   [IX] = time between end-of-delay and first-byte-received
2113
;  description:
2114
;   Reads the sector with given number in the given buffer. This routine should
2115
;   wait for the index pulse and then delay for the given amount of time before
2116
;   actually starting the read sector command
2117
;  return:
2118
;   on success this routine jumps to sector_end
2119
;   on error it jumps to sector_err
2120
2121
driver_routines
2122
driver_select	dw	0
2123
driver_deselect	dw	0
2124
driver_seek	dw	0
2125
driver_rd_addr	dw	0
2126
driver_rd_trck	dw	0
2127
driver_rd_sect	dw	0
2128
ticks_min	dw	0
2129
ticks_max	dw	0
2130
driver_size	equ	$ - driver_routines
2131
2132
driver		dw	phil_driver
2133
2134
;---
2135
; Philips
2136
2137
phil_status	equ	#7ff8
2138
phil_command	equ	#7ff8
2139
phil_track	equ	#7ff9
2140
phil_sector	equ	#7ffa
2141
phil_data	equ	#7ffb
2142
phil_control1	equ	#7ffc
2143
phil_control2	equ	#7ffd
2144
phil_stat2	equ	#7fff
2145
2146
phil_driver	dw	phil_select
2147
		dw	phil_deselect
2148
		dw	phil_seek
2149
		dw	phil_rd_addr
2150
		dw	phil_rd_trck
2151
		dw	phil_rd_sector
2152
		dw	13834
2153
		dw	15290
2154
2155
2156
; 1) select
2157
phil_select	ld	a,(#f348)
2158
		ld	h,#40
2159
		call	#0024		; select FDC slot in page 1
2160
		ld	a,(side)
2161
		ld	(phil_control1),a
2162
		ld	a,#c0		; motor on, led on, drive A
2163
		ld	(phil_control2),a
2164
		ret
2165
2166
2167
; 2) deselct
2168
phil_deselect	ld	a,3
2169
		ld	(phil_control2),a
2170
		ret
2171
2172
2173
; 3) seek
2174
phil_seek
2175
wait_busy_3	ld	a,(phil_status)
2176
		and	1
2177
		jr	nz,wait_busy_3
2178
2179
		ld	a,#0b		; restore, load head
2180
		ld	(phil_command),a
2181
		call	delay
2182
2183
wait_busy_4	ld	a,(phil_status)
2184
		and	1
2185
		jr	nz,wait_busy_4
2186
2187
		ld	a,(cylinder)
2188
		ld	(phil_data),a	; track
2189
		ld	a,#18		; seek
2190
		ld	(phil_command),a
2191
		ret
2192
2193
2194
; 4) rd_addr
2195
phil_rd_addr:
2196
		ld	de,addr_buffer
2197
		ld	ix,0		; counter
2198
		ld	hl,phil_stat2	; irq/dtrq
2199
		ld	bc,phil_data
2200
2201
wait_busy_1	ld	a,(phil_status)
2202
		and	1
2203
		jr	nz,wait_busy_1
2204
2205
		ld	a,#d0		; Forced interrupt command
2206
		ld	(phil_command),a	; otherwise we don't see the index
2207
		ex	(sp),hl
2208
		ex	(sp),hl		; needed?
2209
2210
wait_index_a1	ld	a,(phil_status)
2211
		and	2		; wait till index pulse = 0
2212
		jr	nz,wait_index_a1
2213
wait_index_b1	ld	a,(phil_status)
2214
		and	2		; wait till index pulse = 1
2215
		jr	z,wait_index_b1
2216
2217
addr_loop	ld	a,#c0
2218
		ld	(phil_command),a	; read addr
2219
2220
		; Note: the timinig of this loop is important! Don't change
2221
		; the instructions (e.g. JP->JR) without also changing the
2222
		; other timing critical routines below.
2223
addr_wait	inc	ix		; 12 cycles        <-- this subset
2224
		ld	a,(hl)		;  8               <-- of the loop
2225
		add	a,a		;  5               <-- takes
2226
		jp	p,addr_end      ; 11               <-- 47
2227
		jp	c,addr_wait	; 11               <-- cycles
2228
		ld	a,(bc)		;  8
2229
		ld	(de),a		;  8
2230
		inc	de              ;  7
2231
		jp	addr_wait       ; 11
2232
addr_end
2233
2234
		ld	a,(phil_status)
2235
		and	16
2236
		jr	nz,addr_error_	; prefer to keep this a short jump
2237
		ld	a,ixl
2238
		ld	(de),a
2239
		inc	de
2240
		ld	a,ixh
2241
		ld	(de),a		; store counter
2242
		inc	de
2243
		inc	ix
2244
		inc	ix
2245
		cp	#c0
2246
		jp	c,addr_loop
2247
		jp	addr_done
2248
2249
addr_error_	jp addr_error
2250
2251
2252
; 5) rd_track
2253
phil_rd_trck	ld	de,trck_buffer
2254
		ld	hl,phil_stat2	; irq/dtrq
2255
		ld	bc,phil_data
2256
		ld	ix,0
2257
		ld	a,#e0		; read track
2258
		ld	(phil_command),a
2259
2260
track_wait2	ld	a,(hl)
2261
		add	a,a
2262
		jp	p,track_err
2263
		jp	nc,track_first
2264
		inc	ix
2265
		ld	a,ixh
2266
		inc	a
2267
		jp	nz,track_wait2
2268
		jp	track_no_start
2269
2270
track_wait	ld	a,(hl)
2271
		add	a,a
2272
		jp	p,track_end
2273
		jp	c,track_wait
2274
track_first	ld	a,(bc)
2275
		ld	(de),a
2276
		inc	de
2277
		ld	a,d
2278
		cp	#be
2279
		jp	c,track_wait
2280
		jp	track_too_much
2281
2282
2283
; 6) rd_sector
2284
phil_rd_sector
2285
		ld	a,#d0		; Forced interrupt command
2286
		ld	(phil_command),a	; otherwise we don't see the index
2287
		                        ; pulse status bits
2288
		ld	a,b
2289
		ld	(phil_track),a
2290
		ld	a,c
2291
		ld	(phil_sector),a
2292
2293
		ld	bc,phil_data
2294
		ld	ix,0
2295
		ld	a,(read_speed)
2296
		or	a
2297
		jr	nz,fast_read_1
2298
2299
wait_index_a2	ld	a,(phil_status)
2300
		and	2	; wait till index pulse = 0
2301
		jr	nz,wait_index_a2
2302
wait_index_b2	ld	a,(phil_status)
2303
		and	2	; wait till index pulse = 1
2304
		jr	z,wait_index_b2
2305
2306
		; This loop is tuned for an exact number of Z80 cycles!
2307
delay_loop	dec	hl		;              7 cycles
2308
		ld	a,(0)		; dummy read  14 cycles
2309
		nop			;              5 cycles
2310
		ld	a,h		;              5
2311
		or	l		;              5
2312
		jp	nz,delay_loop	;             11    together 47 cycles
2313
2314
fast_read_1	ld	hl,phil_stat2	; irq/dtrq
2315
		ld	a,#80		; read sector
2316
		ld	(phil_command),a
2317
2318
sector_wait1	inc	ix		; count till first byte is received
2319
		ld	a,(hl)
2320
		add	a,a
2321
		jp	p,sector_err	; command stopped before we got 1st byte
2322
		jp	c,sector_wait1
2323
		ld	a,(bc)
2324
		ld	(de),a
2325
		inc	de
2326
sector_wait2	ld	a,(hl)
2327
		add	a,a
2328
		jp	p,sector_end_
2329
		jp	c,sector_wait2
2330
		ld	a,(bc)
2331
		ld	(de),a
2332
		inc	de
2333
		jp	sector_wait2
2334
2335
sector_end_	ld	a,(phil_status)
2336
		jp	sector_end
2337
2338
2339
;---
2340
; National
2341
2342
natl_status	equ	#7fb8
2343
natl_command	equ	#7fb8
2344
natl_track	equ	#7fb9
2345
natl_sector	equ	#7fba
2346
natl_data	equ	#7fbb
2347
natl_control	equ	#7fbc
2348
natl_stat2	equ	#7fbc
2349
2350
natl_driver	dw	natl_select
2351
		dw	natl_deselect
2352
		dw	natl_seek
2353
		dw	natl_rd_addr
2354
		dw	natl_rd_trck
2355
		dw	natl_rd_sector
2356
		dw	13834
2357
		dw	15290
2358
2359
2360
; 1) select
2361
natl_select	ld	a,(#f348)
2362
		ld	h,#40
2363
		call	#0024		; select FDC slot in page 1
2364
		ld	a,(side)
2365
		rlca
2366
		rlca			; bit 2 = side
2367
		or	#09		; motor on, drive A
2368
		ld	(natl_control),a
2369
		ret
2370
2371
2372
; 2) deselct
2373
natl_deselect	xor	a
2374
		ld	(natl_control),a
2375
		ret
2376
2377
2378
; 3) seek
2379
natl_seek
2380
natl_wait_3	ld	a,(natl_status)
2381
		and	1
2382
		jr	nz,natl_wait_3
2383
2384
		ld	a,#0b		; restore, load head
2385
		ld	(natl_command),a
2386
		call	delay
2387
2388
natl_wait_4	ld	a,(natl_status)
2389
		and	1
2390
		jr	nz,natl_wait_4
2391
2392
		ld	a,(cylinder)
2393
		ld	(natl_data),a	; track
2394
		ld	a,#18		; seek
2395
		ld	(natl_command),a
2396
		ret
2397
2398
2399
; 4) rd_addr
2400
natl_rd_addr:
2401
		ld	de,addr_buffer
2402
		ld	ix,0		; counter
2403
		ld	hl,natl_stat2	; irq/dtrq
2404
		ld	bc,natl_data
2405
2406
natl_busy_1	ld	a,(natl_status)
2407
		and	1
2408
		jr	nz,natl_busy_1
2409
2410
		ld	a,#d0		; Forced interrupt command
2411
		ld	(natl_command),a	; otherwise we don't see the index
2412
		ex	(sp),hl
2413
		ex	(sp),hl		; needed?
2414
2415
natl_index_a1	ld	a,(natl_status)
2416
		and	2		; wait till index pulse = 0
2417
		jr	nz,natl_index_a1
2418
natl_index_b1	ld	a,(natl_status)
2419
		and	2		; wait till index pulse = 1
2420
		jr	z,natl_index_b1
2421
2422
natl_addr_loop	ld	a,#c0
2423
		ld	(natl_command),a	; read addr
2424
2425
		; Note: the timinig of this loop is important! Don't change
2426
		; the instructions (e.g. JP->JR) without also changing the
2427
		; other timing critical routines below.
2428
natl_addr_wait	inc	ix		; 12 cycles        <-- this subset
2429
		ld	a,(hl)		;  8               <-- of the loop
2430
		add	a,a		;  5               <-- takes
2431
		jp	c,natl_addr_end	; 11               <-- 47
2432
		jp	m,natl_addr_wait; 11               <-- cycles
2433
		ld	a,(bc)		;  8
2434
		ld	(de),a		;  8
2435
		inc	de              ;  7
2436
		jp	natl_addr_wait	; 11
2437
natl_addr_end
2438
2439
		ld	a,(natl_status)
2440
		and	16
2441
		jr	nz,natl_addr_err	; prefer to keep this a short jump
2442
		ld	a,ixl
2443
		ld	(de),a
2444
		inc	de
2445
		ld	a,ixh
2446
		ld	(de),a		; store counter
2447
		inc	de
2448
		inc	ix
2449
		inc	ix
2450
		cp	#c0
2451
		jp	c,natl_addr_loop
2452
		jp	addr_done
2453
2454
natl_addr_err	jp addr_error
2455
2456
2457
; 5) rd_track
2458
natl_rd_trck	ld	de,trck_buffer
2459
		ld	hl,natl_stat2	; irq/dtrq
2460
		ld	bc,natl_data
2461
		ld	ix,0
2462
		ld	a,#e0		; read track
2463
		ld	(natl_command),a
2464
2465
natl_trk_wt2	ld	a,(hl)
2466
		add	a,a
2467
		jp	c,track_err
2468
		jp	p,natl_trk_first
2469
		inc	ix
2470
		ld	a,ixh
2471
		inc	a
2472
		jp	nz,natl_trk_wt2
2473
		jp	track_no_start
2474
2475
natl_trk_wait	ld	a,(hl)
2476
		add	a,a
2477
		jp	c,track_end
2478
		jp	m,natl_trk_wait
2479
natl_trk_first	ld	a,(bc)
2480
		ld	(de),a
2481
		inc	de
2482
		ld	a,d
2483
		cp	#be
2484
		jp	c,natl_trk_wait
2485
		jp	track_too_much
2486
2487
2488
; 6) rd_sector
2489
natl_rd_sector
2490
		ld	a,#d0		; Forced interrupt command
2491
		ld	(natl_command),a	; otherwise we don't see the index
2492
		                        ; pulse status bits
2493
		ld	a,b
2494
		ld	(natl_track),a
2495
		ld	a,c
2496
		ld	(natl_sector),a
2497
2498
		ld	bc,natl_data
2499
		ld	ix,0
2500
		ld	a,(read_speed)
2501
		or	a
2502
		jr	nz,natl_fast_read
2503
2504
natl_index_a2	ld	a,(natl_status)
2505
		and	2	; wait till index pulse = 0
2506
		jr	nz,natl_index_a2
2507
natl_index_b2	ld	a,(natl_status)
2508
		and	2	; wait till index pulse = 1
2509
		jr	z,natl_index_b2
2510
2511
		; This loop is tuned for an exact number of Z80 cycles!
2512
natl_delay	dec	hl		;              7 cycles
2513
		ld	a,(0)		; dummy read  14 cycles
2514
		nop			;              5 cycles
2515
		ld	a,h		;              5
2516
		or	l		;              5
2517
		jp	nz,natl_delay	;             11    together 47 cycles
2518
2519
natl_fast_read	ld	hl,natl_stat2	; irq/dtrq
2520
		ld	a,#80		; read sector
2521
		ld	(natl_command),a
2522
2523
natl_sect_wt1	inc	ix		; count till first byte is received
2524
		ld	a,(hl)
2525
		add	a,a
2526
		jp	c,sector_err	; command stopped before we got 1st byte
2527
		jp	m,natl_sect_wt1
2528
		ld	a,(bc)
2529
		ld	(de),a
2530
		inc	de
2531
natl_sect_wt2	ld	a,(hl)
2532
		add	a,a
2533
		jp	c,natl_sect_end
2534
		jp	m,natl_sect_wt2
2535
		ld	a,(bc)
2536
		ld	(de),a
2537
		inc	de
2538
		jp	natl_sect_wt2
2539
2540
natl_sect_end	ld	a,(natl_status)
2541
		jp	sector_end
2542
2543
;---
2544
; Microsol
2545
2546
mics_status	equ	#d0
2547
mics_command	equ	#d0
2548
mics_track	equ	#d1
2549
mics_sector	equ	#d2
2550
mics_data	equ	#d3
2551
mics_control	equ	#d4
2552
mics_stat2	equ	#d4
2553
2554
mics_driver	dw	mics_select
2555
		dw	mics_deselect
2556
		dw	mics_seek
2557
		dw	mics_rd_addr
2558
		dw	mics_rd_trck
2559
		dw	mics_rd_sector
2560
		dw	14135
2561
		dw	15622
2562
2563
2564
; 1) select
2565
mics_select	ld	a,(side)
2566
		rlca
2567
		rlca
2568
		rlca
2569
		rlca			; bit 4 = side
2570
		or	#21		; bit 5 = motor, bit 0 = drive A
2571
		out	(mics_control),a
2572
		ret
2573
2574
2575
; 2) deselct
2576
mics_deselect	xor	a		; no drive selected, motor off
2577
		out	(mics_control),a
2578
		ret
2579
2580
2581
; 3) seek
2582
mics_seek
2583
mics_busy_3	in	a,(mics_status)
2584
		and	1
2585
		jr	nz,mics_busy_3
2586
2587
		ld	a,#0b		; restore, load head
2588
		out	(mics_command),a
2589
		call	delay
2590
2591
mics_busy_4	in	a,(mics_status)
2592
		and	1
2593
		jr	nz,mics_busy_4
2594
2595
		ld	a,(cylinder)
2596
		out	(mics_data),a	; track
2597
		ld	a,#18		; seek
2598
		out	(mics_command),a
2599
		ret
2600
2601
2602
; 4) rd_addr
2603
mics_rd_addr:
2604
		ld	de,addr_buffer
2605
		ld	hl,0		; counter
2606
2607
mics_busy_1	in	a,(mics_status)
2608
		and	1
2609
		jr	nz,mics_busy_1
2610
2611
		ld	a,#d0		; Forced interrupt command
2612
		out	(mics_command),a	; otherwise we don't see the index
2613
		ex	(sp),hl
2614
		ex	(sp),hl		; needed?
2615
2616
mics_index_a1	in	a,(mics_status)
2617
		and	2		; wait till index pulse = 0
2618
		jr	nz,mics_index_a1
2619
mics_index_b1	in	a,(mics_status)
2620
		and	2		; wait till index pulse = 1
2621
		jr	z,mics_index_b1
2622
2623
mics_addr_loop	ld	a,#c0			; read addr
2624
		out	(mics_command),a
2625
2626
		; Note: the timinig of this loop is important! Don't change
2627
		; the instructions (e.g. JP->JR) without also changing the
2628
		; other timing critical routines below.
2629
mics_addr_wait	inc	hl			;  7 cycles   <-- this
2630
		in	a,(mics_stat2)		; 12          <-- takes
2631
		add	a,a			;  5          <-- 46
2632
		jp	c,mics_addr_end		; 11          <-- cycles
2633
		jp	m,mics_addr_wait	; 11          <--
2634
		in	a,(mics_data)		; 12
2635
		ld	(de),a			;  8
2636
		inc	de			;  7
2637
		jp	mics_addr_wait		; 11
2638
mics_addr_end
2639
2640
		in	a,(mics_status)
2641
		and	16			; record not found
2642
		jr	nz,mics_addr_err	; prefer to keep this a short jump
2643
		ld	a,l
2644
		ld	(de),a
2645
		inc	de
2646
		ld	a,h
2647
		ld	(de),a		; store counter
2648
		inc	de
2649
		inc	hl
2650
		inc	hl
2651
		cp	#c0
2652
		jp	c,mics_addr_loop
2653
		jp	addr_done
2654
2655
mics_addr_err	jp addr_error
2656
2657
2658
; 5) rd_track
2659
mics_rd_trck	ld	de,trck_buffer
2660
		ld	hl,0
2661
		ld	a,#e0		; read track
2662
		out	(mics_command),a
2663
2664
mics_trk_wait2	in	a,(mics_stat2)
2665
		add	a,a
2666
		jp	c,track_err
2667
		jp	p,mics_trk_first
2668
		inc	hl
2669
		ld	a,h
2670
		inc	a
2671
		jp	nz,mics_trk_wait2
2672
		jp	track_no_start
2673
2674
mics_trk_wait	in	a,(mics_stat2)
2675
		add	a,a
2676
		jp	c,track_end
2677
		jp	m,mics_trk_wait
2678
mics_trk_first	in	a,(mics_data)
2679
		ld	(de),a
2680
		inc	de
2681
		ld	a,d
2682
		cp	#be
2683
		jp	c,mics_trk_wait
2684
		jp	track_too_much
2685
2686
2687
; 6) rd_sector
2688
mics_rd_sector
2689
		ld	a,#d0		; Forced interrupt command
2690
		out	(mics_command),a	; otherwise we don't see the index
2691
		                        ; pulse status bits
2692
		ld	a,b
2693
		out	(mics_track),a
2694
		ld	a,c
2695
		out	(mics_sector),a
2696
2697
		ld	ix,0
2698
		ld	a,(read_speed)
2699
		or	a
2700
		jr	nz,mics_fast_1
2701
2702
mics_index_a2	in	a,(mics_status)
2703
		and	2	; wait till index pulse = 0
2704
		jr	nz,mics_index_a2
2705
mics_index_b2	in	a,(mics_status)
2706
		and	2	; wait till index pulse = 1
2707
		jr	z,mics_index_b2
2708
2709
		; This loop is tuned for an exact number of Z80 cycles!
2710
mics_delay	dec	hl		;  7 cycles
2711
		cp	0		;  8 (dummy compare)
2712
		nop			;  5
2713
		nop			;  5
2714
		ld	a,h		;  5
2715
		or	l		;  5
2716
		jp	nz,mics_delay	; 11  together 46 cycles
2717
2718
mics_fast_1	ld	a,#80		; read sector
2719
		out	(mics_command),a
2720
2721
mics_sctr_wt1	inc	ix		; count till first byte is received
2722
		in	a,(mics_stat2)
2723
		add	a,a
2724
		jp	c,sector_err	; command stopped before we got 1st byte
2725
		jp	m,mics_sctr_wt1
2726
		in	a,(mics_data)
2727
		ld	(de),a
2728
		inc	de
2729
mics_sctr_wt2	in	a,(mics_stat2)
2730
		add	a,a
2731
		jp	c,mics_sctr_end
2732
		jp	m,mics_sctr_wt2
2733
		in	a,(mics_data)
2734
		ld	(de),a
2735
		inc	de
2736
		jp	mics_sctr_wt2
2737
2738
mics_sctr_end	in	a,(mics_status)
2739
		jp	sector_end
2740
2741
; -----
2742
2743
2744
2745
2746
ofst_tab:	dw	-6,-7,-5,-8,-4,-9,-3,-10,-2,-11,-1,-12,0
2747
                dw	-13,1,-14,2,-15,3,-16,4,-17,5,-18,6,-19,7
2748
		dw	-20,8,-21,9,-22,10,-23,11,-24,12,-25,13,-26
2749
		dw	14,-27,15,-28,16,-29,17,-30,18,-31,29,-32
2750
		dw	20,-33,21,-34,22,-35,23,-36,24,-37,25,-38
2751
		dw	26,-39,27,-40,28,-41,29,-42,30,-43,31,-44
2752
		dw	#8080
2753
addr_mark	db	#A1,#A1,#A1,#FE
2754
2755
debug		db	0
2756
start_track	db	0	; initial value matters
2757
stop_track	db	81	; by default we try 2 extra cylinders
2758
stop_set	db	0
2759
2760
2761
2762
fcb		db	2		; drive B
2763
		db	"DMK-TT-S"	; filename
2764
		db	"DAT"		; extension
2765
		ds	37-12
2766
fcb_debug	db	2		; drive B
2767
		db	"DEBUG   "	; filename
2768
		db	"DAT"		; extension
2769
		ds	37-12
2770
2771
2772
2773
2774
; struct Addr_Mark
2775
;   byte C
2776
;   byte H
2777
;   byte R
2778
;   byte N
2779
;   word CRC
2780
;   word ticks
2781
sizeof_amark	equ	8
2782
ofst_amark_C	equ	0
2783
ofst_amark_H	equ	1
2784
ofst_amark_R	equ	2
2785
ofst_amark_N	equ	3
2786
ofst_amark_CRC	equ	4
2787
ofst_amark_tick	equ	6
2788
2789
2790
; struct Offset_Info
2791
;   word address_mark_offset
2792
;   word data_mark_offset
2793
;   byte data_mark_type
2794
;   byte read_sector_status
2795
;   word sector_size
2796
sizeof_offinfo	equ	10
2797
ofst_oi_addr	equ	0
2798
ofst_oi_data	equ	2
2799
ofst_oi_type	equ	4
2800
ofst_oi_status	equ	5
2801
ofst_oi_size	equ	6
2802
ofst_oi_ptr	equ	8
2803
2804
2805
sizeof_off_buf	equ	64 * sizeof_offinfo
2806
sizeof_dmk_h	equ	128
2807
2808
2809
cylinder	equ	#8000		; db	0     0
2810
side		equ	cylinder+ 1	; db	0     1
2811
retries		equ	side+1		; db	0     2
2812
nb_sectors	equ	retries+1	; dw	0     3
2813
track_len	equ	nb_sectors+2	; dw	0     5
2814
track_stop	equ	track_len+2	; dw	0     7
2815
ticks		equ	track_stop+2	; dw	0     9
2816
ratio		equ	ticks+2		; dw	0    11
2817
2818
crc_retries	equ	ratio+2		; db	0    13
2819
adjust_ofst	equ	crc_retries+1	; dw	0    14
2820
adjust_scale	equ	adjust_ofst+2	; dw	0    16
2821
sector_cntr	equ	adjust_scale+2	; db	0    18
2822
sector_stop	equ	sector_cntr+1	; dw	0    19
2823
addr_buf_ptr	equ	sector_stop+2	; dw	0    21
2824
ofst_buf_ptr	equ	addr_buf_ptr+2	; dw	0    23
2825
dmk_ptr		equ	ofst_buf_ptr+2	; dw	0    25
2826
addr_estimate	equ	dmk_ptr+2	; dw	0    27
2827
read_speed	equ	addr_estimate+2	; db	0    29
2828
sector_buf_ptr	equ	read_speed+1	; dw	0    30
2829
crc_status	equ	sector_buf_ptr+2; db	0    32
2830
debug_ptr	equ	crc_status+1	; dw	0    33
2831
sector_size	equ	debug_ptr+2	; dw	0    35
2832
addr_buf_end	equ	sector_size+2	; dw	0    37
2833
addr_retries	equ	addr_buf_end+2	; db	0    39
2834
2835
addr_buffer	equ	#8100
2836
offset_buffer	equ	addr_buffer+64*sizeof_amark	; can overlap part of addr_buffer
2837
dmk_header	equ	offset_buffer+sizeof_off_buf
2838
trck_buffer	equ	dmk_header+sizeof_dmk_h
2839
sector_buffer	equ	trck_buffer+#1A00	; overlaps 2nd copy of track``
2840
unique_buffer	equ	#CE00		; possibly overlaps sector buffer (that's OK)
2841
                                        ; must start at a 256-byte boundary
2842
debug_buffer	equ	#CF00		; must be 256-bytes aligned