-
Notifications
You must be signed in to change notification settings - Fork 8
/
auxmem.hostfs.s
1081 lines (1003 loc) · 37.9 KB
/
auxmem.hostfs.s
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
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
* AUXMEM.HOSTFS.S
* (c) Bobbi 2021 GPL v3
*
* AppleMOS Host File System
* 29-Aug-2021 Generalised CHKERROR routone, checks for and
* translates ProDOS errors into Acorn errors
* Set &E0=&FF for testing to report ProDOS errors
* 30-Aug-2021 FSC commands moved to here
* Command line set by *RUN, and read by OSARGS
* 20-Sep-2021 *FREE uses new PRDECIMAL routine
* 12-Oct-2021 OSFIND checks return value from calling maincode.
* 12-Oct-2021 BGET and BPUT check for returned error.
* 13-Oct-2021 FIND, BGET, BPUT optimised passing registers to main.
* 13-Oct-2021 ARGS, EOF returns errors, optimised passing registers.
* 14-Oct-2021 Tidied FILE handler.
* 23-Oct-2021 Uses single dispatch to mainmem FILE handler.
* 24-Oct-2021 Tidied FSC handler. Optimised CATALOG, CAT shows access.
* *EX can use two columns. *OPT stored.
* 29-Oct-2021 Bad *command->Bad command, bad *RUN->File not found.
* Optimised RENAME, COPY, CHDIR, DRIVE. FREE<cr> allowed.
* 01-Oct-2021 DRIVE, CHDIR shares same code, checking moved to maincode.
* 02-Oct-2021 ACCESS uses generic access byte parsing.
* PRACCESS shares code with ACCESS.
* 03-Oct-2021 PARSNAME checks filename length<64.
* 09-Oct-2022 Sorted commands into order.
* $B0-$BF Temporary filing system workspace
* $C0-$CF Persistant filing system workspace
FSXREG EQU $C0
FSYREG EQU $C1
FSAREG EQU $C2
FSZPC3 EQU $C3 ; (unused so far)
FSCTRL EQU FSXREG ; =>control block
FSPTR1 EQU $C4 ; =>directory entry
FSPTR2 EQU $C6 ; (unused so far)
FSNUM EQU $C8 ; 32-bit number, cat file count
FSACCBYTE EQU FSNUM+1 ; access bits
FSZPCC EQU $CC ; (unused so far)
FSCMDLINE EQU $CE ; command line address
* OSFIND - open/close a file for byte access
FINDHND PHX
PHY
PHA
CMP #$00 ; A=$00 = close
BEQ :CLOSE
PHA
JSR PARSNAME ; Copy filename->MOSFILE
PLA ; Recover options
>>> XF2MAIN,OFILE
:CLOSE >>> XF2MAIN,CFILE ; Pass A,Y to main code
OSFINDRET >>> ENTAUX
JSR CHKERROR ; Check if error returned
PLY ; Value of A on entry
BNE :S1 ; It wasn't close
TYA ; Preserve A for close
:S1 PLY
PLX
RTS
* OSGBPB - Get/Put a block of bytes to/from an open file
* Supports commands A=1,2,3,4 others unsupported
GBPBHND CMP #4
BCC :S1
RTS ; Not supported: regs unchanged
:S1 PHX
PHY
PHA
>>> WRTMAIN
STX GBPBAUXCB+0 ; Copy address of control block ..
STY GBPBAUXCB+1 ; .. to main mem
>>> WRTAUX
JSR XYtoLPTR ; Copy control block to GBPBBLK ..
LDY #$0C ; .. in main memory
>>> WRTMAIN
:L1 LDA (OSLPTR),Y
STA GBPBBLK,Y
DEY
BPL :L1
>>> WRTAUX
PLA ; A => OSGBPB command
>>> XF2MAIN,GBPB
OSGBPBRET >>> ENTAUX
PLY
PLX
PHY
LDY #$05 ; Check if bytes left = 0
LDA (OSLPTR),Y
BNE :BYTESLEFT
INY
LDA (OSLPTR),Y
BNE :BYTESLEFT
CLC
BRA :S2
:BYTESLEFT SEC ; Set carry if bytes left
:S2 PLY
LDA #$00 ; A=0 means supported command
RTS
* OSBPUT - write one byte to an open file
BPUTHND PHX
PHY
PHA ; Stash char to write
>>> XF2MAIN,FILEPUT ; Pass A,Y to main code
OSBPUTRET >>> ENTAUX
JSR CHKERROR
CLC ; Means no error
PLA
PLY
PLX
RTS
* OSBGET - read one byte from an open file
BGETHND PHX
PHY
>>> XF2MAIN,FILEGET ; Pass A,Y to main code
OSBGETRET >>> ENTAUX
CPY #$01
BCC :EXIT ; If no error, return CC
LDA #$FE
CPY #$4C
BEQ :EXIT ; If at EOF, return CS
TYA
JSR CHKERROR
:EXIT PLY
PLX
RTS
* OSARGS - adjust file arguments
* On entry, A=action
* X=>4 byte ZP control block
* Y=file handle
* Y<>0 A=FF Flush channel Y
* A=00 Read PTR#Y
* A=01 Write PTR#Y
* A=02 Read EXT#Y
* A=03 Write EXT#Y
* (A=04 Read alloc#Y)
* (A=05 Read EOF#Y)
* (A=06 Write alloc#Y)
* Y=0 A=FF Flush all channels
* A=00 Return filing system number in A
* A=01 Read command line address
* (A=02 Read NFS bugfix flag)
* (A=03 Read LIBFS filing system)
* (A=04 Read used disk space)
* (A=05 Read free disk space)
* On exit, A=0 - implemented (except ARGS 0,0)
* A - preserved=unimplemented
* X,Y - preserved
* control block updated for 'read' calls
* control block preserved otherwise
*
ARGSHND PHX
PHY
PHA
CPY #$00
BNE :HASFILE
CMP #$00 ; Y=0,A=0 => current file sys
BNE :S1
PLA
LDA #105 ; 105=AppleFS filing system
PLY
PLX
RTS
:S1 CMP #$01 ; Y=0,A=1 => addr of CLI
BNE :S2
LDA FSCMDLINE+0
STA $00,X
LDA FSCMDLINE+1
STA $01,X
LDA #$FF
STA $02,X
STA $03,X
JMP OSARGSDONE ; Implemented
:S2 CMP #$FF ; Y=0,A=FF => flush all files
BNE :IEXIT
JMP :FLUSH
:IEXIT JMP :EXIT ; Exit preserved
:HASFILE CMP #$00 ; Y!=0,A=0 => read seq ptr
BNE :S3
TXA
>>> XF2MAIN,TELL ; A=ZP, Y=channel
:S3 CMP #$01 ; Y!=0,A=1 => write seq ptr
BNE :S4
>>> WRTMAIN
STY GMARKPL+1 ; Write to MLI control block
LDA $00,X
STA GMARKPL+2
LDA $01,X
STA GMARKPL+3
LDA $02,X
STA GMARKPL+4
>>> WRTAUX
>>> XF2MAIN,SEEK ; A=???, Y=channel
:S4 CMP #$02 ; Y!=0,A=2 => read file len
BNE :S5
TXA
>>> XF2MAIN,SIZE ; A=ZP, Y=channel
:S5 CMP #$FF ; Y!=0,A=FF => flush file
BNE :EXIT
:FLUSH >>> XF2MAIN,FLUSH
:EXIT PLA ; Unimplemented
PLY
PLX
RTS
OSARGSRET >>> ENTAUX
JSR CHKERROR
OSARGSDONE PLA
LDA #0 ; Implemented
PLY
PLX
RTS
* OSFILE - perform actions on entire files/objects
* On entry, A=action
* XY=>control block
* On exit, A=preserved if unimplemented
* A=0 object not found (not load/save)
* A=1 file found
* A=2 directory found (not load/save)
* XY preserved
* control block updated
*
OSFILEMIN EQU $FF ; $FF=LOAD
OSFILEMAX EQU $08 ; $08=MKDIR
FILEHND PHX
PHY
PHA
CLC
ADC #256-OSFILEMIN
CMP #OSFILEMAX+257-OSFILEMIN ; NB: LtoR evaluation
BCS FILEIGNORE
STX FSCTRL+0 ; FSCTRL=>control block
STY FSCTRL+1
LDA (FSCTRL) ; XY=>filename
TAX
LDY #$01
LDA (FSCTRL),Y
TAY
JSR PARSNAME ; Copy filename->MOSFILE
LDY #$11
>>> WRTMAIN
:L1 LDA (FSCTRL),Y ; Copy control block to auxmem
STA FILEBLK,Y
DEY
BPL :L1
>>> WRTAUX
PLA ; Get action back
>>> XF2MAIN,CALLFILE
* On return here, A<$20 return to caller, A>$1F ProDOS error
OSFILERET >>> ENTAUX
JSR CHKERROR ; Check if error returned
PHA
LDY #$11 ; Copy updated control block back
:L3 LDA OSFILECB,Y ; Mainmem left it in OSFILECB
STA (FSCTRL),Y
DEY
BPL :L3
FILEIGNORE PLA ; Returned object type
PLY ; No error, return to caller
PLX
RTS
* FSC Command Table
*******************
* These are commands specific to the filing system that can't be
* called via OSFILE, OSFSC, etc.
* Syntax is:
* <afsp> - ambiguous file specifier, acts on a single file, error if not file, wildcards allowed
* <fsp> - unambiguous file specifier, acts on a single file, error if not file, wildcards not allowed
* <dir> - directory, error if not directory
* <drv> - drive, eg :1 :2 :61, error if not drive
* <*objspec*> - able to act on multiple objects, any object type, wildcards allowed
* <access> - access string
* <title> - disk title
* (<...>) - optional
*
FSCCOMMAND ASC 'ACCESS'
DB $FF
DW FSCACCESS-1 ; ACCESS <*objspec*> <access>, LPTR=>params
ASC 'CD'
DB $FF
DW FSCCHDIR-1 ; CD <dir> , LPTR=>params
ASC 'CHDIR'
DB $FF
DW FSCCHDIR-1 ; CHDIR <dir>, LPTR=>params
ASC 'COPY'
DB $FF
DW FSCCOPY-1 ; COPY <*objspec*> <dest>, LPTR=>params
ASC 'DIR'
DB $FF
DW FSCCHDIR-1 ; DIR <*objspec*>, LPTR=>params
ASC 'DESTROY'
DB $FF
DW FSCDESTROY-1 ; DESTROY <*objspec*> (Y), LPTR=>params
ASC 'DRIVE'
DB $FF
DW FSCDRIVE-1 ; DRIVE <drv>, LPTR=>params
ASC 'FREE'
DB $FF
DW FSCFREE-1 ; FREE (<drv>), LPTR=>params
ASC 'TITLE'
DB $FF
DW FSCTITLE-1 ; TITLE (<drv>) <title>, LPTR=>params
*
DB $FF ; Terminator
* FSC Dispatch Table
********************
FSCDISPATCH DW FSCOPT-1 ; A=0 - *OPT
DW CHKEOF-1 ; A=1 - Read EOF
DW FSCRUN-1 ; A=2 - */filename
DW FSC03-1 ; A=3 - *command
DW FSCRUN-1 ; A=4 - *RUN
DW FSCCAT-1 ; A=5 - *CAT
DW FSCUKN-1 ; A=6
DW FSCUKN-1 ; A=7
DW FSCUKN-1 ; A=8
DW FSCCAT-1 ; A=9 - *EX
DW FSCCAT-1 ; A=10 - *INFO
DW FSCUKN-1 ; A=11
DW FSCRENAME-1 ; A=12 - *RENAME
* OSFSC - miscellanous file system calls
*****************************************
* On entry, A=action, XY=>command line
* or A=action, X=param1, Y=param2
* On exit, A=preserved if unimplemented
* A=0 if implemented
* X,Y=any return values
*
FSCHND CMP #13
BCS FSCUKN
STA FSAREG
STX FSXREG
STY FSYREG
ASL A
TAX
LDA FSCDISPATCH+1,X
PHA
LDA FSCDISPATCH+0,X
PHA
FSCNULL LDA FSAREG
LDY FSYREG
LDX FSXREG ; Set EQ/NE from X
FSCUKN
FSCRET RTS
* OSFSC 00 - *OPT function
* Entered with A=$00 and EQ/NE from X
FSCOPT BEQ :OPT0
CPX #$05
BCS :OPTNULL
CPY #$04
BCS :OPTNULL
LDA FSFLAG2
AND :OPTMSK-1,X
EOR :OPTSET-0,Y
AND :OPTMSK-1,X
EOR :OPTSET-0,Y
:OPT0 STA FSFLAG2
:OPTNULL RTS
:OPTMSK DB $3F,$CF,$F3,$FC
:OPTSET DB $00,$55,$AA,$FF
*FSCUKN
* DO DEBUG
* PHA
* LDA #<OSFSCM
* LDY #>OSFSCM
* JSR PRSTR
* PLA
* FIN
* RTS
* DO DEBUG
*OSFSCM ASC 'OSFSC.'
* DB $00
* FIN
* OSFSC 01 - Read EOF function
* X=File ref number
*
CHKEOF TXA ; A=channel
>>> XF2MAIN,FILEEOF
CHKEOFRET >>> ENTAUX
TAX ; Return code -> X
TYA ; Y=any ProDOS error
JMP CHKERROR
* OSFSC 03 - *command, fall back to *RUN command
* XY=>command line
*
FSC03 JSR XYtoLPTR
LDX #<FSCCOMMAND
LDY #>FSCCOMMAND
JSR CLILOOKUP
BEQ FSCRET ; Matched, return
JSR LPTRtoXY ; Fall through to *RUN
LDA #$FE ; Will become A=$05
* OSFSC 02 - */filename, OSFSC 04 - *RUN filename
* XY=>pathname
*
FSCRUN PHA
STX OSFILECB+0 ; Pointer to filename
STY OSFILECB+1
JSR XYtoLPTR
FSCRUNLP LDA (OSLPTR),Y ; Look for command line
INY
CMP #'!'
BCS FSCRUNLP
DEY
JSR SKIPSPC
JSR LPTRtoXY
STX FSCMDLINE+0 ; Set CMDLINE=>command line
STY FSCMDLINE+1 ; Collected by OSARGS 1,0
PLA
EOR #$FB ; Convert $FE->$05, $02/$04->$Fx
BMI :FSCRUN2 ; *RUN, go direct to LOAD
JSR :FSCCALL ; Do an initial INFO
DEC A ; $01->$00
BEQ :FSCRUN2 ; A file, load and run it
JMP FSCNULL ; Not a file, return all preserved
:FSCRUN2 LDA #$FF ; A=LOAD
STA OSFILECB+6 ; Use file's address
JSR :FSCCALL ; LOAD the file
JSR :CALLCODE ; Call the loaded code
LDA #$00 ; A=0 on return
RTS
:FSCCALL LDX #<OSFILECB ; Pointer to control block
LDY #>OSFILECB
JMP OSFILE
:CALLCODE LDA #$01 ; A=1 - entering code
SEC ; Not from RESET
JMP (OSFILECB+6) ; Jump to EXEC addr
* Display catalog entries and info
* A=5 *CAT, A=9 *EX, A=10 *INFO
* XY=>pathname
*
FSCCAT EOR #$06
CLC
ROR A ; 01100000=*CAT
ROR A ; 11100000=*EX
ROR A ; 10000000=*INFO
ROR A ; b7=long info
STA FSAREG ; b6=multiple items
JSR PARSNAME ; Copy filename->MOSFILE
LDA FSAREG ; Get ARG back
>>> XF2MAIN,CATALOG
STARCATRET >>> ENTAUX
JSR CHKERROR ; See if error occurred
JSR FORCENL
LDA #0 ; 0=OK
RTS
* Print one block of a catalog. Called by CATALOG
* Block is in BLKBUF in main memory
PRONEBLK >>> ENTAUX
LDA #<BLKBUF+4 ; FSPTR1=>first entry
STA FSPTR1+0
LDA #>BLKBUF+4
STA FSPTR1+1
LDA #13 ; Max 13 entries per block
STA FSNUM
:CATLP LDY #$00
>>> RDMAIN
LDA (FSPTR1),Y ; Get storage type
>>> RDAUX
CMP #$E0
BCC :NOTKEY ; Not a key block
* Print directory name
LDA #<:DIRM
LDY #>:DIRM
JSR PRSTR
SEC
:NOTKEY JSR PRONEENT ; CC=entry, CS=header
CLC ; Step to next entry
LDA FSPTR1+0
ADC #$27
STA FSPTR1+0
LDA FSPTR1+1
ADC #$00
STA FSPTR1+1
DEC FSNUM
BNE :CATLP ; Loop for all entries
>>> XF2MAIN,CATALOGRET
:DIRM ASC 'Directory: '
DB $00
* Print a single directory entry
* On entry: FSPTR1 points to dirent in BLKBUF (in main memory)
* CC=entry, CS=header
PRONEENT LDY #$00 ; Characters printed
>>> RDMAIN
LDA (FSPTR1),Y
>>> RDAUX
AND #$0F ; Len of filename
BEQ NULLENT ; Inactive entry
PHP
TAX
:L2 INY
>>> RDMAIN
LDA (FSPTR1),Y
>>> RDAUX
JSR OSWRCH ; Print filename
DEX
BNE :L2
:S2 PLP
BCS :EXITHDR ; Header entry, no info
JSR PRSPACES ; Pad after filename
BIT FSAREG
BMI :CATINFO ; Display object info
JMP PRACCESS
:EXITHDR JMP OSNEWL
* Print object catalog info
:CATINFO LDY #$21
LDX #3
LDA #0
JSR PRADDR0
LDA #'+'
JSR OSWRCH
LDY #$17
JSR PRADDR
JSR PRSPACE
JSR PRACCESS
BIT FSFLAG2
BMI CATLONG ; *OPT 1,2 - detailed EX display
LDY #$0A
PRSPACES JSR PRSPACE
INY
CPY #$10
BCC PRSPACES
NULLENT RTS
* Print extended catalog info
CATLONG LDY #$21
JSR PRDATETIME
LDY #$18
JSR PRDATETIME
JMP OSNEWL
PRDATETIME JSR PRSPACE
JSR PRSPACE
>>> RDMAIN
LDA (FSPTR1),Y
>>> RDAUX
PHA
AND #$1F
JSR PRDECSLH ; Day
INY
>>> RDMAIN
LDA (FSPTR1),Y
>>> RDAUX
ASL A
PLA
ROL A
ROL A
ROL A
ROL A
AND #$0F
JSR PRDECSLH ; Month
>>> RDMAIN
LDA (FSPTR1),Y
>>> RDAUX
PHA
CMP #80
LDA #$19
BCS :CENTURY
LDA #$20
:CENTURY JSR PRHEX ; Century
PLA
LSR A
JSR PRDEC ; Year
JSR PRSPACE
INY
INY
>>> RDMAIN
LDA (FSPTR1),Y
>>> RDAUX
JSR PRDEC ; Hour
LDA #$3A
JSR OSWRCH
DEY
>>> RDMAIN
LDA (FSPTR1),Y ; Minute
>>> RDAUX
PRDEC TAX
LDA #$99
SED
:PRDECLP CLC
ADC #$01
DEX
BPL :PRDECLP
CLD
JMP PRHEX
PRDECSLH JSR PRDEC
LDA #'/'
JMP OSWRCH
* Print object access string
PRACCESS LDX #$04 ; Offset to 'D' char
LDY #$00
>>> RDMAIN
LDA (FSPTR1),Y
>>> RDAUX
CMP #$D0 ; CS=Directory
LDY #$1E
>>> RDMAIN
LDA (FSPTR1),Y ; Permission byte
>>> RDAUX
LDY #$0C ; Char counter
EOR #$C0
* AND #$E3 ; Keep LLB---WR
AND #$C3 ; Keep LL----WR
BCC :PRACC1 ; Not a directory
AND #$FC ; Drop 'WR' bits
:PRACC1 STA FSACCBYTE
BCS :PRACC2 ; Jump to print 'D'
:PRACCLP LDA FSACCBYTE
AND ACCESSBITS,X ; Is bit set?
BEQ :PRACC3
:PRACC2 LDA ACCESSCHRS,X ; If so, print character
JSR OSWRCH
INY ; Inc. char counter
:PRACC3 DEX
BPL :PRACCLP ; Loop for all chars
JMP PRSPACES ; Pad
ACCESSCHRS ASC 'RWBLD'
ACCESSBITS DB $01,$02,$20,$C0,$00
* Print object addresses
PRADDR LDX #3
PRADDRLP >>> RDMAIN
LDA (FSPTR1),Y
>>> RDAUX
PRADDR0 JSR OUTHEX
DEY
DEX
BNE PRADDRLP
PRADDROK RTS
PRSPACE LDA #' '
PRCHAR JMP OSWRCH
* OSFSC $0C - RENAME function
* XY=>pathnames
*
FSCRENAME JSR PARSNAME ; Copy Arg1->MOSFILE
BEQ :SYNTAX ; No <oldname>
JSR PARSLPTR2 ; Copy Arg2->MOSFILE2
BEQ :SYNTAX ; No <newname>
>>> XF2MAIN,RENFILE
:SYNTAX BRK
DB $DC
ASC 'Syntax: RENAME <oldspec> <newspec>'
BRK
* ProDOS returns $40 (Bad filename) for bad renames.
* Not easy to seperate out, so leave as Bad filename error.
ACCRET
RENRET
COPYRET
DESTRET
CHDIRRET >>> ENTAUX
JMP CHKERROR
* Handle *COPY command
* LPTR=>parameters string
*
FSCCOPY JSR PARSLPTR ; Copy Arg1->MOSFILE
BEQ :SYNTAX ; No <source>
JSR PARSLPTR2 ; Copy Arg2->MOSFILE2
BEQ :SYNTAX ; No <dest>
>>> XF2MAIN,COPYFILE ; Do the heavy lifting
:SYNTAX BRK
DB $DC
ASC 'Syntax: COPY <*objspec*> <dest>'
BRK
* Handle *DIR/*CHDIR/*CD (directory change) command
* LPTR=>parameters string
*
FSCCHDIR JSR PARSLPTR ; Copy filename->MOSFILE
BEQ ERRCHDIR ; No <dir>
LDY #$00 ; Y=$00 - CHDIR
FSCCHDIR2 >>> XF2MAIN,SETPFX
ERRCHDIR BRK
DB $DC
ASC 'Syntax: DIR <dir>'
BRK
* Handle *DRIVE command, which is similar to CHDIR
* LPTR=>parameters string
*
FSCDRIVE JSR PARSLPTR ; Copy arg->MOSFILE
TAY ; Y<>$00 - DRIVE
BNE FSCCHDIR2 ; Pass on as CHDIR
:SYNTAX BRK
DB $DC
ASC 'Syntax: DRIVE <drv>'
BRK
* Handle *FREE command
* LPTR=>parameters string
* Syntax is FREE (<drv>)
*
FSCFREE JSR PARSLPTR ; Copy arg->MOSFILE
>>> XF2MAIN,DRVINFO
FREERET >>> ENTAUX
JSR CHKERROR
*
* Disk size is two-byte 512-byte block count
* Maximum disk size is $FFFF blocks = 1FFFF00 bytes = 33554176 bytes = 32M-512
:NOERR SEC
>>> RDMAIN
LDA BLKBUF+2 ; LSB of total blocks
SBC BLKBUF+0 ; LSB of blocks used
TAX ; X=b0-b7 of blocks free
LDA BLKBUF+3 ; MSB of total blocks
SBC BLKBUF+1 ; MSB of blocks used
TAY ; Y=b8-b15 of blocks free
>>> RDAUX
LDA #$00 ; A=b16-b23 of blocks free
JSR :FREEDEC ; Print 'AAYYXX blocks aaayyyxxx bytes '
LDX #<:FREE
LDY #>:FREE
JSR OUTSTR ; Print 'free'<nl>
>>> RDMAIN
LDX BLKBUF+0 ; X=b0-b7 of blocks used
LDY BLKBUF+1 ; Y=b8-b15 of blocks used
>>> RDAUX
LDA #$00 ; A=b16-b23 of blocks used
JSR :FREEDEC ; Print 'AAYYXX blocks aaayyyxxx bytes '
LDX #<:USED
LDY #>:USED
JMP OUTSTR ; Print 'used'<nl>
:FREEDEC STX FSNUM+1
STY FSNUM+2
STA FSNUM+3
* JSR PRHEX ; Blocks b16-b23 in hex
JSR PR2HEX ; Blocks b0-b15 in hex
LDX #<:BLOCKS
LDY #>:BLOCKS
JSR OUTSTR ; ' blocks '
STZ FSNUM+0 ; FSNUM=blocks*512
ASL FSNUM+1
ROL FSNUM+2
ROL FSNUM+3
LDX #FSNUM ; X=>number to print
LDY #8 ; Y=pad up to 8 digits
JSR PRINTDEC ; Print it in decimal
LDX #<:BYTES
LDY #>:BYTES
JMP OUTSTR ; ' bytes '
:BLOCKS ASC ' blocks '
DB 0
:BYTES ASC ' bytes '
DB 0
:FREE ASC 'free'
DB 13,0
:USED ASC 'used'
DB 13,0
* Handle *ACCESS command
* LPTR=>parameters string
*
FSCACCESS JSR PARSLPTR ; Copy filename->MOSFILE
BEQ :SYNTAX ; No filename
STZ FSACCBYTE ; Initialise access to ""
:ACCESSLP1 LDA (OSLPTR),Y ; Get access character
CMP #$0D
BEQ :ACCESSGO ; End of line, action it
INY
AND #$DF ; Upper case
LDX #$04 ; Check five chars 'DLBWR'
:ACCESSLP2 CMP ACCESSCHRS,X
BNE :ACCESSNXT
LDA ACCESSBITS,X ; Add this to access mask
ORA FSACCBYTE
STA FSACCBYTE
:ACCESSNXT DEX
BPL :ACCESSLP2
BMI :ACCESSLP1 ; Check next character
:ACCESSGO LDA FSACCBYTE
EOR #$C0 ; MOSFILE=filename, A=access mask
>>> XF2MAIN,SETPERM
:SYNTAX BRK
DB $DC
ASC 'Syntax: ACCESS <*objspec*> <L|W|R>'
BRK
* Handle *DESTROY command
* LPTR=>parameters string
*
FSCDESTROY
DESTROY JSR PARSLPTR ; Copy filename->MOSFILE
BEQ :SYNTAX ; No filename
>>> XF2MAIN,MULTIDEL
:SYNTAX BRK
DB $DC
ASC 'Syntax: DESTROY <*objspec*>'
BRK
* Handle *TITLE command
* LPTR=>parameters string
* Syntax: *TITLE (<drive>) <title>
*
FSCTITLE JSR PARSLPTR ; Copy arg1->MOSFILE
BEQ :SYNTAX ; No args
JSR PARSLPTR2 ; Copy arg2->MOSFILE2
BNE :S1 ; If two args, skip
>>> WRTMAIN
STZ MOSFILE2 ; One arg, MOSFILE2=""
>>> WRTAUX
:S1 >>> XF2MAIN,DISKTITLE
RTS
:SYNTAX BRK
DB $DC
ASC 'Syntax: TITLE (<drv>) <title>'
BRK
* Parse filename pointed to by XY
* Write filename to MOSFILE in main memory
* Returns length in A with EQ/NE set
PARSNAME JSR XYtoLPTR
PARSLPTR CLC ; Means parsing a filename
JSR GSINIT ; Init general string handling
LDX #$00 ; Length
:L1 JSR GSREAD ; Handle next char
BCS :DONE
>>> WRTMAIN
STA MOSFILE+1,X
>>> WRTAUX
INX
CPX #$40
BNE :L1 ; Name not too long
TXA ; $40=Bad filename
JMP MKERROR
:DONE >>> WRTMAIN
STX MOSFILE ; Length byte (Pascal)
>>> WRTAUX
TXA ; Return len in A
RTS
* Parse filename pointed to by (OSLPTR),Y
* Write filename to MOSFILE2 in main memory
* Returns length in A with EQ/NE set
PARSNAME2 JSR XYtoLPTR
PARSLPTR2 CLC ; Means parsing a filename
JSR GSINIT ; Init gen string handling
LDX #$00 ; Length
:L1 JSR GSREAD ; Handle next char
BCS :DONE
>>> WRTMAIN
STA MOSFILE2+1,X
>>> WRTAUX
INX
CPX #$40
BNE :L1 ; Name not too long
TXA ; $40=Bad filename
JMP MKERROR
:DONE >>> WRTMAIN
STX MOSFILE2 ; Length byte (Pascal)
>>> WRTAUX
TXA ; Return len in A
NOTERROR RTS
ERRNOTFND LDA #$46 ; File not found
* Check returned code for return code or error code
* A<$20 - return to user, A>$1F - generate error
*
CHKERROR CMP #$20
BCC NOTERROR
MKERROR
DO DEBUG
BIT $E0
BPL MKERROR1 ; *DEBUG*
PHA
LDX #15
MKERRLP LDA ERRMSG,X
STA $100,X
DEX
BPL MKERRLP
PLA
PHA
LSR A
LSR A
LSR A
LSR A
JSR ERRHEX
STA $108
PLA
JSR ERRHEX
STA $109
JMP $100
ERRHEX AND #15
CMP #10
BCC ERRHEX1
ADC #6
ERRHEX1 ADC #48
RTS
ERRMSG BRK
DB $FF
ASC 'ERR: $00'
BRK
FIN
* Translate ProDOS error code into BBC error
MKERROR1 CMP #$40
BCS MKERROR2
ORA #$30 ; <$40 -> $30-$3F
MKERROR2 SEC
SBC #$38
CMP #$28
BCC MKERROR3 ; $28-$30, $40-$5F
LDA #$27 ; Otherwise I/O error
MKERROR3 ASL A
TAX
LDA MKERROR4+1,X
PHA
LDA MKERROR4+0,X
PHA
PHP
RTI
MKERROR4 DW ERROR28,ERROR27,ERROR2A,ERROR2B,ERROR2C,ERROR27,ERROR2E,ERROR27
DW ERROR40,ERROR41,ERROR42,ERROR43,ERROR44,ERROR45,ERROR46,ERROR47
DW ERROR48,ERROR49,ERROR4A,ERROR4B,ERROR4C,ERROR4D,ERROR4E,ERROR4F
DW ERROR50,ERROR51,ERROR52,ERROR53,ERROR54,ERROR55,ERROR56,ERROR57
DW ERROR27,ERROR27,ERROR5A,ERROR27,ERROR27,ERROR27,ERROR5E,ERROR27
* $27 - I/O error (disk not formatted)
* $28 - No device con'd (drive not present) Drive not present
* $29 -(GSOS Driver is busy)
* $2A -(Not a drive specifier) DRIVE/FREE: Bad drive
* $2B - Disk write protected. Disk write protected
* $2C - Bad byte count - file too long File too long
* $2D -(GSOS bad block number) (Sector not found?)
* $2E - Disk switched Disk changed
* $2F - Device is offline (drive empty/absent)
* $40 - Invalid pathname syntax. Bad filename
* $41 -(Duplicate filename. split from $47) Is a directory
* $42 - File Control Block table full. Too many open
* $43 - Invalid reference number. Channel not open
* $44 - Path not found. (Dir not found) File not found
* $45 - Volume directory not found. Disk not found
* $46 - File not found. File not found
* $47 - Duplicate filename. (see also $41) File exists
* $48 - Overrun error. Disk full
* $49 - Volume directory full. Directory full
* $4A - Incompatible file format. Disk not recognised
* $4B - Unsupported storage_type. Not a directory
* $4C - End of file has been encountered. End of file
* $4D - Position out of range. Past end of file
* $4E - Access error. (see also $4F) RD/WR: Insufficient access
* $4F -(Access error. split from $4E) REN/DEL/SAV: Locked
* $50 - File already open. Can't - file open
* $51 - Directory count error. Broken directory
* $52 - Not a ProDOS disk. Disk not recognised
* $53 - Invalid parameter. Invalid parameter
* $54 -(Dir not empty when deleting, cf $4E) DEL: Directory not empty
* $55 - Volume Control Block table full. (Too many disks mounted)
* $56 - Bad buffer address.
* $57 - Duplicate volume.
* $58 - Bad volume bitmap/Not block device.