-
Notifications
You must be signed in to change notification settings - Fork 12
Expand file tree
/
Copy pathdisk.asm
More file actions
3818 lines (3747 loc) · 259 KB
/
disk.asm
File metadata and controls
3818 lines (3747 loc) · 259 KB
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
; Disk Color BASIC 1.0 and 1.1
; Copied from the PDF version of Disk Color BASIC Unravelled.
; Fixed up to assemble in Mamou
; Revision History
; $Id: $
; -----------------------------------------------------------------------------
if VERDISK>10
; -----------------------------------------------------------------------------
DHITOK EQU $E1 ; HIGHEST 1.1 DISK TOKEN
CYEAR EQU '2
; -----------------------------------------------------------------------------
else
; -----------------------------------------------------------------------------
DHITOK EQU $E0 ; HIGHEST 1.0 DISK TOKEN
CYEAR EQU '1
; -----------------------------------------------------------------------------
endif
; -----------------------------------------------------------------------------
; FILE ALLOCATION TABLE FORMAT
; THE FILE ALLOCATION TABLE (FAT) CONTAINS THE STATUS OF THE GRANULES ON A DISKETTE.
; THE FAT CONTAINS 6 CONTROL BYTES FOLLOWED BY 68 DATA BYTES (ONE PER GRANULE). ONLY THE
; FIRST TWO OF THE SIX CONTROL BYTES ARE USED. A VALUE OF $FF IS SAVED IN UNALLOCATED
; GRANULES. IF BITS 6 & 7 OF THE DATA BYTE ARE SET, THE GRANULE IS THE LAST GRANULE
; IN A FILE AND BITS 0-5 ARE THE NUMBER OF USED SECTORS IN THAT GRANULE. IF BITS 6 & 7
; ARE NOT SET, THE DATA BYTE CONTAINS THE NUMBER OF THE NEXT GRANULE IN THE FILE.
; OFFSETS TO FAT CONTROL BYTES
FAT0 EQU 0 ; ACTIVE FILE COUNTER : DISK TO RAM FAT IMAGE DISABLE
FAT1 EQU 1 ; VALID DATA FLAG: 0=DISK DATA VALID, <> 0 = NEW FAT
; DATA - DISK DATA INVALID
; 2 TO 5 NOT USED
FATCON EQU 6 ; OFFSET TO START OF FAT DATA (68 BYTES)
; DIRECTORY ENTRY FORMAT
; THE DIRECTORY IS USED TO KEEP TRACK OF HOW MANY FILES ARE STORED ON A DISKETTE
; AND WHERE THE FILE IS STORED ON THE DISK. THE FIRST GRANULE USED BY THE FILE WILL
; ALLOW THE FAT TO TRACK DOWN ALL OF THE GRANULES USED BY THE FILE. IF THE FIRST
; BYTE OF THE DIRECTORY ENTRY IS ZERO, THE FILE HAS BEEN KILLED;
; IF THE FIRST BYTE IS $FF THEN THE DIRECTORY ENTRY HAS NEVER BEEN USED.
; BYTE DESCRIPTION
DIRNAM EQU 0 ; FILE NAME
DIREXT EQU 8 ; FILE EXTENSION
DIRTYP EQU 11 ; FILE TYPE
DIRASC EQU 12 ; ASCII FLAG
DIRGRN EQU 13 ; FIRST GRANULE IN FILE
DIRLST EQU 14 ; NUMBER OF BYTES IN LAST SECTOR
; 16 TO 31 UNUSED
; FILE CONTROL BLOCK FORMAT
; THE FILE STRUCTURE OF COLOR TRS DOS IS CONTROLLED BY A FILE CONTROL BLOCK (FCB)
; THE FCB CONTAINS 25 CONTROL BYTES AND A SECTOR LONG (256 BYTES) DATA BUFFER.
; THE CONTROL BYTES CONTROL THE ORDERLY FLOW OF DATA FROM THE COMPUTER'S RAM TO
; THE DISKETTE AND VICE VERSA. THE OPEN COMMAND INITIALIZES THE FCB; THE INPUT,
; OUTPUT, WRITE, PRINT, GET AND PUT COMMANDS TRANSFER DATA THROUGH THE FCB AND
; THE CLOSE COMMAND TURNS OFF THE FCB.
; TABLES OF OFFSETS TO FCB CONTROL BYTES
; RANDOM FILE
; BYTE DESCRIPTION
FCBTYP EQU 0 ; FILE TYPE: $40=RANDOM/DIRECT, 0=CLOSED
FCBDRV EQU 1 ; DRIVE NUMBER
FCBFGR EQU 2 ; FIRST GRANULE IN FILE
FCBCGR EQU 3 ; CURRENT GRANULE BEING USED
FCBSEC EQU 4 ; CURRENT SECTOR BEING USED (1-9)
; 5 UNUSED
FCBPOS EQU 6 ; CURRENT PRINT POSITION - ALWAYS ZERO IN RANDOM FILES
FCBREC EQU 7 ; CURRENT RECORD NUMBER
FCBRLN EQU 9 ; RANDOM FILE RECORD LENGTH
FCBBUF EQU 11 ; POINTER TO START OF THIS FILE'S RANDOM ACCESS BUFFER
FCBSOF EQU 13 ; SECTOR OFFSET TO CURRENT POSITION IN RECORD
FCBFLG EQU 15 ; GET/PUT FLAG: 0=PUT, 1=PUT
; 16,17 NOT USED
FCBDIR EQU 18 ; DIRECTORY ENTRY NUMBER (0-71)
FCBLST EQU 19 ; NUMBER OF BYTES IN LAST SECTOR OF FILE
FCBGET EQU 21 ; 'GET' RECORD COUNTER: HOW MANY CHARACTERS HAVE BEEN PULLED OUT OF THE CURRENT RECORD
FCBPUT EQU 23 ; 'PUT' RECORD COUNTER: POINTER TO WHERE IN THE RECORD THE NEXT BYTE WILL BE 'PUT'
FCBCON EQU 25 ; OFFSET TO START OF FCB DATA BUFFER (256 BYTES)
; SEQUENTIAL FILE
; BYTE DESCRIPTION
FCBCPT EQU 5 ; INPUT FILE: CHARACTER POINTER - POINTS TO NEXT CHARACTER IN
; FILE TO BE PROCESSED.
; OUTPUT FILE: FULL SECTOR FLAG - IF IT IS 1 WHEN THE FILE IS
; CLOSED IT MEANS 256 BYTES OF THE LAST SECTOR HAVE BEEN USED.
; INPUT OR OUTPUT TO A FILE.
; 9 TO 15 UNUSED
FCBCFL EQU 16 ; CACHE FLAG: 00=CACHE EMPTY, $FF=CACHE FULL
FCBCDT EQU 17 ; CACHE DATA BYTE
; 21,22 UNUSED
FCBDFL EQU 23 ; INPUT FILE ONLY: DATA LEFT FLAG: 0=DATA LEFT, $FF=NO DATA (EMPTY)
FCBLFT EQU 24 ; NUMBER OF CHARACTERS LEFT IN BUFFER (INPUT FILE)
; NUMBER OF CHARS STORED IN BUFFER (OUTPUT FILE)
ORG $C000
FCC "DK"
BRA LRC00C
DCNVEC FDB DSKCON ; DSKCON POINTER
DSKVAR FDB DCOPC ; ADDRESS OF DSKCON VARIABLES
; -----------------------------------------------------------------------------
if VERDISK>10
; -----------------------------------------------------------------------------
DSINIT FDB DOSINI ; DISK INITIALIZATION VECTOR
DOSVEC FDB DOSCOM ; DOS COMMAND VECTOR
; -----------------------------------------------------------------------------
endif
; -----------------------------------------------------------------------------
; ZERO OUT THE RAM USED BY DISK BASIC
LRC00C LDX #DBUF0 ; POINT X TO START OF DISK RAM
LRC00F CLR ,X+ ; CLEAR A BYTE
CMPX #DFLBUF ; END OF DISK'S RAM?
BNE LRC00F ; NO - KEEP CLEARING
LDX #LC109 ; POINT X TO ROM IMAGE OF COMMAND INTERPRETATION TABLE
LDU #COMVEC+20 ; POINT U TO RAM ADDRESS OF SAME
LDB #10 ; 10 BYTES PER TABLE
JSR >LA59A ; MOVE (B) BYTES FROM (X) TO (U)
LDD #LB277 ; SYNTAX ERROR ADDRESS
STD $03,U ; SET JUMP TABLE ADDRESSES OF THE USER COMMAND
STD $08,U ; INTERPRETATION TABLE TO POINT TO SYNTAX ERROR
CLR ,U ; CLEAR BYTE 0 OF USER TABLE (DOESN'T EXIST FLAG)
CLR $05,U ; SET NUMBER OF SECONDARY USER TOKENS TO ZERO
LDD #DXCVEC ; SAVE NEW
STD COMVEC+13 ; POINTERS TO EXBAS
LDD #DXIVEC ; COMMAND AND SECONDARY
STD COMVEC+18 ; COMMAND INTERPRETATION ROUTINES
; MOVE THE NEW RAM VECTORS FROM ROM TO RAM
LDU #RVEC0 ; POINT U TO 1ST RAM VECTOR
LC03B LDA #$7E ; OP CODE OF JMP INSTRUCTION
STA RVEC22 ; SET 1ST BYTE OF 'GET'/'PUT' RAM VECTOR TO 'JMP'
STA ,U+ ; SET 1ST BYTE OF RAM VECTOR TO 'JMP'
LDD ,X++ ; GET RAM VECTOR FROM ROM
STD ,U++ ; STORE IT IN RAM
CMPX #LC139 ; COMPARE TO END OF ROM VALUES
BNE LC03B ; BRANCH IF NOT ALL VECTORS MOVED
LDX #DVEC22 ; GET ROM VALUE OF 'GET'/'PUT' RAM VECTOR
STX RVEC22+1 ; SAVE IT IN RAM
; -----------------------------------------------------------------------------
if VERDISK>10
; -----------------------------------------------------------------------------
LDX #DVEC20 ; GET DISK COMMAND INTERPRETATION LOOP RAM VECTOR
STX RVEC20+1 ; SAVE IN RAM VECTOR TABLE
; -----------------------------------------------------------------------------
endif
; -----------------------------------------------------------------------------
; INITIALIZE DISK BASIC'S USR VECTORS
LDX #DUSRVC ; POINT X TO START OF DISK BASIC USR VECTORS
STX USRADR ; SAVE START ADDRESS IN USRADR
LDU #LB44A ; POINT U TO ADDRESS OF 'FUNCTION CALL' ERROR
LDB #$0A ; 10 USER VECTORS TO INITIALIZE
LC061 STU ,X++ ; SET USR VECTOR TO 'FC' ERROR
DECB ; DECREMENT USR VECTOR COUNTER
BNE LC061 ; BRANCH IN NOT DONE WITH ALL 10 VECTORS
LDX #DNMISV ; GET ADDRESS OF NMI SERVICING ROUTINE
STX NMIVEC+1 ; SAVE IT IN NMI VECTOR
LDA #$7E ; OP CODE OF JMP
STA NMIVEC ; MAKE THE NMI VECTOR A JMP
LDX #DIRQSV ; GET ADDRESS OF DISK BASIC IRQ SERVICING ROUTINE
STX IRQVEC+1 ; SAVE IT IN IRQVEC
LDA #$13 ; INITIALIZE WRITE FAT
STA WFATVL ; TO DISK TRIGGER VALUE
CLR FATBL0 ;
CLR FATBL1 ; INITIALIZE THE ACTIVE FILE COUNTER OF
CLR FATBL2 ; EACH FAT TO ZERO. THIS WILL CAUSE THE FATS
CLR FATBL3 ; TO THINK THERE ARE NO ACTIVE FILES
LDX #DFLBUF ; GET THE STARTING ADDRESS OF THE
STX RNBFAD ; RANDOM FILE BUFFER FREE AREA AND DAVE IT AS THE
; START ADDRESS OF FREE RAM FOR RANDOM FILE BUFFERS
LEAX $0100,X ; SAVE 256 BYTES FOR RANDOM FILE BUFFERS INITIALLY
STX FCBADR ; SAVE START ADDRESS OF FCBS
LEAX $01,X ; ADD ONE AND SAVE THE STARTING
STX FCBV1 ; ADDRESS OF FCB1
CLR FCBTYP,X ; CLEAR THE FIRST BYTE OF FCB 1 (CLOSE FCB)
LEAX FCBLEN,X ; POINT X TO FCB 2
STX FCBV1+2 ; SAVE ITS STARTING ADDRESS IN FCB VECTOR TABLE
CLR FCBTYP,X ; CLEAR THE FIRST BYTE OF FCB 2 (CLOSE FCB)
LEAX FCBLEN,X ; POINT X TO SYSTEM FCB - THIS FCB WILL ONLY
; BE USED TO COPY, LOAD, SAVE, MERGE, ETC
STX FCBV1+4 ; SAVE ITS ADDRESS IN THE FCB VECTOR TABLE
CLR FCBTYP,X ; CLEAR THE FIRST BYTE OF SYSTEM FCB (CLOSE FCB)
LDA #$02 ; SET THE NUMBER OF ACTIVE RESERVED
STA FCBACT ; FILE BUFFERS TO 2 (1,2)
LEAX FCBLEN,X ; POINT X TO ONE PAST THE END OF SYSTEM FCB
TFR X,D ; SAVE THE ADDRESS IN ACCD
TSTB ; ON AN EVEN 256 BYTE BOUNDARY?
; -----------------------------------------------------------------------------
if VERDISK>10
; -----------------------------------------------------------------------------
BEQ LC0BD ; YES
INCA ; NO - ADD 256 TO ADDRESS
LC0BD BITA #$01 ; CHECK TO SEE IF ACCD IS ON AN EVEN
BEQ LC0C2 ; 512 BYTE (ONE GRAPHIC PAGE) BOUNDARY - ADD
INCA ; 256 (INCA) TO IT IF NOT
; -----------------------------------------------------------------------------
else
; -----------------------------------------------------------------------------
BEQ LC0C2 ; YES
INCA ; NO - ADD 256 TO ADDRESS
; -----------------------------------------------------------------------------
endif
; -----------------------------------------------------------------------------
LC0C2 TFR A,B ; COPY ACCA TO ACCB
ADDB #$18 ; SAVE ENOUGH ROOM FOR 4 GRAPHICS PAGES (PCLEAR 4)
STB TXTTAB ; SAVE NEW START OF BASIC ADDRESS
JSR >L96EC ; INITIALIZE EXBAS VARIABLES & DO A NEW
LDA BEGGRP ; GET THE START OF CURRENT GRAPHICS PAGE
ADDA #$06 ; ADD 1.5K (6 X 256 = ONE GRAPHICS PAGE)
STA ENDGRP ; SAVE NEW END OF GRAPHICS PAGE
; -----------------------------------------------------------------------------
if VERDISK>10
; -----------------------------------------------------------------------------
JSR [DSINIT] ; INITIALIZE SWI2,3 JUMP ADDRESSES
; -----------------------------------------------------------------------------
endif
; -----------------------------------------------------------------------------
BSR LC0F0 ; GO INITIALIZE THE FLOPPY DISK CONTROLLER
ANDCC #$AF ; TURN ON IRQ AND FIRQ
LDX #LC139-1 ; POINT X TO DISK BASIC COPYRIGHT MESSAGE
LC0DC JSR STRINOUT ; PRINT COPYRIGHT MESSAGE TO SCREEN
LDX #DKWMST ; GET DISK BASIC WARM START ADDRESS
STX RSTVEC ; SAVE IT IN RESET VECTOR
JMP >LA0E2 ; JUMP BACK TO BASIC
DKWMST NOP ; WARM START INDICATOR
BSR LC0F0 ; INITIALIZE THE FLOPPY DISK CONTROLLER
JSR >LD2D2 ; CLOSE FILES AND DO MORE INITIALIZATION
JMP XBWMST ; JUMP TO EXBAS' WARM START
LC0F0 CLR NMIFLG ; RESET NMI FLAG
CLR RDYTMR ; RESET DRIVE NOT READY TIMER
CLR DRGRAM ; RESET RAM IMAGE OF DSKREG (MOTORS OFF)
CLR DSKREG ; RESET DISK CONTROL REGISTER
LDA #$D0 ; FORCE INTERRUPT COMMAND OF 1793
STA FDCREG ; SEND IT TO 1793
EXG A,A ; DELAY
EXG A,A ; DELAY SOME MORE
LDA FDCREG ; GET 1793 STATUS (CLEAR REGISTER)
RTS
; DISK BASIC COMMAND INTERP TABLES
; -----------------------------------------------------------------------------
if VERDISK>10
; -----------------------------------------------------------------------------
LC109 FCB 20 ; 20 DISK BASIC 1.1 COMMANDS
; -----------------------------------------------------------------------------
else
; -----------------------------------------------------------------------------
LC109 FCB 19 ; 19 DISK BASIC 1.0 COMMANDS
; -----------------------------------------------------------------------------
endif
; -----------------------------------------------------------------------------
FDB LC192 ; DISK BASIC'S COMMAND DICTIONARY
FDB LC238 ; COMMAND JUMP TABLE
FCB 06 ; 6 DISK BASIC SECONDARY FUNCTIONS
FDB LC219 ; SECONDARY FUNCTION TABLE
FDB LC24E ; SECONDARY FUNCTION JUMP TABLE
; RAM HOOKS FOR DISK BASIC
LC113 FDB DVEC0,DVEC1,DVEC2
FDB DVEC3,DVEC4,DVEC5
FDB DVEC6,DVEC7,DVEC8
FDB XVEC9,DVEC10,DVEC11
FDB DVEC12,DVEC13,DVEC14
FDB DVEC15,DVEC12
FDB DVEC17,DVEC18
; DISK BASIC COPYRIGHT MESSAGE
; -----------------------------------------------------------------------------
if VERDISK>10
; -----------------------------------------------------------------------------
LC139 FCC "DISK EXTENDED COLOR BASIC 1.1"
; -----------------------------------------------------------------------------
else
; -----------------------------------------------------------------------------
LC139 FCC "DISK EXTENDED COLOR BASIC 1.0"
; -----------------------------------------------------------------------------
endif
; -----------------------------------------------------------------------------
FCB CR
FCC "COPYRIGHT (C) 198"
FCB CYEAR
FCC " BY TANDY"
FCB CR
FCC "UNDER LICENSE FROM MICROSOFT"
FCB CR,CR,0
; DISK BASIC COMMAND DICTIONARY TABLE
; TOKEN #
LC192 FCS "DIR" ; CE
FCS "DRIVE" ; CF
FCS "FIELD" ; D0
FCS "FILES" ; D1
FCS "KILL" ; D2
FCS "LOAD" ; D3
FCS "LSET" ; D4
FCS "MERGE" ; D5
FCS "RENAME" ; D6
FCS "RSET" ; D7
FCS "SAVE" ; D8
FCS "WRITE" ; D9
FCS "VERIFY" ; DA
FCS "UNLOAD" ; DB
FCS "DSKINI" ; DC
FCS "BACKUP" ; DD
FCS "COPY" ; DE
FCS "DSKI$" ; DF
FCS "DSKO$" ; E0
; -----------------------------------------------------------------------------
if VERDISK>10
; -----------------------------------------------------------------------------
FCS "DOS" ; E1
; -----------------------------------------------------------------------------
endif
; -----------------------------------------------------------------------------
; DISK BASIC COMMAND JUMP TABLE
; COMMAND / TOKEN #
LC1F1 FDB DIR ; DIR / CE
FDB DRIVE ; DRIVE / CF
FDB FIELD ; FIELD / D0
FDB FILES ; FILES / D1
FDB KILL ; KILL / D2
FDB LOAD ; LOAD / D3
FDB LSET ; LSET / D4
FDB MERGE ; MERGE / D5
FDB RENAME ; RENAME / D6
FDB RSET ; RSET / D7
FDB SAVE ; SAVE / D8
FDB WRITE ; WRITE / D9
FDB VERIFY ; VERIFY / DA
FDB UNLOAD ; UNLOAD / DB
FDB DSKINI ; DSKINI /DC
FDB BACKUP ; BACKUP / DD
FDB COPY ; COPY / DE
FDB DSKI ; DSKI$ / DF
FDB DSKO ; DSKO$ / E0
; -----------------------------------------------------------------------------
if VERDISK>10
; -----------------------------------------------------------------------------
FDB DOS ; DOS / E1
; -----------------------------------------------------------------------------
endif
; -----------------------------------------------------------------------------
; SECONDARY FUNCTION DICTIONARY TABLE
; TOKEN #
LC219 FCS "CVN" ; A2
FCS "FREE" ; A3
FCS "LOC" ; A4
FCS "LOF" ; A5
FCS "MKN$" ; A6
FCS "AS" ; A7
; DISK BASIC SECONDARY FUNCTION JUMP TABLE
; FUNCTION / TOKEN #
LC22C FDB CVN ; CVN / A2
FDB FREE ; FREE / A3
FDB LOC ; LOC / A4
FDB LOF ; LOF / A5
FDB MKN ; MKN$ / A6
FDB LB277 ; AS / A7
; DISK BASIC COMMAND INTERPRETATION HANDLER
LC238 CMPA #DHITOK ; COMPARE TO HIGHEST DISK BASIC TOKEN
BHI LC244 ; AND BRANCH IF HIGHER
LDX #LC1F1 ; POINT X TO DISK BASIC COMMAND JUMP TABLE
SUBA #$CE ; SUBTRACT OUT LOWEST DISK BASIC COMMAND TOKEN
JMP >LADD4 ; JUMP TO BASIC'S COMMAND HANDLER
LC244 CMPA #DHITOK ; COMPARE TO HIGHEST DISK BASIC TOKEN
LBLS LB277 ; 'SYNTAX' ERROR IF < DISK BASIC COMMAND TOKEN
JMP [COMVEC+33] ; PROCESS A USER COMMAND TOKEN
; DISK BASIC SECONDARY COMMAND INTERPRETATION HANDLER
LC24E CMPB #($A7-$80)*2 ; COMPARE MODIFIED SECONDARY TOKEN TO
BLS LC256 ; HIGHEST DISK BASIC TOKEN & BRANCH IF HIGHER
JMP [COMVEC+38] ; JUMP TO USER SECONDARY COMMAND HANDLER
LC256 SUBB #($A2-$80)*2 ; SUBTRACT OUT THE SMALLEST SECONDARY
PSHS B ; DISK TOKEN & SAVE MODIFIED TOKEN ON THE STACK
JSR >LB262 ; SYNTAX CHECK FOR '(' AND EVALUATE EXPRESSION
PULS B ; RESTORE MODIFIED TOKEN
LDX #LC22C ; POINT X TO SECONDARY COMMAND JUMP TABLE
JMP >LB2CE ; JUMP TO BASIC'S SECONDARY COMMAND HANDLER
; ERROR DRIVER RAM VECTOR
DVEC17 PULS Y ; PUT THE RETURN ADDRESS INTO Y
JSR >LAD33 ; RESET THE CONT FLAG, ETC
JSR >LD2D2 ; INITIALIZE SOME DISK VARIABLES AND CLOSE FILES
PSHS Y,B ; PUT RETURN ADDRESS AND ERROR NUMBER ON THE STACK
JSR >DVEC7 ; CLOSE ALL FILES
PULS B ; GET THE ERROR NUMBER BACK
CMPB #2*27 ; COMPARE TO THE LOWEST DISK ERROR NUMBER
LBCS XVEC17 ; BRANCH TO EXBAS ERROR HANDLER IF NOT DISK ERROR NUMBER
LEAS $02,S ; PURGE RETURN ADDRESS OFF THE STACK
JSR >LA7E9 ; TURN OFF THE CASSETTE MOTOR
JSR >LA974 ; DISABLE THE ANALOG MULTIPLEXER
CLR DEVNUM ; SET DEVICE NUMBER TO THE SCREEN
JSR >LB95C ; SEND A CR TO THE SCREEN
JSR >LB9AF ; SEND A '?' TO THE SCREEN
LDX #LR_DBERTAB-2*27 ; POINT X TO DISK BASIC'S ERROR TABLE (MINUS LOWEST DISK ERROR NUMBER)
JMP >LAC60 ; JUMP TO BASIC'S ERROR HANDLER
; DISK BASIC ERROR MESSAGES
LR_DBERTAB FCC "BR" ; 27 BAD RECORD
FCC "DF" ; 28 DISK FULL
FCC "OB" ; 29 OUT OF BUFFER SPACE
FCC "WP" ; 30 WRITE PROTECTED
FCC "FN" ; 31 BAD FILE NAME
FCC "FS" ; 32 BAD FILE STRUCTURE
FCC "AE" ; 33 FILE ALREADY EXISTS
FCC "FO" ; 34 FIELD OVERFLOW
FCC "SE" ; 35 SET TO NON-FIELDED STRING
FCC "VF" ; 36 VERIFICATION ERROR
FCC "ER" ; 37 WRITE OR INPUT PAST END OF RECORD
; DISK FILE EXTENSIONS
BASEXT FCC "BAS" ; BASIC FILE EXTENSION
DEFEXT FCC " " ; BLANK (DEFAULT) FILE EXTENSION
DATEXT FCC "DAT" ; DATA FILE EXTENSION
BINEXT FCC "BIN" ; BINARY FILE EXTENSION
; CLS RAM VECTOR
DVEC22 PSHS X,CC ; SAVE X REG AND STATUS
LDX $03,S ; LOAD X WITH CALLING ADDRESS
CMPX #L975F ; COMING FROM EXBAS' GET/PUT?
BNE LC2BF ; NO
CMPA #'#' ; NUMBER SIGN (GET#, PUT#)?
BEQ LC2C1 ; BRANCH IF GET OR PUT TO RANDOM FILE
LC2BF PULS CC,X,PC ; RESTORE X REG, STATUS AND RETURN
; GET/PUT TO A DIRECT/RANDOM FILE
LC2C1 LEAS $05,S ; PURGE RETURN ADDRESS AND REGISTERS OFF OF THE STACK
JSR >LC82E ; EVALUATE DEVICE NUMBER & SET FCB POINTER
STX FCBTMP ; SAVE FCB POINTER
CLR FCBGET,X ; RESET THE GET
CLR FCBGET+1,X ; DATA POINTER
CLR FCBPUT,X ; RESET THE PUT
CLR FCBPUT+1,X ; DATA POINTER
CLR FCBPOS,X ; RESET PRINT POSITION COUNTER
LDA FCBDRV,X ; GET THE FCB DRIVE NUMBER AND
STA DCDRV ; SAVE IT IN DSKCON VARIABLE
JSR GETCCH ; GET CURRENT INPUT CHARACTER FROM BASIC
BEQ LC2EA ; BRANCH IF END OF LINE
JSR SYNCOMMA ; SYNTAX CHECK FOR COMMA
; -----------------------------------------------------------------------------
if VERDISK>10
; -----------------------------------------------------------------------------
JSR >LB73D ; EVALUATE EXPRESSION - RETURN IN (X)
TFR X,D ; SAVE RECORD NUMBER IN ACCD
LC2E6 LDX FCBTMP ; POINT X TO FCB
STD FCBREC,X ; SAVE RECORD NUMBER IN FCB
LC2EA LDD FCBREC,X ; GET RECORD NUMBER
BEQ LC30B ; 'BAD RECORD' ERROR IF RECORD NUMBER = 0
JSR >LC685 ; INCREMENT RECORD NUMBER
; -----------------------------------------------------------------------------
else
; -----------------------------------------------------------------------------
JSR LB3E6 ; EVALUATE EXPRESSION - RETURN IN ACCD
LC2E6 LDX FCBTMP ; POINT X TO FCB
STD FCBREC,X ; SAVE RECORD NUMBER IN FCB
LC2EA JSR >LC685 ; INCREMENT RECORD NUMBER
; -----------------------------------------------------------------------------
endif
; -----------------------------------------------------------------------------
LDD FCBRLN,X ; GET RANDOM FILE RECORD LENGTH AND RANDOM FILE
LDX FCBBUF,X ; BUFFER POINTER AND SAVE THEM ON THE STACK -
PSHS X,B,A ; THESE ARE THE INITIAL VALUES OF A TEMPORARY
; RECORD LENGTH COUNTER AND RANDOM BUFFER
; POINTER WHICH ARE MAINTAINED ON THE STACK
LEAX -2,U ; POINT X TO (RECORD NUMBER -1)
JSR >L9FB5 ; MULT (UNSIGNED) RECORD LENGTH X (RECORD NUMBER -1)
PSHS U,Y ; SAVE PRODUCT ON THE STACK
LDA ,S+ ; CHECK MS BYTE OF PRODUCT
BNE LC30B ; 'BR' ERROR IF NOT ZERO (RECORD NUMBER TOO BIG)
PULS X ; PULL THE BOTTOM 3 PRODUCT BYTES OFF THE STACK;
PULS B ; TOP TWO IN X, BOTTOM IN ACCB; ACCB POINTS TO
; THE FIRST BYTE OF THE SECTOR USED BY THIS RECORD,
; (X) CONTAINS THE SECTOR OFFSET (IN WHICH SECTOR
; FROM THE START THE BYTE IS LOCATED)
LC306 CMPX #(TRKMAX-1)*18 ; 612 SECTORS MAX IN A RANDOM FILE
BLO LC310 ; BRANCH IF RECORD LENGTH O.K.
LC30B LDB #2*27 ; 'BAD RECORD' ERROR
JMP >LAC46 ; JUMP TO ERROR HANDLER
LC310 LDU FCBTMP ; POINT U TO FCB
CMPX FCBSOF,U ; COMPARE SAVED SECTOR OFFSET TO THE CURRENT SECTOR OFFSET
LBEQ LC3CF ; BEING PROCESSED - DO NOT PROCESS A NEW SECTOR IF THEY ARE EQUAL
PSHS X,B ; SAVE BYTE AND SECTOR OFFSET TO RECORD START ON STACK
LDA FCBFLG,U ; CHECK FCB GET/PUT FLAG AND
BEQ LC324 ; BRANCH IF IT WAS A GET
CLR FCBFLG,U ; FORCE GET/PUT TO 'PUT'
LDB #$03 ; DSKCON WRITE OP CODE
BSR LC357 ; GO WRITE A SECTOR - SAVE 'PUT' DATA ON DISK
; CONVERT THE SECTOR OFFSET TO A GRANULE AND SECTOR NUMBER
LC324 LDD $01,S ; GET THE NUMBER OF SECTORS TO THE START OF
JSR >LC784 ; THIS RECORD NUMBER AND CONVERT THEM TO A GRANULE OFFSET
PSHS B ; SAVE GRANULE OFFSET ON THE STACK
JSR >LC779 ; MULTIPLY GRANULE NUMBER X 9 - CONVERT TO NUMBER OF SECTORS
NEGB ; NEGATE LS BYTE OF GRANULE OFFSET AND ADD THE
ADDB $03,S ; LS BYTE OF SECTOR OFFSET - ACCB = SECTOR
; NUMBER (0-8) CORRESPONDING TO THE SECTOR NUMBER WITHIN A
; GRANULE OF THE LAST SECTOR OF THE SECTOR OFFSET
INCB ; = ADD ONE - SECTORS SAVED IN THE FCB START
STB FCBSEC,U ; AT 1 NOT 0 - SAVE IT IN THE FCB
LDB FCBFGR,U ; GET FIRST GRANULE IN FILE
JSR >LC755 ; POINT X TO FAT
LEAU FATCON,X ; POINT U TO FAT DATA
LDA ,S ; GET NUMBER OF GRANULES OFFSET TO RECORD
INCA ; ADD ONE (COMPENSATE FOR DECA BELOW)
LC33E LEAX ,U ; POINT X TO FAT DATA
ABX ; POINT X TO CORRECT GRANULE
DECA ; DECREMENT GRANULE COUNTER
BEQ LC37B ; BRANCH IF CORRECT GRANULE FOUND
STB ,S ; SAVE GRANULE ADDRESS ON STACK
LDB ,X ; GET NEXT GRANULE IN FILE
CMPB #$C0 ; LAST GRANULE IN FILE?
BLO LC33E ; NO - KEEP LOOKING
; THE GRANULE BEING SEARCHED FOR IS NOT PRESENTLY DEFINED IN THIS RANDOM FILE
LDB ,S ; GET OFFSET TO LAST GRANULE
TST VD8 ; CHECK GET/PUT FLAG
BNE LC366 ; AND BRANCH IF PUT
LC352 LDB #2*23 ; 'INPUT PAST END OF FILE' ERROR
JMP >LAC46 ; JUMP TO ERROR HANDLER
LC357 LEAX FCBCON,U ; POINT X TO FCB DATA BUFFER
; READ/WRITE A SECTOR. ENTER WITH OP CODE IN ACCB, BUFFER PTR IN X
LC35A STB DCOPC ; SAVE DSKCON OPERATION CODE VARIABLE
STX DCBPT ; SAVE DSKCON LOAD BUFFER VARIABLE
LEAX ,U ; POINT X TO FCB
JSR >LC763 ; CONVERT FCB TRACK AND SECTOR TO DSKCON VARIABLES
JMP >LD6F2 ; READ/WRITE A TRACK OR SECTOR
; 'PUT' DATA INTO A GRANULE NOT PRESENTLY INCLUDED IN THIS FILE
LC366 PSHS X,A ; SAVE GRANULE COUNTER AND POINTER TO LAST USED GRANULE
JSR >LC7BF ; FIND FIRST FREE GRANULE IN FAT
TFR A,B ; SAVE FREE GRANULE NUMBER IN ACCB
PULS A,U ; PULL LAST GRANULE POINTER AND COUNTER OFF OF STACK
STB ,U ; SAVE NEWLY FOUND GRANULE NUMBER IN ADDRESS OF LAST GRANULE
DECA ; DECREMENT GRANULE COUNTER
BNE LC366 ; GET ANOTHER GRANULE IF NOT DONE
PSHS X,B ; SAVE POINTER TO LAST GRANULE AND OFFSET
JSR >LC71E ; WRITE FAT TO DISK
PULS B,X ; RESTORE POINTER AND OFFSET
; WHEN CORRECT GRANULE IS FOUND, FIND THE RIGHT SECTOR
LC37B LEAS $01,S ; REMOVE GRAN NUMBER FROM STACK
LDU FCBTMP ; POINT U TO FCB
STB FCBCGR,U ; SAVE CURRENT GRANULE IN FCB
LDA #$FF ; SET FCBSOF,U TO ILLEGAL SECTOR OFFSET WHICH WILL
STA FCBSOF,U ; FORCE NEW SECTOR DATA TO BE READ IN
LDA ,X ; GET CURRENT GRANULE
CMPA #$C0 ; IS IT THE LAST GRANULE?
BLO LC3B2 ; NO
ANDA #$3F ; MASK OFF LAST GRANULE FLAG BITS
CMPA FCBSEC,U ; COMPARE CALCULATED SECTOR TO CURRENT SECTOR IN FCB
BHS LC3B2 ; AND BRANCH IF CALCULATED SECTOR IS > LAST SECTOR IN FILE
LDA VD8 ; CHECK GET/PUT FLAG: IF 'GET' THEN 'INPUT
BEQ LC352 ; PAST END OF FILE' ERROR
LDA FCBSEC,U ; GET CURRENT SECTOR NUMBER FROM FCB,
ORA #$C0 ; OR IN THE LAST GRANULE FLAG BITS
STA ,X ; AND SAVE IN FAT
JSR >LC5A9 ; WRITE FAT TO DISK IF NECESSARY
LDX FCBRLN,U ; GET RECORD LENGTH AND CHECK TO
CMPX #SECLEN ; SEE IF IT IS SECLEN (EXACTLY ONE SECTOR)
BNE LC3AD ; BRANCH IF IT IS NOT EXACTLY ONE SECTOR
CMPX FCBLST,U ; BRANCH IF THE NUMBER OF BYTES IN THE LAST SECTOR
BEQ LC3B2 ; IS SET TO ONE SECTOR (SECLEN)
LDA #$81 ; SET THE PRESAVED FLAG (BIT15) AND FORCE
LC3AC FCB $21 ; THE NUMBER OF BYTES IN LAST SECTOR TO 256 (THROWN AWAY BRN INSTRUCTION)
LC3AD CLRA ; SET THE NUMBER OF BYTES IN LAST SECTOR TO ZERO
CLRB ; CLEAR LS BYTE OF ACCD
STD FCBLST,U ; SAVE THE NUMBER OF BYTES IN LAST SECTOR
LC3B2 LDB #$02 ; DSKCON READ OP CODE
LDX FCBRLN,U ; GET RECORD LENGTH AND COMPARE
CMPX #SECLEN ; IT TO SECLEN - EXACTLY ONE SECTOR
BNE LC3C8 ; BRANCH IF NOT EXACTLY ONE SECTOR LONG
LEAS $07,S ; CLEAN UP STACK
LDX FCBBUF,U ; POINT X TO START OF RANDOM FILE BUFFER
LDA VD8 ; CHECK GET/PUT FLAG AND
BEQ LC3C5 ; BRANCH IF GET
LDB #$03 ; DSKCON WRITE OP CODE
LC3C5 JMP >LC35A ; READ/WRITE A SECTOR
LC3C8 JSR >LC357 ; READ A SECTOR INTO FCB DATA BUFFER
PULS B,X ; GET BACK THE BYTE OFFSET TO RECORD: X = NUMBER OF
; SECTORS; ACCB = BYTE POINTER IN SECTOR
STX FCBSOF,U ; SAVE SECTOR OFFSET IN FCB
LC3CF PSHS B ; SAVE BYTE OFFSET ON STACK
JSR >LC755 ; POINT X TO FILE ALLOCATION TABLE
LEAX FATCON,X ; MOVE X TO FAT DATA
LDB FCBCGR,U ; GET CURRENT GRANULE NUMBER
ABX ; POINT X TO PROPER GRANULE IN FAT
LDA ,X ; GET CURRENT GRANULE AND CHECK TO
CMPA #$C0 ; SEE IF IT IS LAST GRANULE
BLO LC40A ; BRANCH IF THIS GRANULE IS < LAST GRANULE
ANDA #$3F ; MASK OFF LAST GRANULE FLAG BITS
CMPA FCBSEC,U ; COMPARE LAST SECTOR USED IN GRANULE TO
BNE LC40A ; CALCULATED SECTOR; BRANCH IF NOT EQUAL
LDD FCBLST,U ; GET NUMBER OF BYTES IN LAST SECTOR
ANDA #$7F ; MASK OFF PRESAVED FLAG (BIT 15)
PSHS B,A ; SAVE NUMBER OF BYTES IN LAST SECTOR ON STACK
CLRA ; LOAD ACCB WITH THE BYTE OFFSET TO CURRENT
LDB $02,S ; RECORD AND ADD THE REMAINING RECORD LENGTH
ADDD $03,S ; TO IT - ACCD = END OF RECORD OFFSET
CMPD ,S++ ; COMPARE THE END OF RECORD OFFSET TO THE NUMBER OF
BLS LC40A ; BYTES USED IN THE LAST SECTOR
TST VD8 ; CHECK GET/PUT FLAG AND BRANCH IF 'GET'
LBEQ LC352 ; TO 'INPUT PAST END OF FILE' ERROR
; IF LAST USED SECTOR, CALCULATE HOW MANY BYTES ARE USED
; IF DATA IS BEING 'PUT' PASTH THE CURRENT END OF FILE
; -----------------------------------------------------------------------------
if VERDISK>10
; -----------------------------------------------------------------------------
CMPD #SECLEN ; COMPARE TO ONE SECTOR'S LENGTH
BLS LC405 ; BRANCH IF REMAINDER OF RECORD LENGTH WILL FIT IN THIS SECTOR
LDD #SECLEN ; FORCE NUMBER OF BYTES = ONE SECTOR LENGTH
; -----------------------------------------------------------------------------
else
; -----------------------------------------------------------------------------
ANDA #$01
; -----------------------------------------------------------------------------
endif
; -----------------------------------------------------------------------------
LC405 ORA #$80 ; SET PRE-SAVED FLAG BIT - ALL PUT RECORDS ARE
; WRITTEN TO DISK BEFORE LEAVING 'PUT'
STD FCBLST,U ; SAVE NUMBER OF BYTES USED IN LAST SECTOR
LC40A PULS B ; PULL BYTE OFFSET OFF OF THE STACK
LEAX FCBCON,U ; POINT X TO FCB DATA BUFFER
ABX ; MOVE X TO START OF RECORD
LDU $02,S ; POINT U TO CURRENT POSITION IN RANDOM FILE BUFFER
PSHS B ; SAVE BYTE OFFSET ON STACK
LDA #-1 ; CONVERT ACCD INTO A NEGATIVE 2 BYTE NUMBER
; REPRESENTING THE REMAINING UNUSED BYTES IN THE SECTOR
ADDD $01,S ; ADD TEMPORARY RECORD LENGTH COUNTER (SUBTRACT
; REMAINING BYTES FROM TEMPORARY RECORD LENGTH)
BHS LC421 ; BRANCH IF THERE ARE ENOUGH UNUSED BYTES TO FINISH THE RECORD
STD $01,S ; SAVE NEW TEMPORARY RECORD LENGTH COUNTER
PULS B ; RESTORE BYTE COUNTER
NEGB ; NEGATE IT - ACCB = THE NUMBER OF BYTES
; AVAILABLE TO A RECORD IN THIS SECTOR
BRA LC429 ; MOVE THE DATA
; BRANCH HERE IF REMAINING RECORD LENGTH WILL FIT IN
; WHAT'S LEFT OF THE CURRENTLY SELECTED SECTOR
LC421 LDB $02,S ; GET REMAINING RECORD LENGTH
CLR $01,S ; CLEAR THE TEMPORARY RECORD LENGTH
CLR $02,S ; COUNTER ON THE STACK
LEAS $01,S ; PURGE BYTE OFFSET FROM STACK
LC429 LDA VD8 ; CHECK GET/PUT FLAG AND
BEQ LC42F ; BRANCH IF GET
EXG X,U ; SWAP SOURCE AND DESTINATION POINTERS
LC42F JSR >LA59A ; TRANSFER DATA FROM SOURCE TO DESTINATION BUFFERS
STU $02,S ; SAVE NEW TEMP RECORD POINTER ON THE STACK (GET)
; MOVE DATA FROM FCB DATA BUFFER TO THE RANDOM FILE BUFFER IF 'GET'
; OR FROM RANDOM FILE BUFFER TO FCB DATA BUFFER IF 'PUT'
LDU FCBTMP ; POINT U TO FCB
LDA VD8 ; CHECK GET/PUT FLAG AND
BEQ LC43E ; BRANCH IF GET
STA FCBFLG,U ; SAVE 'PUT' FLAG IN THE FCB
STX $02,S ; SAVE NEW TEMPORARY RECORD POINTER ON STACK (PUT)
LC43E LDX FCBSOF,U ; GET SECTOR OFFSET COUNTER AND
LEAX $01,X ; ADD ONE TO IT
CLRB ; SET BYTE OFFSET = 0
LDU ,S ; CHECK THE LENGTH OF THE TEMPORARY RECORD LENGTH
LBNE LC306 ; COUNTER AND KEEP MOVING DATA IF <> 0
PULS A,B,X,PC ; PULL TEMPORARY RECORD LENGTH AND
; BUFFER ADDRESS OFF STACK AND RETURN
; OPEN RAM HOOK
DVEC0 LEAS $02,S ; PULL RETURN ADDRESS OFF OF THE STACK
JSR >LB156 ; EVALUATE AN EXPRESSION
JSR >LB6A4 ; GET MODE(I,O,R) - FIRST BYTE OF STRING EXPRESSION
PSHS B ; AND SAVE IT ON STACK
JSR >LA5A2 ; GET DEVICE NUMBER
TSTB ; SET FLAGS
LBLE LA603 ; BRANCH IF NOT A DISK FILE
PULS A ; GET MODE
PSHS B,A ; SAVE MODE AND DEVICE NUMBER (FILE NUMBER)
CLR DEVNUM ; SET DEVICE NUMBER TO SCREEN
JSR SYNCOMMA ; SYNTAX CHECK FOR COMMA
LDX #DATEXT ; POINT TO 'DAT' FOR EXTENSION
JSR >LC938 ; GET FILENAME FROM BASIC
LDD #$01FF ; DEFAULT DISK FILE TYPE AND ASCII FLAG
STD DFLTYP ; SAVE DEFAULT VALUES: DATA, ASCII
LDX #SECLEN ; DEFAULT RECORD LENGTH - 1 PAGE
JSR GETCCH ; GET CHAR FROM BASIC
BEQ LC481 ; BRANCH IF END OF LINE
JSR SYNCOMMA ; SYNTAX CHECK FOR COMMA
JSR >LB3E6 ; EVALUATE EXPRESSION
LDX FPA0+2 ; GET EVALUATED EXPRESSION
LC481 STX DFFLEN ; RECORD LENGTH
LBEQ LB44A ; IF = 0, THEN 'ILLEGAL FUNCTION CALL'
JSR >LA5C7 ; ERROR IF ANY FURTHER CHARACTERS ON LINE
PULS A,B ; GET MODE AND FILE NUMBER
; OPEN DISK FILE FOR READ OR WRITE
LC48D PSHS A ; SAVE MODE ON STACK
JSR >LC749 ; POINT X TO FCB FOR THIS FILE
LBNE LA61C ; 'FILE ALREADY OPEN' ERROR IF FILE OPEN
STX FCBTMP ; SAVE FILE BUFFER POINTER
JSR >LC79D ; MAKE SURE FILE ALLOC TABLE IS VALID
JSR >LC68C ; SCAN DIRECTORY FOR 'FILENAME.EXT'
PULS B ; GET MODE
LDA #INPFIL ; INPUT TYPE FILE
PSHS A ; SAVE FILE TYPE ON STACK
CMPB #'I' ; INPUT MODE?
BNE LC4C7 ; BRANCH IF NOT
; OPEN A SEQUENTIAL FILE FOR INPUT
JSR >LC6E5 ; CHECK TO SEE IF DIRECTORY MATCH IS FOUND
JSR >LC807 ; CHECK TO SEE IF FILE ALREADY OPEN
LDX V974 ; GET RAM DIRECTORY BUFFER
LDD DIRTYP,X ; GET FILE TYPE AND ASCII FLAG
STD DFLTYP ; SAVE IN RAM IMAGE
BSR LC52D ; INITIALIZE FILE BUFFER CONTROL BLOCK
JSR >LC627 ; GO FILL DATA BUFFER
LC4BB JSR >LC755 ; POINT X TO PROPER FILE ALLOCATION TABLE
INC FAT0,X ; ADD ONE TO FAT ACTIVE FILE COUNTER
LDX FCBTMP ; GET FILE BUFFER POINTER
PULS A ; GET FILE TYPE
STA FCBTYP,X ; SAVE IT IN FCB
RTS
LC4C7 ASL ,S ; SET FILE TYPE TO OUTPUT
CMPB #'O' ; FILE MODE = OUTPUT?
BNE LC4E8 ; BRANCH IF NOT
; OPEN A SEQUENTIAL FILE FOR OUTPUT
TST V973 ; DOES FILE EXIST ON DIRECTORY?
BEQ LC4E1 ; BRANCH IF NOT
JSR >LC6FC ; KILL THE OLD FILE
LDA V973 ; GET DIRECTORY SECTOR NUMBER OF OLD FILE AND
STA V977 ; SAVE IT AS FIRST FREE DIRECTORY ENTRY
LDX V974 ; GET RAM DIRECTORY IMAGE OF OLD FILE AND
STX V978 ; SAVE IT AS FIRST FREE DIRECTORY ENTRY
; -----------------------------------------------------------------------------
if VERDISK>10
; -----------------------------------------------------------------------------
LC4E1 JSR >LC567 ; SET UP NEW DIRECTORY ENTRY ON DISK
; -----------------------------------------------------------------------------
else
; -----------------------------------------------------------------------------
LC4E1 BSR LC567 ; SET UP NEW DIRECTORY ENTRY ON DISK
; -----------------------------------------------------------------------------
endif
; -----------------------------------------------------------------------------
BSR LC538 ; INITIALIZE FILE BUFFER
BRA LC4BB ; FLAG AND MAP FCB AS BEING USED
LC4E8 CMPB #'R' ; FILE MODE = R (RANDOM)?
BEQ LC4F2 ; BRANCH IF SO
CMPB #'D' ; FILE MODE = D (DIRECT)?
LBNE LA616 ; 'BAD FILE MODE' ERROR IF NOT
; OPEN A RANDOM/DIRECT FILE
LC4F2 ASL ,S ; SET FILE TYPE TO DIRECT
LDD RNBFAD ; GET ADDRESS OF RANDOM FILE BUFFER AREA
PSHS B,A ; AND SAVE IT ON THE STACK
ADDD DFFLEN ; ADD THE RECORD LENGTH
BLO LC504 ; 'OB' ERROR IF SUM > $FFFF
CMPD FCBADR ; IS IT > THAN FCB DATA AREA?
BLS LC509 ; BRANCH IF NOT
LC504 LDB #2*29 ; 'OUT OF BUFFER SPACE' ERROR
JMP >LAC46 ; JUMP TO ERROR HANDLER
LC509 PSHS B,A ; SAVE END OF RANDOM BUFFER ON STACK
TST V973 ; DID THIS FILE EXIST
; -----------------------------------------------------------------------------
if VERDISK>10
; -----------------------------------------------------------------------------
BNE LC514 ; BRANCH IF SO
BSR LC567 ; SET UP NEW FILE IN DIRECTORY
BRA LC519 ; INITIALIZE FCB
LC514 LDA #$FF ; SET FILE TYPE MATCH = $FF (ILLEGAL VALUE) -
JSR >LC807 ; THIS WILL FORCE ANY OPEN MATCHED FILE TO CAUSE
; A 'FILE ALREADY OPEN' ERROR
; -----------------------------------------------------------------------------
else
; -----------------------------------------------------------------------------
BNE LC519 ; BRANCH IF SO
BSR LC567 ; SET UP NEW FILE IN DIRECTORY
; -----------------------------------------------------------------------------
endif
; -----------------------------------------------------------------------------
LC519 BSR LC52D ; INITIALIZE FCB
COM FCBSOF,X ; SET FCBSOF,X TO $FF (ILLEGAL SECTOR OFFSET) WHICH WILL
; FORCE NEW SECTOR DATA TO BE READ IN DURING GET/PUT
INC FCBREC+1,X ; INITIALIZE RECORD NUMBER = 1
PULS A,B,U ; U = START OF RANDOM FILE BUFFER AREA, ACCD = END
STD RNBFAD ; SAVE NEW START OF RANDOM FILE BUFFER AREA
STU FCBBUF,X ; SAVE BUFFER START IN FCB
LDU DFFLEN ; GET RANDOM FILE RECORD LENGTH
STU FCBRLN,X ; AND SAVE IT IN FCB
BRA LC4BB ; SET FAT FLAG, SAVE FILE TYPE IN FCB
; INITIALIZE FCB DATA FOR INPUT
LC52D BSR LC538 ; INITIALIZE FCB
LDU V974 ; GET RAM DIRECTORY IMAGE
LDU DIRLST,U ; GET NUMBER OF BYTES IN LAST SECTOR OF FILE
STU FCBLST,X ; SAVE IT IN FCB
RTS
; INITIALIZE FILE CONTROL BLOCK
LC538 LDX FCBTMP ; GET CURRENT FILE BUFFER
LDB #FCBCON ; CLEAR FCB CONTROL BYTES
LC53C CLR ,X+ ; CLEAR A BYTE
DECB ; DECREMENT COUNTER
BNE LC53C ; BRANCH IF NOT DONE
LDX FCBTMP ; GET CURRENT FILE BUFFER ADDRESS BACK
LDA DCDRV ; GET CURRENT DRIVE NUMBER AND
STA FCBDRV,X ; SAVE IT IN FCB
LDA V976 ; GET FIRST GRANULE -
STA FCBFGR,X ; SAVE IT AS THE STARTING GRANULE NUMBER AND
STA FCBCGR,X ; SAVE IT AS CURRENT GRANULE NUMBER
LDB V973 ; GET DIRECTORY SECTOR NUMBER
SUBB #$03 ; SUBTRACT 3 - DIRECTORY SECTORS START AT 3
ASLB ; MULTIPLY SECTORS
ASLB ; BY 8 (8 DIRECTORY
ASLB ; ENTRIES PER SECTOR)
PSHS B ; SAVE SECTOR OFFSET
LDD V974 ; GET RAM DIRECTORY IMAGE
SUBD #DBUF0 ; SUBTRACT RAM OFFSET
LDA #$08 ; 8 DIRECTORY ENTRIES/SECTOR
MUL ; NOW ACCA CONTAINS 0-7
ADDA ,S+ ; ACCA CONTAINS DIRECTORY ENTRY (0-71)
STA FCBDIR,X ; SAVE DIRECTORY ENTRY NUMBER
RTS
; SET UP DIRECTORY AND UPDATE FILE ALLOCATION TABLE ENTRY IN FIRST UNUSED SECTOR
LC567 LDB #28*2 ; 'DISK FULL' ERROR
LDA V977 ; GET SECTOR NUMBER OF FIRST EMPTY DIRECTORY ENTRY
LBEQ LAC46 ; 'DISK FULL' ERROR IF NO EMPTY DIRECTORY ENTRIES
STA V973 ; SAVE SECTOR NUMBER OF FIRST EMPTY DIRECTORY ENTRY
STA DSEC ; SAVE SECTOR NUMBER IN DSKCON REGISTER
LDB #$02 ; READ OP CODE
STB DCOPC ; SAVE IN DSKCON REGISTER
JSR >LD6F2 ; READ SECTOR
LDX V978 ; GET ADDRESS OF RAM IMAGE OF UNUSED DIRECTORY
STX V974 ; ENTRY AND SAVE AS CURRENT USED RAM IMAGE
LEAU ,X ; (TFR X,U) POINT U TO DIRECTORY RAM IMAGE
LDB #DIRLEN ; SET COUNTER TO CLEAR 32 BYTES (DIRECTORY ENTRY)
LC586 CLR ,X+ ; CLEAR BYTE
DECB ; DECREMENT COUNTER
BNE LC586 ; CONTINUE IF NOT DONE
LDX #DNAMBF ; POINT TO FILENAME AND EXTENSION RAM IMAGE
LDB #11 ; 11 BYTES IN FILENAME AND EXTENSION
JSR >LA59A ; MOVE B BYTES FROM X TO U
LDD DFLTYP ; GET FILE TYPE AND ASCII FLAG
STD $00,U ; SAVE IN RAM IMAGE
LDB #33 ; FIRST GRANULE TO CHECK
JSR >LC7BF ; FIND THE FIRST FREE GRANULE
STA V976 ; SAVE IN RAM
STA $02,U ; SAVE IN RAM IMAGE OF DIRECTORY TRACK
LDB #$03 ; GET WRITE OPERATION CODE AND SAVE
STB DCOPC ; IT IN DSKCON REGISTER
JSR >LD6F2 ; GO WRITE A SECTOR IN DIRECTORY
LC5A9 PSHS U,X,B,A ; SAVE REGISTERS
JSR >LC755 ; POINT X TO FILE ALLOCATION TABLE
INC FAT1,X ; INDICATE NEW DATA IN FILE ALLOC TABLE
LDA FAT1,X ; GET NEW DATA FLAG
CMPA WFATVL ; HAVE ENOUGH GRANULES BEEN REMOVED FROM THE FAT TO
; CAUSE THE FAT TO BE WRITTEN TO THE DISK
BLO LC5BA ; RETURN IF NO NEED TO WRITE OUT ALLOCATION TABLE
JSR >LC71E ; WRITE FILE ALLOCATION SECTOR TO DISK
LC5BA PULS A,B,X,U,PC ; RESTORE REGISTERS
; CONSOLE IN RAM VECTOR
DVEC4 LDA DEVNUM ; GET DEVICE NUMBER
LBLE XVEC4 ; BRANCH IF NOT DISK FILE
LEAS $02,S ; GET RID OF RETURN ADDRESS
LC5C4 PSHS X,B ; SAVE REGISTERS
CLR CINBFL ; CLEAR BUFFER NOT EMPTY FLAG
LDX #FCBV1-2 ; POINT TO FILE BUFFER VECTOR TABLE
LDB DEVNUM ; GET ACTIVE DISK FILE NUMBER
ASLB ; TIMES 2 - TWO BYTES PER FCB ADDRESS
LDX B,X ; NOW X POINTS TO FILE BUFFER
LDB ,X ; GET FILE TYPE (FCBTYP,X)
CMPB #RANFIL ; IS THIS A RANDOM (DIRECT) FILE?
BNE LC5EC ; BRANCH IF NOT
; GET A BYTE FROM A RANDOM FILE - RETURN CHAR IN ACCA
LDD FCBGET,X ; GET THE RECORD COUNTER
CMPD FCBRLN,X ; COMPARE TO RECORD LENGTH AND
BHS LC5FE ; BRANCH TO BUFFER EMPTY IF >= RECORD LENGTH
ADDD #$0001 ; ADD ONE TO RECORD POINTER AND
STD FCBGET,X ; SAVE IT IN FCB
LDX FCBBUF,X ; POINT X TO START OF RANDOM FILE BUFFER AND
LEAX D,X ; ADD THE RECORD COUNTER TO IT
LDA -1,X ; GET A CHARACTER FROM THE BUFFER
PULS B,X,PC ; RESTORE REGISTERS AND RETURN
; GET A BYTE FROM A SEQUENTIAL FILE
LC5EC LDB FCBCFL,X ; TEST THE CACHE FLAG AND BRANCH IF AN
BEQ LC5F9 ; EXTRA CHARACTER HAS NOT BEEN READ FROM FILE
LDA FCBCDT,X ; GET THE CACHE CHARACTER
CLR FCBCFL,X ; CLEAR THE CACHE FLAG
PULS B,X,PC ; RESTORE REGISTERS AND RETURN
LC5F9 LDB FCBDFL,X ; IS ANY DATA LEFT?
BEQ LC602 ; BRANCH IF SO
LC5FE COM CINBFL ; SET FLAG TO BUFFER EMPTY
PULS B,X,PC ; RESTORE REGISTERS AND RETURN
LC602 LDB FCBCPT,X ; GET CHARACTER POINTER
INC FCBCPT,X ; ADD ONE TO CHARACTER POINTER
DEC FCBLFT,X ; DECREMENT NUMBER OF CHARACTERS LEFT IN FILE BUFFER
BEQ LC611 ; IF LAST CHARACTER, GO GET SOME MORE
ABX ; ADD CHARACTER COUNTER TO X
LDA FCBCON,X ; GET DATA CHARACTER (SKIP PAST 25 FCB CONTROL BYTES
PULS B,X,PC
; GET A CHARACTER FROM FCB DATA BUFFER - RETURN CHAR IN ACCA
LC611 PSHS U,Y ; SAVE REGISTERS
CLRA ;
LEAU D,X ; POINT U TO CORRECT CHARACTER
LDA FCBCON,U ; GET DATA CHAR (SKIP PAST 25 CONTROL BYTES)
PSHS A ; AND SAVE DATA CHARACTER ON STACK
CLR FCBCPT,X ; RESET CHAR POINTER TO START OF BUFFER
LDA FCBDRV,X ; GET DRIVE NUMBER AND SAVE IT IN
STA DCDRV ; DSKCON VARIABLE
BSR LC627 ; GO READ A SECTOR - FILL THE BUFFER
PULS A,Y,U ; RESTORE REGISTERS AND DATA CHARACTER
PULS B,X,PC ; RESTORE REGISTERS AND RETURN
; REFILL THE FCB INPUT DATA BUFFER FOR SEQUENTIAL FILES
LC627 LDA FCBSEC,X ; GET CURRENT SECTOR NUMBER
LC629 INCA ; ADD ONE
PSHS A ; SAVE NEW SECTOR NUMBER ON THE STACK
CMPA #$09 ; NINE SECTORS PER GRANULE
BLS LC631 ; BRANCH IF <= 9
CLRA ; SET TO SECTOR ZERO
LC631 STA FCBSEC,X ; SAVE SECTOR NUMBER
LDB FCBCGR,X ; GET GRANULE NUMBET TO FAT POINTER
LEAU ,X ; POINT U TO FCB (TFR X,U)
JSR >LC755 ; POINT X TO PROPER FILE ALLOCATION TABLE
ABX ; ADD OLD GRANULE NUMBER TO FAT POINTER
LDB FATCON,X ; GET GRANULE NUMBER (6 CONTROL BYTES AT FRONT OF FAT)
LEAX ,U ; POINT X TO FCB
CMPB #$C0 ; IS CURRENT GRANULE LAST ONE IN FILE?
BHS LC64D ; YES
PULS A ; GET SECTOR NUMBER
SUBA #10 ; WAS IT 10? - OVERFLOW TO NEXT GRANULE IF SO
BNE LC65E ; BRANCH IF NOT
STB FCBCGR,X ; SAVE NEW GRANULE NUMBER
BRA LC629 ; SET VARIABLES FOR NEW GRANULE
LC64D ANDB #$3F ; GET NUMBER OF SECTORS USED IN THIS GRANULE
CMPB #$09 ; 9 SECTORS / GRANULE
BLS LC658 ; BRANCH IF OK
LC653 LDB #2*32 ; 'BAD FILE STRUCTURE' ERROR
JMP >LAC46 ; ERROR DRIVER
LC658 SUBB ,S+ ; SUBTRACT CURRENT SECTOR NUMBER AND PULS A
BLO LC67D ; BRANCH IF PAST LAST SECTOR
TFR B,A ; SECTOR NUMBER TO ACCA
LC65E PSHS A ; SAVE SECTOR NUMBER DIFFERENCE
BSR LC685 ; INCREMENT RECORD NUMBER
LDA #$02 ; GET READ OPERATION CODE
STA DCOPC ; AND SAVE IT IN DSKCON VARIABLE
JSR >LC763 ; GET PROPER TRACK AND SECTOR TO DSKCON VARIABLES
LEAU FCBCON,X ; POINT U TO START OF FCB DATA BUFFER
STU DCBPT ; AND SAVE IT IN DSKCON VARIABLE
JSR >LD6F2 ; GO READ A SECTOR INTO FCB BUFFER
CLR FCBLFT,X ; NUMBER OF CHARS LEFT IN BUFFER = 256
LDB ,S+ ; GET SECTOR NUMBER OFF STACK
BNE LC684 ; RETURN IF DATA LEFT; FALL THRU IF LAST SECTOR
LDD FCBLST,X ; GET NUMBER OF BYTES IN THE LAST SECTOR
BNE LC681 ; BRANCH IF SOME BYTES IN LAST SECTOR
LC67D CLRB ; SET NUMBER OF REMAINING BYTES = 256
COM FCBDFL,X ; SET DATA LEFT FLAG TO $FF
LC681 STB FCBLFT,X ; SAVE THE NUMBER OF CHARS LEFT IN BUFFER
LC684 RTS
LC685 LDU FCBREC,X ; GET CURRENT RECORD NUMBER
LEAU $01,U ; BUMP IT
STU FCBREC,X ; PUT IT BACK
RTS
; SCAN DIRECTORY FOR FILENAME.EXT FOUND IN DNAMBF. IF FILENAME FOUND,
; RETURN WITH SECTOR NUMBER IN V973, GRANULE IN V976 AND RAM BUFFER
; CONTAINING DIRECTORY DATA IN V974. IF DISK IS FULL THEN V973,
; V977 = 0. THE FIRST UNUSED SECTOR RETURNED IN V977, RAM IMAGE IN V978
LC68C CLR V973 ; CLEAR SECTOR NUMBER
CLR V977 ; CLEAR TEMP SECTOR COUNTER
LDD #$1102 ; TRACK 17 (DIRECTORY), READ OPERATION CODE
STA DCTRK ; SAVE TRACK NUMBER
STB DCOPC ; SAVE OPERATION CODE (READ)
LDB #$03 ; READ SECTOR 3 (FIRST DIRECTORY SECTOR)
LC69B STB DSEC ; SAVE SECTOR NUMBER IN DSKCON VARIABLE
LDU #DBUF0 ; BUFFER AREA NUMBER 0 AS DATA BUFFER - SAVE
STU DCBPT ; IN DSKCON VARIABLE
JSR >LD6F2 ; GO READ A SECTOR
LC6A5 STU V974 ; SAVE RAM DIRECTORY BUFFER ADDRESS
LEAY ,U ; POINT Y TO DIRECTORY BUFFER
LDA ,U ; GET A BYTE FROM BUFFER
BNE LC6D6 ; BRANCH IF NOT ZERO - FILE IS ACTIVE
BSR LC6D9 ; SET UNUSED FILE POINTERS IF ENTRY HAS BEEN KILLED
LC6B0 LDX #DNAMBF ; POINT TO DISK FILE NAME BUFFER
LC6B3 LDA ,X+ ; COMPARE THE FILENAME AND EXTENSION
CMPA ,U+ ; STORED IN RAM AT DNAMBF TO THE DIRECTORY
BNE LC6C7 ; ENTRY STORED AT ,U (BRANCH IF MISMATCH)
CMPX #DNAMBF+11 ; AT END OF FILE NAME BUFFER?
BNE LC6B3 ; BRANCH IF NOT DONE CHECKING FILENAME
STB V973 ; SAVE SECTOR NUMBER IN DSKCON VARIABLE
LDA FCBFGR,U ; GET NUMBER OF FIRST GRANULE IN FILE
STA V976 ; AND SAVE IT IN V976
RTS
LC6C7 LEAU DIRLEN,Y ; GET NEXT DIRECTORY ENTRY (DIRLEN BYTES PER ENTRY)
CMPU #DBUF0+SECLEN ; AT END OF BUFFER?
BNE LC6A5 ; CHECK NEXT ENTRY IF NOT AT END