10
20
30
40
50
60
70
80
90 :
100
110
120
130
140
150
160
170
180
190
200
210
220
230 :
240 OS_CLI=&FFF7:OSBYTE=&FFF4:OSWORD=&FFF1:OSWRCH=&FFEE
250 OSWRCR=&FFEC:OSNEWL=&FFE7:OSASCI=&FFE3:OSRDCH=&FFE0
260 USERV=&200
270 :
280 ctrl=&80:addr=&82
290 :
300
310
320
330
340
350
360
370 :
380 run%=&FFFF2A00:load%=&FFFF2A00:fname$="OswFE"
390 DIM mcode% &700
400 FOR P=0 TO 1
410 P%=run%:O%=mcode%
420 [OPT P*3+4
430 \ OSWORD &FE entry
440 \ ----------------
450 .L2A00
460 INX:INX :\ Step past header bytes
470 : :\ *BUG* will fail if &xxFE or &xxFF
480 STX &80:STY &81 :\ Point to control block
490 LDA #&80:STA L2EFB :\ Set Tube not being used
500 JMP L2A64 :\ Jump into code
510 :
520 .L2A0E
530 RTS :\ Never called
540 :
550 .L2A0F
560 JSR L2C7D :\ 2A0F 20 7D 2C },
570 LDX #&00:JSR L2A59 :\ Write count in &A3 to track in &FE84 (looks wrong)
580 INX:JSR L2A59 :\ Write sector in &A4 to sector in &FE85
590 INX:JSR L2A59 :\ Write track in &A5 to data in &FE86 (looks wrong)
600 CMP &A3 :\ Compare with count in &A3
610 BEQ L2A3C :\ 2A21 F0 19 p.
620 LDA &A5 :\ Get track from &A5
630 BNE L2A2A :\ 2A25 D0 03 P.
640 JMP L2C91 :\ 2A27 4C 91 2C L.,
650 :
660 .L2A2A
670 ROR L2EFA :\ 2A2A 6E FA 2E nz.
680 SEC :\ 2A2D 38 8
690 ROL L2EFA :\ 2A2E 2E FA 2E .z.
700 LDA #&14 :\ 2A31 A9 14 ).
710 ORA &0D5C:STA &FE84 :\ 2A36 8D 84 FE ..~
720 JSR L2C18 :\ Wait until command completed
730 .L2A3C
740 LDA &A5 :\ 2A3C A5 A5 %%
750 STA &A3 :\ 2A3E 85 A3 .#
760 LDA &A1 :\ 2A40 A5 A1 %!
770 ROR A :\ 2A42 6A j
780 BCC L2A48 :\ 2A43 90 03 ..
790 .L2A45
800 JMP L2EA2 :\ Release and return
810
820 .L2A48
830 BIT &A1 :\ 2A48 24 A1 $!
840 BVS L2A56 :\ 2A4A 70 0A p.
850 LDY #&05 :\ 2A4C A0 05 .
860 LDA (&80),Y :\ 2A4E B1 80 1.
870 CMP #&0B :\ 2A50 C9 0B I.
880 BNE L2A56 :\ 2A52 D0 02 P.
890 BEQ L2A45 :\ 2A54 F0 EF po
900 .L2A56
910 JSR L2C7D :\ Clear &A2 bit 0 - NMI not completed
920 :
930 \ Write to FDC register and ensure it holds
940 .L2A59
950 LDA &A3,X:STA &FE85,X :\ Write to register
960 CMP &FE85,X:BNE L2A59 :\ Loop until it stays
970 RTS
980 :
990 \ OSWORD &FE entry
1000 \ ================
1010 \ (&80)=>control block +2
1020 .L2A64
1030 TSX:STX L2EF4 :\ Save stack pointer
1040 LDA #&10:STA L2EF1 :\ Prepare action=&10
1050 JSR L2A75 :\ Prepare for the operation, seek 0 if needed
1060 JSR L2CAA :\ Do the actual operation, returns with EQ
1070 BEQ L2A45 :\ Jump to release and return result
1080 :
1090 \ (&80),Y
1100 \ Followed by OSWORD &72 SCSI command block:
1110 \ &00 returned result
1120 \ &01 addr b0-b7
1130 \ &02 addr b8-b15
1140 \ &03 addr b16-b23
1150 \ &04 addr b24-b31
1160 \ &05 command
1170 \ &06 drive+sector b16-b20
1180 \ &07 sector b8-b15
1190 \ &08 sector b0-b7
1200 \ &09 sector count
1210 \ &0A restore to track zero before starting, b7=drive 0, b6=drive 1
1220 \ &0B drive 0 setting
1230 \ &0C drive 1 setting
1240 \ &0D
1250 \ &0E
1260 \ &0F
1270 .L2A75
1280 LDA #&00:STA L2EF3 :\ Set result to &00
1290 LDY #&01:LDA (&80),Y:STA &82 :\ Get address from control block
1300 INY:LDA (&80),Y:STA &83 :\ &82/&82 never used
1310 INY:LDA (&80),Y:TAX :\ X=&..XX....
1320 INY:LDA (&80),Y :\ A=&XX......
1330 INX:BEQ L2A92 :\ address=&xxFFxxxx, check I/O
1340 INX:BNE L2A96 :\ address<>&xxFExxxx, skip past
1350 .L2A92
1360 CMP #&FF:BEQ L2A99 :\ Check for &FFxxxxxx
1370 :
1380 \ Not &FFFFxxxx or &FFFExxxx
1390 .L2A96
1400 JSR L2B25 :\ Claim Tube
1410 .L2A99
1420 LDY #&05:LDA (&80),Y :\ Get command
1430 CMP #&08:BEQ L2AB1 :\ &08=Read
1440 CMP #&0A:BEQ L2AB8 :\ &0A=Write
1450 CMP #&0B:BEQ L2AB1 :\ &0B=Seek/Park
1460 LDA #&67:STA L2EF3 :\ Result=&67 - Unsupported FDD command
1470 JMP L2EA2 :\ Release and return
1480 :
1490 .L2AB1
1500 ROL L2EF1:SEC:ROR L2EF1 :\ Read/Seek, set action=&11
1510 .L2AB8
1520 JSR L2AE9 :\ Set up disk controller speeds
1530 JSR L2AC1 :\ Set up NMIs
1540 JMP L2DEE :\ Jump to perform the action
1550 :
1560 .L2AC1
1570 JSR L2B0F :\ Claim NMIs
1580 LDA L2EF6:STA &0D56 :\ Disk speed &00 or &02
1590 LDA L2EF5:STA &0D5C :\ Disk speed &00 or &03
1600 LDA #&00
1610 STA &A0:STA &A2 :\ Clear result and NMI flags
1620 LDA L2EF1:ORA #&20 :\ Set Action to &30 or &31
1630 STA L2EF1:STA &A1
1640 LDA L2EFB:STA &0D5D :\ Tube flag &80 or &81
1650 JMP L2B4E :\ Initialse NMI code
1660 :
1670 .L2AE9
1680 LDA #&00
1690 STA L2EF6:STA L2EF5 :\ Set speed controls to &00
1700 LDA #&FF:LDX #&00
1710 TAY:JSR OSBYTE :\ Read disk speed from kbd options
1720 TXA:PHA
1730 AND #&20:BEQ L2B04
1740 LDA #&03:STA L2EF5 :\ Speed bit5 set, set to &03
1750 .L2B04
1760 PLA:AND #&10:BEQ L2B0E
1770 LDA #&02:STA L2EF6 :\ Speed bit4 set, set to &02
1780 .L2B0E
1790 RTS
1800 :
1810 \ Claim NMIs
1820 .L2B0F
1830 LDA #&8F:LDX #&0C :\ Service &0C - Claim NMIs
1840 LDY #&FF
1850 .L2B15
1860 JSR OSBYTE :\ Make service call
1870 STY L2EF2 :\ Save previous NMI owner
1880 RTS
1890 :
1900 \ Release NMIs
1910 .L2B1C
1920 LDY L2EF2 :\ Get previous NMI owner
1930 LDA #&8F:LDX #&0B :\ Service call &0B - Release NMIs
1940 BNE L2B15
1950 :
1960 \ Claim Tube
1970 .L2B25
1980 LDY #&04 :\ Prepare to copy 4 bytes
1990 BIT L2EFB:BPL L2B42 :\ If Tube already claimed, exit
2000 .L2B2C
2010 LDA (&80),Y:STA L2EFB,Y :\ Copy transfer address
2020 DEY:BNE L2B2C
2030 ROR L2EFB:SEC:ROL L2EFB :\ Set flag to &81
2040 .L2B3B
2050 LDA #&C3:JSR &0406 :\ Claim with ID=&03
2060 BCC L2B3B :\ Loop until claimed
2070 .L2B42
2080 RTS
2090 :
2100 .L2B43
2110 ROR L2EFB:BCC L2B4D :\ Tube not being used, return
2120 LDA #&83:JSR &0406 :\ Release Tube with ID=3
2130 .L2B4D
2140 RTS
2150 :
2160 \ Copy NMI code to NMI area
2170 \ -------------------------
2180 .L2B4E
2190 LDY #&48
2200 .L2B50
2210 LDA L2BCF,Y:STA &0D00,Y :\ Copy NMI code
2220 DEY:BPL L2B50
2230 LDY #&02
2240 .L2B5B
2250 LDA (&80),Y:STA &0D0D,Y :\ Copy I/O address to NMI routine
2260 DEY:BNE L2B5B
2270 BIT &A1:BMI L2B6C
2280 LDA #&5F:STA &0D05
2290 .L2B6C
2300 LDA L2EFB :\ Get IO/Tube flag
2310 ROR A:BCC L2B7D :\ Initialise I/O transder
2320 LDA &A1:AND #&FD:STA &A1
2330 JSR L2B86:BMI L2B80 :\ Initialise Tube transfer
2340 :
2350 .L2B7D
2360 JSR L2BB5 :\ Initialise I/O transfer
2370 .L2B80
2380 LDA &F4:STA &0D34 :\ Set ROM to page in
2390 RTS
2400 :
2410 \ Start Tube transfer
2420 .L2B86
2430 LDA &A1:ROL A :\ Get action
2440 LDA #&00:ROL A :\ Convert into Tube action
2450 LDY #&2E:LDX #&FC :\ XY=>transfer address
2460 JSR &0406
2470 LDA &A1 :\ Get action
2480 AND #&10:BEQ L2BA8 :\ No transfer to happen
2490 BIT &A1:BMI L2BA9
2500 LDY #&07
2510 .L2B9F
2520 LDA L2C43,Y:STA &0D0A,Y :\ Copy Tube code to NMI area
2530 DEY:BPL L2B9F
2540 .L2BA8
2550 RTS
2560 :
2570 .L2BA9
2580 LDY #&07
2590 .L2BAB
2600 LDA L2C4B,Y:STA &0D0A,Y :\ Copy Tube code to NMI area
2610 DEY:BPL L2BAB:RTS
2620 :
2630 .L2BB5
2640 BIT &A1:BMI L2BCE :\ I/O LOAD, nothing to change
2650 LDY #&0D
2660 .L2BBB
2670 LDA L2C35,Y:STA &0D0A,Y :\ Copy I/O SAVE code to NMI area
2680 DEY:BPL L2BBB
2690 LDY #&02
2700 .L2BC6
2710 LDA (&80),Y:STA &0D0A,Y :\ Copy transfer address to NMI area
2720 DEY:BNE L2BC6
2730 .L2BCE
2740 RTS
2750 :
2760 \ FDC NMI routine, copied to NMI space at &0D00
2770 \ =============================================
2780 \ Defaults to IO LOAD code
2790 .L2BCF
2800 .L0D00
2810 PHA
2820 LDA &FE84:AND #&1F :\ Get FDC status, keep error bits
2830 CMP #&03:BNE L0D1A :\ If not DRQ+BSY, completed or error
2840 .L0D0A
2850 LDA &FE87:STA &FFFF :\ Fetch byte to memory
2860 INC &0D0E :\ Update I/O address
2870 BNE L0D18:INC &0D0F
2880 .L0D18
2890 PLA:RTI :\ Return from NMI
2900 :
2910 \ FDC controller error or completion
2920 .L0D1A
2930 AND #&58:BEQ L0D2C :\ Skip if no error bits set, must be completion
2940 STA &A0 :\ Store as result
2950 \ &08 CRC error in data
2960 \ &10 Sector not found
2970 \ &18 CRC error in ID
2980 \ &40 Write protected
2990 ROR &A1:SEC:ROL &A1 :\ Set bit 0, NMI error
3000 .L0D25
3010 ROR &A2:SEC:ROL &A2 :\ Set bit 0, NMI completed
3020 PLA:RTI :\ Return from NMI
3030 :
3040 \ Not an error, must be NMI completed
3050 .L0D2C
3060 BIT &A2:BVC L0D25 :\ If bit6 set, exit completed
3070 LDA &F4:PHA :\ Save current ROM
3080 LDA #&00 :\ ROM number
3090 STA &F4:STA &FE30 :\ Page in ROM (not needed, we are in RAM)
3100 TXA:PHA:JSR L2D59
3110 PLA:TAX:PLA
3120 STA &F4:STA &FE30 :\ Restore ROM
3130 PLA:RTI :\ Return from NMI
3140 \ End of NMI code
3150 \ ===============
3160 :
3170 \ Wait until &A2.bit 0 is set indicating NMI completed
3180 \ If &0D5D.bit4 set, allow Escape to abort
3190 .L2C18
3200 LDA &A2:ROR A:BCC L2C1E :\ Jump forward
3210 RTS :\ &A2 changed, exit
3220 .L2C1E
3230 LDA &0D5D :\ Get Escape-allowed flag
3240 AND #&10:BEQ L2C18 :\ &0%d%.b4=0, Escape not allowed, loop back
3250 BIT &FF:BPL L2C18 :\ Loop back if no Escape
3260 LDA #&00:STA &FE80 :\ Reset 1770
3270 LDA #&6F:STA &A0 :\ Result=&7F - Aborted
3280 JMP L2EA2 :\ Release and return
3290 :
3300 \ Copied to NMI area for I/O SAVE
3310 .L2C35
3320 LDA &FFFF:STA &FE87 :\ Copy byte from memory to disk
3330 INC &0D0B :\ Update embedded address
3340 BNE L2C43:INC &0D0C
3350 :
3360 \ Copied to NMI area for Tube SAVE
3370 .L2C43
3380 LDA &FEE5:STA &FE87 :\ Copy byte C->H
3390 BCS L2C51 :\ Skip past I/O address update
3400 :
3410 \ Copied to NMI area for Tube LOAD
3420 .L2C4B
3430 LDA &FE87:STA &FEE5 :\ Copy byte H->C
3440 .L2C51
3450 BCS L2C59 :\ Skip past I/O address update
3460 :
3470 .L2C53
3480 BIT &A1:BMI L2C64 :\ 2C55 30 0D 0.
3490 LDA &A3 :\ 2C57 A5 A3 %#
3500 .L2C59
3510 CMP #&14 :\ If <&14, convert to WriteSector
3520 LDA #&A0:BCC L2C66 :\ CMS=WriteSector
3530 ORA &0D56:BNE L2C66 :\ Otherwise, CMD=Seek+speed
3540 :
3550 .L2C64
3560 LDA #&80 :\ CMD=ReadSector
3570 .L2C66
3580 STA &A6:JSR L2C7D :\ Clear &A6 bit 0 - NMI not completed
3590 LDA &A6:JSR L2C9E :\ If &2EFA.b0 set, set 'e' in CMD
3600 STA &FE84:RTS :\ Write FDC command
3610 :
3620 \ Select side 2
3630 \ -------------
3640 .L2C74
3650 LDA &0D5E:ORA #&04 :\ Update DRVSEL with SIDE=1
3660 STA &0D5E:RTS
3670 :
3680 .L2C7D
3690 ROR &A2:CLC:ROL &A2:RTS :\ Clear bit 0 - NMI not completed
3700 :
3710 .L2C83
3720 LDA &A2:AND #&F7:STA &A2 :\ Clear bit 3 -
3730 RTS
3740 :
3750 .L2C8A
3760 LDA &A2:AND #&FD:STA &A2 :\ Clear bit 1 -
3770 RTS
3780 :
3790 .L2C91
3800 LDA #&00:STA &A3 :\ Set to 0
3810 ORA &0D5C:STA &FE84 :\ Do 'Restore', head=on, verify=off
3820 JMP L2C18 :\ Wait until completed or Abort
3830 :
3840 .L2C9E
3850 ROR L2EFA :\ 2C9E 6E FA 2E nz.
3860 BCC L2CA6 :\ 2CA1 90 03 ..
3870 ORA #&04 :\ 2CA3 09 04 ..
3880 CLC :\ 2CA5 18 .
3890 .L2CA6
3900 ROL L2EFA :\ 2CA6 2E FA 2E .z.
3910 RTS :\ 2CA9 60 `
3920 :
3930 \ Do the actual disk operation
3940 \ ----------------------------
3950 .L2CAA
3960 JSR L2A0F :\ Write &A3-&A5 to FE85-&FE87
3970 LDA &A2:ORA #&40:STA &A2 :\ Set bit6
3980 LDY #&07
3990 LDA (&80),Y:STA &0D58 :\ Get sector b8-b15
4000 INY:LDA (&80),Y :\ Get sector b0-b7
4010 INY:CLC:ADC (&80),Y :\ (sector b0-b7)+count
4020 STA &0D59
4030 BCC L2CC9:INC &0D58 :\ Increment carry
4040 .L2CC9
4050 \ &0D58/&0D59=sector number after last sector, sector+count
4060 :
4070 LDA &0D58:TAX :\ X=sectorend b8-b15
4080 LDA &0D59 :\ A=sectorend b0-b7
4090 LDY #&FF:JSR L2E96 :\ DIV/MOD10, Y=track, A=sector
4100 CMP #&00:BNE L2CDB :\ Not sector 0, not start of a track
4110 LDA #&0A :\ Use sector 10 as end sector
4120 .L2CDB
4130 \ Y=end track, A=end sector with &00 converted to &0A
4140 :
4150 LDY #&09:SEC:SBC (&80),Y :\ endsector-count
4160 BCS L2CFF :\ No overflow, within one track
4170 LDA #&0A:SEC:SBC &A4 :\ 10-secnum = seccount
4180 STA &0D58 :\ Store as seccount for this track
4190 LDA (&80),Y:SEC:SBC &0D58 :\ count - seccount
4200 LDX #&00 :\ X=0, A=sectount
4210 LDY #&FF:JSR L2E96 :\ DIV/MOD10, Y=track, A=sector
4220 STY &0D57:STA &0D59 :\ Y=tracks, A=sector
4230 BPL L2D10 :\ Jump forward to continue
4240 :
4250 .L2CFF
4260 LDY #&09:LDA (&80),Y:STA &0D58 :\ sector count
4270 LDA #&FF:STA &0D57
4280 LDA #&00:STA &0D59
4290 :
4300 .L2D10
4310 LDA #&00:STA &0D5A
4320 INC &0D57 :\ Incr. track count
4330 DEC &0D58 :\ Decr. sec. count
4340 LDX #&01:JSR L2A59 :\ Write sector in &A4 to sector in &FE86
4350 JSR L2C53 :\ Write read/write/seek command to FDC
4360 .L2D23
4370 JSR L2C18 :\ Wait until command completes
4380 LDA &A2
4390 AND #&02:BEQ L2D3E :\ &A2 bit 1 clear, skip...
4400 JSR L2C7D :\ Clear &A2 bit 0 - NMI not completed
4410 JSR L2C8A :\ Clear &A2 bit 1
4420 LDA #&54 :\ &54=StepIn+update+verify
4430 ORA &0D5C:STA &FE84 :\ Write FDC command with step speed
4440 INC &A3:BNE L2D23 :\ Incr. track, loop back to do another
4450 :
4460 .L2D3E
4470 LDA &A2
4480 AND #&08:BEQ L2D73 :\ Finished, exit
4490 JSR L2C7D :\ Clear &A2 bit 0 - NMI not completed
4500 JSR L2C83 :\ Clear &A2 bit 3
4510 INC &A3 :\ Incr. track
4520 JSR L2C74 :\ Select SIDE=1
4530 LDA #&04 :\ &04=Restore+verify
4540 ORA &0D5C:STA &FE84 :\ Restore to track zero
4550 BPL L2D23 :\ Loop back for more
4560 :
4570 \ Called here from NMI code, operation completed
4580 \ Check various things, and increment to next sector
4590 .L2D59
4600 JSR L2C7D :\ Clear &A2 bit 0 - NMI not completed
4610 JSR L2D74 :\ Update track/sector/etc
4620 TXA:BNE L2D68 :\ Not completed, write FDC command
4630 ROR &A2:SEC:ROL &A2 :\ Set &A2 bit 0 - NMI completed
4640 RTS
4650 :
4660 .L2D68
4670 JSR L2C8A :\ Clear bit 1
4680 LDA &A6:JSR L2C9E :\ Get FDC command, set bit 4 if needed
4690 STA &FE84 :\ Write command to FDC
4700 .L2D73
4710 RTS
4720 :
4730 .L2D74
4740 LDA &0D58:BNE L2DDD :\ endsector not zero, jump to...
4750 LDA &0D57:BNE L2D8D :\ trackcount<>0, update track
4760 LDA &0D59:BNE L2D87 :\ sectorcount<>0, update sector
4770 LDX #&00:BEQ L2DED :\ All done, return with X=&00
4780 :
4790 .L2D87
4800 DEC &0D59 :\ Decr. number of sectors
4810 JMP L2DE0 :\ Write incremented sectornumber to FDC
4820 :
4830 .L2D8D
4840 LDA &0D5A:BNE L2DD7 :\ 2D90 D0 45 PE
4850 ROR L2EFA:SEC:ROL L2EFA
4860 LDA &FE85 :\ Get current track from FDC
4870 CMP #&4F:BCC L2DBF :\ <track79, skip
4880 LDA &0D5E :\ Get drive control
4890 AND #&04:BEQ L2DAC :\ If side 0, jump to step to side 1
4900 LDX #&00:JMP L2DE2 :\ At end of disk, jump to return X=&00, done
4910 :
4920 .L2DAC
4930 LDA #&FF:STA &A3
4940 JSR L2C74 :\ Select SIDE=1
4950 LDA &0D5E:STA &FE80 :\ Write updated drive control
4960 LDA &A2:ORA #&08 :\ Set bit 3 -
4970 BNE L2DC3
4980 :
4990 .L2DBF
5000 LDA &A2:ORA #&02 :\ Set bit 1 -
5010 .L2DC3
5020 STA &A2 :\ Update flags
5030 DEC &0D57:BEQ L2DCF :\ Decrement
5040 LDA #&0A:STA &0D5A :\ Track length = 10 (?)
5050 .L2DCF
5060 LDA #&FE:STA &A4
5070 LDX #&00:BEQ L2DE2 :\ jump to return X=&00, done
5080 :
5090 .L2DD7
5100 DEC &0D5A :\ 2DD7 CE 5A 0D NZ.
5110 JMP L2DE0 :\ 2DDA 4C E0 2D L`-
5120 :
5130 .L2DDD
5140 DEC &0D58 :\ 2DDD CE 58 0D NX.
5150 .L2DE0
5160 LDX #&FF :\ Prepare to return X=&FF - Not done
5170 .L2DE2
5180 INC &A4 :\ Increment sector number
5190 TXA:PHA
5200 LDX #&01:JSR L2A59 :\ Write sector in &A4 to sector in &FE86
5210 PLA:TAX
5220 .L2DED
5230 RTS
5240 :
5250 \ Prepare to do a disk operation, NMIs claimed and set up
5260 \ -------------------------------------------------------
5270 .L2DEE
5280 LDY #&06:LDA (&80),Y :\ Get drive+sector high
5290 STA &A6 :\ Store drive number in b5-b7
5300 AND #&1F:BNE L2E5A :\ Keep sector b16-b20, jump if >&FFFF
5310 BIT &A6:BVC L2E02 :\ Test drive b1 - drive 2,3,6,7
5320 LDA #&65:STA &A0 :\ Result=&65 - Bad drive
5330 BNE L2E5E :\ Release and return
5340 :
5350 .L2E02
5360 LDA &A6 :\ Get drive
5370 AND #&20:BNE L2E0E :\ If 1,5 skip
5380 LDA #&21 :\ Something missing here?
5390 LDA #&29:BNE L2E12 :\ Drive 0,4 control=&29 noRST+0+SDEN+SIDE0+0+DS0
5400 .L2E0E
5410 LDA #&22 :\ Something missing here?
5420 LDA #&2A :\ Drive 1,5 control=&2A noRST+0+SDEN+SIDE0+DS1+0
5430 .L2E12
5440 STA &0D5E :\ Set drive selection setting
5450 ROR L2EFA:SEC:ROL L2EFA :\ Set bit0 of L2EFA - seems to be unused
5460 JSR L2E49 :\ Get sector/track/side and check for overflow
5470 LDA &0D5E:STA &FE80 :\ Select drive and side
5480 ROR A:BCC L2E37 :\ bit0=0, drive 1, skip past
5490 :
5500 \ Drive 0/4
5510 LDY #&0B:LDA (&80),Y:STA &A3 :\ Get setting from length byte 0
5520 LDY #&0A:LDA (&80),Y:ROL A :\ Get flags byte, normally &00
5530 BCC L2E48 :\ If XY+10.bit7=0, exit
5540 BCS L2E45 :\ If XY+10.bit7=1, call something and exit
5550 :
5560 \ Drive 1/5
5570 .L2E37
5580 LDY #&0C:LDA (&80),Y:STA &A3 :\ Data setting from length byte 1
5590 LDY #&0A:LDA (&80),Y :\ Get flags byte, normally &00
5600 ROL A:ROL A :\ Get bit 6
5610 BCC L2E48 :\ If XY+10.bit6=0, exit
5620 :
5630 \ If drive bit set in XY?10, set &A3 from length?drive,
5640 \ then ignore &A3 and restore to track zero, wait for completion.
5650 .L2E45
5660 JSR L2C91 :\ Restore to trck zero, wait for completion
5670 .L2E48
5680 RTS
5690 :
5700 \ So, XY+10 used as a bitmap of extra actions
5710 \ %1xxxxxxx - drive 0 do a restore before action
5720 \ %x1xxxxxx - drive 1 do a restore before action
5730 :
5740 .L2E49
5750 LDY #&07:LDA (&80),Y :\ Get sector b8-b15
5760 CMP #&06:BCC L2E7A :\ <&600, ok
5770 BNE L2E5A :\ >&600, fail
5780 INY:LDA (&80),Y :\ Get sector b0-b7
5790 CMP #&40:BCC L2E60 :\ <&640, ok
5800 .L2E5A
5810 LDA #&61:STA &A0 :\ Result=&61 - Sector out of range
5820 .L2E5E
5830 BNE L2EA2 :\ Release and return
5840 :
5850 \ Sector<&640 - valid sector for a floppy disk
5860 .L2E60
5870 LDA &A1
5880 AND #&10:BEQ L2E7A
5890 LDY #&09:LDA (&80),Y :\ Get sector count
5900 DEY:CLC:ADC (&80),Y :\ Add to start sector
5910 BCS L2E74 :\ sec+num>&xxFF, fail
5920 CMP #&41:BCC L2E7A :\ sec+num<&641, ok
5930 .L2E74
5940 LDA #&63:STA &A0 :\ Result=&63 - Volume error
5950 BNE L2EA2 :\ Release and return
5960 \
5970 \ Ah ha, &61 Sector error is start sector>end of disk
5980 \ &63 Volume error is start+count>end of disk
5990 :
6000 \ Sector<&600 - valid for a floppy disk
6010 .L2E7A
6020 LDY #&07:LDA (&80),Y :\ Get sector b8-b15
6030 TAX
6040 INY:LDA (&80),Y :\ Get sector b0-b7
6050 LDY #&FF:JSR L2E96 :\ Y=sector DIV 10, A=sector MOD 10
6060 STA &A4:STY &A5 :\ Set disk sector and track
6070 TYA:SEC:SBC #&50 :\ Check for side 1
6080 BMI L2EA1 :\ Track<80, exit
6090 STA &A5 :\ Update with track-80
6100 JMP L2C74 :\ Jump to select SIDE=1
6110 :
6120 \ DIV/MOD 10
6130 \ ----------
6140 .L2E96
6150 SEC:SBC #&0A:INY:BCS L2E96
6160 DEX:BPL L2E96:ADC #&0A :\ Y=XA DIV 10, A=XA MOD 10
6170 .L2EA1
6180 RTS
6190 :
6200 \ Operation complete, release and set result
6210 \ ------------------------------------------
6220 .L2EA2
6230 LDX L2EF4:TXS :\ Restore stack
6240 LDA L2EF1 :\
6250 AND #&20:BEQ L2ED7 :\
6260 LDA &0D5E :\ Get drive control
6270 ROR A :\ Move DS0 into Carry
6280 LDA &A3 :\ Get a value
6290 BCC L2EC3 :\ DS0=0, skip to deal with drive 1
6300 :
6310 \ Store drive 0 byte in length.0 and clear bit7 in flag
6320 LDY #&0B:STA (&80),Y :\ Store value in (ctrl),11
6330 LDY #&0A:LDA (&80),Y :\ Get (ctrl),10
6340 AND #&7F:STA (&80),Y :\ Remove bit7 and update
6350 BCS L2ECF :\ Skip past to get result
6360 :
6370 \ Store drive 1 byte in length.1 and clear bit6 in flag
6380 .L2EC3
6390 LDY #&0C:STA (&80),Y :\ Store value in (ctrl),12
6400 LDY #&0A:LDA (&80),Y :\ Get (ctrl),10
6410 AND #&BF:STA (&80),Y :\ Remove bit6 and update
6420 :
6430 .L2ECF
6440 LDA &A0:STA L2EF3 :\ Store returned result
6450 JSR L2B1C :\ Release NMIs
6460 :
6470 .L2ED7
6480 JSR L2B43 :\ Release Tube
6490 LDY #&00
6500 LDA L2EF3:STA (&80),Y :\ Store result in control block
6510 LDX &80:DEX:DEX :\ Get original X
6520 LDA L2EF3:BEQ L2EEC :\ Get result, skip if OK
6530 ORA #&40 :\ Not OK, ORA with &40 to indicate FDD
6540 .L2EEC
6550 LDY &81 :\ Get original Y
6560 AND #&7F:RTS :\ Drop bit7 and return
6570 \ Return value irrelevent as OSWORD handler restores original A
6580 :
6590 .L2EF1:EQUB &00 :\ Action, &10=Write, &11=Read
6600 .L2EF2:EQUB &00 :\ Previous NMI owner
6610 .L2EF3:EQUB &00 :\ Result - initially set to &00
6620 .L2EF4:EQUB &00 :\ Saved stack pointer
6630 .L2EF5:EQUB &00 :\ Disk speed &00 or &03
6640 .L2EF6:EQUB &00 :\ Disk speed &00 or &02
6650 BRK :\ 2EF7 00 .
6660 BRK :\ 2EF8 00 .
6670 BRK :\ 2EF9 00 .
6680 .L2EFA:EQUB &00 :\ &00/&01 - never seems to be used
6690 .L2EFB:EQUB &00 :\ &81=Tube being used, &80=Tube not being used
6700 .L2EFC:EQUD &00000000 :\ Tube transfer address
6710 :
6720 \ WORDV entry
6730 \ ===========
6740 .exec%
6750 .L2F00
6760 JMP L2F05 :\ Jump to handler
6770 .L2F03
6780 EQUW 0 :\ oldUSERV store
6790 .L2F05
6800 CMP #&FE:BEQ L2F0C :\ If OSWORD &FE, skip past
6810 JMP (L2F03) :\ Continue via oldUSERV
6820 .L2F0C
6830 JMP L2A00 :\ Jump to OSWORD &FE code
6840 :
6850 \ Left-over data
6860 EQUS STRING$(&2F7A-P%,CHR$0)
6870 EQUS " SEEK " :\ 2F7A 20 53 45 45 SEE
6880 EQUB &01 :\ 2F7E 4B 20 20 01 K .
6890 EQUB &14 :\ 2F82 14 .
6900 EQUB &00 :\ 2F83 00 .
6910 EQUS STRING$(&2FC0-P%,CHR$0)
6920 EQUS " SOFT " :\ 2FC0 20 53 4F 46 SOF
6930 EQUB &01 :\ 2FC4 54 20 20 01 T .
6940 EQUB &00 :\ 2FC8 00 .
6950 EQUB &00 :\ 2FC9 00 .
6960 EQUS " TUBE " :\ 2FCA 20 54 55 42 TUB
6970 EQUB &01 :\ 2FCE 45 20 20 01 E .
6980 EQUB &06 :\ 2FD2 06 .
6990 EQUB &04 :\ 2FD3 04 .
7000 EQUS STRING$(&3000-P%,CHR$0)
7010 ]NEXT
7020 A$=fname$+" "+STR$~mcode%+" "+STR$~O%+" "+STR$~(exec%OR&FFFF0000)+" "+STR$~load%
7030 PRINT"Saving ";A$:OSCLI "SAVE "+A$:PRINT