-
Notifications
You must be signed in to change notification settings - Fork 2
/
disk.asm
3318 lines (3318 loc) · 136 KB
/
disk.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
* Disk Color BASIC 1.1
* Copied from the PDF version of Disk Color BASIC Unravelled.
* Fixed up to assemble in Mamou
*
* Revision History
*
* September 1, 2021 - Started Disk Squanchy BASIC
*# $Id: $
*
DHITOK EQU $E1 HIGHEST 1.1 DISK TOKEN
CYEAR EQU '2
*
*
*
**
**** 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
*FCBTYP EQU 0 FILE TYPE: $10=INPUT, $20=OUTPUT, 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)
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.
*FCBPOS EQU 6 CURRENT PRINT POSITION
*FCBREC EQU 7 CURRENT RECORD NUMBER: HOW MANY WHOLE SECTORS HAVE BEEN
* 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
*FCBDIR EQU 18 DIRECTORY ENTRY NUMBER (0-71)
*FCBLST EQU 19 NUMBER OF BYTES IN LAST SECTOR OF FILE
* 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)
FCBCON EQU 25 OFFSET TO FCB DATA BUFFER (256 BYTES)
* ORG $C000
*MAGICDG FCC 'DK'
LC002
* BRA LC00C
*DCNVEC FDB DSKCON DSKCON POINTER
*DSKVAR FDB DCOPC ADDRESS OF DSKCON VARIABLES
*DSINIT FDB DOSINI DISK INITIALIZATION VECTOR
*DOSVEC FDB DOSCOM DOS COMMAND VECTOR
**** ZERO OUT THE RAM USED BY DISK BASIC
LC00C LDX #DBUF0 POINT X TO START OF DISK RAM
LC00F CLR ,X+ CLEAR A BYTE
CMPX #DFLBUF END OF DISK'S RAM?
BNE LC00F 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
* LDX #DVEC20 GET DISK COMMAND INTERPRETATION LOOP RAM VECTOR
* STX RVEC20+1 SAVE IN RAM VECTOR TABLE
**** 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?
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
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
* JSR [DSINIT] INITIALIZE SWI2,3 JUMP ADDRESSES
JSR DOSINI INITIALIZE SWI2,3 JUMP ADDRESSES
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
JMP >SBASRS SET WARM START FLAG, ENTER BASIC
*DKWMST NOP WARM START INDICATOR
DKWMST
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
LC109 FCB 20 20 DISK BASIC 1.1 COMMANDS
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
*LC139 FCC 'DISK EXTENDED COLOR BASIC 1.1'
* FCB CR
* FCC 'COPYRIGHT (C) 198'
* FCB CYEAR
* FCC ' BY TANDY'
* FCB CR
* FCC 'UNDER LICENSE FROM MICROSOFT'
LC139 FCC 'DISK EXTENDED SQUANCHY BASIC'
* FCB CR,CR,0
FCB 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
FCS 'DOS' E1
* 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
FDB DOS DOS / E1
* 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 #LC290-2*27 POINT X TO DISK BASIC'S ERROR TABLE
JMP >LAC60 JUMP TO BASIC'S ERROR HANDLER
* DISK BASIC ERROR MESSAGES
LC290 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
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
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 #(35-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
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
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
LC4E1 JSR >LC567 SET UP NEW DIRECTORY ENTRY ON DISK
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
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
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
INCB NEXT SECTOR
CMPB #11 11 SECTORS MAX IN DIRECTORY
BLS LC69B BRANCH IF MORE SECTORS
RTS
LC6D6 COMA COMPLEMENT FIRST BYTE IN DIRECTORY EMTRY
BNE LC6B0 BRANCH IF FILE IS ACTIVE - FALL THRU IF NOT USED
* SET POINTERS FOR FIRST UNUSED DIRECTORY ENTRY
LC6D9 LDA V977 UNUSED ENTRY ALREADY FOUND?
BNE DVEC12 RETURN IF UNUSED ENTRY ALREADY FOUND
STB V977 SECTOR CONTAINING THIS DIRECTORY ENTRY
STU V978 POINTS TO RAM AREA WHERE DIRECTORY DATA IS STORED
DVEC12 RTS
LC6E5 LDB #2*26 'NE' ERROR
TST V973 WAS A DIRECTORY MATCH FOUND?
BNE DVEC12 RETURN IF FOUND
JMP >LAC46 JUMP TO ERROR HANDLER IF NOT FOUND
* KILL COMMAND
KILL JSR >LC935 GET FILENAME.EXT FROM BASIC
JSR >LA5C7 'SYNTAX' ERROR IF MORE CHARACTERS ON LINE
JSR >LC79D GET VALID FAT DATA
BSR LC68C TEST FOR FILE NAME MATCH IN DIRECTORY
BSR LC6E5 MAKE SURE THE FILE EXISTED
LC6FC LDA #$FF * MATCH FILE TYPE = $FF; THIS WILL CAUSE AN 'AO'
* * ERROR TO BE GENERATED IF ANY FILE TYPE IS OPEN
JSR >LC807 CHECK TO MAKE SURE FILE IS NOT OPEN
LDX V974 *GET RAM IMAGE OF DIRECTORY
CLR ,X *AND ZERO FIRST BYTE - KILL FILE (DIRNAM,X)
LDB #$03 =WRITE OPERATION CODE - SAVE
STB DCOPC =IT IN DSKCON VARIABLE
JSR >LD6F2 WRITE A SECTOR
LDB DIRGRN,X GET NUMBER OF FIRST GRANULE IN FILE
LC70F BSR LC755 POINT X TO PROPER FILE ALLOCATION TABLE
LEAX FATCON,X SKIP 6 CONTROL BYTES
ABX POINT TO CORRECT ENTRY
LDB ,X GET NEXT GRANULE
LDA #$FF *GET FREE GRANULE FLAG AND
STA ,X *MARK GRANULE AS FREE
CMPB #$C0 WAS THIS THE LAST GRANULE?
BLO LC70F * KEEP FREEING GRANULES IF NOT LAST ONE
* * WRITE FILE ALLOCATION SECTOR TO DIRECTORY - DO NOT WRITE
* * THE SIX CONTROL BYTES AT THE START OF THE FAT TO THE DISK
LC71E LDU #DBUF0 =POINT U TO DISK BUFFER 0 AND
STU DCBPT =SAVE IT AS DSKCON VARIABLE
LDD #$1103 * WRITE DIRECTORY TRACK - SAVE
STA DCTRK * TRACK AND WRITE OPERATION CODE IN
STB DCOPC * DSKCON VARIABLES
LDB #$02 = GET FILE ALLOCATION SECTOR AND
STB DSEC = SAVE IN DSKCON VARIABLE
BSR LC755 POINT X TO PROPER FILE ALLOCATION TABLE
CLR FAT1,X RESET FLAG INDICATING VALID FAT DATA HAS BEEN STORED ON DISK
LEAX FATCON,X MOVE (X) TO START OF GRANULE DATA
LDB #GRANMX 68 BYTES IN FAT
JSR >LA59A MOVE ACCB BYTES FROM FAT RAM IMAGE TO DBUF0
* ZERO OUT ALL OF THE BYTES IN THE FAT SECTOR WHICH DO NOT CONTAIN THE GRANULE DATA
LC739 CLR ,U+ CLEAR A BYTE
CMPU #DBUF0+SECLEN FINISHED THE WHOLE SECTOR?
BNE LC739 NO
JMP >LD6F2 WRITE A SECTOR
* ENTER WITH ACCB CONTAINING FILE NUMBER (1-15); EXIT WITH X POINTING
* TO CORRECT FILE BUFFER; FLAGS SET ACCORDING TO FILE TYPE.
LC744 PSHS B SAVE FILE NUMBER ON STACK
LDB DEVNUM GET DEVICE NUMBER (FILE NUMBER)
FCB $8C SKIP TWO BYTES (THROWN AWAY CMPX INSTRUCTION)
LC749 PSHS B SAVE FILE NUMBER ON STACK
ASLB X2: 2 BYTES PER POINTER
LDX #FCBV1-2 POINT X TO START OF FCB POINTERS
LDX B,X POINT X TO PROPER FCB
LDB FCBTYP,X SET FLAGS ACCORDING TO FILE TYPE
PULS B,PC RESTORE FILE NUMBER
* POINT X TO DRIVE ALLOCATION TABLE
LC755 PSHS B,A SAVE ACCD ON STACK
LDA DCDRV GET DRIVE NUMBER
LDB #FATLEN GET LENGTH OF FILE ALLOCATION TABLE
MUL MULTIPLY BY DRIVE NUMBER TO GET OFFSET
LDX #FATBL0 START OF FILE ALLOCATION TABLE
LEAX D,X POINT TO RIGHT TABLE
PULS A,B,PC RESTORE ACCD
* CONVERT GRANULE NUMBER TO TRACK & SECTOR NUMBER - X MUST BE POINTING TO CORRECT
* FCB; THE TRACK AND SECTOR NUMBER WILL BE STORED IN DSKCON REGISTERS
LC763 LDB FCBCGR,X GET GRANULE NUMBER
LSRB DIVIDE BY 2 - 2 GRANULES / TRACK
STB DCTRK TRACK NUMBER
CMPB #17 TRACK 17 = DIRECTORY TRACK
BLO LC76E BRANCH IF < DIRECTORY TRACK
INC DCTRK INCR TRACK NUMBER IF > DIRECTORY TRACK
LC76E ASLB MULTIPLY TRACK NUMBER BY 2
NEGB NEGATE GRANULE NUMBER
ADDB FCBCGR,X B=0 IF EVEN GRANULE; 1 IF ODD
BSR LC779 RETURN B=0 FOR EVEN GRANULE NUMBER, B=9 FOR ODD GRANULE NUMBER
ADDB FCBSEC,X ADD SECTOR NUMBER
STB DSEC SAVE SECTOR NUMBER
RTS
* MULTIPLY ACCD BY 9
LC779 PSHS B,A TEMP STORE ACCD ON STACK
ASLB *
ROLA * MULTIPLY BY 2
ASLB =
ROLA = MULTIPLY BY FOUR
ASLB *
ROLA * MULTIPLY BY EIGHT
ADDD ,S++ ADD ONE = MULTIPLY BY NINE
RTS
* CONVERT ACCD INTO A GRANULE NUMBER - RETURN RESULT IN ACCB;
* ENTER WITH ACCD CONTAINING A NUMBER OF SECTORS. RETURN IN ACCB
* THE NUMBER (0-67) CORRESPONDING TO THE NUMBER OF COMPLETE
* GRANULES CONTAINED IN THAT MANY SECTORS.
* DIVIDE BY 90, MULTIPLY BY 10 IS FASTER THAN DIVIDE BY 9
LC784 CLR ,-S CLEAR A TEMPORARY SLOT ON THE STACK
LC786 INC ,S * DIVIDE ACCD BY 90 - SAVE THE
SUBD #9*10 * QUOTIENT+1 ON THE STACK - REMAINDER
BPL LC786 * IN ACCB
LDA ,S = PUT THE QUOTIENT+1 IN ACCA AND
STB ,S = SAVE REMAINDER ON STACK
LDB #10 * MULTIPLY (QUOTIENT+1)
MUL * BY 10
PULS A PUT THE REMAINDER IN ACCA
LC796 DECB * DECREMENT THE GRANULE COUNT BY ONE FOR
ADDA #$09 * EVERY NINE SECTORS (1 GRANULE) IN THE
BMI LC796 * REMAINDER - COMPENSATE FOR THE + 1 IN QUOTIENT+1
CLRA CLEAR MS BYTE OF ACCD
LC79C RTS
* MAKE SURE RAM FILE ALLOCATION TABLE DATA IS VALID
LC79D BSR LC755 POINT X TO FAT FOR THE CORRECT DRIVE NUMBER
TST FAT0,X CHECK TO SEE IF ANY FILES ARE ACTIVE