-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path%-EXTENDER.lst.asm
3901 lines (3773 loc) · 464 KB
/
%-EXTENDER.lst.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
; -------------------------------------------------------------------------------------------------------------------------------
; This is the ROM-add-on that acts depending upon the drive number, via DW4 or via DOS as usual
; Verified 43 commands of the DosPlus49b, all of them worked flawlessly with drive / VDK of any size (180-360-360-720)
; I have left BOOT apart because it seems that only drive1 can be booted
; To BOOT an OS-9 or NitrOS-9 disk it should be mounted on DriveWire slot 0
; and it has to be a special boot disk to communicate with the DW server via parallel adapter or Becker Port
; NOTE: The commands that modify directory sectors (T20), don't update backup T16 (by these DOS design)
; -------------------------------------------------------------------------------------------------------------------------------
; From $fc to $ff will contain a slot number for units 1-2-3-4
; if they are greater than 4, then they must be pointing to a reserved DW4 slot, else they are actual floppy drives (1 to 4)
; last modification: slot 0 is also considered to be Drivewire (for booting OS-9 or NitrOS-9)
; numbers from 1 to 4 are ONLY accepted at the UNIT with the SAME number and just for physical drives
; -------------------------------------------------------------------------------------------------------------------------------
; This extender is intended for DPlus50
; DW42-0.25.12 - 2021-05-28 by Pere Serrat (pser1)
; DW42-0.25.13 - 2021-05-29 Mike Miller: Added multiboot BOOT command to allow RSDOS boot track disks
; Note - requires DOS repatch
; Mike Miller: Update size output to display large filesizes in SDIR, SDRIVE
; DW42-0.25.14 - 2021-06-03 Pere Serrat: corrects RSboot upgrade
; DW42-0.25.15 - 2021-06-04 Pere Serrat: adds cpyMPIcfg (copy of MPI config byte $ff7f)
; and modifies tstMPI to be fully compatible with mega-mini-MPI
; -------------------------------------------------------------------------------------------------------------------------------
; ROM routines
009F getNChr equ $9f ; get next char from input buffer
00A5 redLChr equ $a5 ; get last read char from input buffer
8000 basini equ $8000 ; basic rom beginning
8344 syserr equ $8344 ; system error
8371 okprmpt equ $8371 ; BASIC OK prompt, command loop
83ED basvect2 equ $83ed ; initialize BASIC
841F basvect1 equ $841f ; reset BASIC vectors, reset stack etc
849F runbasic equ $849f ; run_basic, enable IRQs etc
84ED romcmd equ $84ed ; rom entry to dispatch a tokenized command
89AA ckComma equ $89aa ; check for comma routine
89B4 synerr equ $89b4 ; rom entry to show syntax error
8B8D fcerr equ $8b8d ; entry to send message error
8E51 asc2Num equ $8e51 ; convert ASCII to number (1 byte)
8E83 get16bN equ $8e83 ; get a 16 bit number into x
90A5 sendCR equ $90a5 ; send a CR to screen
90E5 outstr equ $90e5 ; print string at X+1 to DEVNUM
957A outnum equ $957a ; print number in d to devnum
9A89 backspc equ $9a89 ; print a backspace to DEVNUM
B3B4 resetRt equ $b3b4 ; reset routine
B44F wrmStrt equ $b44f ; warmStart routine
B54A outchr equ $b54a ; print char A to DEVNUM
B7AA getfnam equ $b7aa ; read file name and length into $1d1
B84B ioerror equ $b84b ; IO_error
BCAB outRegA equ $bcab ; output reg A to screen as number
C000 romini equ $c000 ; beginning of roms area
C0F9 gtbtsig equ $c0f9 ; get Boot signature
C14E rdbttrk equ $c14e ; load disk track
; -------------------------------------------------------------------------------------------------------------------------------
; VARIABLES
0003 ErasCtr equ $03 ; sector count in eraser
0010 noexec equ $10 ; inhibit exec after loading
0011 bootflag equ $11 ; zero if run from command line, $55 if autorun on boot
0012 dnum equ $12 ; assigned drive number by dw4 server
0012 tokens equ #18 ; to be incremented each time words are added = NEW COMMANDS
001A newtok equ $1a ; this works with dos cartridge plugged in!
0050 FPA0 equ $50 ; number of bytes to flash
0052 oldSlot equ $52 ; FPA2 (re-used)
0053 oldBank equ $53 ; FPA3 (re-used)
0076 bufPtr equ $76 ; (re-used) pointer to buffer end for new name
0076 chksum equ $76 ; checksum of the sector to be sent to dw4 (2 bytes)
0076 dsktyp equ $76 ; (re-used) only for SDRIVE creating file. 0=DSK, 1=VDK
0076 dSource equ $76 ; 2 bytes (re-used)
0076 endadr equ $76 ; last loaded address - probably no conflict but collides with chksum equ $76
0076 hdwFlo equ $76 ; slot number where floppies are found (only for tstHDW)
0077 hdwSdc equ $77 ; slot number where SDC is found (only for tstHDW)
0086 TargBank equ $86 ; bank to be flashed
0089 curlow equ $89 ; low byte of cursor position
00B0 usrptr equ $b0 ; pointer to usr vector base
00E6 bigfil equ $e6 ; too big file flag - probably no conflict but collides with internal use of $e6 in format by dplus
00E7 retry equ $e7 ; to catch 1st acess to DW4 drives error
00EB DCDRV equ $eb ; bank number
00EE DCBPT equ $ee ; pointer to subroutines
00F8 cpyPtr equ $f8 ; (re-used) pointer to buffer end for SDIR
00F8 numUni equ $f8 ; unit number for new Commands (link, mount, bank)
00F8 oriNum equ $f8 ; number of requested slot-bank (re-used)
00F9 cpyWhat equ $f9 ; command that identifies BANK - SLOT (re-used)
00F9 numDir equ $f9 ; number of received dirs (re-used)
00F9 sdcSlot equ $f9 ; 1 byte (re-used)
00F9 swMap1 equ $f9 ; flag to switch to map1 (re-used)
00F9 trknum equ $f9 ; tracknumber in process for DSKINIT 4th patch
00FA dDest equ $fa ; 2 bytes (re-used)
00FA geodat equ $fa ; numTracks - numSect x track (2 bytes)
00FA itsRead equ $fa ; number of received items in a dir page (re-used)
00FA valPar equ $fa ; (re-used) value for parameter to send into B
00FB cmdNum equ $fb ; (re-used) command code to be sent
00FB itsDone equ $fb ; number of items shown of a page
00FB secxtrk equ $fb ; numSect x track (low byte of previous word)
00FC drvtab equ $fc ; system table for linked numbers to the 4 units (fc-fd-fe-ff)
0114 floSDC equ $114 ; bit 0 for unit 1, bit 1 for unit 2. If 0 use Floppy, if 1 use SDC
; bit 2 is 1 if Floppies present else 0
; bit 3 is 1 if SDC present else 0
; bit 5-4 show the slot where floppies are connected (0-3)
; bit 7-6 show the slot where SDC is connected (0-3)
0115 idxHD equ $115 ; index to a HD array (maximum 90 discs of 720+1 sectors DW4 VDK type) (values 1-90)
0134 newstb equ $134 ; base of new stub
015E hokini equ $15e ; first system hook
01A8 hokend equ $1a8 ; last system hook
01CD sstack equ $1cd ; backup of original stack
01CF sector equ $1cf ; counter, used when loading file contents, just below namebuf/DECB header
01D1 nambuf equ $1d1 ; fixed by BASIC, read filename function which stores in $1d1
01D1 namebuf equ $1d1 ; fixed by BASIC read filename function
01D1 decbhdr equ namebuf ; DECB headers get copied in here
01D9 startbuf equ namebuf+8 ; dw input data buffer, can reuse buffer after DECB header slot
02D9 endbuf equ startbuf+256 ; end of buffer area
03D9 fST16 equ $3d9 ; first sector of Track 16 (backup DIR)
03EA newusr equ $3ea ; will use $3ea - $3fd = 20 bytes (New USR area)
03FF cpyMPIcfg equ $03ff ; candidate to be a copy in RAM of $ff7f byte ($3EB - $3FF seem safe places ...)
; -------------------------------------------------------------------------------------------------------------------------------
; RAM area
3000 ramini equ $3000 ; where to copy the rom
6EFF rammax equ $6eff ; ram limit to send to highram (16k - 256 bytes) as a rom program to be run
6FFF rmaxld equ $6fff ; ram limit to load into low memory (for basic roms)
; -------------------------------------------------------------------------------------------------------------------------------
; SAM area
FFD8 R1CLR equ $ffd8 ; to clear fast poke $ffd9
FFDE RAMROM equ $ffde ; to go MAP0, resetting $ffdf (MAP1)
; -------------------------------------------------------------------------------------------------------------------------------
; HDW related addresses
FF20 BBOUT equ $ff20 ; used for DW4
FF20 PIA1Base equ $ff20 ; used by DWRead/DWWrite
FF22 BBIN equ $ff22 ; used for DW4
FF40 CMDREG equ $ff40 ; command register (write)
FF40 STATREG equ $ff40 ; status register (read)
FF41 PREG1 equ $ff41 ; param register 1
FF42 PREG2 equ $ff42 ; param register 2
FF42 DATREGA equ PREG2 ; first data register
FF43 PREG3 equ $ff43 ; param register 3
FF43 DATREGB equ PREG3 ; second data register
FF48 CTRLATCH equ $ff48 ; controller latch (write)
FF4A FLSHREG equ $ff4a ; Flash Register in SDC
FF4B BANKREG equ $ff4b ; Bank select in SDC
; HIGH nibble = ROM (/CTS)
; LOW nibble = HARDWARE (/SCS)
FF7F MPIcfg equ $ff7f ; value used in Tandy MultiPacks to save slots used (/CTS and /SCS)
; -------------------------------------------------------------------------------------------------------------------------------
; CONSTANTS
; Status Register Masks
0001 BUSY equ %00000001 ; set while a command is executing
0002 READY equ %00000010 ; set when ready for a data transfer
0080 FAILsdc equ %10000000 ; set on command failure
; Mode and Command Values
0000 destPtr equ 0 ; ofsset to get to the pointer to destination buffer (2 bytes)
000B CMDMODE equ $0b ; was $43 for CoCo - control latch value to enable command mode
0050 dimask equ $50 ; disable IRQ and FIRQ
0050 IntMasks equ $50 ; used by DWRead/DWWrite
0080 CMDREAD equ $80 ; read logical sector
00A0 CMDWRITE equ $a0 ; write logical sector
00AF eimask equ $af ; enable interrupts
00C0 CMDEX equ $c0 ; extended command
00D2 OP_READEX equ 'R'+$80 ; $D2 - Read one sector (DW4 opcode)
00E0 CMDEXD equ $e0 ; extended command with data block
00F2 OP_REREADEX equ 'r'+$80 ; $F2 - Re-read one sector (DW4 opcode)
00F3 E_CRC equ $f3 ; Same as NitrOS-9 E$CRC
; ===============================================================================================================================
; CODE BEGINNING
IF drgbin > 0 ; to create Patcher - Extender binaries
DFF7 org $e000-9 ; to create the BIN header
DFF7 55 fcb #$55 ; header values for a Dragon binary file. magic 1st byte
DFF8 02 fcb #$02 ; file type
DFF9 6000 fdb #$6000 ; load
DFFB 1BE7 fdb #absEnd-$e000 ; length
DFFD 6002 fdb #$6002 ; exec
DFFF AA fcb #$aa ; magic end byte
ELSE
org $e000 ; real program beginning
put $e000 ; allocated at $e000
ENDIF
; -------------------------------------------------------------------------------------------------------------------------------
; PROGRAM INIT
E000 4549 mark fcb $45,$49 ; "EI" mark to signal to the DOS that this extension wants to be called to initialize itself
E002 7EE58F jmp initext ; initialize extension
E005 161B7F lbra reptch ; direct jump to DOSPlus patcher
; -------------------------------------------------------------------------------------------------------------------------------
; Entry point for DOS command dispatcher. 1st patch
; Data received:
; A = track number
; B = command code (2=READ - 3=Unknown - 4=WRITE - 7=VERIFY(dummy read)
; X = address of system variable "number of sectors x track" for this drive
; Y = LSN
; U = sector counter (if not directory track)
; -------------------------------------------------------------------------------------------------------------------------------
E008 3402 entry pshs a ; save register 'A' (code overwritten. It's the first instruction in the DOS)
E00A 3401 pshs cc ; save flags
E00C 8D0F bsr phyvir ; detect physical or virtual drive
E00E 241E bcc dw4 ; if greater than 4 is a DriveWire slot number
E010 4D tsta ; is linked value equal 0? - demanat per KenH
E011 271B beq dw4 ; yes, so DriveWire slot 0
; -------------------------------------------------------------------------------------------------------------------------------
; The DOS part respects the original code
; -------------------------------------------------------------------------------------------------------------------------------
E013 3501 todos puls cc ; restore flags
E015 170CA1 lbsr flOrSd ; control access to floppy or SDC
E018 8602 lda #$02 ; get value #2 (number of retries). It's the second instruction in the DPlus49b
E01A 7EC10A jmp $c10a ; back to next sentence of DOS original code
; -------------------------------------------------------------------------------------------------------------------------------
; Detects if drive is physical or virtual (code in A)
; returns Carry set if DW4 slot number detected (now any value greater than 4)
; must use extended addressing because for DSKINIT, DP arrives here with $FF and if not virtual should return like that
; -------------------------------------------------------------------------------------------------------------------------------
E01D 3410 phyvir pshs x ; save working register
E01F 8E00FB ldx #drvtab-1 ; point to 1 byte before the slots table
E022 B600EB lda >$00eb ; get drive number
E025 A686 lda a,x ; get slot number for that drive
E027 B70012 sta >dnum ; put it into DW4 variable
E02A 8105 cmpa #5 ; is a DW4 number? - if not, Carry will be set
E02C 3590 puls x,pc ; restore register and return
; -------------------------------------------------------------------------------------------------------------------------------
; The dw4 part distinguishes between READ, VERIFY and WRITE opcodes
; -------------------------------------------------------------------------------------------------------------------------------
E02E 3501 dw4 puls cc ; get saved flags
; to avoid problems created by SOUND and PLAY over DW4
E030 3402 pshs a ; save register
E032 8602 lda #2 ; get value to mark output
E034 B7FF20 sta BBOUT ; to DW4
E037 4F clra ; set counter
E038 4A dw4L01 deca ; decrement counter
E039 26FD bne dw4L01 ; not zero, loopback
E03B 3502 puls a ; restore register
E03D 3474 pshs b,x,y,u ; save rest of registers (A was already onto stack) before recalculatimg Y
E03F 1A50 orcc #dimask ; disable interrupts to work with dw4
E041 8D4A bsr calcy ; do not relay on Y. Recalculate it from $eb-ec-ed
E043 8D68 bsr ctrlHD ; control index in HD if needed
E045 3021 leax 1,y ; X points now to the rigth dw4 sector (skipping the header) - [DW needs registers X-Y inverted!)
E047 109EEE ldy <$ee ; Y points to RAM buffer address
E04A C102 cmpb #2 ; is this a read command?
E04C 270F beq reddw4 ; yes, read sector from dw4
E04E C107 cmpb #7 ; is this a verify command?
E050 2606 bne wrtdw4 ; no, write sector to dw4
E052 108EFCFF ldy #$fcff ; initial byte of 256 area to be overwritten while verifying
E056 2005 bra reddw4 ; go read that sector
E058 BDE2C7 wrtdw4 jsr dowrit ; write a sector from buffer to dw4
E05B 2010 bra verify ; verify operation result
; -------------------------------------------------------------------------------------------------------------------------------
; This part asks dw4 a sector to be read and dw4 log reflects it accordingly. It is as simple as possible.
; -------------------------------------------------------------------------------------------------------------------------------
E05D BDFA84 reddw4 jsr DoRead ; call dw4 to read one sector
E060 250B bcs verify ; if operation error, give message
E062 2609 bne verify ; if incompleted, give message
E064 E6E4 ldb ,s ; get pushed B (opcode / command)
E066 C102 cmpb #2 ; is it read?
E068 261F bne jstvfy ; no, adapt flags and exit
E06A BDE20D jsr correct ; correct LSN if needed
E06D 3574 verify puls b,x,y,u ; restore received registers
E06F 3502 puls a ; and first one pushed
E071 2506 bcs failed ; detect operation error
E073 2604 bne failed ; detect incomplete read operation
E075 5F clrb ; operation succesful - no error code returned in B
E076 1CAF outgo andcc #eimask ; enable interrupts
E078 39 rts ; return to caller
E079 0DE7 failed tst <retry ; is flag retry ON ($01)?
E07B 2706 beq fail01 ; no, exit
E07D 2B04 bmi fail01 ; if negative exit too
E07F 00E7 neg <retry ; to get value $FF
E081 2085 bra entry ; try it again
E083 C6A6 fail01 ldb #$a6 ; set error code (unknown = ??)
E085 1A01 orcc #%00000001 ; set Carry flag (error)
E087 20ED bra outgo ; return
E089 1A04 jstvfy orcc #%00000100 ; set flag Z=1
E08B 20E0 bra verify ; exit via verify
; -------------------------------------------------------------------------------------------------------------------------------
; This is used to calculate the LSN number from system variables $ec (track) and $ed (sector)
; Controls the number of sides of the disks to change 18 s/t to 36
; returns the calculated LSN in register Y
; -------------------------------------------------------------------------------------------------------------------------------
E08D 3416 calcy pshs d,x ; save working registers
E08F 8E06A6 ldx #$6a6 ; point to byte before sectors x track table
E092 D6EB ldb <$eb ; get drive number
E094 A685 lda b,x ; get number of sectors x track for this drive
E096 D6EC calcy01 ldb <$ec ; get track number
E098 3D mul ; calculate sectors amount
E099 1F01 tfr d,x ; X gets this value
E09B 96ED lda <$ed ; get sector number
E09D 4A deca ; decrement
E09E 3186 leay a,x ; add to X and pass result to Y
E0A0 3596 puls d,x,pc ; restore registers and return
; -------------------------------------------------------------------------------------------------------------------------------
; Aternative entry for DSKINIT that comes without data in $6a7-8-9-a. So this one relies on system variable $f4 (as numSides)
; -------------------------------------------------------------------------------------------------------------------------------
E0A2 3416 caldi pshs d,x ; save working registers
E0A4 8612 lda #$12 ; sectors x track (single side)
E0A6 0DF4 tst <$f4 ; is disk single sided?
E0A8 2701 beq ecaldi ; yes, skip next
E0AA 48 asla ; double number of sectors x track
E0AB 20E9 ecaldi bra calcy01 ; jump to calculation routine
; -------------------------------------------------------------------------------------------------------------------------------
; to apply index to a DW4 HD on drive 4 if it is the case
; -------------------------------------------------------------------------------------------------------------------------------
E0AD 3406 ctrlHD pshs a,b ; save register
E0AF D6EB ldb <$eb ; get drive number
E0B1 C104 cmpb #4 ; is it 4?
E0B3 2613 bne eCtrl ; no, exit
E0B5 F60115 ldb idxHD ; get index of disc to be accesed
E0B8 C101 cmpb #1 ; is index 0 or 1?
E0BA 230C bls eCtrl ; yes, no offset
E0BC 5A decb ; else deduct one
E0BD 31A5 leay b,y ; Y = LSN + index
E0BF 86F0 lda #240 ; maximum acceptable value that can be used to multiply the index
E0C1 3D mul ; D = 240 * Index (if index=90, result 21360 -> $5370) always will be positive
E0C2 31AB leay d,y ; Y = LSN + 241*index
E0C4 31AB leay d,y ; Y = LSN + 481*index
E0C6 31AB leay d,y ; Y = LSN + 721*index now we have calculated the real LSN to be used, no loops!
E0C8 3586 eCtrl puls a,b,pc ; restore register and return
; -------------------------------------------------------------------------------------------------------------------------------
; Process that substitutes the calls to "WriteTrack". It is used ONLY by DSKINIT
; Writes the 18 sectors of one side in a loop
; If sector number received is 0, will write to side 1, else ($ff) will do side 2
; -------------------------------------------------------------------------------------------------------------------------------
E0CA 3401 inidsk pshs cc ; save flags
E0CC BDE01D jsr phyvir ; is drive physical or virtual?
E0CF 240B bcc virtual ; virtual, process it
E0D1 4D tsta ; is linked value 0?
E0D2 2708 beq virtual ; yes, so DW4 slot 0
E0D4 3501 puls cc ; get saved flags
E0D6 CC47F4 ldd #$47f4 ; physical, do nothing. This was overwritten by the patch
E0D9 7EC328 jmp $c328 ; back to DOS
; to avoid problems created by SOUND and PLAY over DW4
E0DC 0DEC virtual tst <$ec ; is track 0?
E0DE 260D bne iniD01 ; no, skip section
E0E0 3402 pshs a ; save register
E0E2 8602 lda #2 ; get value to mark output
E0E4 B7FF20 sta BBOUT ; to DW4
E0E7 4F clra ; set counter
E0E8 4A iniL01 deca ; decrement counter
E0E9 26FD bne iniL01 ; not zero, loopback
E0EB 3502 puls a ; restore register
E0ED 3501 iniD01 puls cc ; get saved flags
E0EF 1A50 orcc #dimask ; disable interrupts to work with dw4
E0F1 4F clra ; value 0
E0F2 1F8B tfr a,dp ; set direct page to 0
E0F4 setdp 0 ; notify compiler
E0F4 3476 pshs d,x,y,u ; save registers
E0F6 8D42 bsr filbuf ; fill buffer
E0F8 D6EC ldb <$ec ; get track number
E0FA C114 cmpb #$14 ; is this the directory (T20 track)?
E0FC 2607 bne wrt00 ; no, init the track
E0FE 0DF3 tst <$f3 ; yes, is it side 2? (0 means side 1)
E100 2603 bne wrt00 ; init side 2!
; yes, don't waste time, it will be filled later
E102 4F clra ; mark no error
E103 2025 bra eIni01 ; exit
E105 4C wrt00 inca ; 1st track of side 1
E106 0DF3 tst <$f3 ; is it side 1?
E108 2702 beq wrt01 ; yes, skip next one
E10A 8613 lda #19 ; get 1st track of side 2
E10C 97ED wrt01 sta <$ed ; update system variable
E10E 8D92 bsr caldi ; calculate first LSN to write to (into Y)
E110 8D9B bsr ctrlHD ; control index of HD if needed
E112 3021 leax 1,y ; X points to the rigth dw4 sector (skipping the header) - [DW needs them inverted!)
E114 109EEE ldy <$ee ; Y points to RAM buffer address
E117 C612 ldb #18 ; number of sectors to be initialized
E119 E7E2 stb ,-s ; put counter in stack
E11B BDE2C7 wrtmor jsr dowrit ; write sector to DW4
E11E 2510 bcs failed2 ; detect operation error
E120 260E bne failed2 ; detect incomplete read operation
E122 3001 leax 1,x ; point to next LSN
E124 6AE4 dec ,s ; dec counter
E126 26F3 bne wrtmor ; if not yet 0, do next one
E128 3261 leas 1,s ; get rid of counter
E12A 3576 eIni01 puls d,x,y,u ; restore registers (0 will be pulled for A)
E12C 4D eIniDsk tsta ; update flags
E12D 1CAF andcc #eimask ; enable interrupts
E12F 39 rts ; return
E130 3261 failed2 leas 1,s ; get rid of counter
E132 3576 puls d,x,y,u ; restore registers
E134 86FF lda #$ff ; mark error for Dskinit function
E136 1A01 orcc #$01 ; set Carry flag (error)
E138 20F2 bra eIniDsk ; return to caller
; -------------------------------------------------------------------------------------------------------------------------------
; Fill the buffer pointed by $ee all with value $e5
; -------------------------------------------------------------------------------------------------------------------------------
E13A 3454 filbuf pshs b,x,u ; save registers
E13C 9EEE ldx <$ee ; get buffer address
E13E CEE5E5 ldu #$e5e5 ; value to put
E141 8D32 bsr cpu2xb ; put 128 times U at X
E143 35D4 puls b,x,u,pc ; restore registers and return
; -------------------------------------------------------------------------------------------------------------------------------
; Fill the directory track T20 for DW4 and floppy as well
; Only used by DSKINIT, but to be sure, it controls a return address in the stack to work else returns
; -------------------------------------------------------------------------------------------------------------------------------
E145 3446 fildir pshs d,u ; save working registers
E147 CCC9EF ldd #$c9ef ; return address when called to write directory tracks by DSKINIT
E14A 10A364 cmpd 4,s ; is it the write track call?
E14D 2607 bne efildir ; not the write track command, skip fill subroutines
E14F 8D0D bsr fil16s ; fill buffer for the 16 Dir sectors
E151 8D2A bsr ffat1 ; fill buffer for FAT 1st sector
E153 BDE1D2 jsr ffat2 ; fill buffer for FAT 2nd sector
E156 3546 efildir puls d,u ; restore registers
E158 8E0800 ldx #$800 ; overwritten line by interceptor
E15B 7EC9F6 jmp $c9f6 ; back to DOS
; -------------------------------------------------------------------------------------------------------------------------------
; Fill the buffer for the 16 directory sectors with 10 unused entries
; -------------------------------------------------------------------------------------------------------------------------------
E15E 8E0A00 fil16s ldx #$a00 ; point to third buffer
E161 DE8A ldu <$8a ; get 16 bits zero
E163 8D10 bsr cpu2xb ; put 128 times U at X
E165 8689 lda #$89 ; code to mark not used entry
E167 8E0A00 ldx #$a00 ; point to the beginning again
E16A A784 fild02 sta ,x ; mark an entry
E16C 308819 leax 25,x ; point to next one
E16F 8C0AE8 cmpx #$ae8 ; done 10 entries?
E172 25F6 blo fild02 ; no, loop back
E174 39 rts ; return
; -------------------------------------------------------------------------------------------------------------------------------
; Put value in U in bytes pointed by X, B times (each time a word)
; -------------------------------------------------------------------------------------------------------------------------------
E175 C680 cpu2xb ldb #128 ; number of words to write
E177 EF81 cp01 stu ,x++ ; write one
E179 5A decb ; decrement counter
E17A 26FB bne cp01 ; if not 0, loopback
E17C 39 rts ; return
; -------------------------------------------------------------------------------------------------------------------------------
; Fill the first FAT sector. Must mark as used only the 18 sectors of Tracks 20 and 16 if applies
; -------------------------------------------------------------------------------------------------------------------------------
E17D 8E0800 ffat1 ldx #$800 ; point to first buffer
E180 96F2 lda <$f2 ; get number of tracks
E182 C612 ldb #$12 ; sectors x track (single side)
E184 0DF4 tst <$f4 ; is disk single sided?
E186 2701 beq ffat100 ; yes, skip next
E188 58 aslb ; double number of sectors x track
E189 DDFA ffat100 std <geodat ; save geometry data for later use
E18B C65A ldb #90 ; there are 180 FAT bytes, so 90 words, but 180k discs need only HALF that!
E18D DEFA ldu <geodat ; get geometry data
E18F 11832812 cmpu #$2812 ; is it a Single Sided Single Density disk (180k)?
E193 2601 bne ffat101 ; no, skip next
E195 56 rorb ; yes, divide by 2 to get 45 words
E196 CEFFFF ffat101 ldu #$ffff ; code to mark 16 free sectors
E199 8DDC bsr cp01 ; copy B times U at X
E19B 3341 leau 1,u ; create 0 value
E19D EF81 ffat102 stu ,x++ ; clear a word
E19F 8C08FC cmpx #$900-4 ; reached end of buffer minus 4 bytes to put geometry data there?
E1A2 25F9 blo ffat102 ; no, loopback
E1A4 DCFA ldd <geodat ; get geometry data
E1A6 ED81 ffat103 std ,x++ ; save it in 1st FAT sector
E1A8 43 coma ; complement
E1A9 53 comb ; both bytes
E1AA ED84 std ,x ; store again in FAT
E1AC C624 ldb #36 ; This the FAT byte where dir T16 begins for single sided discs
E1AE 96FB lda <secxtrk ; get sectors x track
E1B0 8112 cmpa #$12 ; is it single?
E1B2 2701 beq ffat104 ; yes, skip next
E1B4 58 aslb ; double to 72 (the same place for Double Side disks)
E1B5 3404 ffat104 pshs b ; save value for later use
E1B7 86F0 lda #$f0 ; flag value for parameter '/' (leave T16 free for data storage)
E1B9 91E6 cmpa <$e6 ; has $e6 this value?
E1BB 2702 beq ffat105 ; yes, don't mark sector T16 as used
E1BD 8D05 bsr markfat ; mark used sectors of T16
E1BF D6FB ffat105 ldb <secxtrk ; get sectors x track
; distance between T16 and T20 is 4 * tracks * N_Sxt / 8 bits = NSxt / 2
E1C1 56 rorb ; convert distance to FAT bytes to add to
E1C2 EBE0 addb ,s+ ; the previously pushed FAT byte for T16, clear stack
E1C4 8E0800 markfat ldx #$800 ; point to the begining of the FAT
E1C7 3085 leax b,x ; add offset to 1st DIR sector byte of that track
E1C9 4F clra ; 16 bit zero
E1CA 5F clrb ; to mark 16
E1CB ED81 std ,x++ ; used sectors by DIR track
E1CD 86FC lda #%11111100 ; and two zero bits more
E1CF A784 sta ,x ; to complete the 18 reserved sectors for any directory Track
E1D1 39 rts ; return
; -------------------------------------------------------------------------------------------------------------------------------
; Fill the second FAT sector. This is only used for 720k discs
; -------------------------------------------------------------------------------------------------------------------------------
E1D2 8E0900 ffat2 ldx #$900 ; point to second buffer
E1D5 DCFA ldd <geodat ; get geometry data
E1D7 10835024 cmpd #$5024 ; is it a 720K disc?
E1DB 2607 bne ffat201 ; no, do not put $FFs
E1DD CEFFFF ldu #$ffff ; to mark free sectors
E1E0 C65A ldb #90 ; must mark 180 bytes
E1E2 8D93 bsr cp01 ; copy B times U at X
E1E4 DE8A ffat201 ldu <$8a ; get 16 bits zero
E1E6 EF81 ffat202 stu ,x++ ; put 2 zero bytes
E1E8 8C0A00 cmpx #$a00 ; reached end of buffer?
E1EB 25F9 blo ffat202 ; no, loopback
E1ED 39 rts ; return
; -------------------------------------------------------------------------------------------------------------------------------
; Keep the good track number to avoid strange sequences. Called by DSKINIT and
; called from other points, one of them the COPY routine and from SAVE as well ...
; Has a control to detect that it is called from DSKINIT, else do nothing at all!
; when applied to DW4 the track number suffers non lineal sequences. Here we correct that
; -------------------------------------------------------------------------------------------------------------------------------
E1EE 3406 modtrk pshs d ; save register
E1F0 CCC9E1 ldd #$c9e1 ; the return address that identifies DSKINIT
E1F3 10A367 cmpd 7,s ; is the one corresponding to DSKINIT?
E1F6 2610 bne notdsk ; no, do nothing
E1F8 96EC lda <$ec ; get track number
E1FA 97F9 sta <trknum ; save in variable
E1FC BDD36B jsr $d36b ; (buf_read_sector) - this line was overwritten by patch
E1FF 96F9 lda <trknum ; get saved track number
E201 97EC sta <$ec ; back to its place
E203 3506 emodtrk puls d ; restore register
E205 7ED1A7 jmp $d1a7 ; back to DOS
E208 BDD36B notdsk jsr $d36b ; (buf_read_sector) - this line was overwritten by patch
E20B 20F6 bra emodtrk ; clean stack and back to DOS
; -------------------------------------------------------------------------------------------------------------------------------
; Part to detect a bigger than 180k disc and update tables accordingly. The same if disc was changed
; If read sector has no geometry data, we go to the other possible localization for directory ($168 - $2D0) (+1 for DW4)
; X is updated to the new LSN to be read, if necessary
; must be avoided ONLY when working with an HD at unit 4 (idxHD $115 >1)
; -------------------------------------------------------------------------------------------------------------------------------
E20D 3466 correct pshs d,y,u ; save registers
E20F 96EB lda <$eb ; get unit number
E211 8104 cmpa #4 ; is it #4?
E213 2605 bne cor00 ; no, skip control
E215 7D0115 tst idxHD ; working on a HD in a disk with index > 0?
E218 2639 bne ecorok ; yes, exit
E21A DCEC cor00 ldd <$ec ; get track-sector numbers
E21C 10831401 cmpd #$1401 ; is it 1st FAT sector?
E220 2631 bne ecorok ; no, exit
E222 CCC869 ldd #$c869 ; get return address from BACKUP command
E225 10A3E814 cmpd 20,s ; is this the case?
E229 2728 beq ecorok ; yes, exit
E22B DEEE ldu <$ee ; get read buffer address
E22D ECC900FE ldd $fe,u ; get complemented geodata bytes
E231 43 coma ; complement both bytes
E232 53 comb ; A=tracks; B=sectors x track ... possible values: 2812 - 2824 - 5012 - 5024
; their 1st FAT sector will equal that one: 0169 - 02d1 - 0169 - 02d1 (+1 due to DW4)
E233 10A3C900FC cmpd $fc,u ; do they equal the not complemented ones?
E238 2717 beq ecorok1 ; yes, we have a right FAT sector, update system tables and exit
; Bad 1st FAT sector read, we must change single <--> double as required
E23A 8C0169 cmpx #$0169 ; was sector read $0169 (single sided)
E23D 2605 bne cor01 ; no, change to single sided
E23F 8E02D1 ldx #$02d1 ; yes, change to double sided
E242 2003 bra cor02 ; go save new 1st FAT LSN
E244 8E0169 cor01 ldx #$0169 ; get single sided value
E247 8D10 cor02 bsr updtab ; update system tables (in some cases they are not yet filled)
E249 109EEE ldy <$ee ; get buffer address
E24C BDFA84 jsr DoRead ; read newly calculated T20 1st FAT LSN
E24F 2006 bra ecor ; exit
E251 8D06 ecorok1 bsr updtab ; update system tables
E253 1A04 ecorok orcc #%00000100 ; set flag Z=1, result OK
E255 1CFE andcc #%11111110 ; clear Carry flag, no errors
E257 35E6 ecor puls d,y,u,pc ; restore registers and return
; -------------------------------------------------------------------------------------------------------------------------------
; Updates system tables using param X as LSN for 1st DIR track (should get here with DW4 value)
; Affects system tables at $61c (dir LSN) and $6a7 (sectors x track)
; -------------------------------------------------------------------------------------------------------------------------------
E259 CE0616 updtab ldu #$616 ; point 6 bytes before drives info table
E25C D6EB ldb <$eb ; get drive number
E25E 8606 lda #6 ; register length
E260 3D mul ; calculate offset
E261 311F leay -1,x ; system works with $0168 or $02d0 (DW4 adds one because of the header)
E263 10AFCB sty d,u ; put LSN at requested drive table
E266 8612 lda #$12 ; default value for single sided
E268 8C0169 cmpx #$0169 ; is new value single sided?
E26B 2701 beq cor03 ; yes, skip next
E26D 48 asla ; double value
E26E CE06A6 cor03 ldu #$6a6 ; point 1 byte before sectors x track table
E271 D6EB ldb <$eb ; get drive number
E273 A7C5 sta b,u ; update value in table for that drive
E275 39 rts ; return
; -------------------------------------------------------------------------------------------------------------------------------
; Updates table $6a6 if drive is virtual. Uses data from stack (only BACKUP)
; -------------------------------------------------------------------------------------------------------------------------------
E276 3416 patbck pshs d,x ; save registers
E278 8E00FB ldx #drvtab-1 ; point to 1 byte before the slots table
E27B A6C4 lda ,u ; get source drive from stack hole
E27D 8D0C bsr updsxt ; update sectors x track
E27F A649 lda 9,u ; get destination drive from stack hole
E281 8D08 bsr updsxt ; update sectors x track
E283 3516 puls d,x ; restore registers
E285 A648 lda 8,u ; these 2 sentences were
E287 3D mul ; overwritten by patcher
E288 7EC839 jmp $c839 ; back to DOS
; -------------------------------------------------------------------------------------------------------------------------------
; Updates sectors x track of that drive (comes in A)
; -------------------------------------------------------------------------------------------------------------------------------
E28B E686 updsxt ldb a,x ; get associated slot number in drives table
E28D 2704 beq upds01 ; if cero is a special DW4 case, process it
E28F C104 cmpb #4 ; is it lower than 5?
E291 230B bls eupd ; yes, is a physicall drive, do not process it
E293 3410 upds01 pshs x ; save register
E295 8E06A6 ldx #$6a6 ; point 1 byte before sectors x track table
E298 E648 ldb 8,u ; get number of sectors x track in stack hole
E29A E786 stb a,x ; into table for that drive
E29C 3510 puls x ; restore register
E29E 39 eupd rts ; return
; -------------------------------------------------------------------------------------------------------------------------------
; This part avoids calling a hardware routine when the drive is virtual
; and when floppies allow it, in order to avoid that the FDC floppy light stays on forever
; -------------------------------------------------------------------------------------------------------------------------------
E29F 3403 noHdw pshs a,cc ; save A and flags
E2A1 BDE01D jsr phyvir ; detect drive type
E2A4 240F bcc retHdw ; if virtual, return
E2A6 4D tsta ; is linked value 0?
E2A7 270C beq retHdw ; yes, so DW4 slot 0
E2A9 3503 puls a,cc ; restore A and flags
; so it goes for floppies or SDC
E2AB 170A0B lbsr flOrSd ; will take care of destination hdw
E2AE 1A50 orcc #dimask ; first overwritten instruction
E2B0 66E4 ror ,s ; second overwritten instruction
E2B2 7EC174 jmp $c174 ; back to DOS
E2B5 0DE7 retHdw tst <retry ; is flag off (0)?
E2B7 2602 bne ret01 ; no, skip next
E2B9 0CE7 inc <retry ; turn flag ON ($01)
E2BB 3262 ret01 leas 2,s ; get rid of 2 pushed regs
E2BD 66E4 ror ,s ; get rid of pushed carry value
E2BF 35FB puls a,cc,dp,x,y,u,pc ; restore registers and return
; -------------------------------------------------------------------------------------------------------------------------------
; This intercepts the std DOS reset routine
; -------------------------------------------------------------------------------------------------------------------------------
E2C1 170308 dosReset lbsr initask ; put initial values
E2C4 7EB44F jmp wrmStrt ; call basic warmstart
; -------------------------------------------------------------------------------------------------------------------------------
; This part sends sectors to dw4 to be written. It is a block very similar to DoRead() but must work a bit different:
; Must send three blocks of data: The dw4 command, the data and the checksum, all of them in just one chunk
; -------------------------------------------------------------------------------------------------------------------------------
E2C7 9612 dowrit lda <dnum ; get drive number (real dw4 number)
E2C9 5F clrb ; LSN bits 23-16
E2CA 3436 pshs a,b,x,y ; save registers / data STACK: RETADRS, YL, YH, SectorL, SectorH, $0, dnum
E2CC 8E0000 ldx #0 ; zero to calculate Checksum for that sector
E2CF 4F clra ; byte counter (256)
E2D0 E6A0 calc ldb ,Y+ ; read a byte
E2D2 3A abx ; add to checksum
E2D3 4A deca ; decrement counter
E2D4 26FA bne calc ; if not all 256, keep on
E2D6 9F76 stx <chksum ; save checksum
E2D8 8657 lda #$57 ; dw4 OP_WRITE (write one sector)
E2DA 3402 rewrit pshs a ; save command onto stack STACK: RETADRS, YL, YH, SectorL, SectorH, $0, dnum, OP_WRITE
E2DC 30E4 leax ,s ; point X to top of stack
E2DE 108E0005 ldy #5 ; 5 bytes
E2E2 BDFB57 jsr DWWrite ; send 5 bytes to dw4: OP_WRITE, dnum, $0, Sector(H-L)
E2E5 3502 puls a ; discard command STACK: RETADRS, YL, YH, SectorL, SectorH, $0, dnum
E2E7 AE64 ldx 4,s ; get sector buffer pointer = received Y
E2E9 108E0100 ldy #$0100 ; to write 256 bytes
E2ED BDFB57 jsr DWWrite ; send sector (256 bytes)
E2F0 109E76 ldy <chksum ; get calculated checksum
E2F3 3420 pshs y ; save it onto stack STACK: RETADRS, YL, YH, SectorL, SectorH, $0, dnum, ChksumL, ChksumH
E2F5 30E4 leax ,s ; point X to top of stack
E2F7 108E0002 ldy #2 ; 2 bytes
E2FB BDFB57 jsr DWWrite ; send checksum to dw4
; get answer from dw4 for the whole pack
E2FE 3121 leay 1,y ; after a DWRITE Y returns zeroed, so this way it becomes equal to one
E300 BDFAD2 jsr DWRead ; read dw4 answer - this overwrites dnum byte
E303 3262 leas 2,s ; discard checksum STACK: RETADRS, YL, YH, SectorL, SectorH, $0, Returnedvalue
E305 2513 bcs writex ; detected framing error
E307 2611 bne writex ; detected not all bytes received
E309 A6E4 lda ,s ; get server answer (in old dnum position)
E30B 270D beq writex ; zero=OK, go out
E30D 81F3 cmpa #$F3 ; error type = #E_CRC?
E30F 2608 bne writer ; not this one, go out signaling error
E311 9612 lda <dnum ; get drive number
E313 A7E4 sta ,s ; put again in stack STACK: RETADRS, YL, YH, SectorL, SectorH, $0, dnum
E315 8677 lda #$77 ; dw4 code for OP_REWRITE
E317 20C1 bra rewrit ; go to rewrite same sector again
E319 53 writer comb ; sets the carry flag (ERROR)
E31A 35B6 writex puls a,b,x,y,pc ; restore received registers and return STACK: - - -
; -------------------------------------------------------------------------------------------------------------------------------
E31C 0D4457342653444320455854454E444552202856302E32352E3135290D psmsg fcc 13,"DW4&SDC EXTENDER (V0.25.15)",13
E339 4259205045524520534552524154202832303231290D0D00 fcn "BY PERE SERRAT (2021)",13,13
; --------------------------------------------------------------------------------------------------------------------------------
E351 204C4F4144494E4720524F4D0D00 ldtextr fcn / LOADING ROM/,13 ; initial message to the user
E35F 0D524F4D204C454E4754483A2000 endtxt fcn $0d, /ROM LENGTH: / ; message to show rom length
E36D 0D524F4D20544F4F2042494700 bigrom fcn $0d, /ROM TOO BIG/ ; message for roms greater than 16k-256bytes
E37A 4E4F5420412044573420534C4F540D00 notdw4 fcn /NOT A DW4 SLOT/,13 ; message for lrom without params and with default drive <> dw4
E38A 544F4B454E20544F4F204C4F570D00 low fcn /TOKEN TOO LOW/,13 ; message for not recognized token
E399 544F4B454E20544F4F20484947480D00 high fcn /TOKEN TOO HIGH/,13 ; message for not recognized token
E3A9 4452495645204D55535420455155414C20554E49540D00 drverr fcn /DRIVE MUST EQUAL UNIT/,13 ; message for drive <> unit for physical drives
E3C0 4953204C494E4B454420544F20414E4F5448455220554E49540D00 alrput fcn /IS LINKED TO ANOTHER UNIT/,13 ; message for trying to use an already linked disc
E3DB 554E4954204C494E4B0D00 headlnk fcn /UNIT LINK/,13 ; header for LLINK
E3E6 2020202000 spaces fcn / / ; text for detail line in LLINK
E3EB 4C4F4144494E4720424F4F5420545241434B00 ldtext fcn /LOADING BOOT TRACK/ ; message for OS9boot
E3FE 0D4E4F5420414E204F5320424F4F5420545241434B00 noostxt fcn $0d, /NOT AN OS BOOT TRACK/ ; errro message for os9boot
E414 202300 xidxTxt fcn / #/ ; text that precedes HD index number
E417 535452494E4720544F4F204C4F4E470D00 Str2Long fcn /STRING TOO LONG/,13 ; message for param string too long
E428 4E4F204D50492050524553454E540D00 NotAnMPI fcn /NO MPI PRESENT/,13 ; message for no NPI and ... next message too
E438 4E4F205344432050524553454E540D00 NotAnSDC fcn /NO SDC PRESENT/,13 ; message for no SDC present
E448 NotActSDC
E448 4E4F20414354495645205344430D00 fcn /NO ACTIVE SDC/,13 ; mmesage for not selected SDC
E457 BadFmtType
E457 464F524D41542056414C5545204E4F542056414C49440D00 fcn /FORMAT VALUE NOT VALID/,13 ; message for parameter invalid
E46F 494E44455820544F4F20484947480D00 idxHigh fcn /INDEX TOO HIGH/,13 ; index higher than max allowed
E47F 43555252454E542044495220495320524F4F540D00 noCurDir fcn /CURRENT DIR IS ROOT/,13 ; message to user
E494 4E4F5420504F535349424C450D00 canNot fcn /NOT POSSIBLE/,13 ; message for switching not possible
E4A2 3A2D2D4E4F20444953432D2D0D00 sdcNoDsc fcn /:--NO DISC--/,13 ; message for no disk in sdc drive
E4B0 3A544F54414C20534543544F52533A2000 totSect fcn /:TOTAL SECTORS: / ; text for detail in SDRIVE
E4C1 5344462000 datSDF fcn /SDF / ; text for SDRIVE
E4C6 4449522000 datDIR fcn /DIR / ; text for SDRIVE
E4CB 2020202000 datNUL fcn / / ; text for SDRIVE
E4D0 2020634F4E5400 msgCont fcn / cONT/ ; message to user CONTinue
E4D7 20206558495400 msgExit fcn / eXIT/ ; message to user EXIT
E4DE 494E56414C494420504152414D455445522056414C55450D00 wrongPar fcn /INVALID PARAMETER VALUE/,13 ; message
E4F7 535441434B20434F4E464C494354530D00 stackPrb fcn /STACK CONFLICTS/,13 ; error message
E508 54494D454F55540D00 timeout fcn /TIMEOUT/,13 ; error message for SDC access
E511 targetInUse
E511 54415247455420494E205553450D00 fcn /TARGET IN USE/,13 ; error message for SDC
E520 dirNotFound
E520 4449524543544F5259204E4F5420464F554E440D00 fcn /DIRECTORY NOT FOUND/,13 ; error message for SDC
E535 pathNameInvalid
E535 494E56414C494420504154484E414D450D00 fcn /INVALID PATHNAME/,13 ; error message for SDC
E547 miscHardware
E547 4D4953432E204841524457415245204552524F520D00 fcn /MISC. HARDWARE ERROR/,13 ; error message for SDC
E55D 554E4B4E4F574E204552524F520D00 unknown fcn /UNKNOWN ERROR/,13 ; error message for SDC
E56C targetNotFound
E56C 544152474554204E4F5420464F554E440D00 fcn /TARGET NOT FOUND/,13 ; error message for SDC
E57E 4E4F2036344B20434F4D50555445520D00 not64K fcn /NO 64K COMPUTER/,13 ; error message for SDC
; -------------------------------------------------------------------------------------------------------------------------------
; install new routines
; Creates a new USR table and fills it with calls to 'FC ERROR'
; usess the old USR table space to create a new STUB for the
; new commands that will be added after the D.O.S. ones
; -------------------------------------------------------------------------------------------------------------------------------
E58F 1A50 initext orcc #dimask ; disable interrupts
E591 308D1E55 leax newusr,pcr ; new address table for usr's
E595 9FB0 stx usrptr ; save at memory variable
E597 108E8B8D ldy #fcerr ; address for error message
E59B 860A lda #10 ; number of usr's
E59D 10AF81 nxtvec sty ,X++ ; fill element table
E5A0 4A deca ; decrement counter
E5A1 26FA bne nxtvec ; not finished, go back
E5A3 8612 lda #tokens ; get number of new tokens
E5A5 B70134 sta newstb ; store at stub base byte
E5A8 308C72 leax newrds,pcr ; base of new reserved words table
E5AB BF0135 stx newstb+1 ; save on stub
E5AE 308C4C leax newdsp,pcr ; address of dispatching routine
E5B1 BF0137 stx newstb+3 ; save on stub
E5B4 8EE31B ldx #psmsg-1 ; point to message string
E5B7 BD90E5 jsr outstr ; show to screen
E5BA B6FF7F lda MPIcfg ; get received MPI config value for mega-mini-MPI compatibility
E5BD 8433 anda #$33 ; avoid using bits 7-6-3-2
E5BF B703FF sta cpyMPIcfg ; initialize copy
E5C2 B7FF7F sta MPIcfg ; update config byte
E5C5 8D05 bsr initask ; put initial values
E5C7 1CAF andcc #eimask ; enable interrupts
E5C9 7EF8A8 jmp expert ; goto auto-start experiments
; -------------------------------------------------------------------------------------------------------------------------------
E5CC 0FE7 initask clr <retry ; NO retry mark
E5CE CC0102 ldd #$0102 ; default values for the first two physical drives
E5D1 8E00FC ldx #$fc ; point to config area
E5D4 ED81 std ,x++ ; save these values
E5D6 CCF6F5 ldd #$f6f5 ; default values for Units 3-4 pointing to DW4 slots (245-246)
E5D9 ED84 std ,x ; save these values
E5DB DC8A ldd <$8a ; get 16 bits zero
E5DD FD0114 std floSDC ; clear $114 and $115
; pre-test on MPI
E5E0 1705F0 lbsr tstMPI ; is there an MPI?
E5E3 2604 bne initsk01 ; no, go to individual checks
E5E5 170548 lbsr tstHARD ; yes, verify connected hardware
E5E8 39 rts ; return
; else verify individual elements (only one active)
E5E9 17060B initsk01 lbsr tstSDC ; is SDC active?
E5EC 2709 beq fndSDC ; yes, skip next test
E5EE 17061D lbsr tstFLO ; is FDC active instead?
E5F1 2609 bne fndNthg ; no, go out, no harware present at all
E5F3 8604 fndFDC lda #%00000100 ; set FDC present and let both SDC drives OFF
E5F5 2002 bra savHdwF ; go save it
E5F7 860B fndSDC lda #%00001011 ; mark SDC present and put both SDC drives ON
E5F9 B70114 savHdwF sta floSDC ; save result
E5FC 39 fndNthg rts ; return
; -------------------------------------------------------------------------------------------------------------------------------
; Command dispatcher called from BASIC
; decodes the received token and passes it with the address
; of the new dispatch table to the ROM command execution
; -------------------------------------------------------------------------------------------------------------------------------
E5FD 811A newdsp cmpa #newtok ; compare to first defined token
E5FF 250C blo lowerr ; if lower show error
E601 812C cmpa #newtok+tokens ; compare to last one
E603 240E bhs higher ; if higher show error
E605 801A suba #newtok ; first token converts to 0
E607 308C68 leax nwtb01,pcr ; get new commands dispatch table base address
E60A 7E84ED jmp romcmd ; pass to rom command execution
E60D 308DFD79 lowerr leax low,pcr ; point to message
E611 2004 bra new1 ; show error and return to interpreter
E613 308DFD82 higher leax high,pcr ; point to message
E617 BD90E5 new1 jsr outstr ; show the selected error
E61A 7E89B4 jmp synerr ; rom will show syntax error message
; -------------------------------------------------------------------------------------------------------------------------------
; new reserved words
; -------------------------------------------------------------------------------------------------------------------------------
E61D 44574C4F41C4 newrds fcc /DWLOA/,$C4 ; char 'D' OR $80 dwload = DLOAD (the new into this ROM)
E623 4D4F554ED4 fcc /MOUN/,$D4 ; char 'T' OR $80 mounT = Associate a VDK to a Drive Number
E628 4C494ECB fcc /LIN/,$CB ; char 'K' or $80 linK = fill unit cell with received data
E62C 4C4C494ECB fcc /LLIN/,$CB ; char 'K' or $80 llinK = show units links
E631 444FD3 fcc /DO/,$D3 ; char 'S' or $80 doS = Boot a NitrOS-9 disc
E634 4C524FCD fcc /LRO/,$CD ; char 'M' or $80 lroM = Load or Run a ROM image
E638 42414ECB fcc /BAN/,$CB ; char 'K' or $80 banK = change active SDC-bank
E63C 534C4FD4 fcc /SLO/,$D4 ; char 'T' OR $80 sloT = change to another MPI slot ($ef)
E640 5344524956C5 fcc /SDRIV/,$C5 ; char 'E' or $80 sdrivE = multipurpose for SDC-card
E646 534449D2 fcc /SDI/,$D2 ; char 'R' or $80 sdiR = multipurpose for SDC-card
E64A 48444944D8 fcc /HDID/,$D8 ; char 'X' or $80 hdidX = select the index disc in an HD array (max 90)
E64F 534D4B4449D2 fcc /SMKDI/,$D2 ; char 'R' or $80 smkdiR = create a directory in the SDC-card
E655 534B494CCC fcc /SKIL/,$CC ; char 'L' or $80 skilL = kill a file or an empty directory in a SDC-card
E65A 535245CE fcc /SRE/,$CE ; char 'N' or $80 sreN = rename a file in a SDC-card
E65E 554E4C4F41C4 fcc /UNLOA/,$C4 ; char 'D' OR $80 unloaD = token to be used just as parameter ($f6)
E664 534348C4 fcc /SCH/,$C4 ; char 'D' OR $80 schD = to change ACTUAL Directory
E668 57524954C5 fcc /WRIT/,$C5 ; char 'E' or $80 writE = write to a flash bank
E66D 53434F50D9 fcc /SCOP/,$D9 ; char 'Y' or $80 scopY = copy ROM from bank or slot to RAM
; -------------------------------------------------------------------------------------------------------------------------------
; Dispatch table. This is an indirect table
; it contains the start address of every new command
; -------------------------------------------------------------------------------------------------------------------------------
E672 F8F7 nwtb01 fdb dwload ; routine for DWLOAD command
E674 E6A3 fdb mount ; routine for MOUNT command
E676 E711 fdb link ; routine for LINK command
E678 E78E fdb llink ; routine for LLINK command
E67A E7EB fdb os9boot ; routine to boot NitrOS-9
E67C E86B fdb xlrom ; routine to load - run a ROM image
E67E EA11 fdb xbank ; routine to switch SDC active bank
E680 EC2B fdb xslot ; routine to change of MPI slot
E682 ED1B fdb xsdrive ; routine for SDC-card DRIVE functions
E684 F30F fdb xsdir ; routine for SDC-card DIR functions
E686 ED01 fdb xHDidx ; routine to select index of HD
E688 F20C fdb xsmkdir ; routine for SMKDIR command
E68A F236 fdb xskill ; routine for SDELETE command
E68C F23D fdb xsren ; routine for SRENAME command
E68E E775 fdb snError ; simply show syntax error
E690 F2D4 fdb xschd ; routine for SCHD command
E692 F4B5 fdb xwrite ; routine for WRITE command
E694 F67F fdb xscopy ; routine for SCOPY command
; -------------------------------------------------------------------------------------------------------------------------------
; Dispatch routines for the new added commands
; -------------------------------------------------------------------------------------------------------------------------------
; Routine to mark as invalid the four I/O buffers
; -------------------------------------------------------------------------------------------------------------------------------
E696 4F mrkmod clra ; get a 0
E697 8E0636 ldx #$636 ; point to 1st I/O buffer flags data
E69A C615 ldb #21 ; offset to last I/O
E69C A785 mo01 sta b,x ; mark as invalid
E69E C007 subb #7 ; offset to previous I/O
E6A0 2AFA bpl mo01 ; if not negative, loopback
E6A2 39 rts ; return
; -------------------------------------------------------------------------------------------------------------------------------
; Command to ask DW4 to mount a VDK file and get the slot number back
; -------------------------------------------------------------------------------------------------------------------------------
E6A3 1700BA mount lbsr readunit ; read unit number
E6A6 D7F8 stb <numUni ; save it as number of Unit
E6A8 BD89AA jsr ckComma ; CkComma
E6AB BDB7AA jsr getfnam ; GetNam into $1d1 (nambuf)
E6AE 8E01D0 ldx #nambuf-1 ; byte before packet buffer start
E6B1 6F84 clr ,x ; zero MSB to make a 16 bit value for Y
E6B3 10AE81 ldy ,x++ ; length of file name (16 bit)
E6B6 2756 beq failvdk ; if len=0 no file entered
E6B8 E61F ldb -1,x ; length of name (8 bit)
; Adding .VDK if not termination entered, costs 31 bytes
E6BA 3414 pshs b,x ; save pointer to beginning of name and name length
E6BC A680 isdot lda ,x+ ; get a char from name
E6BE 812E cmpa #'.' ; is it a dot?
E6C0 2718 beq alrdot ; yes, stop search, quit loop
E6C2 5A decb ; decrement counter
E6C3 26F7 bne isdot ; not end of string, get next char name
E6C5 CC2E56 ldd #$2e56 ; get chars ".V"
E6C8 ED81 std ,x++ ; add to end of name
E6CA CC444B ldd #$444b ; get chars "DK"
E6CD ED81 std ,x++ ; add to end of name
E6CF E6E4 ldb ,s ; get old name length
E6D1 CB04 addb #4 ; add 4 (because of .VDK added)
E6D3 E7E4 stb ,s ; update new length in stack
E6D5 F701D1 stb nambuf ; save new length in byte before string
E6D8 3124 leay 4,y ; correction to name length - DW parameter
E6DA 3402 alrdot pshs a ; save register
E6DC 8602 lda #2 ; get value to mark output
E6DE B7FF20 sta BBOUT ; to DW4
E6E1 4F clra ; set counter
E6E2 4A mount01 deca ; decrement counter
E6E3 26FD bne mount01 ; not zero, loopback
E6E5 3502 puls a ; restore register
E6E7 3514 puls b,x ; restore pointer and length
E6E9 6F85 clr b,x ; zero terminate name string (for error)
E6EB 6C83 inc ,--x ; 1 = DriveWire OP_NAMEOBJ_MOUNT command
E6ED 3122 leay 2,y ; length of DW packet = name length + 2
E6EF 1A50 orcc #dimask ; disable interrupts to work with DW4
E6F1 BDFB57 jsr DWWrite ; send file request to server
E6F4 8E0012 ldx #dnum ; our drive number variable
E6F7 6F84 clr ,x ; clear it
E6F9 3121 leay 1,y ; read one byte back
E6FB BDFAD2 jsr DWRead ; get drive number
E6FE 1CAF andcc #eimask ; enable interrupts again
E700 6D84 tst ,x ; verify received value
E702 2605 bne vdkok ; successful mount
E704 C619 ldb #$19 ; code for MO ERROR
E706 7E8344 jmp syserr ; show error message (syserr)
E709 D612 vdkok ldb <dnum ; pass slot to B
E70B 8D25 bsr stval ; verify / store new value
E70D 39 rts ; return
E70E 7EB84B failvdk jmp ioerror ; I/O error message
; -------------------------------------------------------------------------------------------------------------------------------
; Command to link a Unit with a drive number or a DW4 slot number
; -------------------------------------------------------------------------------------------------------------------------------
E711 8D4D link bsr readunit ; read unit number
E713 D7F8 stb <numUni ; save it as number of Unit
E715 8D65 bsr opt8bit ; search another param 8 bit number
E717 260E bne link01 ; if greater than 0, goto more tests
; requested slot #0
E719 D6F8 ldb <numUni ; get unit number
E71B C101 cmpb #1 ; is it 1?
E71D 2604 bne notalw ; no, error. Only unit 1 is allowed to be linked to slot #0
E71F 0FFC clr <$fc ; put 0 value in first cell (unit 1, value 0)
E721 200E bra link03 ; exit
E723 C608 notalw ldb #$08 ; code for FC error
E725 2045 bra basyserr ; show error message
E727 C104 link01 cmpb #4 ; is new value greater than 4 (DW4)?
E729 2204 bhi link02 ; yes, skip test
E72B D1F8 cmpb <numUni ; equals new drive number the unit number? (mandatory!)
E72D 262B bne numError ; no, show unit error
E72F 8D01 link02 bsr stval ; verify and store new value
E731 39 link03 rts ; return
; -------------------------------------------------------------------------------------------------------------------------------
; Verifies that the new value (B) is not linked to another unit. If good, saves it
; -------------------------------------------------------------------------------------------------------------------------------
E732 8E00FB stval ldx #$00fb ; point one byte before drive/slot table
E735 8604 lda #4 ; counter (number of units)
E737 E186 stv02 cmpb a,x ; equals new value the contents of that slot?
E739 2715 beq stv04 ; yes, see if it is the same unit
E73B 4A deca ; decrement counter
E73C 26F9 bne stv02 ; if not 0, loopback
E73E 8E00FB estval ldx #$00fb ; point to one byte before data table
E741 96F8 lda <numUni ; get unit number
E743 8104 cmpa #4 ; is unit 4?
E745 2603 bne stv03 ; no, skip next
E747 7F0115 clr idxHD ; set index to HD to 0
E74A E786 stv03 stb a,x ; store slot into table
E74C 17FF47 lbsr mrkmod ; modify data to flag drive changes to system
E74F 39 rts ; everything alright, return
E750 91F8 stv04 cmpa <numUni ; is unit with this value the same as destination in LINK command?
E752 27EA beq estval ; yes, acceptable, return
E754 3262 leas 2,s ; get rid of return address
; show error. We do not admit the same slot number in two units!
; bra already ; *** Fall Thru *** not needed
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
E756 8EE3BF already ldx #alrput-1 ; point to error message
E759 10 fcb #$10 ; to jump over next one
E75A 8EE3A8 numError ldx #drverr-1 ; point to error message
E75D 7E90E5 jmp outstr ; show message and return to interpreter
; -------------------------------------------------------------------------------------------------------------------------------
E760 0FF8 readunit clr <numUni ; clear unit number
E762 8D0D bsr getunit ; get a one digit number
E764 2704 beq errNum ; if zero jump to device error
E766 C104 cmpb #4 ; is it greater than 4?
E768 2305 bls OKnext ; no, goto OK
E76A C628 errNum ldb #$28 ; device number error (bas_err_DN)
E76C 7E8344 basyserr jmp syserr ; bas_system_error
E76F 0EA5 OKnext jmp <redLChr ; bas_poll_char
; -------------------------------------------------------------------------------------------------------------------------------
E771 9DA5 getunit jsr <redLChr ; get a char (bas_poll_char)
E773 2603 bne r8b01 ; if there is something, skip next
E775 7E89B4 snError jmp synerr ; show error message (BAS-SN-Error)
E778 BDE786 r8b01 jsr get8bit ; get a number (8bits)
E77B 39 rts ; return
; -------------------------------------------------------------------------------------------------------------------------------
E77C 9DA5 opt8bit jsr <redLChr ; get a char (bas_poll_char)
E77E 2705 beq eo8b ; if 0, return
E780 BD89AA jsr ckComma ; check if there is a comma separator (CkComa)
E783 8D01 bsr get8bit ; get a 8 bits number
E785 39 eo8b rts ; return
; -------------------------------------------------------------------------------------------------------------------------------