-
Notifications
You must be signed in to change notification settings - Fork 0
/
plus3ROM1.asm
8733 lines (8106 loc) · 184 KB
/
plus3ROM1.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
OUTPUT "p3t_rom1.rom"
ORG $0000
; **************************************************
; *** SPECTRUM +3 ROM 1 DISASSEMBLY (SYNTAX ROM) ***
; **************************************************
; The Spectrum ROMs are copyright Amstrad, who have kindly given permission
; to reverse engineer and publish Spectrum ROM disassemblies.
; =====
; NOTES
; =====
; ------------------------
; Disassembly Contributors
; ------------------------
; Garry Lancaster
;
; The ROM disassembly was created with the aid of dZ80 V1.10, and incorporates work from
; "The canonical list of +3 oddities" by Ian Collier.
; -----------------
; Assembler Details
; -----------------
; This file can be assembled to produce a binary image of the ROM
; with Interlogic's Z80ASM assembler (available for Z88, QL, DOS and Linux).
; Note that the defs directive is used and this causes a block of $00 bytes to be created.
;**************************************************
; +3DOS routine addresses
DEFINE DOS_INITIALISE $0100
DEFINE DOS_VERSION $0103
DEFINE DOS_OPEN $0106
DEFINE DOS_CLOSE $0109
DEFINE DOS_ABANDON $010C
DEFINE DOS_REF_HEAD $010F
DEFINE DOS_READ $0112
DEFINE DOS_WRITE $0115
DEFINE DOS_BYTE_READ $0118
DEFINE DOS_BYTE_WRITE $011B
DEFINE DOS_CATALOG $011E
DEFINE DOS_FREE_SPACE $0121
DEFINE DOS_DELETE $0124
DEFINE DOS_RENAME $0127
DEFINE DOS_BOOT $012A
DEFINE DOS_SET_DRIVE $012D
DEFINE DOS_SET_USER $0130
DEFINE DOS_GET_POSITION $0133
DEFINE DOS_SET_POSITION $0136
DEFINE DOS_GET_EOF $0139
DEFINE DOS_GET_1346 $013C
DEFINE DOS_SET_1346 $013F
DEFINE DOS_FLUSH $0142
DEFINE DOS_SET_ACCESS $0145
DEFINE DOS_SET_ATTRIBUTES $0148
DEFINE DOS_OPENDRIVE $014B
DEFINE DOS_SET_MESSAGE $014E
DEFINE DOS_REF_XDPB $0151
DEFINE DOS_MAP_B $0154
DEFINE DD_INTERFACE $0157
DEFINE DD_INIT $015A
DEFINE DD_SETUP $015D
DEFINE DD_SET_RETRY $0160
DEFINE DD_READ_SECTOR $0163
DEFINE DD_WRITE_SECTOR $0166
DEFINE DD_CHECK_SECTOR $0169
DEFINE DD_FORMAT $016C
DEFINE DD_READ_ID $016F
DEFINE DD_TEST_UNSUITABLE $0172
DEFINE DD_LOGIN $0175
DEFINE DD_SEL_FORMAT $0178
DEFINE DD_ASK_1 $017B
DEFINE DD_DRIVE_STATUS $017E
DEFINE DD_EQUIPMENT $0181
DEFINE DD_ENCODE $0184
DEFINE DD_L_XDPB $0187
DEFINE DD_L_DPB $018A
DEFINE DD_L_SEEK $018D
DEFINE DD_L_READ $0190
DEFINE DD_L_WRITE $0193
DEFINE DD_L_ON_MOTOR $0196
DEFINE DD_L_T_OFF_MOTOR $0199
DEFINE DD_L_OFF_MOTOR $019C
; +3DOS Error codes
DEFINE rc_ready $00
DEFINE rc_wp $01
DEFINE rc_seek $02
DEFINE rc_crc $03
DEFINE rc_nodata $04
DEFINE rc_mark $05
DEFINE rc_unrecog $06
DEFINE rc_unknown $07
DEFINE rc_diskchg $08
DEFINE rc_unsuit $09
DEFINE rc_badname $14
DEFINE rc_badparam $15
DEFINE rc_nodrive $16
DEFINE rc_nofile $17
DEFINE rc_exists $18
DEFINE rc_eof $19
DEFINE rc_diskfull $1A
DEFINE rc_dirfull $1B
DEFINE rc_ro $1C
DEFINE rc_number $1D
DEFINE rc_denied $1E
DEFINE rc_norename $1F
DEFINE rc_extent $20
DEFINE rc_uncached $21
DEFINE rc_toobig $22
DEFINE rc_notboot $23
DEFINE rc_inuse $24
;--------------------------------------------------
; The floating-point calculator commands
; include "fpcalc.def"
DEFINE jump_true $00
DEFINE EXchange $01
DEFINE delete $02
DEFINE SUBtract $03
DEFINE multiply $04
DEFINE DIvision $05
DEFINE to_power $06
DEFINE logic_or $07
DEFINE no_and_no $08
DEFINE no_l_eql $09
DEFINE no_gr_eq $0A
DEFINE nos_neql $0B
DEFINE no_grtr $0C
DEFINE no_less $0D
DEFINE nos_eql $0E
DEFINE ADDition $0F
DEFINE strandno $10
DEFINE str_l_eql $11
DEFINE str_gr_eq $12
DEFINE strs_neql $13
DEFINE str_grtr $14
DEFINE str_less $15
DEFINE strs_eql $16
DEFINE strs_add $17
DEFINE val_str $18
DEFINE usr_str $19
DEFINE read_in $1A
DEFINE NEGate $1B
DEFINE code $1C
DEFINE val $1D
DEFINE len $1E
DEFINE sin $1F
DEFINE cos $20
DEFINE tan $21
DEFINE asn $22
DEFINE acs $23
DEFINE atn $24
DEFINE ln $25
DEFINE EXp $26
DEFINE INt $27
DEFINE sqr $28
DEFINE sgn $29
DEFINE abs $2A
DEFINE peek $2B
DEFINE IN_port $2C
DEFINE usr_no $2D
DEFINE str_str $2E
DEFINE chr_str $2F
DEFINE not $30
DEFINE duplicate $31
DEFINE n_mod_m $32
DEFINE jump $33
DEFINE stk_data $34
DEFINE DEC_jr_nz $35
DEFINE less_0 $36
DEFINE greater_0 $37
DEFINE end_calc $38
DEFINE get_argt $39
DEFINE truncate $3A
DEFINE fp_calc_2 $3B
DEFINE e_to_fp $3C
DEFINE re_stack $3D
DEFINE series_06 $86
DEFINE series_08 $88
DEFINE series_0c $8C
DEFINE stk_zero $A0
DEFINE stk_one $A1
DEFINE stk_half $A2
DEFINE stk_pi_2 $A3
DEFINE stk_ten $A4
DEFINE st_mem_0 $C0
DEFINE st_mem_1 $C1
DEFINE st_mem_2 $C2
DEFINE st_mem_3 $C3
DEFINE st_mem_4 $C4
DEFINE st_mem_5 $C5
DEFINE get_mem_0 $E0
DEFINE get_mem_1 $E1
DEFINE get_mem_2 $E2
DEFINE get_mem_3 $E3
DEFINE get_mem_4 $E4
DEFINE get_mem_5 $E5
;--------------------------------------------------
.org $0000
; ROM 1 Header
m0000: DM "Syntax"
DS 2
; RST $08 - The "Error" restart
m0008: JP m2ada ; jump to error handler
DS 5
; RST $10 - The "Print a character restart"
m0010: RST 28H
DW $0010 ; call RST $10 in ROM 3
RET
DS 4
; RST $18 - The "Collect character" restart
m0018: RST 28H
DW $0018 ; call RST $18 in ROM 3
RET
DS 4
; RST $20 - The "Collect next character" restart
m0020: RST 28H
DW $0020 ; call RST $20 in ROM 3
RET
DS 4
; RST $28 : Call a routine in ROM 3, then return to ROM 1
; The address following the RST 28 instruction is called, then control
; is returned to the instruction following the address
m0028: EX (SP),HL ; save HL, get return address
PUSH AF ; save AF
LD A,(HL) ; A=low byte of address to call
INC HL
INC HL ; HL=address of instruction to return to
LD (RETADDR),HL ; save
m0030: DEC HL
LD H,(HL)
LD L,A ; HL=address to call in ROM 3
POP AF ; restore AF
JP m00aa ; jump on
NOP
; The maskable interrupt routine
m0038: PUSH AF ; save registers
PUSH HL
LD HL,(FRAMES) ; increment FRAMES
INC HL
LD (FRAMES),HL
LD A,H
OR L
JR NZ,m0048
INC (IY+$40)
m0048: PUSH BC
PUSH DE
CALL m0176 ; scan keyboard
CALL m0074 ; call disk motor timeout routine
POP DE ; restore registers
POP BC
POP HL
POP AF
EI ; re-enable interrupts & exit
RET
m0056: DM "Start: ", 0
m005e: DM "system", 0, 0
; The NMI routine
m0066: PUSH AF ; save registers
PUSH HL
LD HL,(NMIADD) ; get routine address
LD A,H
OR L
JR Z,m0070
JP (HL) ; execute if non-zero address
m0070: POP HL ; restore registers & exit
POP AF
RETN
; The disk motor timeout routine
m0074: LD BC,PBANKM
LD A,(BANKM)
OR $07
OUT (C),A ; page in page 7
LD A,(timeout)
OR A
JR Z,m00a1 ; move on if already off
LD A,(FRAMES)
BIT 0,A
JR NZ,m00a1 ; only decrement counter every other frame
LD A,(timeout)
DEC A ; decrement timeout counter
LD (timeout),A
JR NZ,m00a1 ; move on if non-zero
LD BC,PBANK678
LD A,(BANK678)
AND $F7
LD (BANK678),A
OUT (C),A ; turn motor off
m00a1: LD BC,PBANKM
LD A,(BANKM)
OUT (C),A ; page in last memory configuration
RET
; Continuation of RST 28: call a routine in ROM 3
m00aa: LD (TARGET),HL ; save ROM 3 address in TARGET
LD HL,REGNUOY
EX (SP),HL ; stack REGNUOY address beneath TOS
PUSH HL
LD HL,(TARGET) ; get HL=target address in ROM 3
EX (SP),HL ; restore HL & save target address on stack
PUSH AF ; stack AF & BC
PUSH BC
DI ; disable interrupts
JP STOO ; jump to STOO - pages in ROM 3, returns to
; target routine which returns to REGNUOY
; where ROM 1 is paged back and jump made
; back to RETADDR
; These are copies of the key tables from ROM 3
; The L-mode keytable with CAPS-SHIFT
m00bc: DM "BHY65TGV"
DM "NJU74RFC"
DM "MKI83EDX"
DM $0E, "LO92WSZ"
DM " ", $0D, "P01QA"
; The extended-mode keytable (unshifted letters)
m00e3: DB $E3,$C4,$E0,$E4
DB $B4,$BC,$BD,$BB
DB $AF,$B0,$B1,$C0
DB $A7,$A6,$BE,$AD
DB $B2,$BA,$E5,$A5
DB $C2,$E1,$B3,$B9
DB $C1,$B8
; The extended mode keytable (shifted letters)
m00fd: DB $7E,$DC,$DA,$5C
DB $B7,$7B,$7D,$D8
DB $BF,$AE,$AA,$AB
DB $DD,$DE,$DF,$7F
DB $B5,$D6,$7C,$D5
DB $5D,$DB,$B6,$D9
DB $5B,$D7
; The control code keytable (CAPS-SHIFTed digits)
m0117: DB $0C,$07,$06,$04
DB $05,$08,$0A,$0B
DB $09,$0F
; The symbol code keytable (letters with symbol shift)
m0121: DB $E2,$2A,$3F,$CD
DB $C8,$CC,$CB,$5E
DB $AC,$2D,$2B,$3D
DB $2E,$2C,$3B,$22
DB $C7,$3C,$C3,$3E
DB $C5,$2F,$C9,$60
DB $C6,$3A
; The extended mode keytable (SYM-SHIFTed digits)
m013b: DB $D0,$CE,$A8,$CA
DB $D3,$D4,$D1,$D2
DB $A9,$CF
; This is a copy of the "keyboard scanning" subroutine from
; o028E in ROM 3
m0145: LD L,$2F
LD DE,$FFFF
LD BC,$FEFE
m014d: IN A,(C)
CPL
AND $1F
JR Z,m0162
LD H,A
LD A,L
m0156: INC D
RET NZ
m0158: SUB $08
SRL H
JR NC,m0158
LD D,E
LD E,A
JR NZ,m0156
m0162: DEC L
RLC B
JR C,m014d
LD A,D
INC A
RET Z
CP $28
RET Z
CP $19
RET Z
LD A,E
LD E,D
LD D,A
CP $18
RET
; This is a copy of the "keyboard" subroutines from o02BF in ROM 3
m0176: CALL m0145
RET NZ
LD HL,KSTATE
m017d: BIT 7,(HL)
JR NZ,m0188
INC HL
DEC (HL)
DEC HL
JR NZ,m0188
LD (HL),$FF
m0188: LD A,L
LD HL,KSTATE+$04
CP L
JR NZ,m017d
CALL m01d5
RET NC
LD HL,KSTATE
CP (HL)
JR Z,m01c7
EX DE,HL
LD HL,KSTATE+$04
CP (HL)
JR Z,m01c7
BIT 7,(HL)
JR NZ,m01a8
EX DE,HL
BIT 7,(HL)
RET Z
m01a8: LD E,A
LD (HL),A
INC HL
LD (HL),$05
INC HL
LD A,(REPDEL)
LD (HL),A
INC HL
LD C,(IY+$07)
LD D,(IY+$01)
PUSH HL
CALL m01ea
POP HL
LD (HL),A
m01bf: LD (LAST_K),A
SET 5,(IY+$01)
RET
m01c7: INC HL
LD (HL),$05
INC HL
DEC (HL)
RET NZ
LD A,(REPPER)
LD (HL),A
INC HL
LD A,(HL)
JR m01bf
; This is a copy of the "K-Test" subroutine from o031E in ROM 3
m01d5: LD B,D
LD D,$00
LD A,E
CP $27
RET NC
CP $18
JR NZ,m01e3
BIT 7,B
RET NZ
m01e3: LD HL,m00bc ; the main keytable
ADD HL,DE
LD A,(HL)
SCF
RET
; This is a copy of the "Keyboard decoding" subroutine from o0333 in
; ROM 3
m01ea: LD A,E
CP $3A
JR C,m021e
DEC C
JP m,m0206
JR Z,m01f8
ADD A,$4F
RET
m01f8: LD HL,m00e3-"A"
INC B
JR Z,m0201
LD HL,m00fd-"A"
m0201: LD D,$00
ADD HL,DE
LD A,(HL)
RET
m0206: LD HL,m0121-"A"
BIT 0,B
JR Z,m0201
BIT 3,D
JR Z,m021b
BIT 3,(IY+$30)
RET NZ
INC B
RET NZ
ADD A,$20
RET
m021b: ADD A,$A5
RET
m021e: CP $30
RET C
DEC C
JP m,m0254
JR NZ,m0240
LD HL,m013b-"0"
BIT 5,B
JR Z,m0201
CP $38
JR NC,m0239
SUB $20
INC B
RET Z
ADD A,$08
RET
m0239: SUB $36
INC B
RET Z
ADD A,$FE
RET
m0240: LD HL,m0117-"0"
CP $39
JR Z,m0201
CP $30
JR Z,m0201
AND $07
ADD A,$80
INC B
RET Z
XOR $0F
RET
m0254: INC B
RET Z
BIT 5,B
LD HL,m0117-"0"
JR NZ,m0201
SUB $10
CP $22
JR Z,m0269
CP $20
RET NZ
LD A,$5F
RET
m0269: LD A,$40
RET
; The FORMAT command
m026c: RST 28H
DW $0018 ; get character after FORMAT
m026f: CP $E0
JP Z,m03e3 ; move on if LPRINT
CP $CA
JP Z,m1e02 ; move on if not LINE
CP $CC
JP Z,m1dd9
m027e: RST 28H
DW o1C8C ; get a string expression
CALL m10b1 ; check for end-of-statement
RST 28H
DW o2BF1 ; get string from stack
LD A,C
DEC A
DEC A
OR B
JR Z,m0291 ; move on if length is 2
m028d: CALL m2ada
DB $4E ; else error "Invalid drive"
m0291: INC DE
LD A,(DE) ; check 2nd char
DEC DE
CP ":"
JR Z,m029c
CALL m2ada
DB $4E ; error "Invalid drive" if not colon
m029c: LD A,(DE)
AND $DF ; get capitalised drive letter
CP "A"
JR Z,m02ab ; move on if A:
CP "B"
JR Z,m02ab ; or B:
CALL m2ada
DB $4E ; else error "Invalid drive"
m02ab: CALL m2b89 ; page in DOS workspace
SUB "A"
PUSH AF ; save unit number to format
LD HL,FLAGS3
BIT 4,(HL)
JR NZ,m02bf ; move on if disk interface present
CALL m2b64 ; page in normal memory
CALL m2ada
DB $4C ; else error "Format not supported on +2A"
m02bf: POP AF
OR A
JR Z,m02d3 ; move on for unit 0
PUSH AF
LD HL,FLAGS3
BIT 5,(HL)
JR NZ,m02d2 ; move on if drive B: present
CALL m2b64 ; page in normal memory
CALL m2ada
DB $4B ; else error "Drive B: not present"
m02d2: POP AF ; get unit
m02d3: PUSH AF
LD C,A
PUSH BC
ADD A,"A"
CALL m32b6 ; save TSTACK in page 7
CALL m3f00
DW DOS_REF_XDPB ; point IX at XDPB
CALL m32ee ; restore TSTACK
JR C,m02ec ; move on if no error
CALL m2b64 ; page in DOS memory
CALL m0e9a ; cause DOS error
DB $FF
m02ec: POP BC
CALL m32b6 ; save TSTACK in page 7
CALL m3f00
DW DD_LOGIN ; login disk
CALL m32ee ; restore TSTACK
JR NC,m0306 ; move on if error
OR A
JR NZ,m0315 ; move on if disk isn't +3 format
CALL m0381 ; ask if wish to abandon
JR NZ,m0315 ; move on if not
CALL m2b64 ; page in normal memory
RET ; exit
m0306: CP $05
JR Z,m0315 ; move on if error was "missing address mark"
CP $09
JR Z,m0315 ; or "unsuitable media"
CALL m2b64 ; page in normal memory
CALL m0e9a ; cause DOS error
DB $FF
m0315: POP AF ; get unit number
PUSH AF
ADD A,"A"
CALL m32b6 ; save TSTACK in page 7
CALL m3f00
DW DOS_REF_XDPB ; point IX to XDPB
CALL m32ee ; restore TSTACK
JR C,m032d
CALL m2b64 ; page in normal memory
CALL m0e9a ; cause any DOS error
DB $FF
m032d: XOR A
CALL m32b6 ; save TSTACK in page 7
CALL m3f00
DW DD_SEL_FORMAT ; select +3 format
CALL m32ee ; restore TSTACK
JR C,m0342
CALL m2b64 ; page in normal memory
CALL m0e9a ; cause any DOS error
DB $FF
m0342: POP AF
LD C,A ; C=unit number
XOR A ; start at track 0
m0345: LD D,A
CALL m036f ; fill format buffer
LD E,$E5 ; filler byte
LD B,$07 ; page 7
LD HL,tmp_buff ; buffer address
PUSH AF
CALL m32b6 ; save TSTACK in page 7
CALL m3f00
DW DD_FORMAT ; format a track
CALL m32ee ; restore TSTACK
JR C,m0365
CALL m2b64 ; page in normal memory
CALL m0e9a ; cause any DOS error
DB $FF
m0365: POP AF
INC A ; increment track
CP $28
JR NZ,m0345 ; back if more to do
CALL m2b64 ; page in normal memory
RET ; done
; Subroutine to fill scratch area with format buffer details
m036f: LD B,$09 ; 9 sectors
LD HL,tmp_buff+$23 ; end of scratch area
m0374: LD (HL),$02 ; 512-byte sectors
DEC HL
LD (HL),B ; sector number
DEC HL
LD (HL),$00 ; head 0
DEC HL
LD (HL),D ; track number
DEC HL
DJNZ m0374
RET
; Subroutine to display "disk already formatted message",
; and get a key, exiting with Z set if user wishes to abandon
m0381: LD HL,m03a7
m0384: LD A,(HL) ; get next char
OR A
JR Z,m038e ; move on if null
RST 28H
DW $0010 ; output char
m038b: INC HL
JR m0384 ; loop back
m038e: RES 5,(IY+$01) ; signal "no key"
m0392: BIT 5,(IY+$01)
JR Z,m0392 ; wait for key
LD A,(LAST_K) ; get key
AND $DF ; capitalise
CP "A" ; is it "A"?
PUSH AF
PUSH HL
RST 28H
DW o0D6E ; clear lower screen
POP HL
POP AF
RET ; exit with Z set if abandon requested
; Formatting message
m03a7: DM "Disk is already formatted.", $0D
DM "A to abandon, other key continue", 0
; The FORMAT LPRINT command
m03e3: RST 28H
DW $0020 ; get next char
m03e6: RST 28H
DW o1C8C ; get string expression
RST 28H
DW $0018 ; get next char
m03ec: CP $3B
CALL NZ,m10b1 ; check for end-of-statement if not $3B
JR NZ,m041c ; move on if not $3B
RST 28H
DW $0020 ; get next char
m03f6: RST 28H
DW o1C8C ; get string expression
CALL m10b1 ; check for end-of-statement
RST 28H
DW o2BF1 ; get 2nd string from stack
LD A,C
DEC A
OR B ; check length
JR Z,m0407
JP m028d ; "Invalid drive" error if not 1
m0407: LD A,(DE)
AND $DF ; capitalise 2nd string character
LD HL,FLAGS3 ; prepare to change FLAGS3
CP "E"
JR NZ,m0415
m0411: SET 2,(HL) ; if 2nd string "E", set "expand tokens" flag
JR m041c
m0415: CP "U"
JP NZ,m028d ; if 2nd string not "U", error
RES 2,(HL) ; if "U", reset "expand tokens" flag
m041c: RST 28H
DW o2BF1 ; get first string from stack
LD A,C
DEC A
OR B ; check length
JR Z,m0427
JP m028d ; "Invalid drive" error if not 1
m0427: LD A,(DE)
AND $DF ; capitalise 1st string character
LD HL,FLAGS3 ; prepare to change FLAGS3
CP "R"
JR NZ,m0434
SET 3,(HL) ; if "R", set print to RS232 flag
RET
m0434: CP "C"
JR NZ,m043b
RES 3,(HL) ; if "C", reset print to RS232 flag
RET
m043b: CP "E"
JR NZ,m0442
SET 2,(HL) ; if "E", set "expand tokens" flag
RET
m0442: CP "U"
JP NZ,m028d ; if not "U", error
RES 2,(HL) ; if "U", reset "expand tokens" flag
RET
; The ERASE command
; *BUG* No channel is opened before outputting the "Erase (Y/N)?" message,
; so this is output to the last used stream.
; *BUG* The lower screen is not cleared if "N" is pressed
m044a: RST 28H
DW o2BF1 ; get string from stack
LD A,B
OR C ; check length
JR NZ,m0455
CALL m2ada
DB $2C ; bad filename error if zero
m0455: PUSH BC ; save addresses
PUSH DE
PUSH DE
POP HL ; HL=address of filename
PUSH BC
LD A,"*"
CPIR
POP BC
JR Z,m046d ; move on if * wildcard present
PUSH DE
POP HL
PUSH BC
LD A,"?"
CPIR
POP BC
JR Z,m046d ; move on if ? wildcard present
JR m0499 ; move on for a single file
m046d: LD HL,merase
CALL m04c1 ; output "Erase "
CALL m04ca ; output filespec
LD HL,myn
CALL m04c1 ; output "? (Y/N"
m047c: LD HL,FLAGS
RES 5,(HL) ; signal "no key available"
m0481: BIT 5,(HL)
JR Z,m0481 ; loop until keypress
RES 5,(HL) ; signal "no key available"
LD A,(LAST_K) ; get key
AND $DF ; make uppercase
CP "N"
JR NZ,m0493 ; move on if not "N"
POP DE ; exit without doing anything
POP BC ; (lower screen should have been cleared)
RET
m0493: CP "Y"
JR Z,m0499
JR m047c ; loop back for another key if not "Y"
m0499: RST 28H
DW o0D6E ; clear lower screen
POP DE
POP BC
LD HL,tmp_fspec
EX DE,HL
CALL m3f63 ; copy filespec into page 7
CALL m2b89 ; page in DOS workspace
LD A,$FF
LD (DE),A ; add terminator
LD HL,tmp_fspec
CALL m32b6 ; save TSTACK in page 7
CALL m3f00
DW DOS_DELETE ; delete filespec
CALL m32ee ; restore TSTACK
CALL m2b64 ; page in normal memory
RET C ; exit if ok
CALL m0e9a ; cause DOS error
DB $FF
; Subroutine to output a null-terminated string
m04c1: LD A,(HL) ; get next char
OR A
RET Z ; exit if null
INC HL
RST 28H
DW $0010 ; output char
m04c8: JR m04c1 ; loop back
; Subroutine to output a filespec at DE, length BC
m04ca: LD A,(DE) ; get next char
RST 28H
DW $0010 ; output char
m04ce: INC DE
DEC BC
LD A,B
OR C
JR NZ,m04ca ; back for more
RET
; Erase messages
m04d5: RST 28H
DW $C101
LD (BC),A
INC (HL)
LD B,B
LD B,C
NOP
NOP
LD ($38E1),A
RET
DB 0,0,0
; The MOVE command
m04e5: RST 28H
DW o2BF1 ; get 2nd string
LD A,B
OR C ; check length
JR NZ,m04f0
CALL m2ada
DB $2C ; bad filename error if zero
m04f0: LD A,(DE)
CP '+'
JP Z,m0541 ; move on if changing attributes
CP '-'
JP Z,m0541 ; move on if changing attributes
LD HL,tmp_fspec
EX DE,HL
CALL m3f63 ; copy filename to page 7
CALL m2b89 ; page in DOS workspace
LD A,$FF
LD (DE),A ; add terminator
m0508: INC DE
CALL m2b64 ; page in normal memory
PUSH DE ; save pointer for source filename
RST 28H
DW o2BF1 ; get 1st string
LD A,B
OR C ; check length
JR NZ,m0518
CALL m2ada
DB $2C ; bad filename error if zero
m0518: POP HL ; HL=address to place source filename
PUSH HL
EX DE,HL
CALL m3f63 ; copy source filename to page 7
CALL m2b89 ; page in DOS workspace
LD A,$FF
LD (DE),A ; add terminator
CALL m2b64 ; page in normal memory
POP HL
LD DE,tmp_fspec
CALL m2b89 ; page in DOS workspace
CALL m32b6 ; save TSTACK in page 7
CALL m3f00
DW DOS_RENAME ; do rename
CALL m32ee ; restore TSTACK
CALL m2b64 ; page in normal memory
RET C ; exit if done ok
CALL m0e9a ; cause DOS error
DB $FF
; Here we use MOVE to alter attributes of a file
m0541: LD A,C
DEC A
DEC A
OR B
JR Z,m054b ; move on if 2nd string length=2
CALL m2ada
DB $47 ; invalid attribute error
m054b: LD A,(DE)
LD B,A ; B='+' or '-'
INC DE
LD A,(DE)
AND $DF ; A=uppercase attribute
CP "P" ; check attribute letter
JR Z,m0561
CP "S"
JR Z,m0561
CP "A"
JR Z,m0561
CALL m2ada