forked from prime6809/NASDOS
-
Notifications
You must be signed in to change notification settings - Fork 0
/
nasdos.asm
executable file
·3528 lines (2960 loc) · 80.5 KB
/
nasdos.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
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
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
; z80dasm 1.1.2
; command line: z80dasm.exe -v --origin=0xd000 --sym-output=dossym.asm --sym-input=nasdefs.asm --block-def=blocks.txt -l -t -o nasdos.asm nasdos.rom
;
; Re assemblable version of NAS-DOS version 1.4.
; Created Jan 2014, Phill Harvey-Smith.
; Originally disassembled Jan 2014 from the MESS nasdos.rom, which was a modified copy
; of nasdos 1.4. Updated 2018-12-05 to match v1.4 ROMS dumped from PHS' Nascom 3.
;
; To be built with z80asm : https://www.nongnu.org/z80asm/
;
;; If you rebuild at a different address, no NASDOS utilities
;; will work because all NASDOS entry points are hard-coded.
;; If you try to load this to RAM, the ]V command will not work
;; because it assumes DOSCold is in ROM and overwrites it.
org 0d000h
DOSCold:
jp DoDOSCold ; Cold start
DOSWarm:
jp DoDOSWarm ; warm start
DOSInit:
jp DoDOSInit ; Init drive 0
DOSFRMT:
jp DoDOSFRMT ; Format a disk
DOSRSCT:
jp DoDOSRSCT ; Read a sector
DOSRTRK:
jp DoDOSRTRK ; Read a track
DOSWSCT:
jp DoDOSWSCT ; Write a sector
DOSWTRK:
jp DoDOSWTRK ; Write a track
DOSCMND:
jp DoDOSCMND ; Write a command to the FDC
DOSDSEL:
jp DoDOSDSEL ; Drive select
jp 0ffffh ;d01e c3 ff ff . . .
jp 0ffffh ;d021 c3 ff ff . . .
; BLOCK 'data00' (start 0xd024 end 0xd076)
DLSPD:
defb DOSSides ; Sides per disk
DLTPS:
defb DOSTrkPerDsk ; Tracks per side
DLDPS:
defb 007h ; Drives per system
; Workspace pointer, to block of 8 bytes in RAM.
WORKSP:
defw WKSPACE
; Dos version no as ASCII?
defb 031h ;d029 31 1
defb 02eh ;d02a 2e .
defb 034h ;d02b 34 4
defb 010h ;d02c 10 .
; Re-enable ints and return
DoEIRET:
ei
ret
; Unknow and un jumped to routine, seems to just print the following text and
; return to nas-sys. Something to do with DOS serial no perhaps ?
PrintSerialno:
rst $28
defb '(C)Copyright 1982 & 1983 '
defb 'Lucas Logic Ltd.'
defb 'by'
defb 00dh
defb 'Dove Computer Services'
defb 00dh,000h
; Original version (hack) from MESS had the copyright text removed!
; 0123456789ABCDEF
; defb ' '
; defb ' '
; defb ' '
; defb ' 51103',0dh,00h
; defb 000h, 000h, 000h, 000h
; defb 000h, 000h, 000h, 000h
; defb 000h, 000h, 000h, 000h
rst $18
defb MRET ; Return to NAS-SYS
;
; Initialize DOS.
;
DoDOSInit:
ld a,WDCmdForceInt ; Force interrupt, reset FDC
out (CmdStatReg),a ; Send command
ld a,CTRLBMotor+CTLBDS0 ; Turn motor on and select drive 0 (021h)
out (CTRLReg),a
in a,(CTRLReg) ; Read status reg
and MaskDriveSide ; Select just drive id & side (01fh)
dec a ; Check for zero : drive 0, side 0
ld a,01fh
ret nz ; not drive 0 side 0
in a,(CmdStatReg) ; read status
push hl ; save HL
ld hl,(WORKSP) ; get pointer to workspace in RAM
ld (hl),0ffh ; Set first byte
pop hl ; Restore HL & return
ret
;
; Format a disk.
; Entry :
; A = logical drive no to format.
;
DoDOSFRMT:
push af ; Save AF
ld091h:
rst 28h ; Display string
defb 'Skew? (1-8) ',000h
ld09fh:
rst 18h ; Get character from keyboard wait & blink
defb BLINK
cp 031h ; Check between 1..8
jr c,ld091h ; lower : prompt again
cp 039h ; > 8
jr nc,ld091h ; higher : prompt again
rst 30h ; Display typed character
push af ; Save skew
rst 18h ; Output CRLF
defb CRLF
pop af ; Restore skew
and 00fh ; Convert to binary by masking off MSN
ld hl,DOSFormatBuf ; Format buffer at 1000h
push hl ; Save buffer ptr
; I suspect the following code is a bunch of loops that generate the raw sectors for
; each track to be formatted
ld b,DOSSecPerTrk ; 16 bytes of 0
ld0b6h:
ld (hl),000h
inc hl
djnz ld0b6h
pop hl ; Restore buffer ptr
; fill in a table of 16 bytes containing the sector numbers of the sectors on the track
; with the appropreate skew factor
ld b,000h ; Zero B, BC now contains 16 bit skew
ld c,a ; Skew into c
ld d,001h ; Start sector no
ld0c1h:
ld a,(hl) ; Get byte from buffer
inc hl ; point to next byte
or a ; Set flags
jr nz,ld0cfh ; End : skip
dec hl ; Move back 1
ld (hl),d ; store sector no ?
inc d ; next sector no
ld a,DOSSecPerTrk ; Number of sectors / track
sub d ; Calculate number left
jr c,ld0e3h ; done all : exit
add hl,bc ; add skew to pointer
ld0cfh:
push hl ; Save buffer ptr & skew
push bc ;
ld bc,DOSRawSecBuf ; point to end of buffer
or a ;
sbc hl,bc ; Subtract end from current pos, will be -ve if not end of buffer
pop bc ; Restore buffer ptr & skew
pop hl
jr c,ld0c1h ; not past end of buffer, continue
push bc ; Save skew
ld bc,0-DOSSecPerTrk ; move HL back inside buffer by adding 64K-16
add hl,bc ; this will wrap around back inside buffer
pop bc ; restore skew
jr ld0c1h ; do next
ld0e3h:
pop af ; Restore & re-save logical drive ID
push af
call LogToPhysDrv ; Convert to physical drive
or CTRLBMotor ; Mask in motor on
out (CTRLReg),a ; Send to control reg
call CheckDriveReady ; Check that the drive has come on and has a disk in
jr nz,ld107h ; Error :
rst 10h ; RCAL
defb (ld14d-$)-1
jr nz,ld107h ; Error : exit
ld a,(DLSPD) ; Get sides per disk
dec a ; Test double sided
jr z,ld107h ; nope : skip
in a,(CTRLReg) ; Read control reg
and MaskDrives ; Mask out all but drive ID
or CTRLBMotor + CTLBSide ; Turn on motor select side 1
out (CTRLReg),a ; Do it
rst 18h ; SCAL
defb CRLF ; Print EOL
rst 10h ; RCAL
defb (ld14d-$)-1 ; destination offset
ld107h:
ld c,a ;
pop af ; Restore drive
call DoDOSDSEL ; Select it
ld a,c ;
push af ; Save
rst 28h ; Print stringz
defb 00dh
defb 'Creating Directory',000h
ld hl,DOSRawSecBuf ; Point to buffer
push hl ; Save
ld (hl),0ffh ; fill in first byte
ld de,DOSRawSecBuf+1 ; point to second byte in buffer
ld bc,00fffh ; count
ldir ; fast fill !
pop hl ; Restore
ld de,00001h ;
ld b,DOSSecPerTrk ; Sector count
ld137h:
call sub_d396h ; Write the sector out
jr nz,ld143h ;
inc e ;
djnz ld137h ; More sectors to do, do them
rst 18h ; SCAL
defb CRLF ; output EOL
pop af ; Restore & return
ret
ld143h:
rst 28h ; Print stringz
defb '-',000h
rst 18h ; SCAL
defb ERRM ; exit with error
pop af ; Restore
ld a,0ffh ; Flag error
or a
ret
ld14d:
; restore to track 0
ld a,WDCmdRestore + WDCHeadLoad + WDCStepRate
call DoDOSCMND ; Send to FDC
ld hl,FormatData ; Point to data for format
ld de,DOSRawSecBuf ; Point just past sector number buffer
ld158h:
ld c,(hl)
ld a,c ; get block count
or a ; end ?
jr z,ld175h ; yep : exit
inc hl
ld15eh:
push hl ; Save pointer for later
ld15fh:
pop hl
push hl
ld b,(hl) ; Get bytecount
inc hl
ld163h:
ld a,(hl) ; Get value
inc hl
ld165h:
ld (de),a ; Put byte in format buffer
inc de ; point to next byte of buffer
djnz ld165h ; Loop until no more
ld b,(hl) ; get next byte count
inc hl
ld a,b
or a
jr nz,ld163h ; if nonzero loop again
dec c ; Decrement block count
jr nz,ld15fh ; Keep going if more to do
pop af ;
jr ld158h ;
ld175h:
ld a,(DLTPS) ; Get tracks per side
ld e,a ;
; restore to track 0
ld a,WDCmdRestore + WDCHeadLoad + WDCStepRate
call DoDOSCMND ; Send to FDC
jp c,RetDOSErrInvFmt ; Jump on error
;
; Scan over the raw sector data in RAM, and fill in the sector ID
; and track numbers.
;
ld181h:
push de
ld hl,01040h ; Offset in buffer
ld de,00170h ; Size of each (raw sector) entry ?
ld a,DOSSecPerTrk ; Sector count ?
ld b,a ; Process this many sectors
ld ix,DOSFormatBuf ; Buffer base (secor ids)
ld18fh:
in a,(TrackReg) ; Read track
ld (hl),a ; Put in sector header
inc hl ; Next byte in buffer
and 001h ; Mask in odd / even bit
rlca ; a=a*8
rlca ;
rlca ;
ld c,a ; save a
in a,(CTRLReg) ; Read control reg
and MaskDriveSide ; Mask out all but drive & side
or CTRLBMotor ; Mask in motor on
out (CTRLReg),a ; Do it
and CTLBSide ; Mask out all but side
rrca ; Shift it to bit 0
rrca
rrca
rrca
ld (hl),a ; Put it in buffer
inc hl ; Next byte
ld a,(ix+000h) ; Get sector ID
dec a ; decrement (sector id 0..f)
xor c ; mask in track odd / even .
inc a ; inc id (01..10)
inc ix ; Point to next id
ld (hl),a ; Save in raw sector
add hl,de ; move to next entry
djnz ld18fh ; loop if more to do
pop de ; Restore
ld hl,DOSRawSecBuf ; Point to raw data buffer
push de ; Save regs
push hl
ld a,WDCmdWriteTrack + WDCDelay5ms ; Write the track
call SendCMDandData ; Send the command and format data
pop de ; Restore
push af ; Save AF while we print
or a ;
sbc hl,de ;
in a,(TrackReg) ; Read trackreg
rst 18h ; SCAL
defb B2HEX ; Print track as hex
rst 28h ; Print string
defb '-',000h
rst 18h ; SCAL
defb TBCD3 ; Output HL as hex
pop af ; Restore status from FDC
pop de
jr nz,RetDOSErrInvFmt ; Error : exit error ff
; HL at this point contains the last byte written to the track.
push hl ; save byte count
ld bc,017e0h ; low vbalue for last byte
or a ; clear flags
sbc hl,bc ; check it
pop hl ; restore hl
jr c,RetDOSErrInvFmt ; too few bytes written disk spinning too fast!
push hl ; save byte count
ld bc,018a0h ; high value for last byte written
or a ; clear flags
sbc hl,bc ; check it
pop hl ; restore hl
jr nc,RetDOSErrInvFmt ; too many bytes written disk spinning too slow!
xor a ;d1e6 af .
dec e ;d1e7 1d .
ret z ;d1e8 c8 .
ld a,WDCmdStepIn + WDCTrkUpdate+ WDCHeadLoad + WDCStepRate
call DoDOSCMND ; Step to next track
cp 020h ; Error ?
jr z,ld181h ; Nope : do next
RetDOSErrInvFmt:
ld a,DOSErrInvFmt ; Error : Invalid format
or a ; Set flags
ret ; return to caller
; Raw sector data definition table
; byte defs count value
FormatData:
; beginning of track pre-amble
defb 001h ; 1 repeat
defb 020h, 04eh ; byte def(s)
defb 000h ; terminator
; sector data
defb DOSSecPerTrk ; 10h repeats
defb 00ch, 000h
defb 003h, 0f5h
defb 001h, 0feh ; ID address mark
defb 004h, 001h ; Track, side, sector id, sector len (filled in later)
defb 001h, 0f7h ; CRC calculated and written by FDC
defb 016h, 04eh
defb 00ch, 000h
defb 003h, 0f5h
defb 001h, 0fbh ; Data address mark
defb 080h, 040h ; data in 2 blocks of 128
defb 080h, 040h
defb 001h, 0f7h ; CRC calculated and written by FDC
defb 036h, 04eh
defb 000h ; terminator
; track filler
defb 003h ; 03h repeats
defb 0ffh, 04eh ; byte def(s)
defb 000h ; terminator
defb 000h ; table terminator
; Entry : A=logical drive no
; Exit : A=physical drive no (ds bit).
LogToPhysDrv:
push bc ; Save regs
ld b,a ; Save drive no
ld a,(DLSPD) ; Get logical sides / disk
dec a ; dec side count
jr z,ld227h ; Zero : exit
sla b ; drive no = drive no * 2
jr c,ld22dh ;
ld227h:
ld a,b ; Recover logical drive no
and 00fh ; Mask out MSN
cp b ; MSN set ?
jr z,ld230h ; No : continue
ld22dh:
pop bc ; Restore
scf ; Flag error
ret ; Return
ld230h:
push af ; Save drive no
srl a ;
ld b,a ;d233 47 G
inc b ;d234 04 .
xor a ;d235 af .
scf ;d236 37 7
ld237h:
rla ;d237 17 .
djnz ld237h ;d238 10 fd . .
ld b,a ;d23a 47 G
pop af ;d23b f1 .
bit 0,a ;d23c cb 47 . G
ld a,b ;d23e 78 x
pop bc ;d23f c1 .
ret z ;d240 c8 .
or 010h ;d241 f6 10 . .
ret ;d243 c9 .
;
; Select a drive
;
; Entry :
; A = logical drive number 0..7
; Exit :
; A = FDC status
;
DoDOSDSEL:
push af ; Save Regs
call LogToPhysDrv ; Translate logical drive no to physical
or CTRLBMotor ; Mask in motor control
out (CTRLReg),a ; Select drive and turn on motor
call CheckDriveReady ; Is the drive up to speed and loaded ?
jr nz,ld294h ; Nope : error exit
pop af ; Restore logical drive nr
call LogToPhysDrv ; Translate logical drive no to physical
and 00fh ; Make sure it's valid
push bc ; Save reg
ld b,a ; B=physical drive
push hl ; Save HL
ld hl,(WORKSP) ; Get workspace pointer in HL
ld a,(hl) ; Get first byte of workspace
pop hl ; Restore HL
cp b ; Is saved drive same as current ?
ld a,b ; Copy current drive back to a
pop bc ; Restore BC
jr z,ld292h ; Current drive = saved
push hl ; Save HL
ld hl,(WORKSP) ; Get workspace pointer in HL
ld (hl),a ; Set saved drive = current
inc hl ;
inc hl ;
push bc ; Save BC
ld b,005h ; retry count
ld26eh:
ld a,WDCmdReadAddr+WDCDelay5ms ; Read address
call sub_d2f0h ; Give command to FDC
jr z,ld288h ; Address read ok ? yep : skip
djnz ld26eh ; Decrement count, and try again if not 0
in a,(CTRLReg) ; Read control reg
and MaskDrives ; Mask out all but drive id
or CTRLBMotor ; Mask in motor control
out (CTRLReg),a ; Select drive and turn on motor
ld a,WDCmdRestore + WDCHeadLoad + WDCStepRate ; Restore to track 0
call DoDOSCMND ; Do it!
pop bc ; Restore regs
pop hl
jr ld296h ; return error 01fh
ld288h:
pop bc ; Restore BC
ld hl,(WORKSP) ; Point HL at workspace
inc hl ; +2
inc hl
ld a,(hl) ; Get first byte of ID (track no)
pop hl ; Restore HL
out (TrackReg),a ; Update track register
ld292h:
xor a ; Zero A & flag no error
ret
ld294h:
pop bc ; Restore regs
pop af
ld296h:
ld a,DOSErr1F ; Error code
or a ; Flag error
ret
; Check for drive being ready, waits with timeout.
; Exit: A=Error code flags.nz on error
CheckDriveReady:
push bc ; Save regs
ld bc,00000h ; Zero counter?
ld29eh:
in a,(INTReg) ; Read int masks
bit 1,a ; Is drive ready ?
jr z,ld2adh ; Yes : exit
call ShortDelay ; Wait a little while
jr nz,ld29eh ; if count nozero, loop again
ld a,DOSErr1F ; Set error code
jr ld2aeh
ld2adh:
xor a ; Make sure A=0
ld2aeh:
pop bc ; Restore
or a ; Set flags to flag error (or not)
ret
;
; Read a track / Read sector.
; Entry :
; A = Drive
; D = Track
; E = Sector
; HL = Address of buffer
; Exit :
; A = FDC Error code.
;
DoDOSRTRK:
call DoDOSDSEL ; Select drive
ret nz ; Error : exit
ld a,WDCmdReadTrack+WDCDelay5ms ; Read track command
jr ld2bfh
DoDOSRSCT:
call DoDOSDSEL ; Select drive
ret nz ; Error : exit
ld a,WDCmdReadSec ; Read a sector
ld2bfh:
push hl ; Save buffer pointer
ld hl,(WORKSP) ; Get pointer to workspace
inc hl ; +1
ld (hl),a ; Save command
pop hl ; Restore buffer pointer
call sub_d2e2h ; Read data to buffer
ret z ; Error : exit
; Error so re-calibrate the drive and try again !
; Step in
ld a,WDCmdStepIn + WDCTrkUpdate + WDCHeadLoad + WDCStepRate
call sub_d2deh ; Send to FDC
ret z ; Error : exit
; Restore to track 0 & verify
ld a,WDCmdRestore + WDCHeadLoad + WDCVerifyTrk + WDCStepRate
call sub_d2deh ; Send to FDC
ret z ; Error : exit
; Step out
ld a,WDCmdStepOut + WDCTrkUpdate + WDCHeadLoad + WDCStepRate
call sub_d2deh ; Send to FDC
ret z ; Error : exit
; Restore to track 0
ld a,WDCmdRestore + WDCHeadLoad + WDCStepRate
sub_d2deh:
call DoDOSCMND ; Send to FDC
ret c ; ok : return
sub_d2e2h:
call SeekToSideTrack ; Seek to the required track
ret nz ; Return on error
ld a,e ; Get sector no
out (SectorReg),a ; Send it to FDC
push hl ; Save buffer ptr
ld hl,(WORKSP) ; Point to workspace
inc hl ; offset 1
ld a,(hl) ; Get current WD command
pop hl ; Restore buffer ptr
; Falls through to....
sub_d2f0h:
di ; Ints off
push bc ; Save regs
push hl
ld c,INTReg ; Read INTReg when done
out (CmdStatReg),a ; Send command to FDC
jr ld2fbh ; Skip data read
ld2f9h:
ld (hl),a ; Save data byte in memory
inc hl ; point to next
ld2fbh:
in b,(c) ; Poll INTReg, set flags.
jr z,ld2fbh ; Wait for int ("command done")
in a,(DataReg) ; Read FDC Data reg, flags unchanged
jp m,ld2f9h ; Was DRQ active when we read INTReg?
; If yes, go store the data byte
; The effect of that in/jp sequence is to *always* do one extra
; read of the data register. Real hardware does not care, but
; emulators may complain.
in a,(CmdStatReg) ; Read status reg
or a ; Set flags
jr z,ld30bh ; Status ok ==0 ?
pop hl ; Recover & resave HL
push hl
ld30bh:
pop bc ; Drop saved HL
pop bc ; Recover BC
jp DoEIRET ; Re enable ints & return
;
; Seek to the track in D, setting side as needed.
;
SeekToSideTrack:
push bc ; Save regs
push de
ld a,(DLTPS) ; Get tracks per side
ld315h:
dec a ; Max track TPS -1
cp d ; Check specified track
jr nc,SeekToTrack ; Les than max, seek to it
ld a,(DLSPD) ; Get logical sides / disk
dec a ; decrement
jr z,ld35fh ; Zero : error track to large
ld a,(DLTPS) ; Get tracks per side
push af ; Save AF
rla ; A=A*2
dec a ; -1
sub d ; -target track
ld d,a ; into D
dec d ; -1
pop af ; Restore AF
dec a ; Max track TPS -1
cp d ; Cheack again
jr c,ld35fh ; Still greater : Error
in a,(CTRLReg) ; Read control reg
and MaskDriveSide ; Mask out all but drives & side
or CTLBSide + CTRLBMotor ; Select second side & turn on motor
out (CTRLReg),a
SeekToTrack:
in a,(CTRLReg) ; Read control reg
and MaskDriveSide ; Mask out all but drives & side
ld c,a ; Take a copy for later
or CTRLBMotor ; Mask in motor
out (CTRLReg),a ; Send it
in a,(CTRLReg) ; Read control reg
and MaskDriveSide ; Mask out all but drives & side
cp c ; Same as saved copy from above
jr nz,ld359h ; nope !
in a,(TrackReg) ; Read track reg
cp d ; Are we already on required track ?
jr z,ld35ch ; yes : skip
ld a,d ; get required track in a
out (DataReg),a ; put it in data reg
ld a,WDCmdSeek + WDCHeadLoad + WDCVerifyTrk + WDCStepRate
call DoDOSCMND ; Send seek command to FDC
jr c,ld359h ; Error : exit
bit 4,a ; Check for seek error
scf ;
jr z,ld35ch ; nope : return ok
ld359h:
ld a,DOSErrTimeOut ; Return error
or a ; set flags
ld35ch:
pop de ; Restore & return
pop bc
ret
ld35fh:
ld a,DOSErrInvDat ; Flag error
or a
jr ld35ch
;
; Execute an FDC command.
; Entry :
; A = FDC command byte
; Exit :
; A = FDC status byte. Carry set on error.
;
DoDOSCMND:
di ; Disable ints
push bc ; Save BC
ld bc,08000h ; Setup timeout count (was 4000h in MESS version).
out (CmdStatReg),a ; Send command to FDC
ld36bh:
in a,(INTReg) ; Check for int
rra ; get IntRQ flag into carry
jr nc,ld377h ; No int yet ? : continue waiting
in a,(CmdStatReg) ; Read FDC status
or a ; Set flags
ld373h:
pop bc ; Restore BC
jp DoEIRET ; Enable ints and return
ld377h:
call ShortDelay ; Wait a while
jr nz,ld36bh ; if no timeout : continue waiting
ld a,DOSErrTimeOut ; Return error
or a ; Set flags
scf ; Flag error
jr ld373h ; return
; Entry : BC=counter
; Exit : BC=BC-1, flags set for BC==0
ShortDelay:
dec bc ; Decrement count
ld a,b ; Set flags so we know when bc=0
or c
ex (sp),hl ; burn some time
ex (sp),hl
ex (sp),hl
ex (sp),hl
ret
;
; Write a track / Write sector.
; Entry :
; A = Drive
; D = Track
; E = Sector
; HL = Address of buffer
; Exit :
; A = FDC Error code.
;
DoDOSWTRK:
call DoDOSDSEL ; Select drive
ret nz ; Error : exit
ld a,WDCmdWriteTrack + WDCDelay5ms ; Write track command
jr ld398h
DoDOSWSCT:
call DoDOSDSEL ; Select drive
ret nz ; Error : exit
sub_d396h:
ld a,WDCmdWriteSec ; Write sector command
ld398h:
push hl ; Save buffer pointer
ld hl,(WORKSP) ; Get pointer to workspace
inc hl ; +1
ld (hl),a ; Save command
pop hl ; Restore buffer pointer
call sub_d3bbh ;d39f cd bb d3 . . .
ret z ; Error : exit
; Error so re-calibrate the drive and try again !
; Step in
ld a,WDCmdStepIn + WDCTrkUpdate + WDCHeadLoad + WDCStepRate
call sub_d3b7h ; Send to FDC
ret z ; Error : exit
; Restore to track 0 & verify
ld a,WDCmdRestore + WDCHeadLoad + WDCVerifyTrk + WDCStepRate
call sub_d3b7h ; Send to FDC
ret z ; Error : exit
; Step out
ld a,WDCmdStepOut + WDCTrkUpdate + WDCHeadLoad + WDCStepRate
call sub_d3b7h ; Send to FDC
ret z ; Error : exit
; Restore to track 0
ld a,WDCmdRestore + WDCHeadLoad + WDCStepRate
sub_d3b7h:
call DoDOSCMND ; Send to FDC
ret c ; ok : return
sub_d3bbh:
call SeekToSideTrack ; Seek to the required track
ret nz ; Return on error
ld a,e ; Get sector no
out (SectorReg),a ; Send it to FDC
push hl ; Save buffer ptr
ld hl,(WORKSP) ; Point to workspace
inc hl ; offset 1
ld a,(hl) ; Get current WD command
pop hl ; Restore buffer ptr
jr nc,SendCMDandData ; skip
cp WDCmdWriteTrack + WDCDelay5ms ; Is it write track ?
jr z,SendCMDandData ; Yes : skip
ld a,WDCmdWriteSec + WDCDelay5ms ; no : add delay to write sector
;
; Disable ints, the send command (in A) to FDC followed by data at HL.
;
SendCMDandData:
di ; Ints off
push bc ; Save regs
push hl
ld c,INTReg ; Read intreg when done
out (CmdStatReg),a ; Send command to FDC
ld3d8h:
ld a,(hl) ; Get data byte to send to FDC
inc hl ; update data ptr
ld3dah:
in b,(c) ; Poll int reg
jr z,ld3dah ; Wait until int happens
out (DataReg),a ; output data reg
jp m,ld3d8h ; IntRQ active yet ? no : do next byte
dec hl ; decrement data ptr
in a,(CmdStatReg) ; read status register
or a ; set flags
jr z,ld3ebh ; no error ? yep : return
pop hl ; Restore data ptr
push hl ; resave
ld3ebh:
pop bc ; Restore BC
pop bc
jp DoEIRET ; Enable ints and return
rst 38h ;d3f0 ff .
rst 38h ;d3f1 ff .
rst 38h ;d3f2 ff .
rst 38h ;d3f3 ff .
rst 38h ;d3f4 ff .
rst 38h ;d3f5 ff .
rst 38h ;d3f6 ff .
sub_nop1:
ret ;d3f7 c9 .
nop ;d3f8 00 .
nop ;d3f9 00 .
sub_nop2:
ret ;d3fa c9 .
nop ;d3fb 00 .
nop ;d3fc 00 .
sub_nop3:
ret ;d3fd c9 .
nop ;d3fe 00 .
nop ;d3ff 00 .
;;; START of second ROM
DoDOSCold:
jp cold1
DoDOSWarm:
rst 10h ; RCAL
defb (warm1-$)-1 ; Routine offset
jr warm2
;
; Cold start routine.
;
cold1:
ld sp,01000h ; Setup stack pointer
call 0000dh ; Init NAS-SYS
call sub_cold2 ;d40d cd 03 d8 . . .
ld hl,DoDOSWarm ; Point to warm start routine
ld a,(USRMCP) ; Check USRMCP vector
cp OpCodeJP ; has it been set ? (is it a jp instruction).
jr nz,ld41dh ; nope skip, use DoDOSWarm
ld hl,(USRMCP+1) ; get vector address into HL
ld41dh:
push hl ; Save USRMCP address
ld a,OpCodeJP ; Save a jp in cold start vector
ld (WFDC),a
ld (USRMCP),a ; and warm start vector
ld hl,DoDOSWarm ; Point to warm start routine
ld (USRMCP+1),hl ; Set jump address
ld hl,DOSCold ; Point to cold start routine
ld (WFDC+1),hl ; Set cold start jump address
ld a,05dh ; set command character to ]
ld (CMDCHR),a
ld hl,CMDTAB ; Point to command table
ld (WCMTAB),hl ; Save it
ret
warm1:
pop hl ; restore USRMCP .
ld (SUOUT+1),hl ; Save in user output jump
rst 28h ; Display signon message
defb '-- NAS-DOS 1 -->' ; Signon message
defb 'D40238' ; Dos serial number, printed on manual.
defb '<',00h
; Hacked version from MESS contained :
; defb 'Disc Operating System ',0
; at exit from RST $28 a will contain zero.
call DOSARH ; Call dos assembler routine handler function 0
ld bc,055dfh ; ????
rst 18h ; Call NAS-SYS
defb MRET ; return to NAS-SYS
;
; Scan input line for disk command ?
;
warm2:
push af ; Save AF
cp 00dh ; End of input line ?
jr z,ld46ah ; Yep : scan it
ld468h:
pop af ; Nope: restore & return