forked from prime6809/NASDOS
-
Notifications
You must be signed in to change notification settings - Fork 0
/
nasdos_sd.asm
executable file
·3153 lines (2629 loc) · 73 KB
/
nasdos_sd.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/
;
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:
include "sd_sub2.asm" ; does HW init & training then falls through
;;; Restore the default drives for NASDOS (Profile 1)
ld a, CPRES+1
call putcmd
call t2rs2t ;get status, but ignore it [NAC HACK 2020Jun24] die if not mounted??
push hl ; save HL
ld hl,(WORKSP) ; get pointer to workspace in RAM
ld (hl),0ffh ; Set first byte
pop hl ; Restore HL & return
xor a ; signal success
ret
;
; Format a disk.
; Entry :
; A = logical drive no to format.
;
DoDOSFRMT:
push af ; Save AF
rst 18h ; SCAL
defb ERRM ; exit with error
pop af ; Restore
ld a,0ffh ; Flag error
or a
ret
;; Drive/Track/Sector to Drive/Offset
;; Internal subroutine
;; entry:
;; A = drive (0-7)
;; D = track
;; E = sector
;; return with
;; A = drive (0-3) - incoming value / 2
;; DE = bits 23:8 of file offset, incorporating the
;; side bit from A
;;
;; NO OTHER REGISTERS AFFECTED
;; NAS-DOS numbers sectors from 1 so the first thing to do
;; is to decrement the sector number
;2 2 2 2 1 1 1 1 1 1 1 1 1 1
;3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 byte offset in disk image
; o o o o o o o o offset within 256-byte sector
; s s s s 4-bit sector
; S 1-bit Side (for interleaving 2-sided disk images)
; t t t t t t t 7-bit track
;D D D D D D D D E E E E E E E E DE out
DTS2DO:
dec e ;reference sectors to 0 rather than 1
push bc ;preserve
srl a ;drive logical->physical
ld b, a ;preserve physical drive
jr nc, side0
;; odd logical drive maps to SIDE=1
set 4, e ;set SIDE=1 in E
side0: ld a, d ;get track
sla a ;move LS bit of track to b1
sla a ;to b2
sla a ;to b3
sla a ;to b4
sla a ;to b5
or e ;merge S and s bits to track bits in A
ld e, a ;E is now complete
srl d ;get rid of track b0
srl d ;get rid of track b1
srl d ;get rid of track b2. D is now complete
ld a, b ;restore physical drive
pop bc ;restore
ret ;done
;
; Read a track / Read sector.
; Entry :
; A = Drive
; D = Track
; E = Sector
; HL = Address of buffer
; Exit :
; A = FDC Error code.
;
DoDOSRTRK:
ld a, $42
or a
ret ; Error : exit [NAC HACK 2020Jul09] TODO!! Cannot really implement it. Probably never used. I don't even think it works.
DoDOSRSCT:
call DTS2DO ; Convert to linear addressing
push af ; preserve drive ID (fid)
or CSEEK ; merge seek with fid
call putcmd ; send command to SDcard
;;; send 32-bit offset formed by DE*256 (trivial!)
xor a
call putval ;LS byte of count
ld a,e
call putval ;next byte of count
ld a,d
call putval ;next byte of count
xor a
call putval ;MS byte of count
call t2rs2t ;Get status in A
;; 0 = error so Z => error
;;; read. Data to HL. 1 sector of 256 bytes.
pop af ;restore drive ID (fid)
or CSRD ;sector read; 256 bytes
call putcmd
call gorx
push bc
ld b,0 ;counts as 256
rdsect: call getval
ld (hl),a
inc hl
djnz rdsect ;read data loop for 1 sector
pop bc
call rs2t ;get status in A, set flags, go back to tx
;; status from Arduino: 1=success, 0=fail so Z => error
;; but NAS-DOS expects 0 = success, non-zero = error code.
;; (actually, PolyDos is the same..)
; xor 1 ;now, 0=> success.
xor a ;clear A, set Z => success.
ret
;;; [NAC HACK 2019Oct30] temp!!
;;; need to make sure drive ID is legal, and maybe do some other stuff here?
DoDOSDSEL: ret
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:
ld a, $42
or a
ret ; Error : exit [NAC HACK 2020Jul09] TODO!! Cannot really implement it. Probably never used. I don't even think it works. Even format does not use it.
;;; [NAC HACK 2020Jul12] review where WORKSP +0 (PHYSDRV) and +1 (WDCMD) are used and why.. do I need to replicate; which parts of the code use them etc.
DoDOSWSCT:
call DTS2DO ; Convert to linear addressing
push af ; preserve drive ID (fid)
or CSEEK ; merge seek with fid
call putcmd ; send command to SDcard
;;; send 32-bit offset formed by DE*256 (trivial!)
xor a
call putval ;LS byte of count
ld a,e
call putval ;next byte of count
ld a,d
call putval ;next byte of count
xor a
call putval ;MS byte of count
call t2rs2t ;Get status in A
;; 0 = error so Z => error
;;; write. Data at HL. 1 sector of 256 bytes.
pop af ; restore drive ID (fid)
or CSWR ; sector write; 256 bytes
call putcmd
push bc
ld b,0 ;counts as 256
wrsect: ld a,(hl)
call putval
inc hl
djnz wrsect ;write data loop for 1 sector
pop bc
call t2rs2t ;get status in A, set flags, go back to tx
;; status from Arduino: 1=success, 0=fail so Z => error
;; but NAS-DOS expects 0 = success, non-zero = error code.
;; (actually, PolyDos is the same..)
; xor 1 ;now, 0=> success.
xor a ;clear A, set Z => success.
ret
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 .
;;; Defines and low-level subroutines
include "sd_sub_defs.asm"
include "sd_sub1.asm"
;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; more subroutines, just for these utilities.
;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; go from tx to rx, get status then go to tx.
;;; Set flags based on status byte
;;; corrupts: AF
t2rs2t: call gorx
;;; FALL-THROUGH and subroutine
;;; get status then go to tx.
;;; Set flags based on status byte
;;; corrupts: AF
rs2t: call getval ;status
call gotx ;does not affect A
or a ;update flags
ret
ROM0SZ: EQU $ - DOSCold
PAD0: EQU 400h - ROM0SZ
DS PAD0, 0ffh
;;; 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
ret
ld46ah:
ld hl,(CURSOR) ; Get pos of cursor
rst 18h ; SCAL
defb CPOS ; Get address of first character of it's line
ld a,(CMDCHR) ; Get command character
cp (hl) ; Is it our command character ?
jr nz,ld468h ; Nope : exit
ld b,a ; b= command char
ld (hl),020h ; replace with space
rst 18h ; SCAL
defb CRLF ; Output CR LF
ld hl,(CURSOR) ; Get pos of cursor
ld de,0ffc0h ; DE=-40h
add hl,de ; HL=HL-40h, point to line before
ld a,b ; recover command char
ld (hl),a ; put it back in line
ex de,hl ; point de at command line
inc de ; move past command char
ld a,(de) ; get char of actual command
cp 041h ; is it A or after ?
jr c,ld468h ; nope : exit
cp 05bh ; is it before Z
jr nc,ld468h ; nope : exit
ld (00ffeh),sp ; Make some room on stack
ld sp,00ffeh
push af ;
sub 041h ; convert command to binary
sla a ; convert to table offset
push de ; save command line pointer
ld e,a ; Transfer offset to DE
ld d,000h ; Zero MSB
ld hl,(WCMTAB) ; get address of table
add hl,de ; point to table entry for this command
ld e,(hl) ; Get address of routine into DE
inc hl
ld d,(hl)
ex de,hl ; save address of comand into hl
pop de ; restore command line pointer
inc de ; move to next character on command line
pop af ; restore
ld bc,DOSCmdOk ;
push bc
jp (hl) ; execute command routine
DOSCmdErr:
rst 18h ; Output 'Error'
defb ERRM
jr ld4b8h ; Exit : command done
DOSCmdOk:
rst 28h ; Display ok message.
defb 'Ok.', 00dh, 000h
ld4b8h:
ld sp,(00ffeh) ; Restore Stack pointer
pop af ; Restore AF
xor a ; Zero A .
ret ; Return to caller
;
; Load a basic program
; ]Bd:fname
; on entry DE points to the command line after the command byte
;
DOSCmdB:
call ReadDriveID ; Read drive ID & set drive
call ReadFilename ; Read filename
jr nc,ld4dah ; Found : skip on
; Filename not found on command line, look for it on the first line of
; basic program
ld de,(BASTXT) ; Get pointer to start of basic text
inc de ; Increment past link & line number
inc de
inc de
inc de
ld a,(de) ; Get a byte from basic
cp TokREM ; Is the first line a REM ?
jr nz,DOSCmdErr ; Nope : error
inc de ; Move past it
call ReadFilename ; Try to read filename from basic
jr c,DOSCmdErr ; Error if not found
ld4dah:
ld hl,(PROGND) ; Get address of end of program
ld (VAREND),hl ; Set end of variables & arrays to same address
ld (ARREND),hl
ex de,hl ; Save end of save area
ld hl,BASBaseAddr ; Point to base address of basic
ld bc,ld7fdh ;
jp ld65eh ;
;
; Clean directory
; ]Cd
; Warning corrupts memory from 01000h to 02c00h
;
DOSCmdC:
call ReadDriveID ; Read drive ID & set drive
call DOSCmdSure ; Verify user wants to proceed, exit if not
; fill 01e00h-02c00h with 0FFh
ld hl,01e00h ; Beginning of block
ld (hl),0ffh ; Set first byte
ld de,01e01h ; dest 1 byte further on
ld bc,00dffh ; Count
ldir ; fill memory
ld hl,DIRCleanAddr ; Load at 1000h
ld de,DIRFirstSec ; Track (D) =0 , first sector (E)
ld bc,DIRSize ; Sectors in dir
ld a,(WDRV) ; Get drive
push af ; Save params for later
push bc
push de
call DOSARH ; Call dos to read dir
defb AREAD
ld hl,DIRCleanAddr ; Scan loaded dir
ld de,DIRNewAddr ; Into new buffer as cleaned
push de ; Save new buff ptr
ld b,DIREntryCount ; Process up to this many entries
ld51ch:
ld a,(hl) ; Fetch a byte from buffer
cp DIRDeleted ; Deleted file ?
jr z,ld52ch ; Yes : skip past
jr nc,ld534h ; End of dir entries ? yep : exit
push bc ; Save entry count
ld bc,DIREntryLen ; Copy entry to new buffer
ldir
pop bc ; Restore entry count
jr ld532h ; skip
ld52ch:
push de ; Save new buff ptr
ld de,DIREntryLen ; Skip past deleted in source
add hl,de
pop de ; Restore new buff ptr
ld532h:
djnz ld51ch ; if more entries keep going
ld534h:
pop hl ; Restore location, size etc of dir
pop de
pop bc
pop af
call DOSARH ; Re-save cleaned dir.
defb ASAVE
ret
;
; display the directory from a drive
; ]Dd
;
DOSCmdD:
call ReadDriveID ; Read drive ID & set drive
rst 28h ; Print text
defb ' Id:',000h
call DOSARH ; Read directory header
defb AREADH
rst 10h ; RCAL
defb (OutputFilename-$)-1 ; display filename
call DOSARH ; Open directory
defb AOPEND
ld hl,00000h ;
push hl ;
ld554h:
rst 28h ; Print text
defb 00dh
defb ' File name Exec Load Size Tr Sc'
defb 00dh, 000h
ld d,00ch ; Print 12 lines per page
ld57ch:
call DOSARH ; Read directory
defb AREADD
jr c,ld5d5h ; Done all : exit
rst 28h ; Print stringz
defb ' ',000h ; left margin
ld a,(WDDRV) ; Get working drive
or 030h ; convert to ASCII
rst 30h ; print it
ld58ch:
ld a,DOSSeperator ; Print seperator
rst 30h
rst 10h ; RCAL
defb (OutputFilename-$)-1 ; offset
rst 28h ; Print stringz
defb ' ',000h ; space after filename
ld l,(ix+000h) ; Retrieve exec address
ld h,(ix+001h)
push de ; Save DE
ld e,(ix+002h) ; Retrieve load address
ld d,(ix+003h)
rst 18h ; SCAL
defb TX1 ; Output HL (exec) and DE (load) as hex
pop de ; Restore DE
ld5a5h:
ld l,(ix+006h) ; Retrieve size
ld h,(ix+007h) ;
push hl ; Save it
rst 18h ; SCAL
defb TBCD3 ; output size as hex
ld a,(ix+004h) ; Retrieve start track
rst 18h ; SCAL
defb B2HEX ; Output it
rst 18h ; SCAL
defb SPACE ; output a space
ld a,(ix+005h) ; Retrieve start sector
rst 18h ; SCAL
defb B2HEX ; Output it
rst 18h ; SCAL
defb CRLF ; Output EOL
pop bc ; Restore regs
pop hl ; running total of used sectors
add hl,bc ; Add current file total to running total
push hl ; Save running total
dec d ; done all files in this page ?
jr nz,ld57ch ; nope : loop again
call WaitKeyWithCursor ; Wait for a keypress
jr ld554h ; do next page
OutputFilename:
ld b,DOSMaxFNLen ; filename length
ld5cah:
ld a,(ix+000h) ; get character from buffer
and 07fh ; make it 7 bit ASCII
rst 30h ; Print it
inc ix ; increment buffer pointer
djnz ld5cah ; loop if more characters
ret ; return
ld5d5h:
pop de ; Restore DE
ld hl,DOSDataSecs ; Max data sectors per disk
or a ; clear carry
sbc hl,de ; Calculate free sectors
rst 18h ; SCAL
defb TBCD3 ; Output HL as hex
rst 28h ; output stringz
defb 'sctrs',00dh,000h
ret
;
; Execute a file
; ]Ed:filename
;
DOSCmdE:
call ReadIDFilename ; Read drive ID and filename
call DOSARH ; Load / Chain file
defb ACHAIN
jr ld62ch ; Error if it returns (fails).
;
; Format a disk
; ]Fd:diskname:
;
DOSCmdF:
call ReadIDFilename ; Read drive ID and filename
call DOSCmdSure ; Prompt user to confirm
ld a,(WDRV) ; Get drive id
call DOSARH ; Tell dos to format disk
defb AFORM
push af ; Save drive id
call DOSARH ; Read dir header
defb AREADH
push ix ; de=ix, loaded sec address
pop de
ld bc,00008h ; 8 bytes
ld hl,(WFILE) ; point at disk filename
ldir ; copy into sector
ld hl,ld7c6h ; Point at 'random' number
ld bc,00003h ; 3 bytes
ldir ; copy into sector
call DOSARH ; resave disk header
defb ASAVEH
pop af ;d619 f1 .
inc a ;d61a 3c <
ret nz ;d61b c0 .
rst 28h ;d61c ef .
defb 'Fmt.',000h
jr ld62ch ;d622 18 08 . .
;
; Load a file, do not execute.
; ]Ld:filename
;
DOSCmdL:
call ReadIDFilename ; Read drive ID and filename
call DOSARH ; Read whole file
defb AREADF
ret nc ; Return if no error else fall through
ld62ch:
jp DOSCmdErr ;d62c c3 ae d4 . . .
;
; Save object code
; ]Od:filename:llll hhhh eeee (low addr, high addr, exec addr).
;
DOSCmdO:
call ReadIDFilename ; Read drive ID and filename
rst 18h ; SCAL
defb RLIN ; Read HEX words to ARGS
jr c,ld62ch ; Error :
ld a,(ARGN) ; Get the number of arguments converted
cp 003h ; must be 3
jr nz,ld62ch ; Error : invalid no of args
rst 18h ; SCAL
defb ARGS ; Collect args
rst 10h ; RCAL
defb (ld65eh-$)-1 ; Save the file
jp ClearARGS ; Skip
;
; Save a NAS-PEN file
; ]Pd:filename
;
DOSCmdP:
call ReadDriveID ; Read drive ID from command line
call ReadFilename ; Read filename from command line
jr nc,ld654h ; Got it, skip