Floppy 1551 ROM-Listing
Suche
Index
FAQ
Kontakt
Zurück
;
; 	    The Complete Commodore 1551 ROM disassembly
;			by Attila Grósz
;		     http://yape.plus4.net
;                  grosza_AT_hotmail_DOT_com
;
;			   revision 0
;
;	      Based on 1541 ROM disassembly from AAY1541
;
;

; ROM is mapped between $C000-$FFFF in the drive memory
	ORG $C000 - 2
	DW  $C000
; Zeropage vectors
zp0E = $0E ;(3)
zp12 = $12 ;(1)
zp15 = $15 ;(7)
zp1E = $1E ;(24)
zp20 = $20 ;(37)
zp27 = $27 ;(38) address of current buffer
zp32 = $32 ;(3)
zp34 = $34 ;(3)
zp45 = $45 ;(9)
zp49 = $49 ;(15)
zp4E = $4E ;(6)
zp59 = $59 ;(4)
zp6A = $6A ;(3)
zp6C = $6C ;(25)
zp6E = $6E ;(79)
zp70 = $70 ;(22)
zp74 = $74 ;(8)
zp7F = $7F ;(42) counter for erased files
zp81 = $81 ;(17)
zp82 = $82 ;(11)
zp8D = $8D ;(85)
zpA4 = $A4 ;(9)  Pointer: Next byte in command buffer [0200]
zpA6 = $A6 ;(10)
zpC0 = $C0 ;(4)
zpC4 = $C4 ;(3)
zpC9 = $C9 ;(2)
zpCB = $CB ;(1)
zpE5 = $E5 ;(1)
;-------------------
; Zeropage variables
;-------------------
;
zp00 = $00 ;(9)  cpu data direction register
zp01 = $01 ;(65) cpu port, FDC control register
; bit 0: drive head stepper 0 (STP)
; bit 1: drive head stepper 1 (STP)
; bit 2: drive motor on/off (MTR)
; bit 3: drive LED (ACT)
; bit 4: write protect sensor (WPS)
; bit 5: density select #0 (DS0)
; bit 6: density select #1 (DS1)
; bit 7: byte latched (1 - yes, 0 - no)
;
zp02 = $02 ;(14) Command code for buffer 0
zp03 = $03 ;(2)  Command code for buffer 1
zp04 = $04 ;(3)  Command code for buffer 2
zp05 = $05 ;(1)  Command code for buffer 3
zp06 = $06 ;(6)  Command code for buffer 4
zp07 = $07 ;(2)  Command code for buffer 5 (unused)
zp08 = $08 ;(6)	 Track and sector for buffer 0
zp09 = $09 ;(5)
zp0A = $0A ;(2)	 Track and sector for buffer 1
zp0C = $0C ;(1)	 Track and sector for buffer 2
zp14 = $14 ;(6) disk id 1
zp18 = $18 ;(6) block header id 1
zp19 = $19 ;(6) block header id 2
zp1A = $1A ;(5) track blockheader
zp1B = $1B ;(5) sector blockheader
zp1C = $1C ;(3) checksum of block header
zp1D = $1D ;(5) current drive number (always 0)
zp22 = $22 ;(8) write protect flag for drive 0 or 1
zp23 = $23 ;(2) write protect flag for drive 1 (unused)
zp24 = $24 ;(4)
zp26 = $26 ;(1)
zp29 = $29 ;(6) FDC current track
zp2B = $2B ;(14) drive status flag
           ;     bit 5: drive motor
           ;     bit 6: stepper motor
           ;     bit 7: drive ready
zp2D = $2D ;(10)
zp2E = $2E ;(19)
zp2F = $2F ;(2)
zp30 = $30 ;(8)
zp31 = $31 ;(7)
zp36 = $36 ;(4)
zp37 = $37 ;(4)
zp38 = $38 ;(5)
zp39 = $39 ;(7)
zp3A = $3A ;(2) temporary stack storage
zp3B = $3B ;(9) stepper motor direction (<$80 inner, >=$80 outer)
zp3C = $3C ;(6)
zp3D = $3D ;(3) last sector read
zp3E = $3E ;(2) next sector to be read
zp3F = $3F ;(5) GCR/BIN indicator for current buffer
zp40 = $40 ;(11) current track
zp41 = $41 ;(17)
zp42 = $42 ;(18)
zp43 = $43 ;(20)
zp44 = $44 ;(18)
zp47 = $47 ;(4)
zp48 = $48 ;(9)
zp4B = $4B ;(4)
zp4C = $4C ;(3)
zp4D = $4D ;(5)
zp50 = $50 ;(5)
zp51 = $51 ;(3)
zp52 = $52 ;(5)
zp53 = $53 ;(10)
zp54 = $54 ;(9)
zp55 = $55 ;(2) drive LED flash counter
zp56 = $56 ;(2)
zp57 = $57 ;(6)
zp58 = $58 ;(6)
zp5B = $5B ;(4) TALK flag
zp5C = $5C ;(4) LISTEN flag (1/0)
zp5D = $5D ;(4) format string of disk after init (2A)
zp5E = $5E ;(1)
zp5F = $5F ;(6)
zp61 = $61 ;(2) ROM-test checksum
zp62 = $62 ;(4)
zp63 = $63 ;(3)
zp65 = $65 ;(1)
zp66 = $66 ;(3) device number
zp68 = $68 ;(6)
zp69 = $69 ;(4)
zp72 = $72 ;(4)
zp76 = $76 ;(2) LED blink flag (#$E0 = on)
zp77 = $77 ;(2) last track number
zp78 = $78 ;(69) current drive number
zp79 = $79 ;(86) current track
zp7A = $7A ;(83) current sector
zp7B = $7B ;(102) current channel
zp7C = $7C ;(58) secondary address
zp7D = $7D ;(6)  secondary address from computer
zp7E = $7E ;(26)
zp84 = $84 ;(7)
zp85 = $85 ;(3)
zp86 = $86 ;(3)
zp87 = $87 ;(2)
zp89 = $89 ;(12)
zp8A = $8A ;(7)
zp8B = $8B ;(2)
zp8C = $8C ;(1)
zp8F = $8F ;(1)
zp91 = $91 ;(5) pointer in record
zp92 = $92 ;(15)
zp93 = $93 ;(14)
zp94 = $94 ;(7)
zp95 = $95 ;(10) EOI
zp96 = $96 ;(2)
zp97 = $97 ;(8)
zp98 = $98 ;(26) buffer number
zp99 = $99 ;(6)	 Pointer to first filename
zp9A = $9A ;(55)
zp9B = $9B ;(6)
zpA8 = $A8 ;(38)
zpAC = $AC ;(1)
zpAD = $AD ;(2)
zpAE = $AE ;(1)
zpAF = $AF ;(24)
zpB5 = $B5 ;(1)
zpB6 = $B6 ;(10)
zpBC = $BC ;(9)
zpC2 = $C2 ;(13)
zpC8 = $C8 ;(10)
zpCE = $CE ;(18)
zpD2 = $D2 ;(1)
zpD3 = $D3 ;(1)
zpD4 = $D4 ;(4)
zpD8 = $D8 ;(1)
zpD9 = $D9 ;(7)
zpDA = $DA ;(2)
zpDD = $DD ;(1)
zpDE = $DE ;(7)
zpDF = $DF ;(2)
zpE2 = $E2 ;(1)
zpE3 = $E3 ;(18)
zpE4 = $E4 ;(5)
zpE7 = $E7 ;(1)
zpE8 = $E8 ;(18)
zpE9 = $E9 ;(2)
zpEB = $EB ;(1)
zpED = $ED ;(12)
zpF1 = $F1 ;(1)
zpF3 = $F3 ;(13)
zpF7 = $F7 ;(1)
zpF8 = $F8 ;(3)
zpF9 = $F9 ;(12)
zpFA = $FA ;(12)
zpFB = $FB ;(10)
zpFC = $FC ;(4)
zpFD = $FD ;(5)
zpFE = $FE ;(3)
zpFF = $FF ;(9)
;
; GCR overflow area and stack $100-$1ff
;
V_0100 = $0100
V_0101 = $0101
V_0102 = $0102
V_0103 = $0103
V_0111 = $0111
V_0112 = $0112
V_011B = $011B
V_01A9 = $01A9
V_01FF = $01FF
;
; Command buffer, parser, tables, variables $200-$2ff
;
V_0200 = $0200  ; input buffer $0200-$0229 for command string,
L_0201 = $0201
V_0202 = $0202
V_0203 = $0203
V_0204 = $0204
V_0205 = $0205
V_0206 = $0206
V_022A = $022A	; command number temporary storage (Command code)
V_022B = $022B	; Logical index, channel 0
V_022C = $022C	; Logical index, channel 1
V_022D = $022D	; Logical index, channel 2
V_023A = $023A
V_023B = $023B
V_023C = $023C
V_023D = $023D
V_023E = $023E
V_0243 = $0243
V_0244 = $0244
V_0249 = $0249 	; end of error message
V_024A = $024A 	; active data/file type
V_024B = $024B 	; filename/string length
V_024C = $024C	; Temp. channel number (secondary address)
V_024D = $024D	; Current work with drive number
V_024E = $024E	; Work area to find the best sector
V_024F = $024F	; Buffer allocated
V_0250 = $0250	; Buffer allocated
V_0251 = $0251	; Flag: BAM changed, drive 0
V_0253 = $0253	; Flag for directory entry found (FF = Not found, 00 = Found)
V_0254 = $0254	; Flag for directory output
V_0255 = $0255	; Flag: Waiting for command
V_0256 = $0256  ; buffer allocation register
V_0257 = $0257	; Last used buffer
V_0258 = $0258	; Record length
V_0259 = $0259	; Track of side sector
V_025A = $025A	; Sector of side sector
V_025B = $025B	; Last work (buffers) $025B-$025F
V_0260 = $0260	; Directory sector (buffers) $0260-$0265
V_0266 = $0266	; File's index in directory (buffers) $0266-$026B
V_026C = $026C  ; error flag, counter for led flash?
V_026E = $026E  ; last program's drive number
V_026F = $026F  ; last sector number
V_0270 = $0270  ; temporary storage for channel number
V_0272 = $0272  ; number of blocks free
V_0273 = $0273
V_0274 = $0274	; length of filename/input
V_0275 = $0275
V_0276 = $0276
V_0277 = $0277  ; nr of commas
V_0278 = $0278
V_0279 = $0279  ; nr of commas
V_027A = $027A	; pointer to drive number
V_027B = $027B
V_027F = $027F
V_0280 = $0280
V_0281 = $0281
V_0284 = $0284
V_0285 = $0285
V_0286 = $0286
V_0287 = $0287
V_028A = $028A	; wildcard flag
V_028B = $028B 	; syntax flag
V_028C = $028C  ; number of drives to look for
V_028D = $028D	; Flag: Looking for drive
V_028E = $028E	; last drive number
V_028F = $028F	; Flag: Found in directory
V_0290 = $0290	; Directory sector
V_0291 = $0291	; Sector for first available file
V_0292 = $0292	; Index (in directory) for first available file
V_0293 = $0293	; For the last directory entry 0
V_0294 = $0294	; Current buffer-index
V_0295 = $0295	; Counter: Files
V_0296 = $0296	; Flag: Name matching wild cards
V_0297 = $0297	; Active operating mode (R or W)
V_0298 = $0298	; dos error flag, Flag: Work return
V_0299 = $0299	; Pointer: Re-read error
V_029A = $029A	; Total tracks
V_029B = $029B	; Pointer: BAM last update $029B-$029C
V_029D = $029D	; BAM: image sector (drive 0)
V_02A1 = $02A1	; BAM image $02A1-$02B0
V_02B0 = $02B0
V_02B1 = $02B1	; Buffer for directory output, $02B1-$02D4
V_02B2 = $02B2
V_02B3 = $02B3
V_02C3 = $02C3
V_02C4 = $02C4
V_02D5 = $02D5
V_02F9 = $02F9	; Flag: Don't write BAM
V_02FA = $02FA	; Number of free blocks, low byte for drive 0 and 1, $02FA-$02FB
V_02FC = $02FC	; Number of free blocks, hi byte for drives 0 and 1, $02FC-$02FD
V_02FE = $02FE	; Stepper motor sequence
V_02FF = $02FF
; 4 data buffers, 0-3, $0300-06ff
V_03A9 = $03A9
V_04A9 = $04A9
L_04C5 = $04C5
V_04FF = $04FF
V_0504 = $0504
V_0605 = $0605
V_0610 = $0610
V_06A9 = $06A9
; $0700-07ff	BAM resident in memory
S_08FF = $08FF
V_2036 = $2036
V_21F1 = $21F1
S_3008 = $3008
;
; TIA 6523 registers $4000-$4005
;
; Port registers A, B and C
V_4000 = $4000	; I/O port towards the computer
V_4001 = $4001	; connected to the shift register of the R/W head
V_4002 = $4002	; drive control, status and sync register
;
; bit 7: DAV (DAta Valid)
; 	handshake from bit #6 from $FEF2/FEC2 of plus/4
; bit 6: SYNC
; 	0 -> SYNC found
; 	1 -> no SYNC
; bit 5: MODE (jumper)
; 	drive number (0 -> 8, 1 -> 9)
; bit 4: MODE (R/W head)
; 	0 -> head in write mode
; 	1 -> head in read mode
; bit 3: ACK (ACKnowledge)
; 	handshake to bit #7 of $FEF2/$FEC2
; bit 2: DEV
; 	1 -> drive mapped at $FEF0 on plus/4
; 	0 -> drive mapped at $FEC0 on plus/4
; bit 1: STATUS1 - mapped at $FEF1/FEC1 on plus/4
; bit 0: STATUS0 - mapped at $FEF1/FEC1 on plus/4
; 		  01 Timeout during reading
; 		  10 Timeout during writing
; 		  11 End of data
;
; Data direction registers for ports A, B and C
V_4003 = $4003
V_4004 = $4004
V_4005 = $4005

;--------- Copyright text
T_C000	DB "DAVID G SIRACUSA CBM COPYRIGHT 84"

;--------- Start of 1551 ROM program

S_C022	LDA V_4000	; read data from computer
	CMP V_4000	; port stable?
	BEQ B_C02D	; if yes, then jump
	JMP L_EABD	; otherwise back to main wait loop
	;
B_C02D	AND #$0F	; lowest 4 bits only
	ASL A		; * 2
	TAY		; Y = A, make it an index
	LDA V_C046,Y	; look up address of subroutine
	STA zp6E
	LDA V_C046 + 1,Y
	STA zp6E+1	; $6E/$6F
	LDA V_4002
	AND #$F7
	STA V_4002	; ACK handshake
	JMP ($006E)	; *** Indirect jump to TCBM bus command handler
	;
	; Jump vectors for TCBM bus commands,
	; only $01 - $04 are valid. The 264 is sending these values
	; OR-ed with $80 through the TCBM interface.
	;
V_C046	DB $66,$C0	; $C066: N/A
	DB $71,$C0	; $C071: Command w/ dev nr coming (TALK/LISTEN/UNTALK/UNLISTEN)
	DB $D6,$C0	; $C0D6: Command w/ sec addr. coming (0x60, 0xE0, 0xF0)
	DB $F6,$C0	; $C0F6: Data comes to the drive (filename, command, data etc.)
	DB $4E,$C1	; $C14E: Data goes to computer
	DB $66,$C0
	DB $66,$C0
	DB $66,$C0
	DB $66,$C0
	DB $66,$C0
	DB $66,$C0
	DB $66,$C0
	DB $66,$C0
	DB $66,$C0
	DB $66,$C0
	DB $66,$C0	; N/A
	;
; $C066
S_C066 	LDA V_4002	; not a valid command
	ORA #$08	; just acknowledge
	STA V_4002
	JMP L_EABD	; and jump back to main loop
	;
	; Command w/ dev nr coming (TALK/LISTEN/UNTALK/UNLISTEN)
	;
B_C071	LDA V_4002
	BMI B_C071	; wait for DAV handshake from plus/4
	LDA V_4000	; read port data in from plus/4
	PHA		; save to stack
	LDA zp58	;
	BPL B_C08B	; MSB not set?
	LDA #$00	; reset end flag
	STA zp95
	LDA zp59        ; read last data byte
	JSR B_C0F6
	LDA #$00
	STA zp58	;
B_C08B	PLA		; read port value back from stack
	TSX
	STX zp59+1
	LDX #$00
	STA zp8F	; save command
	TAY		; backup A (command) in Y
	AND #$60
	CMP #$40	; talk?
	BEQ B_C0A8	; yes
	CMP #$20	; listen?
	BEQ B_C0C0	; yes
	LDY #$00	; otherwise DATA ($60)
	LDX #$03
	STX zp6E        ; set blink rate ?
	SEI		; disable interrupt
	JMP L_E984
	;
B_C0A8	STX zp5B        ; reset TALK flag
	TYA             ; code in accu
	CMP #$5F	; UNTALK ?
	BEQ B_C0BC	; yes...
	STA zp5B        ; set TALK flag
	STX zp5C        ; reset LISTEN flag
L_C0B3	LDA #$20
	STA zp7C	; save sec. address
	STA zp7D
	JMP L_C133
	;
B_C0BC	LDA #$00
	BEQ B_C135	; always jump

B_C0C0	TYA		; read back A from Y
	CMP #$3F	; UNLISTEN?
	BNE B_C0CF	; no
	LDA #$FF	;
	STA zp95
	LDX #$00
	STX zp5C	; reset flag for listen
	BEQ B_C0BC	; always jump

B_C0CF	STA zp5C	; must be UNTALK then
	STX zp5B
	JMP L_C0B3
	;
	; Command w/ sec addr. coming (0x60, 0xE0, 0xF0)
	;
B_C0D6	LDA V_4002
	BMI B_C0D6	; wait for DAV
	TSX
	STX zp59+1
	LDA V_4000
	STA zp7D	; store secondary address
	TAY
	AND #$0F
	STA zp7C	; store secondary address again
	TYA
	AND #$F0
	CMP #$E0	; CLOSE?
	BNE B_C0F2	; not, then must be OPEN
	JSR S_DBF7	; jump to CLOSE
B_C0F2	LDA #$00
	BEQ B_C135	; always jump to finish
	;
	; Data comes to the drive (filename, command, data etc.)
	;
B_C0F6	LDA V_4002
	BMI B_C0F6	; wait for DAV handshake from computer
	TSX
	STX zp59+1	; save stack pointer
	LDA V_4000	; read data bus
	PHA		; save
	LDA zp58
	BPL B_C12A	; branch if MSB not set, and set it now
	LDA zp59	; read data read last time
	STA zp7E	; store
	JSR S_D217	; open channel
	BCS B_C114
	LDA zpF3,X
	ROR A
	BCS B_C127
B_C114	LDA zp7D	; read sec. addr. as received from computer
	AND #$F0	; get just the command bits...
	CMP #$F0	; open channel command?
	BEQ B_C127	; yes, then jump
	LDA zp7C	; otherwise load secondary address (channel nr?)
	CMP #$01	; = 1 ?
	BEQ B_C130	; yes
	PLA
	LDA #$02
	BNE B_C135	; always jump
B_C127	JSR S_D0D3	; write data into buffer
B_C12A	LDA zp58
	ORA #$80
	STA zp58
B_C130	PLA		; copy back saved data from bus
	STA zp59	; store
L_C133	LDA #$00

B_C135	AND #$03
	ORA #$08
	STA zp97	; preserve status, set ACK bit
	LDA V_4002
	ORA zp97	; send it to machine
	STA V_4002
B_C143	LDA V_4002
	BPL B_C143	; wait for DAV handshake from plus/4
	AND #$FC	; send ACK to plus/4
	STA V_4002
	RTS
;
;$C14E  -------- Data goes to computer
;
B_C14E	LDA V_4002
	BMI B_C14E	; wait for DAV handshake from plus/4
	LDA #$FF
	STA V_4003	; set TIA port A to all outputs
	TSX		; save stack pointer
	STX zp59+1	; ... to $5A
	LDA zp7C	; read saved secondary address
	CMP #$13	; 19
	BCC B_C163	; bigger, then skip
	AND #$0F
B_C163	CMP #$0F	; command channel ?
	BNE B_C169	; no...
	LDA #$10	; if 15 then make it 16
B_C169	TAX		; make and index from it
	SEC
	LDA V_022B,X
	BMI B_C176
	AND #$0F
	STA zp7B
	TAX
	CLC
B_C176	BCS B_C17E
	LDX zp7B
	LDA zpF3,X
	BMI B_C189
B_C17E	LDA #$0D	; CR
	STA V_4000	; send $0D to computer via TIA port A
	LDA #$0A
	STA zp97
	BNE B_C1A7
B_C189	LDA V_023E,X
	STA V_4000	; send the rest of the buffer
	LDA zpF3,X
	AND #$08
	EOR #$08
	ASL A
	ASL A
	ASL A		; multiply by 8 (becomes $40 (64) or 0)
	PHA
	JSR S_D4F9
	PLA
	CMP #$40
	BNE B_C1A3
	LDA #$03
B_C1A3	ORA #$08
	STA zp97	; $97 = $38
B_C1A7	LDA V_4002
	AND #$FC	; clear status bits in TIA
	ORA zp97	; copy status
	STA V_4002	; send...
B_C1B1	LDA V_4002
	BPL B_C1B1	; wait for DAV handshake from machine
	LDX #$00
	STX V_4003	; set TIA port A to input
	AND #$F7
	STA V_4002	; clear ACK handshake
B_C1C0	LDA V_4002	; received?
	BMI B_C1C0	; not yet
	ORA #$08	; set ACK handshake...
	AND #$FC	; ...clear status bits...
	STA V_4002	; ... done
	RTS
;$C1CD  --------
S_C1CD	LDX #$0D	; CR
	STX V_4000	; send to computer
	LDA #$0A	; $8 / $2
	STA zp97
	BNE B_C1A7	; jump always, set error status and device in TIA
S_C1D8	LDA #$01
	JMP B_C135
	;
	LDX V_0274	; X = length of filename
	DEX		; decrease by 1
	BEQ B_C1FB	; zero?
	LDA L_0201
	TAY
	CMP #$52	; "R"
	BEQ B_C220	; yes...
	CMP #$53	; "S"
	BEQ B_C220	; yes...
	CMP #$39	; 9?
	BEQ B_C208	; yes
	CMP #$38	; 8?
	BNE B_C203	; no... then error
B_C1F7	LDX #$08
	BNE B_C20A	; always jump, set device number to 8
B_C1FB	LDA zp66
	CMP #$08	; check device number
	BEQ B_C208	; = 8 ? then jump
	BNE B_C1F7
B_C203	LDA #$31
	JMP L_C2B2	; 31, 'syntax error'
	;
	; Set device number flag in TIA register
	;
B_C208	LDX #$09	; set device number to 9
B_C20A	STX zp66
	TXA
S_C20D	ASL A
	ASL A		; accu * 4 = $24
	AND #$04	; isolate device nr flag in register
	EOR #$04	; toggle device number flag towards computer...
	STA zp97
	LDA V_4002
	AND #$FB
	ORA zp97	; and then ...
	STA V_4002	; ... set device number (0 for #8 and 1 for #9)
	RTS
;$C220  --------
B_C220	DEX
	BEQ B_C203
	LDX #$01
	LDA V_0202
	CPY #$52	; "R"
	BEQ B_C22D
	DEX
B_C22D	STA zp68,X
	RTS

;$C230  -------- Interpret command from computer

S_C230	LDA #$00
	STA V_02F9
	LDA V_028E	; last drive number
	STA zp78	; drive number
	JSR L_E7FB	; prepare 'ok' message
	LDA zp7D	; secondary address
	BPL B_C24A
	AND #$0F
	CMP #$0F	; 15, command channel
	BEQ B_C24A	; yes
	JMP L_D8EE	; to OPEN command
	;
B_C24A	JSR S_C39D	; determine line length and erase flags
	LDA (zpA4),Y	; get first character
	STA V_0275	; and store
	LDX #$0C	; 12

B_C254	LDA V_F0C6 + 1,X	; commands
	CMP V_0275	; compare to first character
	BEQ B_C264	; found?
	DEX
	BPL B_C254
	LDA #$31	; not found
	JMP L_C2B2	; 31, 'syntax error'
	;
B_C264	STX V_022A	; number of command words
	CPX #$0A
	BCC B_C26E	; command number < 10? (1541 has 9!!!)
	JSR S_C2D8	; test for 'R', 'S', and 'N'
B_C26E	LDX V_022A	; command number
	LDA V_F0D4,X	; jump address lo
	STA zp6E
	LDA V_F0E1,X	; jump address hi
	STA zp6E+1
	JMP ($006E)	; *** Indirect jump to command
	;
L_C27E	LDA #$00
	STA V_02F9
	;
L_C283	LDA V_026C
	BNE L_C2B2
	LDY #$00
	TYA		; error number 0
	STY zp79	; track number 0
L_C28D	STY zp7A	; sector number 0
	STY zpA4
	JSR S_E806	; prepare 'ok' message
	JSR S_F3F0	; erase error flag

L_C297	LDA zp78	; drive number
	STA V_028E	; save as last drive number
	TAX
	LDA #$00
	STA zp5F,X
	JSR S_C2A7	; erase input buffer
	JMP L_D62D	; close internal channel

	; Erase input buffer

S_C2A7	LDY #$28	; erase 41 characters
	LDA #$00
B_C2AB	STA V_0200,Y	; $200 to $228
	DEY
	BPL B_C2AB
	RTS

;------------------------------------
;$C2B2  -------- Output error message
;------------------------------------

L_C2B2	LDY #$00
	STY zp79	; track = 0
	STY zp7A	; sector = 0
	JMP S_E781	; error number acc, generate error message

	; Check input line

S_C2BB	LDX #$00
	STX V_027A	; pointer to drive number
	LDA #$3A	; ':'
	JSR S_C352	; test line to ':' or to end
	BEQ B_C2CC	; no colon found?
	DEY
	DEY
	STY V_027A	; point to drive number (before colon)
B_C2CC	JMP L_C452

	; Check ':' on input line

S_C2CF	LDY #$00	; pointer to input buffer
	LDX #$00	; counter for commas
	LDA #$3A	; ':'
	JMP S_C352
	;
S_C2D8	JSR S_C2CF
	BNE S_C2E2
B_C2DD	LDA #$34
	JMP L_C2B2	; 34, 'syntax error'
	;
S_C2E2	DEY
	DEY		; set pointer to colon
	STY V_027A	; position of the drive number
	TXA		; comma before the colon
	BNE B_C2DD	; yes, then 'syntax error'
S_C2EA	LDA #$3D	; '='
	JSR S_C352	; check input to '='
	TXA		; comma found?
	BEQ B_C2F4	; no
	LDA #$40	; bit 6
B_C2F4	ORA #$21	; and set bit 0 and 5
	STA V_028B	; flag for syntax check
	INX
	STX V_0277
	STX V_0278
	LDA V_028A	; wildcard found?
	BEQ B_C312	; no
	LDA #$80
	ORA V_028B	; set bit 7
	STA V_028B
	LDA #$00
	STA V_028A	; reset wildcard flag
B_C312	TYA		; '=' found?
	BEQ B_C33E	; no
	STA V_027A,X
	LDA V_0277	; number of commas before '='
	STA V_0279
	LDA #$8D	; shift CR
	JSR S_C352	; check line to end
	INX		; increment comma counter
	STX V_0278	; store number of commas
	DEX
	LDA V_028A	; wildcard found?
	BEQ B_C32F	; no
	LDA #$08	; set bit 3
B_C32F	CPX V_0277	; comma after '='?
	BEQ B_C336	; no
	ORA #$04	; set bit 2
B_C336	ORA #$03	; set bits 0 and 1
	EOR V_028B
	STA V_028B	; as flag for syntax check
B_C33E	LDA V_028B	; syntax flag
	LDX V_022A	; command number
	AND V_F0E5,X	; combine with check byte
	BNE B_C34A
	RTS
;$C34A  --------
B_C34A	STA V_026C	; set error flag
	LDA #$30
	JMP L_C2B2	; 30, 'syntax error'

	; Search character in input buffer

S_C352	STA V_0275	; save character
B_C355	CPY V_0274	; already done?
	BCS B_C388	; yes
	LDA (zpA4),Y	; get char from buffer
	INY
	CMP V_0275	; compared with char
	BEQ B_C38A	; found
	CMP #$2A	; '*'
	BEQ B_C36A
	CMP #$3F	; '?'
	BNE B_C36D
B_C36A	INC V_028A	; set wildcard flag
B_C36D	CMP #$2C	; ','
	BNE B_C355
	TYA
	STA V_027B,X	; note comma position
	LDA V_028A	; wildcard flag
	AND #$7F
	BEQ B_C383	; no wildcard
	LDA #$80
	STA zpE8,X	; note flag
	STA V_028A	; and save as wildcard flag
B_C383	INX		; increment comma counter
	CPX #$04	; 4 commas already?
	BCC B_C355	; no, continue
B_C388	LDY #$00
B_C38A	LDA V_0274	; set flag for line end
	STA V_027B,X
	LDA V_028A	; wildcard flag
	AND #$7F
	BEQ B_C39B	; no wildcard
	LDA #$80
	STA zpE8,X	; set flag
B_C39B	TYA
	RTS

;$C39D  -------- Check line length

S_C39D	LDY zpA4	; pointer to command input buffer
	BEQ B_C3B5	; zero?
	DEY
	BEQ B_C3B4	; one?
	LDA V_0200,Y	; pointer to input buffer
	CMP #$0D	; 'CR'
	BEQ B_C3B5	; yes, line end
	DEY
	LDA V_0200,Y	; preceding character
	CMP #$0D	; 'CR'
	BEQ B_C3B5	; yes
	INY
B_C3B4	INY		; pointer to old value again
B_C3B5	STY V_0274	; same line length
	CPY #$2A	; compare with 42 characters
	LDY #$FF
	BCC S_C3C6	; smaller, ok
	STY V_022A
	LDA #$32
	JMP L_C2B2	; 32, 'syntax error' line too long

	; Clear flags for command input

S_C3C6	LDY #$00
	TYA
	STA zpA4	; pointer to input buffer lo
	STA V_0258	; record length
	STA V_024A	; file type
	STA V_0296
	STA zp99
	STA V_0279	; comma counter
	STA V_0277	;      "
	STA V_0278	;      "
	STA V_028A	; wildcard flag
	STA V_026C	; error flag
	LDX #$05
B_C3E7	STA V_0279,X	; flags for line analysis
	STA zpD8,X	; directory sectors
	STA zpDD,X	; buffer pointer
	STA zpE2,X	; drive number
	STA zpE7,X	; wildcard flag
	STA V_027F,X	; track number
	STA V_0284,X	; sector number
	DEX
	BNE B_C3E7
	RTS

;$C3FC  -------- Preserve drive number

S_C3FC	LDA V_0278	; number of commas
	STA V_0277	; save
	LDA #$01
	STA V_0278	; number of drive numbers
	STA V_0279
S_C40A	LDY V_028E	; last drive number
	LDX #$00
B_C40F	STX zp99
	LDA V_027A,X	; position of the colon
	JSR S_C426	; get drive number before colon
	LDX zp99
	STA V_027A,X	; save exact position
	TYA
	STA zpE3,X	; drive number in table
	INX
	CPX V_0278	; got all drive numbers?
	BCC B_C40F	; no, continue
	RTS
;$C426  -------- Search for drive number
S_C426	TAX		; note position
	LDY #$00
	LDA #$3A	; ':'
	CMP L_0201,X	; colon behind it?
	BEQ B_C43C	; yes
	CMP V_0200,X	; colon here?
	BNE B_C436	; no
	INX
B_C436	TYA
B_C437	AND #$01	; drive number
B_C439	TAY
	TXA
	RTS
;$C43C  --------
B_C43C	LDA V_0200,X	; get drive number
	INX
	INX
	CMP #$30	; '0'?
	BEQ B_C437
	CMP #$31	; '1'?
	BEQ B_C4B2
	BNE B_C436	; no, use last drive number
	TYA		; last drive number
	ORA #$80	; set bit 7, uncertain drive number
	AND #$81	; erase remaining bits
	BNE B_C439
	BNE B_C439

	; Get drive number

V_C452
L_C452	LDA #$00
	STA V_028B	; erase syntax flag
	LDY V_027A	; position in command line
B_C45A	LDA (zpA4),Y	; get chars from command buffer
	JSR S_C4A5	; get drive number
	BPL B_C472	; certain number?
	INY		; increment pointer
	CPY V_0274	; line end?
	BCS B_C46D	; yes
	LDY V_0274
	DEY
	BNE B_C45A	; search line for drive number
B_C46D	DEC V_028B
	LDA #$00
B_C472	AND #$01
	STA zp78	; drive number
	RTS
;$C477  --------
S_C477	LDA zp78	; drive number
	EOR #$01	; switch bit 0
	AND #$01
	STA zp78
	RTS

;$C480  -------- Check given file type

S_C480	LDY #$00
	LDA V_0277	; '=' found?
	CMP V_0278
	BEQ B_C4A0	; no
	DEC V_0278	; get pointer
	LDY V_0278
	LDA V_027A,Y	; set pointer to character behind '='
	TAY
	LDA (zpA4),Y	; pointer to buffer
	LDY #$04	; compare with marker for file type
B_C498	CMP V_F0FB + 1,Y ; 'S', 'P', 'U', 'R'
	BEQ B_C4A0	; agreement
	DEY
	BNE B_C498
B_C4A0	TYA
	STA V_0296	; note file type (1-4)
	RTS
;$C4A5  -------- Check given drive number
S_C4A5	CMP #$30	; '0'
	BEQ B_C4AF
	CMP #$31	; '1'
	BEQ B_C4B2
	ORA #$80	; no zero or one, then set bit 7
B_C4AF	AND #$81
	RTS
;$C4B2  -------- Verify drive number
B_C4B2	LDA #$31
	JMP L_C2B2
	;
S_C4B7	LDA #$00
	STA zp6E
	STA V_028D	; reset for looking for drive flag
	PHA
	LDX V_0278	; number of drive numbers
B_C4C2	PLA		;
	ORA zp6E
	PHA
	LDA #$01
	STA zp6E
	DEX
	BMI B_C4DC
	LDA zpE3,X
	BPL B_C4D5
	ASL zp6E
	ASL zp6E	; $6e * 4
B_C4D5	LSR A		; ac = ac * 2
	BCC B_C4C2	; not overflow? then back
	ASL zp6E	; $6e * 2
	BNE B_C4C2	; not zero? then back
B_C4DC	PLA
	TAX
	LDA V_C528 + 2,X	; get syntax flag
	PHA
	AND #$03
	STA V_028C
	PLA
	ASL A
	BPL B_C527
	LDA zpE3
L_C4ED	AND #$01	; isolate drive number
	STA zp78
	LDA V_028C
	BEQ B_C521
	JSR S_C722	; initialize drive
	BEQ B_C50D	; error?
	JSR S_C477	; switch to other drive
	LDA #$00
	STA V_028C
	JSR S_C722	; initialize drive
	BEQ B_C526	; no error?
	BEQ B_C526
V_C508
B_C508	LDA #$74
	JSR L_C2B2	; 74, 'drive not ready'
B_C50D	JSR S_C477
	JSR S_C722	; initialize drive
	PHP
	JSR S_C477	; switch to other drive
	PLP
	BEQ B_C526	; no error?
	LDA #$00
	STA V_028C	; number of drives
	BEQ B_C526
B_C521	JSR S_C722	; initialize drive
	BNE B_C508	; error?
B_C526	RTS
;$C527  --------
B_C527	ROL A		; drive number from carry after bit 0
V_C528	JMP L_C4ED	; *** Self mod. indirect jump!

	; Flags for drive check

	DB $00,$80,$41,$01,$01,$01,$01,$81
	DB $81,$81,$81,$42,$42,$42,$42

	; Search for file in directory

S_C53A	JSR S_C4B7	; initialize drive
L_C53D	LDA #$00
	STA V_0292	; pointer
	JSR S_C691	; read first directory block
	BNE B_C55D	; entry present?
B_C547	DEC V_028C	; drive number clear?
	BPL B_C54D	; no
	RTS
;$C54D  --------
B_C54D	LDA #$01
	STA V_028D
	JSR S_C477	; change drive...
	JMP L_C53D	; ...and search
	;
B_C558	JSR S_C6FC	; search next file in directory
	BEQ B_C56D	; not found?
B_C55D	JSR S_C5BD	; verify directory entry
	LDA V_028F
	BEQ B_C566	; more files?
	RTS
;$C566  --------
B_C566	LDA V_0253
	BMI B_C558	; file not found?
	BPL B_C55D	; yes
B_C56D	LDA V_028F
	BEQ B_C547
	RTS
;$C573  --------
S_C573	JSR S_C6E9	; search next directory block
	BEQ B_C58F	; not found?
	BNE B_C59F
B_C57A	LDA #$01
	STA V_028D
	JSR S_C477	; change drive
S_C582	LDA #$00
	STA V_0292	; read directory block
	JSR S_C691	; found?
	BNE B_C59F
	STA V_028F
B_C58F	LDA V_028F
	BNE B_C5BC
	DEC V_028C
	BPL B_C57A
	RTS
;$C59A  --------
S_C59A	JSR S_C6FC	; next entry in directory
	BEQ B_C58F	; not found?
B_C59F	JSR S_C5BD	; check entry
	LDX V_0253
	BPL B_C5AE	; file found?
	LDA V_028F
	BEQ S_C59A	; yes
	BNE B_C5BC	; no, then done
B_C5AE	LDA V_0296
	BEQ B_C5BC
	LDA zpE8,X	; file type
	AND #$07
	CMP V_0296	; same as desired file type?
	BNE S_C59A	; no
B_C5BC	RTS
;$C5BD  --------
S_C5BD	LDX #$FF
	STX V_0253	; flag for data found
	INX
	STX V_028A
	JSR B_C66E	; set pointer to data
	BEQ B_C5D1
B_C5CB	RTS
;$C5CC  --------
B_C5CC	JSR S_C679	; pointer to next file
	BNE B_C5CB	; end, then done
B_C5D1	LDA zp78	; drive number
	EOR zpE3,X
	LSR A
	BCC B_C5E3
	AND #$40
	BEQ B_C5CC
	LDA #$02
	CMP V_028C	; search both drives?
	BEQ B_C5CC	; yes
B_C5E3	LDA V_027A,X
	TAX
	JSR S_C787	; get length of filename
	LDY #$03
	JMP L_C602
	;
B_C5EF	LDA V_0200,X	; get chars out of command line
	CMP (zp8D),Y	; same character in directory?
	BEQ B_C600	; yes
	CMP #$3F	; '?'
	BNE B_C5CC	; no
	LDA (zp8D),Y	; shift blank, end of name?
	CMP #$A0	; yes
	BEQ B_C5CC
B_C600	INX		; increment pointer
	INY
L_C602	CPX V_0276	; end of the name in the command?
	BCS B_C610	; yes
	LDA V_0200,X	; next character
	CMP #$2A	; '*'
	BEQ B_C61A	; yes, file found
	BNE B_C5EF	; continue search
B_C610	CPY #$13	; 19
	BCS B_C61A	; reached end of name
	LDA (zp8D),Y
	CMP #$A0	; shift blank, end of name
	BNE B_C5CC	; not found
B_C61A	LDX V_0279
	STX V_0253
	LDA zpE8,X
	AND #$80
	STA V_028A
	LDA V_0294
	STA zpDE,X
	LDA zp7A	; sector number of the directory
	STA zpD9,X	; enter in table
	LDY #$00
	LDA (zp8D),Y	; file type
	INY
	PHA
	AND #$40	; isolate search-protect bit
	STA zp6E	; (6) and save
	PLA
	AND #$DF	; erase bit 7
	BMI B_C641
	ORA #$20	; set bit 5
B_C641	AND #$27	; erase bits 3 and 4
	ORA zp6E	; get bit 6 again
	STA zp6E
	LDA #$80
	AND zpE8,X	; isolate flag for wildcard
	ORA zp6E
	STA zpE8,X	; write in table
	LDA zpE3,X
	AND #$80
	ORA zp78	; drive number
	STA zpE3,X
	LDA (zp8D),Y
	STA V_0280,X	; first track of file
	INY
	LDA (zp8D),Y
	STA V_0285,X	; get sector from directory
	LDA V_0258	; record length
	BNE B_C66E
	LDY #$15
	LDA (zp8D),Y	; record length
	STA V_0258	; get from directory
B_C66E	LDA #$FF
	STA V_028F
	LDA V_0278
	STA V_0279
S_C679	DEC V_0279
	BPL B_C67F
	RTS
;$C67F  --------
B_C67F	LDX V_0279
	LDA zpE8,X	; wildcard flag set?
	BMI B_C68B	; yes
	LDA V_0280,X	; track number already set
	BNE S_C679	; yes
B_C68B	LDA #$00
	STA V_028F
	RTS
;$C691  --------
S_C691	LDY #$00
	STY V_0291
	DEY
	STY V_0253
	LDA V_F0C3	; 18, directory track
	STA zp79
	LDA #$01
	STA zp7A	; sector 1
	STA V_0293
	JSR S_D5C8	; read sector
L_C6A9	LDA V_0293
	BNE B_C6AF
	RTS
;$C6AF  --------
B_C6AF	LDA #$07
	STA V_0295	; number of directory entries (-1)
	LDA #$00
	JSR S_D649	; get pointer from buffer
	STA V_0293	; save as track number
L_C6BC	JSR S_D63B	; set buffer pointer
	DEC V_0295	; decrement counter
	LDY #$00
	LDA (zp8D),Y	; first byte from directory
	BNE B_C6E0
	LDA V_0291
	BNE S_C6FC
	JSR S_DF76	; get track and sector number
	LDA zp7A
	STA V_0291	; sector number
	LDA zp8D
	LDX V_0292
	STA V_0292	; buffer pointer
	BEQ S_C6FC
	RTS
;$C6E0  --------
B_C6E0	LDX #$01
	CPX V_0292	; buffer pointer to one?
	BNE B_C714
	BEQ S_C6FC
S_C6E9	LDA V_F0C3	; 18, track number of BAM
	STA zp79	; track number
	LDA V_0290
	STA zp7A	; sector number
	JSR S_D5C8	; read block
	LDA V_0294
	JSR S_D61B	; set buffer pointer
S_C6FC	LDA #$FF
	STA V_0253	; erase-file found flag
	LDA V_0295
	BMI B_C70E	; all directory entries checked?
	LDA #$20
	JSR S_D31C	; increment buffer ptr by 32, next entry
	JMP L_C6BC	; and continue
	;
B_C70E	JSR S_D5A0	; set buffer pointer
	JMP L_C6A9	; read next block
	;
B_C714	LDA zp8D
	STA V_0294
	JSR S_DF76	; get track & sector number from buffer
	LDA zp7A
	STA V_0290	; save sector number
	RTS
;$C722  -------- Test and initalise drive
S_C722	LDX zp78
	LSR zp22,X
	BCC B_C74A
	LDA #$FF
	STA V_0298	; set error flag
	JSR S_D12A	; read directory track
	LDY #$FF
	CMP #$02	; 20, 'read error'?
	BEQ B_C740
	CMP #$03	; 21, 'read error'?
	BEQ B_C740
	CMP #$0F	; 74, 'drive not ready'?
	BEQ B_C740
	LDY #$00
B_C740	LDX zp78	; drive number
	TYA
	STA zp5F,X	; save error flag
	BNE B_C74A
	JSR S_D15E	; load BAM
B_C74A	LDX zp78	; drive number
	LDA zp5F,X	; transmit error code
	RTS

;$C74F  -------- Name of file in directory buffer

S_C74F	PHA
	JSR S_C787	; get end of the name
	JSR S_C769	; write filename in buffer
	PLA
	SEC
	SBC V_024B	; compare length with maximal length
	TAX
	BEQ B_C768
	BCC B_C768
	LDA #$A0	; pad with 'shift blank'
B_C762	STA (zp8D),Y
	INY
	DEX
	BNE B_C762
B_C768	RTS

;$C769  -------- Copy filename to work buffer

S_C769	TYA		; buffer number
	ASL A
	TAY		; times 2 as pointer
	LDA $009A,Y
	STA zp8D
	LDA $009B,Y	; buffer pointer after $9b/$9c
	STA zp8D+1
	LDY #$00
B_C778	LDA V_0200,X	; transmit characters in buffer
	STA (zp8D),Y
	INY
	BEQ B_C786	; buffer already full?
	INX
	CPX V_0276
	BCC B_C778
B_C786	RTS

;$C787  -------- Search for end of name in command

S_C787	LDA #$00
	STA V_024B
	TXA
	PHA
B_C78E	LDA V_0200,X	; get characters out of buffer
	CMP #$2C	; ','
	BEQ B_C7A9
	CMP #$3D	; '='
	BEQ B_C7A9
	INC V_024B	; increment length of name
	INX
	LDA #$0F	; 15
	CMP V_024B
	BCC B_C7A9	; greater?
	CPX V_0274	; end of input line?
	BCC B_C78E
B_C7A9	STX V_0276
	PLA
	TAX		; pointer to end of name
	RTS
;$C7AF  --------
S_C7AF	LDA zp7C
	PHA		; secondary address and channel number
	LDA zp7B
	PHA
	JSR S_C7BF	; create file entry for directory
	PLA
	STA zp7B
	PLA		; get data back
	STA zp7C
	RTS
;$C7BF  --------
S_C7BF	LDA #$11	; 17
	STA zp7C	; secondary address
	JSR S_D1FB	; open channel to read
	JSR S_D63B	; set buffer pointer
	LDA V_0253
	BPL B_C7D8	; not yet last entry?
	LDA V_028D
	BNE B_C7DD
	JSR S_C8E7	; write 'blocks free.'
	CLC
	RTS
;$C7D8  --------
B_C7D8	LDA V_028D
	BEQ B_C7FC
B_C7DD	DEC V_028D
	BNE B_C7EF
	DEC V_028D
	JSR S_C477
	JSR S_C8E7
	SEC
	JMP S_C477
	;
B_C7EF	LDA #$00
	STA V_0273
	STA V_028D	; drive 0
	JSR S_C898	; create header ???
	SEC
	RTS
;$C7FC  --------
B_C7FC	LDX #$18
	LDY #$1D
	LDA (zp8D),Y	; number of blocks hi
	STA V_0273	; in buffer
	BEQ B_C809	; zero?
	LDX #$16
B_C809	DEY
	LDA (zp8D),Y	; number of blocks lo
	STA V_0272	; in buffer
	CPX #$16
	BEQ B_C81D
	CMP #$0A	; 10
	BCC B_C81D
	DEX
	CMP #$64	; 100
	BCC B_C81D
	DEX
B_C81D	JSR S_C88D	; erase buffer
	LDA (zp8D),Y	; file type
	PHA
	ASL A		; bit 7 in carry
	BPL B_C82B	; bit 6 not set?
	LDA #$3C	; '<' for protected file
	STA V_02B2,X	; write behind file type
B_C82B	PLA
	AND #$0F	; isolate bits 0-3
	TAY		; as file type marker
	LDA V_F106,Y	; 3rd letter of the file type
	STA V_02B1,X	; in buffer
	DEX
	LDA V_F101,Y	; 2nd letter of the file type
	STA V_02B1,X	; in buffer
	DEX
	LDA V_F0FB + 1,Y	; 1st letter of the file type
	STA V_02B1,X	; in buffer
	DEX
	DEX
	BCS B_C84C	; file not closed?
	LDA #$2A	; '*'
	STA V_02B2,X	; before file type in buffer
B_C84C	LDA #$A0	; pad with 'shift blank'
	STA V_02B1,X	; in buffer
	DEX
	LDY #$12
B_C854	LDA (zp8D),Y	; filenames
	STA V_02B1,X	; write in buffer
	DEX
	DEY
	CPY #$03
	BCS B_C854
	LDA #$22	; '='
	STA V_02B1,X	; write before file type
B_C864	INX
	CPX #$20
	BCS B_C874
	LDA V_02B1,X	; character from buffer
	CMP #$22	; '='
	BEQ B_C874
	CMP #$A0	; 'shift blank' at end of name
	BNE B_C864
B_C874	LDA #$22	; fill through '='
	STA V_02B1,X
B_C879	INX
	CPX #$20
	BCS B_C888
	LDA #$7F	; bit 7
	AND V_02B1,X
	STA V_02B1,X	; erase in the remaining chars
	BPL B_C879
B_C888	JSR S_C59A	; search for the directory entry
	SEC
	RTS

;$C88D  -------- Clear Directory Output Buffer

S_C88D	LDY #$1B
	LDA #$20
B_C891	STA V_02B0,Y	; write in buffer
	DEY
	BNE B_C891
	RTS

;$C898  -------- Create header with disk name

S_C898	JSR S_EF84	; initialize if needed
	JSR S_EF4A	; read disk name
	JSR S_C88D	; erase buffer
	LDA #$FF
	STA zp6E
	LDX zp78	; drive number
	STX V_0272	; as block number lo in buffer
	LDA #$00
	STA V_0273	; block number lo
	LDX zp98	; buffer number
	LDA V_F123,X	; hi-byte of the buffer address
	STA zp8D+1
	LDA V_F0C6	; $90, position of disk name
	STA zp8D	; save
	LDY #$16
	LDA (zp8D),Y	; pad buffer with 'shift blank'
	CMP #$A0
	BNE B_C8CE
	LDA #$31	; '1'
	DB $2C
B_C8C6	LDA (zp8D),Y	; character from buffer
	CMP #$A0	; compare with 'shift blank'
	BNE B_C8CE
	LDA #$20	; ' ' blank
B_C8CE	STA V_02B3,Y	; in buffer
	DEY
	BPL B_C8C6
	LDA #$12	; 'RVS ON'
	STA V_02B1	; in buffer
	LDA #$22	; '"'
	STA V_02B2	; write before
	STA V_02C3	; and after disk name
	LDA #$20	; ' ' blank
	STA V_02C4	; behind it
	RTS

;$C8E7  -------- Print 'blocks free.'

S_C8E7	JSR S_C88D	; erase buffer
	LDY #$0B	; 12 characters
B_C8EC	LDA V_C8F8,Y	; 'blocks free.'
	STA V_02B1,Y	; write in buffer
	DEY
	BPL B_C8EC
	JMP S_EDB8	; number of free blocks in front
	;
; $C8F8 'Blocks free.'
V_C8F8	DB "BLOCKS FREE."

	; Perform [S] - Scratch command

	JSR S_C480	; ascertain file type
	JSR S_C40A	; get drive number
	JSR S_C4B7	; initialize drive if needed
	LDA #$00
	STA zp7F	; counter for erased files
	JSR S_C582	; search for file in directory
	BMI B_C953	; not found?
B_C916	JSR S_DEF2	; is file open
	BCC B_C94E	; yes
	LDY #$00
	LDA (zp8D),Y	; file type
	AND #$40	; scratch protect
	BNE B_C94E	; yes
	JSR S_C997	; erase file and note in directory
	LDY #$13
	LDA (zp8D),Y	; track number of the first side-sector
	BEQ B_C936	; none present?
	STA zp79	; note track number
	INY
	LDA (zp8D),Y	; and sector number
	STA zp7A
	JSR S_C95E	; erase side-sector
B_C936	LDX V_0253	; file number
	LDA #$20
	AND zpE8,X	; bit 5 set?
	BNE B_C94C	; yes, file not closed
	LDA V_0280,X	; get track...
	STA zp79
	LDA V_0285,X	; ...and sector
	STA zp7A
	JSR S_C95E	; erase file
B_C94C	INC zp7F	; increment number of erased files
B_C94E	JSR S_C573	; search for next file
	BPL B_C916	; if present, erase
B_C953	LDA zp7F	; number of erased files
	STA zp79	; save as 'track'
	LDA #$01	; 1 as disk status
	LDY #$00	; 0 as 'sector'
	JMP L_C28D	; message 'files scratched'

	; Erase file

S_C95E	JSR S_EDCA	; free block in BAM
	JSR S_D5C8
	JSR S_EF84	; get buffer number in BAM
	LDA zpA8,X
	CMP #$FF
	BEQ L_C975
	LDA V_02F9
	ORA #$40
	STA V_02F9
L_C975	LDA #$00
	JSR S_D61B	; buffer pointer to zero
	JSR S_D271	; get track
	STA zp79
	JSR S_D271	; get sector
	STA zp7A
	LDA zp79	; track number
	BNE B_C98E	; not equal to zero
	JSR S_ED5F	; write BAM
	JMP L_D37D	; close channel
	;
B_C98E	JSR S_EDCA	; free block in BAM
	JSR S_D5A0	; read next block
	JMP L_C975	; and continue

	; Erase dir entry

S_C997	LDY #$00
	TYA
	STA (zp8D),Y	; set file type to zero
	JSR S_DF99	; write block
	JMP S_D6EC	; and check

	; Perform [D] - Backup command (Unused)

L_C9A2	LDA #$31
	JMP L_C2B2	; 31, 'syntax error'
	;
	JMP L_C2B2

	; Format disk ??

V_C9A7
S_C9A7	LDA #$03
	JSR S_D808
	LDX #$03
	LDA #$F0
	STA zpFF
	STA V_02FE
	JSR L_C9C8	;
	LDA #$01
	STA zp0E
	LDA #$00
	STA zp0E+1
	LDA #$80
	STA V_02FE
	JMP L_C9C8
	;
L_C9C8	LDY #$03
B_C9CA	LDA V_02FE
	STA zp02,X
	JSR S_D819
	CMP #$02
	BCC B_C9E4	; smaller than two, then ok
	LDA #$FF
	STA zp40
	STA zpFF
	DEY
	BNE B_C9CA
	LDX #$00
	JMP L_E746	; 21, 'read error'
	;
B_C9E4	RTS

;$C9E5  -------- Perform [C] - Copy command

	LDA #$E0
	STA V_024F
	JSR S_EF3C
	JSR S_EF84	; get buffer number of BAM
	LDA #$FF
	STA zpA8,X
	LDA #$0F
	STA V_0256
	JSR S_C2CF	; check input line
	BNE B_CA01
	JMP L_C9A2	; 31, 'syntax error'
	;
B_CA01	JSR S_C2E2	; check input
	JSR S_C40A	; test drive number
	LDA V_028B	; flag for syntax check
	AND #$55	; "U"
	BNE B_CA1D
	LDX V_027A
	LDA V_0200,X	; character of the command
	CMP #$2A	; '*'
	BNE B_CA1D
B_CA18	LDA #$30
	JMP L_C2B2	 ; 30, 'syntax error'
	;
B_CA1D	LDA V_028B	; syntax flag
	AND #$D9
	BNE B_CA18	; 30, 'syntax error'
	JMP L_CA47
	;
	LDA #$00
	STA V_0258
	STA V_028C	; number of drives
	STA V_0280	; track number in directory
	STA V_0281
	LDA zpE4
	AND #$01
	STA zp78	; drive number
	ORA #$01
	STA V_0291
	LDA V_027B
	STA V_027A
	RTS
;$CA47  --------
L_CA47	JSR S_C53A	; search for file in directory
	LDA V_0278	; number of filenames in command
	CMP #$03	; smaller than three?
	BCC B_CA96	; yes
	LDA zpE3	; first drive number
	CMP zpE4	; second drive number
	BNE B_CA96	; not on same drive?
	LDA zpDE	; directory block of the 1st file
	CMP zpDF	; same directory block as second file?
	BNE B_CA96	; no
	LDA zpD9	; directory sector of first file
	CMP zpDA	; same directory sector as second file?
	BNE B_CA96	; no
	JSR S_CBC1	; is file present?
	LDA #$01
	STA V_0279
	JSR S_CAEF
	JSR S_D235	; get data type
	BEQ B_CA77	; rel-file? yes
	CMP #$02	; prg-file?
	BNE B_CA7C	; no
B_CA77	LDA #$64
	JSR L_C2B2	; 64, 'file type mismatch'
B_CA7C	LDA #$12	; 18
	STA zp7C	; secondary address
	LDA V_023C
	STA V_023D
	LDA #$FF
	STA V_023C
	JSR S_DB61	; prepare append
	LDX #$02
	JSR S_CAAE	; copy file
	JMP L_C27E	; done
	;
B_CA96	JSR S_CA9C	; copy file
	JMP L_C27E	; done

	;

S_CA9C	JSR S_CBDC	;
	LDA zpE3	; drive number of first file
	AND #$01
	STA zp78	; backup drive number
	JSR S_D5D9
	JSR S_D81E	; enter file in directory
	LDX V_0277
S_CAAE	STX V_0279
	JSR S_CAEF
	LDA #$11	; 17
	STA zp7C
	JSR S_D1FB	;
	JSR S_D235	; get data type
	BNE B_CAC3	; no rel-file?
	JSR S_CB48
B_CAC3	LDA #$08
	STA zp95
	JMP L_CACD
	;
B_CACA	JSR S_D0BA	; write byte in buffer
L_CACD	JSR S_CB2A	; and get byte
	LDA #$80
	JSR S_DEE1	; test bit 7
	BEQ B_CACA	; not set?
	JSR S_D235	; check file type
	BEQ B_CADF	; rel-file?
	JSR S_D0BA	; get data byte in buffer
B_CADF	LDX V_0279
	INX
	CPX V_0278
	BCC S_CAAE
	LDA #$12	; 18
	STA zp7C
	JMP L_DC39	; close channel
	;
S_CAEF	LDX V_0279
	LDA zpE3,X	; drive number
	AND #$01
	STA zp78	; save
	LDA V_F0C3	; 18, directory track
	STA zp79	; save
	LDA zpD9,X	; directory sector
	STA zp7A
	JSR S_D5C8	; read block
	LDX V_0279
	LDA zpDE,X	; pointer in block
	JSR S_D61B	; set buffer pointer
	LDX V_0279
	LDA zpE8,X	; file type
	AND #$07	; isolate
	STA V_024A	; and save
	LDA #$00
	STA V_0258
	JSR S_DAD7	; get parameters for rel-file
	LDY #$01
	JSR S_D235	; get file type
	BEQ B_CB26	; rel-file?
	INY
B_CB26	TYA
	JMP S_D61B	; set buffer pointer
	;
S_CB2A	LDA #$11	; 17
	STA zp7C
S_CB2E	JSR S_D4ED	; open channel and get byte
	STA zp7E
	LDX zp7B	; channel number
	LDA zpF3,X	; ... as index
	AND #$08	; isolate end marker
	STA zp95
	BNE B_CB47	; not set?
	JSR S_D235	; get data type
	BEQ B_CB47	; rel-file?
	LDA #$80
	JSR L_DED2	; set bit 7
B_CB47	RTS
;$CB48  --------
S_CB48	JSR S_D329	; set drive number
	JSR S_E306
	LDA zp93
	PHA
	LDA zp92
	PHA
	LDA #$12	; 18
	STA zp7C
	JSR S_D217	; open write channel
	JSR S_D329	; set drive number
	JSR S_E306
	JSR S_E3D7
	LDA zp93
	STA zp7F+1
	LDA zp92
	STA zp7F
	LDA #$00
	STA zp81
	STA zp91
	STA zp94
	PLA
	STA zp92
	PLA
	STA zp93
	JMP L_E476

	; Perform [R] - Rename command

	JSR S_C40A	; get drive number from command line
	LDA zpE4
	AND #$01
	STA zpE4	; 2nd drive number
	CMP zpE3	; compare with 1st drive number
	BEQ B_CB8C	; same?
	ORA #$80
B_CB8C	STA zpE3
	JSR S_C53A	; search for file in directory
	JSR S_CBDC	; does name exist?
	LDA zpE4
	AND #$01
	STA zp78	; drive number
	LDA zpDA
	STA zp7A	; sector number
	JSR S_DF92	; read block from directory
	JSR S_D6EC	; ok?
	LDA zpDF	; pointer to directory entry
	CLC
	ADC #$03	; pointer plus 3 to file name
	JSR S_D61B	; set buffer pointer
	JSR S_E0CE	; get buffer number
	TAY
	LDX V_027A
	LDA #$10	; 16 characters
	JSR S_C74F	; write name in buffer
	JSR S_DF99	; write block to directory
	JSR S_D6EC	; ok?
	JMP L_C27E	; done, prepare disk status

	; Check if file present

S_CBC1	LDA zpE9	; file type
	AND #$07
	STA V_024A	; save
	LDX V_0278
B_CBCB	DEX
	CPX V_0277
	BCC B_CBDB
	LDA V_0280,X	; track number
	BNE B_CBCB	; not zero?
	LDA #$62
	JMP L_C2B2	; 62, 'file not found'
	;
B_CBDB	RTS
;$CBDC  --------
S_CBDC	JSR S_CBC1	; does file exist with old name?
B_CBDF	LDA V_0280,X	; track number of new file
	BEQ B_CBE9	; file erased?
	LDA #$63
	JMP L_C2B2	; 63, 'file exists'
	;
B_CBE9	DEX
	BPL B_CBDF
	RTS

;$CBED  -------- Perform [M] - Memory command

	LDA L_0201	; 2nd character from buffer
	CMP #$2D	; '-'
	BNE B_CC3D
	LDA V_0203
	STA zp6E
	LDA V_0204
	STA zp6E+1	; address in $6E/$6F
	LDY #$00
	LDA V_0202	; 3rd character from buffer
	CMP #$52	; "R"
	BEQ B_CC12	; to memory read
	CMP #$57	; "W"
	BEQ B_CC42	; to memory write
	CMP #$45	; "E"
	BNE B_CC3D
	JMP ($006E)	; *** Indirect jump!

	; M-R memory read

B_CC12	LDA (zp6E),Y	; read byte
	STA zp7E
	LDA V_0274	; length of command line
	CMP #$06	; less than 6?
	BCC B_CC37	; yes
	LDX V_0205	; number
	DEX
	BEQ B_CC37	; only one byte?
	TXA		; number of bytes
	CLC
	ADC zp6E	; plus start address
	INC zp6E
	STA V_0249	; end pointer
	LDA zp6E
	STA zpA6	; buffer pointer for error message
	LDA zp6E+1	; set to start address for 'M-R'
	STA zpA6+1
	JMP L_D596	; byte out
	;
B_CC37	JSR S_D1FB	; open read channel
	JMP L_D58D	; byte out
	;
B_CC3D	LDA #$31
	JMP L_C2B2	; 31, 'syntax error'

	; M-W memory write

B_CC42	LDA V_0206,Y	; read character
V_CC45	STA (zp6E),Y	; and save
	INY
	CPY V_0205	; number of characters
	BCC B_CC42	; all characters?
	RTS

;$CC4E  -------- Perform [U] - User command
;
; User commands:
;
; User command	Function
; ------------  --------
; u0		Restore default user command table address ($FFEA)
; u1 or ua	Block read replacement at $CE51
; u2 or ub	Block write replacement at $CE8b
; u3 or uc	Jump to $0500
; u4 or ud	Jump to $0503
; u5 or ue	Jump to $0506
; u6 or uf	Jump to $0509
; u7 or ug	Jump to $050c
; u8 or uh	Jump to $050f
; u9 or ui	Jump to ($fffa) reset tables ($ea39)
; u: or uj	Power up vector ($e9b5)
;
	LDY L_0201	; second char
	CPY #$30	; '0'
	BNE B_CC5E	; no
S_CC55	LDA #$EA
	STA zp6A	; pointer to table of user-addresses
	LDA #$FF	; $FFEA
	STA zp6A+1
	RTS
;$CC5E  --------
B_CC5E	JSR S_CC64
	JMP L_C27E	; done, prepare error message
	;
S_CC64	DEY
	TYA
	AND #$0F	; isolate number
	ASL A		; times 2
	TAY		; make an index of it
	LDA (zp6A),Y	; as pointer in table
	STA zp74
	INY		; address at $74/$75
	LDA (zp6A),Y
	STA zp74+1
	JMP ($0074)	; *** Indirect jump, execute function!

	; Open direct access channel, number

L_CC76	LDA V_028E	; last drive number
	STA zp78
	LDA zp7C	; channel number
	PHA		; check drive and initialize
	JSR S_C722
	PLA
	STA zp7C
	LDX V_0274	; length of filename
	DEX
	BNE B_CC97	; greater than one?
	LDA #$01
	JSR S_D338	; layout buffer and channel
	JMP L_CCE3	; set flags, done
	;
B_CC92	LDA #$70
	JMP L_C2B2	; 70, 'no channel'
	;
B_CC97	LDY #$01
	JSR B_CD6E	; get buffer number
	LDX V_0285	; buffer number
	CPX #$05	; bigger than 5?
	BCS B_CC92	; 70, 'no channel'
	LDA #$00
	STA zp6E
	STA zp6E+1
	SEC
B_CCAA	ROL zp6E
	ROL zp6E+1
	DEX
	BPL B_CCAA
	LDA zp6E
	AND V_024F
	BNE B_CC92
	LDA zp6E+1
	AND V_0250
	BNE B_CC92
	LDA zp6E
	ORA V_024F
	STA V_024F
	LDA zp6E+1
	ORA V_0250
	STA V_0250
	LDA #$00
	JSR S_D338	; search channel
	LDX zp7B	; channel number
	LDA V_0285	; buffer number
	STA zpA8,X
	TAX
	LDA zp78	; drive number
	STA zp02,X
	STA V_025B,X
L_CCE3	LDX zp7C	; secondary address
	LDA V_022B,X
	ORA #$40	; set READ and WRITE flags
	STA V_022B,X
	LDY zp7B	; channel number
	LDA #$FF
	STA V_0244,Y	; end pointer
	LDA #$89
	STA $00F3,Y	; set READ and WRITE flags
	LDA $00A8,Y	; buffer number
	STA V_023E,Y
	ASL A		; times 2
	TAX
	LDA #$01
	STA zp9A,X	; buffer pointer to one
V_CD05	LDA #$0E
	STA $00ED,Y	; flag for direct access
	JMP L_C27E	; done

	; Perform [B] - Block/Buffer command

	LDY #$00
	LDX #$00
	LDA #$2D	; '-'
	JSR S_C352	; search for minus sign
	BNE B_CD22	; found?
B_CD18	LDA #$31
	JMP L_C2B2	; 31, 'syntax error'
	;
B_CD1D	LDA #$30
	JMP L_C2B2	; 30, 'syntax error'
	;
B_CD22	TXA
	BNE B_CD1D
	LDX #$05
	LDA V_0200,Y	; char from buffer
B_CD2A	CMP V_CD4F,X	; compare with 'AFRWEP'
	BEQ B_CD34	; found?
	DEX
	BPL B_CD2A	; compare with all characters
	BMI B_CD18	; not found, error
B_CD34	TXA
	ORA #$80	; command number, set bit 7
	STA V_022A
	JSR S_CD5F + 2	; get parameters
	LDA V_022A
	ASL A		; number times 2
	TAX		; as index
	LDA V_CD56,X	; address of command hi
	STA zp6E+1
	LDA V_CD54 + 1,X	; address lo
B_CD4A	STA zp6E
	JMP ($006E)	; *** Indirect jump to command
	;
V_CD4F	EOR (zp45+1,X)	; AFRWEP
; $CD51
	DB "R"
; $CD52
	DB "WE"
V_CD54	BVC B_CD4A + 1
V_CD56	CMP V_CDE6 + 1
	PHA
	DEC V_CE65
; $CD5D
	DB $97,$CE
S_CD5F	LDX V_A0CE
	BRK
	LDX #$00	; Get parameters form block commands
	LDA #$3A	; ':'
	JSR S_C352	; test line to colon
	BNE B_CD6E	; found?
	LDY #$03	; no, begin at 4th character
B_CD6E	LDA V_0200,Y	; search for separating char
	CMP #$20	; ' ' blank
	BEQ B_CD7D
	CMP #$1D	; cursor right
	BEQ B_CD7D
	CMP #$2C	; ',' comma
	BNE B_CD84
B_CD7D	INY
	CPY V_0274	; line end?
	BCC B_CD6E
	RTS
;$CD84  --------
B_CD84	JSR S_CD93	; preserve next parameter
	INC V_0277	; increment parameter counter
	LDY V_0279
	CPX #$04	; compare with maximum number
	BCC B_CD7D
	BCS B_CD1D	; 30, 'syntax error'
S_CD93	LDA #$00
	STA zp6E
	STA zp6E+1	; erase storage area for decimal numbers
	STA zp70+1
	LDX #$FF
B_CD9D	LDA V_0200,Y	; get characters from input buffer
	CMP #$40
	BCS B_CDBC	; no digits?
	CMP #$30	; '0'
	BCC B_CDBC	; no digits?
	AND #$0F	; convert ASCII digits to hex
	PHA		; and save
	LDA zp6E+1
	STA zp70	; move digits one further
	LDA zp6E
	STA zp6E+1
	PLA
	STA zp6E	; note read number
	INY		; increment pointer in input buffer
	CPY V_0274	; line end reached
	BCC B_CD9D	; no
B_CDBC	STY V_0279	; save pointer
	CLC
	LDA #$00
B_CDC2	INX
	CPX #$03
	BCS B_CDD6	; convert hex digits to one byte
	LDY zp6E,X
B_CDC9	DEY
	BMI B_CDC2
	ADC V_CDE4,X	; add decimal value
	BCC B_CDC9
	CLC
	INC zp70+1
	BNE B_CDC9
B_CDD6	PHA
	LDX V_0277	; counter for paramaters
	LDA zp70+1
	STA V_0280,X	; hi-byte
	PLA
	STA V_0285,X	; lo-byte
	RTS
;$CDE4  -------- Decimal values  1, 10, 100
V_CDE4	DB $01,$0A,$64
;	-------- B-F block free
V_CDE7	DB " "		; get track, sector and drive number
	INC zpCE
	JSR S_EDCA	; free block
	JMP L_C27E	; done, prepare error message
	;
	LDA #$01
	STA V_02F9
	;
	; B-A block allocate
	;
	JSR S_CEE6	; get track, sector and drive number
	LDA zp7A	; sector
	PHA		; save
	JSR S_F065	; find block in BAM
	BEQ B_CE0B	; block allocated?
	PLA		; desired sector
	CMP zp7A	; = next free sector?
	BNE B_CE1E	; no
	JSR S_EDFB	; allocate block in BAM
	JMP L_C27E	; done
	;
B_CE0B	PLA
B_CE0C	LDA #$00
	STA zp7A	; sector 0
	INC zp79	; next track
	LDA zp79	; track number
	CMP V_F11A	; 36, last track number + 1
	BCS B_CE23	; >=, then 'no block'
	JSR S_F065	; find free block in next track
	BEQ B_CE0C	; not found, check next track
B_CE1E	LDA #$65
	JSR S_E781	; 65, 'no block' next free block
B_CE23	LDA #$65
	JSR L_C2B2	; 65, 'no block' no more free blocks
	;
	; Read block to buffer
	;
S_CE28	JSR S_CEE3	; open channel, set parameters
	JMP S_D5B3	; read block from disk
	;
S_CE2E	JSR S_D23F	; set pointer to buffer
	LDA (zp9A,X)	; get byte
	RTS

;$CE34  -------- Read block from disk

S_CE34	JSR S_CE28	; open channel, read block
	LDA #$00
	JSR S_D61B	; set buffer pointer to zero
	JSR S_CE2E	; get a byte from the buffer
	STA V_0244,Y
	LDA #$89	; set read and write flag
	STA $00F3,Y
	RTS

;$CE48  -------- B-R block read

	JSR S_CE34	; read block from disk
	JSR S_D53F	; prepare byte from buffer
S_CE4E	JMP L_C27E	; prepare error message
	;
	; U1, Block read without changing buffer pointer
	;
	JSR S_CD5F + 2	; get parameters of the command
	JSR S_CE34	; read block from disk
	LDA V_0244,Y	; end pointer
	STA V_023E,Y	; save as data byte
	LDA #$FF
	STA V_0244,Y	; end pointer to $FF
	JMP L_C27E	; done, prepare error message
	;
	; B-W block write
	;
V_CE65	JSR S_CEE3	; open channel
	JSR S_D63B	; set buffer pointer
	TAY
	DEY
	CMP #$02	; buffer pointer lo less than 2?
	BCS B_CE73	; no
	LDY #$01
B_CE73	LDA #$00
	JSR S_D61B	; buffer pointer to zero
	TYA
	JSR S_D10D	; write byte in buffer
	TXA
	PHA
	JSR S_D5B7	; write block to disk
	PLA
	TAX
	LDY zp7B
	JSR S_D541	; get byte from buffer
	JMP L_C27E	; done, error message
	;
	; U2, Block write without changing buffer pointer
	;
V_CE8B	JSR S_CD5F + 2	; get command parameters
	JSR S_CEE3	; open channel
	JSR S_D5B7	; and write block to disk
	JMP L_C27E	; done
	;
	; B-E block execute
	;
	JSR S_CE28	; open channel and read block
	LDA #$00
	STA zp6E	; address low
	LDX zp98	; buffer number
	LDA V_F123,X	; buffer address high
	STA zp6E+1
	JSR S_CEAB	; execute routine
	JMP L_C27E	; done
	;
S_CEAB	JMP ($006E)	; *** Indirect jump to routine
	;
	; B-P block pointer
	;
	JSR S_CEC3	; open channel, get buffer number
	LDA zp98	; buffer number
	ASL A		; * 2
	TAX		; as index
	LDA V_0286	; pointer value
	STA zp9A,X	; save as buffer pointer
	JSR S_D23F	; prepare a byte in buffer
	JSR S_D541	; for output
	JMP L_C27E	; done
	;
	;  Open channel
	;
S_CEC3	LDX zp99
	INC zp99
	LDA V_0285,X	; buffer number
	TAY
	DEY
	DEY
	CPY #$0C	; buffer number smaller than 14?
	BCC B_CED6	; yes
B_CED1	LDA #$70
	JMP L_C2B2	; 70, 'no channel'
	;
B_CED6	STA zp7C	; secondary address
	JSR S_D1FB	; open channel
	BCS B_CED1	; already allocated, 'no channel'
	JSR S_E0CE	; buffer number
	STA zp98	; set
	RTS

;$CEE3  -------- Check buffer number and open channel

S_CEE3	JSR S_CEC3	; check buffer number and open channel
S_CEE6	LDX zp99	; channel number
	LDA V_0285,X	; buffer address
	AND #$01
	STA zp78	; drive number
	LDA V_0287,X
	STA zp7A	; sector
	LDA V_0286,X
	STA zp79	; track
	JSR S_D6B0	; track and sector ok?
	RTS

;$CEFD  -------- Set pointer for REL file

S_CEFD	JSR S_CF1B	; record number * record length
	JSR S_CF5D	; divide by 254
	LDA zp89	; remainder = pointer in data block
	STA zp94	; data pointer
	JSR S_CF60	; divide by 120 = side-sector number
	INC zp94
	INC zp94	; data pointer + 2 (track/sector pointer!)
	LDA zp84	; result of division
	STA zp92	; equals side-sector number
	LDA zp89	; remainder
	ASL A		; times 2
	CLC
	ADC #$10	; plus 16
	STA zp93	; =pointer in side-sector to data block
	RTS
;$CF1B  --------
S_CF1B	JSR S_CF8F	; erase work storage
	STA zp8B
	LDX zp7B	; channel number
	LDA zpB6,X	; record number lo
	STA zp89
	LDA zpBC,X	; record number hi
	STA zp8A
	BNE B_CF30
	LDA zp89
	BEQ B_CF3B	; record number not zero?
B_CF30	LDA zp89
	SEC
	SBC #$01	; then subtract one
	STA zp89
	BCS B_CF3B
	DEC zp8A
B_CF3B	LDA zpC8,X	; record length
	STA zp6E
B_CF3F	LSR zp6E
	BCC B_CF46
	JSR S_CFA3	; record number * record length
B_CF46	JSR S_CF9B	; shift register left
	LDA zp6E
	BNE B_CF3F
	LDA zp91
	CLC
	ADC zp84
	STA zp84
	BCC B_CF5C	; result in $8B/$8C/$8D
	INC zp85
	BNE B_CF5C
	INC zp86
B_CF5C	RTS

;$CF5D  -------- Divide by 254

S_CF5D	LDA #$FE
	DB $2C
	; Divide by 120
S_CF60	LDA #$78
	BIT V_06A9
	STA zp6E	; divisor
	LDA #$00
	STA zp89
	STA zp8A
	LDX #$18
B_CF6F	ASL zp84
	ROL zp85
	ROL zp86
	ROL zp89
	ROL zp8A
	LDA zp89
	SEC
	SBC zp6E
	TAY
	LDA zp8A
	SBC #$00
	BCC B_CF8B
	INC zp84
	STA zp8A
	STY zp89
B_CF8B	DEX
	BNE B_CF6F
	RTS

;$CF8F  -------- Erase work storage

S_CF8F	LDA #$00
	STA zp84
	STA zp85
	STA zp86
	RTS
;$CF98  -------- Left shift 3-byte register twice
	JSR S_CF9B
	; Left shift 3-byte register once
S_CF9B	CLC
	ROL zp89
	ROL zp8A
	ROL zp8B
	RTS

;$CFA3  -------- Add 3-byte registers

S_CFA3	CLC
	LDX #$FD
B_CFA6	LDA zp87,X	; register $84/$85/$86
	ADC zp8C,X	; add to register $89/$8a/$8b
	STA zp87,X
	INX
	BNE B_CFA6
	RTS
;$CFB0  --------
S_CFB0	LDX #$00
B_CFB2	TXA
	STA zpD4,X
	INX
	CPX #$04
	BNE B_CFB2
	LDA #$06
	STA zpD4,X
	RTS
;$CFBF  --------
S_CFBF	LDY #$04
	LDX zp7B	; channel number
L_CFC3	LDA $00D4,Y
	STX zpD4,Y
	CMP zp7B	; channel number
	BEQ B_CFD3
	DEY
	BMI S_CFB0
	TAX
	JMP L_CFC3
	;
B_CFD3	RTS
;$CFD4  --------
S_CFD4	JSR S_CFBF
	LDX zp7B
	LDA zpA8,X
	BMI B_CFDF
	LDA zpAF,X
B_CFDF	CMP #$FF
	BEQ B_CFFB
	LDA zpA8,X
	EOR #$80
	STA zpA8,X
	PHA
	LDA zpAF,X
	EOR #$80
	STA zpAF,X
	TAY
	PLA
	BPL B_CFF5
	TYA
B_CFF5	AND #$BF
	TAX
	JMP S_D6EC
	;
B_CFFB	LDA zpA8,X
	BPL B_D001
	LDA zpAF,X
B_D001	AND #$BF
	TAY
	LDA V_025B,Y
	AND #$01
	STA zp78
	JSR S_D3E4
	BPL B_D015
	LDA #$70
	JMP L_C2B2
	;
B_D015	LDX zp7B
	ORA #$80
	LDY zpA8,X
	BPL B_D021
	STA zpA8,X
	BMI B_D023
B_D021	STA zpAF,X
B_D023	LDA zp79	; track
	PHA
	LDA zp7A	; sector
	PHA
	LDA #$01
	STA zp70
	LDA zpA8,X
	BPL B_D033
	LDA zpAF,X
B_D033	AND #$BF
	TAY
	LDA V_F123,Y
	STA zp70+1
	LDY #$00
	LDA (zp70),Y
	STA zp7A
	LDA #$00
	STA zp70
	LDA zpA8,X
	BPL B_D04B
	LDA zpAF,X
B_D04B	AND #$BF
	TAY
	LDA V_F123,Y
	STA zp70+1
	LDY #$00
	LDA (zp70),Y
	STA zp79
	BEQ B_D085
	JSR S_D235
	BEQ B_D06B
	JSR S_DEE6
	BNE B_D06B
	JSR S_D0AB
	JMP L_D07C
	;
B_D06B	LDX zp7B
	LDA zpA8,X
	EOR #$80
	STA zpA8,X
	LDA zpAF,X
	EOR #$80
	STA zpAF,X
	JSR S_DF92
L_D07C	PLA
	STA zp7A	; get sector
	PLA
	STA zp79	; and track number
	JMP L_D08E
	;
B_D085	PLA
	STA zp7A	; get back sector
	PLA
	STA zp79	; and track number
	JSR S_D0AB
L_D08E	JSR S_E0CE
	TAX
	JMP S_D6EC	; and verify
	;
B_D095	LDA #$70
	JMP L_C2B2	; 70, 'no channel'
	;
S_D09A	JSR S_CFBF
	JSR S_E0F2
	BNE B_D0AA
	JSR S_D3E4
	BMI B_D095
	JSR S_E0FD
B_D0AA	RTS

;$D0AB  -------- Change buffer

S_D0AB	LDX zp7B	; channel number
	LDA zpA8,X
	EOR #$80
	STA zpA8,X
	LDA zpAF,X	; rotate bit 7 in table
	EOR #$80
	STA zpAF,X
	RTS

;$D0BA  -------- Write data in buffer

S_D0BA	LDX #$12	; channel 18
	STX zp7C
	JSR S_D217	; open write channel
	JSR S_D235	; check file type
	BCC B_D0CB	; no rel-file
	LDA #$20
	JSR B_DED8	; change buffer
B_D0CB	LDA zp7C	; secondary address
	CMP #$0F	; 15?
	BEQ B_D0F4	; yes
	BNE B_D0DB	; no
S_D0D3	LDA zp7D	; secondary address
	AND #$8F
	CMP #$0F	; greater than 15?
	BCS B_D0F4	; then input buffer
B_D0DB	JSR S_D235	; check file type
	BCS B_D0E5	; rel-file or direct access?
	LDA zp7E	; data byte
	JMP L_D2F3	; write in buffer
	;
B_D0E5	BNE B_D0EA	; direct access file?
	JMP L_E1E6	; write data byte in rel-file
	;
B_D0EA	LDA zp7E
	JSR S_D10D	; write data byte in buffer
	LDY zp7B	; channel number
	JMP S_D541	; prepare next byte for output
	;
B_D0F4	LDA #$04	; channel 4
	STA zp7B	; corresponding input buffer
	JSR S_D63B	; set buffer pointer
	CMP #$2A	; 40
	BEQ B_D104	; buffer end?
	LDA zp7E
	JSR S_D10D	; write data byte in buffer
B_D104	LDA zp95	; end flag set?
	BEQ B_D109	; yes
	RTS
;$D109  --------
B_D109	INC V_0255	; set command flag
	RTS

;$D10D  -------- Write data byte in buffer

S_D10D	PHA		; save data byte
	JSR S_E0CE	; get buffer number
	BPL B_D119	; associated buffer?
	PLA
	LDA #$61
	JMP L_C2B2	; 61, 'file not open'
	;
B_D119	ASL A		; buffer number times 2
	TAX		; as index
	PLA		; data byte
	STA (zp9A,X)	; write in buffer
	INC zp9A,X	; increment buffer pointer
	RTS

;$D121  -------- Perform [I] - Initalise command

	JSR S_C2BB	; find drive number
	JSR S_D15E	; load BAM
	JMP L_C27E	; prepare disk status
	;
	; Read BAM from disk
	;
S_D12A	JSR S_EF7A
	TAY
	LDX zpA8,Y
	CPX #$FF
	BNE B_D148
	PHA
	JSR S_D3E4
	TAX
	BPL B_D140
	LDA #$70
	JSR S_E784	; 70, 'no channel'
B_D140	PLA
	TAY
	TXA
	ORA #$80
	STA $00A8,Y
B_D148	TXA
	AND #$0F
	STA zp98
	LDX #$00
	STX zp7A	; sector 0
	LDX V_F0C3	; 18
	STX zp79	; track 18
	JSR S_D808	; transmit parameter to disk controller
	LDA #$B0	; command code 'read block header'
	JMP B_D6DF	; transmit to disk controller
	;
	; Load BAM
	;
S_D15E	JSR S_EF3C
	JSR S_D465
	JSR S_D12A	; read block
	LDX zp78	; drive number
	LDA #$00
	STA V_0251,X	; reset flag for "BAM changed'
	JSR L_D6D9
	LDA zp98
	ASL A
	TAX
	LDA #$02	; buffer pointer to $200
	STA zp9A,X
	LDA (zp9A,X)	; get character from buffer
	LDX zp78	; drive number
	STA zp5D,X
	LDA #$00
	STA zp22,X	; flag for write protect
	STA zp5F,X	; flag for read error
	;
	; Calculate blocks free
	;
L_D185	JSR S_EDA5	; buffer address to $6C/$6D
	LDY #$04	; begin at position 4
	LDA #$00
	TAX
B_D18D	CLC
	ADC (zp6C),Y	; add number of free blocks per track
	BCC B_D193
	INX		; X as hi-byte
B_D193	INY
	INY
	INY
	INY		; plus 4
	CPY #$48	; track 18?
	BEQ B_D193	; then skip
	CPY #$90	; last track number?
	BNE B_D18D	; no
	PHA		; lo-byte
	TXA		; hi-byte
	LDX zp78	; drive number
	STA V_02FC,X	; hi-byte to $2FC
	PLA		; lo-byte
	STA V_02FA,X	; to $2FA
	RTS
;$D1AB  --------
S_D1AB	JSR S_D805	; parameters to disk controller
	JSR S_D1D3	; read block
	JSR S_D6EC	; ok?
	JSR S_D247	; get byte from buffer
	STA zp79	; track
	JSR S_D247	; next byte from buffer
	STA zp7A	; sector
	RTS
;$D1BF  --------
L_D1BF	JSR S_D1AB
	LDA zp79	; track
	BNE B_D1C7
	RTS
;$D1C7  --------
B_D1C7	JSR S_CFD4	; change buffer
	JSR S_D805	; parameters to disk controller
	JSR S_D1D3	; read block
	JMP S_CFD4	; change buffer
	;
	; Read block
	;
S_D1D3	LDA #$80	; code for 'read'
	BNE B_D1D9
S_D1D7	LDA #$90	; code for 'write'
B_D1D9	STA V_024D	; save
	JSR S_E0CE	; get buffer number
	TAX
	JSR L_D659	; get track/sector, read/write block
	TXA
	PHA
	ASL A		; buffer pointer times 2
	TAX
	LDA #$00
	STA zp9A,X	; pointer in buffer to zero
	JSR S_D235	; get file type
	CMP #$04	; rel-file or direct access?
	BCS B_D1F8	; yes
	INC zpB6,X
	BNE B_D1F8	; increment block counter
	INC zpBC,X
B_D1F8	PLA
	TAX
	RTS

;$D1FB  -------- Open channel for reading

S_D1FB	LDA zp7C	; secondary address
	CMP #$13	; 19
	BCC B_D203	; smaller?
	AND #$0F
B_D203	CMP #$0F
	BNE B_D209
	LDA #$10	; 16
B_D209	TAX
	SEC		; pre-set error
	LDA V_022B,X	; channel number
	BMI B_D216	; reserved already? then return with Carry set
	AND #$0F	; isolate channel nr
	STA zp7B	; save as current channel
	TAX		; ... to X
	CLC		; flag for ok
B_D216	RTS

;$D217  -------- Open channel for write

S_D217	LDA zp7C	; secondary address
	CMP #$13	; 19
	BCC B_D21F	; smaller?
	AND #$0F
B_D21F	TAX
	LDA V_022B,X	; channel number
	TAY
	ASL A
	BCC B_D231
	BMI B_D233
B_D229	TYA
	AND #$0F
	STA zp7B
	TAX
	CLC		; flag for ok
	RTS
;$D231  --------
B_D231	BMI B_D229
B_D233	SEC		; flag for channel allocated
	RTS

;$D235  -------- Get file type into accu
;
; also returns the Z flag set when REL ($04) type
;
S_D235	LDX zp7B
	LDA zpED,X
	LSR A
	AND #$07
	CMP #$04	; 'REL'?
	RTS

;$D23F  -------- Get buffer and channel numbers

S_D23F	JSR S_E0CE	; get buffer number
	ASL A
	TAX
	LDY zp7B
	RTS

;$D247  -------- Get a byte from buffer

S_D247	LDX zp7B	; get buffer and channel number
	LDA zpA8,X
	BPL B_D24F
	LDA zpAF,X
B_D24F	AND #$BF
	ASL A
	TAX
	LDY zp7B
	LDA V_0244,Y	; end pointer
	BEQ B_D26C
	LDA (zp9A,X)	; get byte from buffer
	PHA
	LDA zp9A,X	; buffer pointer
	CMP V_0244,Y	; equal end pointer?
	BNE B_D268	; no
	LDA #$FF	; buffer pointer to -1
	STA zp9A,X
B_D268	PLA		; data byte
	INC zp9A,X	; increment buffer pointer
	RTS
;$D26C  --------
B_D26C	LDA (zp9A,X)	; get character from buffer
	INC zp9A,X	; increment buffer pointer
	RTS

;$D271  -------- Get byte and read next block

S_D271	JSR S_D247	; get byte from buffer
	BNE B_D2E7	; not last character?
	STA zp7E	; save data byte
	LDA V_0244,Y	; end pointer
	BEQ B_D285	; yes
	LDA #$80
	STA $00F3,Y	; READ-flag
	LDA zp7E	; data byte
	RTS
;$D285  --------
B_D285	JSR S_CFD4	; change buffer and read next block
	LDA #$00
	STA zp6E	; set buffer pointer to zero
	LDX zp7B	; get channel number
	LDA zpA8,X	; buffer number
	BPL B_D294
	LDA zpAF,X	; buffer number from 2nd table
B_D294	AND #$BF	; erase V bit
	ASL A
	TAX
	LDA zp9B,X	; buffer pointer hi
	STA zp8D+1
	LDA zp6E
	STA zp9A,X	; buffer pointer lo, new value
	STA zp8D
	JSR S_D247	; get first byte from buffer
	CMP #$00	; track number zero
	BEQ B_D2E8	; yes, then last block
	STA zp79	; save last track number
	JSR S_D247	; get next byte
	STA zp7A	; save as following track
	JSR S_CFD4	; change buffer and read next block
	LDX zp7B
	LDA zpA8,X
	BPL B_D2BB
	LDA zpAF,X	; get drive number
B_D2BB	AND #$BF	; erase V bit
	TAX
	LDA V_025B,X	; isolate drive number
	AND #$01
	STA zp78	; and save
	LDX zp7B
	LDA zpA8,X
	BPL B_D2CD
	LDA zpAF,X
	; Transmit parameter to disk controller
B_D2CD	AND #$BF
	ASL A
	TAY
	LDA zp79	; track number
	STA $0008,Y	; transmit
	LDA zp7A	; sector number
	STA $0009,Y	; transmit
	LDA zp78	; drive number
	ASL A		; * 2
	TAX		; make an index from it
	JSR S_D1D3	; transmit read command
	JSR S_CFD4	; change buffer and read block
	LDA zp7E	; get data byte
B_D2E7	RTS
;$D2E8  --------
B_D2E8	JSR S_D247	; get next byte from buffer
	LDY zp7B
	STA V_0244,Y	; save as end pointer
	LDA zp7E	; get data byte back
	RTS
;$D2F3  -------- Write byte in buffer and block
L_D2F3	JSR S_D10D	; byte in buffer
	BEQ B_D2F9	; buffer full?
	RTS
;$D2F9  --------
B_D2F9	JSR S_D329	; get drive number
	JSR S_EF89	; find free block in BAM
	LDA #$00
	JSR S_D61B	; buffer pointer to zero
	LDA zp79
	JSR S_D10D	; track number as first byte
	LDA zp7A
	JSR S_D10D	; sector number as second byte
	JSR S_D1D7	; write block
	JSR S_CFD4	; change buffer
	JSR S_D805	; parameter to disk controller
	LDA #$02
	JMP S_D61B	; buffer pointer to 2
	;
S_D31C	STA zp6E
	JSR S_D63B	; get buffer pointer
	CLC
	ADC zp6E
	STA zp9A,X	; and increment
	STA zp8D
	RTS

;$D329  -------- Get drive number

S_D329	JSR S_E0CE	; get drive number
	TAX
	LDA V_025B,X
	AND #$01	; isolate drive number
	STA zp78	; and save
	RTS

;$D335  -------- Find write channel and buffer

S_D335	SEC		; flag for writing
	BCS B_D339
	;
	; Find read channel and buffer
	;
S_D338	CLC		; flag for reading
B_D339	PHP		; save
	STA zp6E	; buffer number
	JSR L_D37D	; close channel
	JSR S_D4D1	; allocate free channel
	STA zp7B	; channel number
	LDX zp7C	; secondary address
	PLP
	BCC B_D34B	; read channel?
	ORA #$80	; flag for writing
B_D34B	STA V_022B,X	; set
	AND #$3F
	TAY
	LDA #$FF	; default value
	STA $00A8,Y
	STA $00AF,Y	; write in associated table
	STA $00CE,Y
	DEC zp6E	; decrement buffer number
	BMI B_D37C	; done already?
	JSR S_D3E4	; find buffer
	BPL B_D36D	; found?
L_D365	JSR S_D3B0	; erase flags in table
	LDA #$70
	JMP L_C2B2	; 70, 'no channel'
	;
B_D36D	STA $00A8,Y	; buffer number in table
	DEC zp6E	; buffer number
	BMI B_D37C	; already done?
	JSR S_D3E4	; find buffer
	BMI L_D365	; not found?
	STA $00AF,Y	; buffer number in table
B_D37C	RTS

;$D37D  -------- Close channel

L_D37D	LDA zp7C	; secondary address
	CMP #$0F	; 15?
	BNE B_D384	; no
	RTS		; else done already
;$D384  --------
B_D384	LDX zp7C
	LDA V_022B,X	; channel number
	CMP #$FF	; not associated (=free)?
	BEQ B_D3AF	; then done
	AND #$3F
	STA zp7B	; channel number
	LDA #$FF
	STA V_022B,X	; erase association in table
	LDX zp7B
	LDA #$00
	STA zpF3,X	; erase READ and WRITE flag
	JSR S_D3B0	; free buffer
	LDX zp7B	; channel number
	LDA #$01	; set bit 0
B_D3A3	DEX
	BMI B_D3A9	; shift to correct position
	ASL A
	BNE B_D3A3
B_D3A9	ORA V_0256	; free in allocation register
	STA V_0256
B_D3AF	RTS
;$D3B0  -------- Free buffer
S_D3B0	LDX zp7B	; channel number
	LDA zpA8,X	; buffer number
	CMP #$FF
	BEQ B_D3C1	; not associated?
	PHA
	LDA #$FF
	STA zpA8,X	; erase buffer association
	PLA
	JSR S_D445	; erase buffer allocation register
B_D3C1	LDX zp7B	; channel number
	LDA zpAF,X
	CMP #$FF	; associated in second table?
	BEQ B_D3D2	; no
	PHA
	LDA #$FF
	STA zpAF,X	; erase association
	PLA
	JSR S_D445	; erase buffer in allocation register
B_D3D2	LDX zp7B	; channel number
	LDA zpCE,X
	CMP #$FF	; associated in 3rd table?
	BEQ B_D3E3	; no
	PHA
	LDA #$FF
	STA zpCE,X	; erase association
	PLA
	JSR S_D445	; erase buffer in allocation register
B_D3E3	RTS
;$D3E4  -------- Find buffer
S_D3E4	TYA
	PHA
	LDY #$01
	JSR S_D40C
	BPL B_D3F9
	DEY
	JSR S_D40C
	BPL B_D3F9
	JSR S_D48B
	TAX
	BMI B_D408
B_D3F9	LDA zp78
	STA zp02,X
	STA V_025B,X
	TXA
	ASL A
	TAY
	LDA #$02
	STA $009A,Y
B_D408	PLA
	TAY
	TXA
	RTS
;$D40C  --------
S_D40C	LDX #$07
B_D40E	LDA V_024F,Y
	AND V_EE54,X	; erase bit
	BEQ B_D41A
	DEX
	BPL B_D40E
	RTS
;$D41A  --------
B_D41A	LDA V_024F,Y
	EOR V_EE54,X	; rotate bit
	STA V_024F,Y
	TXA		; buffer number
	DEY
	BMI B_D42A
	CLC
	ADC #$08
B_D42A	TAX		; buffer number
B_D42B	RTS
;$D42C  --------
L_D42C	LDX zp7B
	LDA zpA8,X
	BMI B_D43B
	TXA
	CLC
	ADC #$07
	TAX
	LDA zpA8,X
	BPL B_D42B
B_D43B	CMP #$FF
	BEQ B_D42B
	PHA
	LDA #$FF
	STA zpA8,X
	PLA
S_D445	AND #$0F
	TAY		; buffer number
	INY
	LDX #$10	; 16
B_D44B	ROR V_0250
	ROR V_024F	; rotate 16-bit allocation register
	DEY
	BNE B_D455
	CLC		; erase bit for buffer
B_D455	DEX
	BPL B_D44B
	RTS

;$D459  -------- Close all channels

S_D459	LDA #$0E	; 14
	STA zp7C	; secondary address
B_D45D	JSR L_D37D	; close channel
	DEC zp7C	; next secondary address
	BNE B_D45D
	RTS

;$D465  -------- Close all channels of other drives

S_D465	LDA #$0E	; 14
	STA zp7C	; secondary address
B_D469	LDX zp7C
	LDA V_022B,X	; association table
	CMP #$FF	; channel associated?
	BEQ B_D486	; no
	AND #$3F
	STA zp7B	; channel number
	JSR S_E0CE	; get buffer number
	TAX
	LDA V_025B,X	; drive number
	AND #$01	; isolate
	CMP zp78	; equal to actual drive number
	BNE B_D486	; no
	JSR L_D37D	; close channel
B_D486	DEC zp7C	; next channel
	BPL B_D469
	RTS
;$D48B  --------
S_D48B	LDA zp6E
	PHA
	LDY #$00
B_D490	LDX zpD4,Y
	LDA zpA8,X
	BPL B_D49A
	CMP #$FF
	BNE B_D4B0
B_D49A	TXA
	CLC
	ADC #$07
	TAX
	LDA zpA8,X
	BPL B_D4A7
	CMP #$FF
	BNE B_D4B0
B_D4A7	INY
	CPY #$05
	BCC B_D490
	LDX #$FF
	BNE B_D4CC
B_D4B0	STX zp6E
	AND #$3F
	TAX
B_D4B5	LDA zp02,X
	BMI B_D4B5
	CMP #$02
	BCC B_D4C5
	LDX zp6E
	CPX #$07
	BCC B_D49A
	BCS B_D4A7
B_D4C5	LDY zp6E
	LDA #$FF
	STA $00A8,Y
B_D4CC	PLA
	STA zp6E
	TXA
	RTS

;$D4D1  -------- Find channel and allocate

S_D4D1	LDY #$00
	LDA #$01	; set bit 0
B_D4D5	BIT V_0256
	BNE B_D4E3	; channel free?
	INY
	ASL A		; rotate bit to left
	BNE B_D4D5	; all channels checked?
	LDA #$70
	JMP L_C2B2	; 70, 'no channel'
	;
B_D4E3	EOR #$FF	; rotate bit model
	AND V_0256	; erase bit
	STA V_0256	; allocate channel
	TYA
	RTS

;$D4ED  -------- Get byte for output

S_D4ED	JSR S_D1FB	; open channel for reading
	JSR S_D4F9	; get byte in output register
	LDX zp7B	; channel number
	LDA V_023E,X	; get byte
	RTS
;$D4F9  --------
S_D4F9	LDX zp7B	; channel number
	LDA zpED,X	; check file type
	LSR A
	AND #$07
	CMP #$04	; REL?
	BNE B_D507	; no...
	JMP L_E25B	; get byte from REL-file
	;
B_D507	LDA zp7C	; secondary address
	CMP #$0F	; 15
	BEQ B_D567	; yes, read error channel
	LDA zpF3,X
	AND #$08	; end flag set?
	BNE B_D526	; no
	JSR S_D235	; check file type
	CMP #$07	; direct access file?
	BNE B_D521	; no
	LDA #$89	; set READ and WRITE flag
	STA zpF3,X
	JMP L_D531
	;
B_D521	LDA #$00
	STA zpF3,X	; erase READ and WRITE flag
	RTS
;$D526  --------
B_D526	LDA zp7C	; secondary address
	BEQ B_D55C	; zero, LOAD?
	JSR S_D235	; check file type
	CMP #$04	; rel-file or direct access?
	BCC B_D553	; no
L_D531	JSR S_D23F	; get buffer and channel number
	LDA zp9A,X	; buffer pointer
	CMP V_0244,Y	; equal end pointer?
	BNE S_D53F	; no
	LDA #$00
	STA zp9A,X	; buffer pointer to zero
S_D53F	INC zp9A,X	; increment buffer pointer
S_D541	LDA (zp9A,X)	; get byte from buffer
	STA V_023E,Y	; into output register
	LDA zp9A,X	; buffer pointer
	CMP V_0244,Y	; equal end pointer?
	BNE B_D552	; no
	LDA #$81
	STA $00F3,Y	; set flags
B_D552	RTS
;$D553  --------
B_D553	JSR S_D271	; get byte from buffer
L_D556	LDX zp7B	; channel number
	STA V_023E,X	; byte in output register
	RTS
;$D55C  --------
B_D55C	LDA V_0254	; flag for directory?
	BEQ B_D553	; no
	JSR S_EBD4	; create directory line
	JMP L_D556
	;
B_D567	JSR S_D63B	; set buffer pointer
	CMP #$D4
	BNE B_D586
	LDA zp8D+1
	CMP #$02
	BNE B_D586
	LDA #$0D	; CR
	STA zp7E	; in output register
	JSR S_F3F0	; erase error flags
	LDA #$00
	JSR S_E800	; create 'ok' message
	DEC zpA6	; set buffer pointer back
	LDA #$80	; set READ flag
	BNE B_D598
B_D586	JSR S_D247	; get byte from buffer
	STA zp7E	; into output register
	BNE L_D596
L_D58D	LDA #$D4
	JSR S_D61B	; set buffer pointer in front of error pointer
	LDA #$02
	STA zp9B,X	; hi-address
L_D596	LDA #$88	; set READ flag
B_D598	STA zpF8
	LDA zp7E	; data byte
	STA V_0243	; into output register
	RTS

;$D5A0  -------- Read next block

S_D5A0	JSR S_E0CE	; get buffer number
	ASL A		; times 2
	TAX		; make an index of it
	LDA #$00
	STA zp9A,X	; buffer pointer to zero
	LDA (zp9A,X)	; get first byte from buffer
	BEQ B_D5B2	; no block following?
	DEC zp9A,X	; buffer pointer to -1
	JMP S_D271	; read next block
	;
B_D5B2	RTS

;$D5B3  -------- Read block

S_D5B3	LDA #$80	; command code for reading
	BNE B_D5B9	; always jump
	; Write block
S_D5B7	LDA #$90	; command code for writing
B_D5B9	ORA zp78	; drive number
	STA V_024D	; save code
	LDA zp98
	JSR S_D808	; parameter to disk controller
	LDX zp98
	JMP L_D6E6	; execute command
	;
	; Allocate buffer and read block
	;
S_D5C8	LDA #$01
S_D5CA	STA V_024A	; file type to sequential
	LDA #$11	; 17
	STA zp7C	; secondary address
	JSR S_DD7D	; allocate buffer and read block
	LDA #$02
	JMP S_D61B	; buffer pointer to 2
	;
	; Allocate new block
	;
S_D5D9	LDA #$12	; 18
	STA zp7C	; secondary address
	JMP L_DE15	; allocate new block
	;
	; Write dir block
	;
S_D5E0	JSR S_DF76	; get track and sector number
	LDA #$01
	STA zp6E	; a block
	LDA zp68	; save step width 10 for block
	PHA		; allocation
	LDA #$03
	STA zp68
	JSR S_EF98	; find free block in BAM
	PLA
	STA zp68	; get step width back
	LDA #$00
	JSR S_D61B	; buffer pointer to zero
	LDA zp79
	JSR S_D10D	; track number in buffer
	LDA zp7A
	JSR S_D10D	; sector number in buffer
	JSR S_D1D7	; write block to disk
	JSR S_D6EC	; and verify
	LDA #$00
	JSR S_D61B	; buffer pointer to zero
B_D60E	JSR S_D10D	; fill buffer with zeroes
	BNE B_D60E
	JSR S_D10D	; zero as following track
	LDA #$FF
	JMP S_D10D	; $FF as number of bytes
	;
	; Set buffer pointer
	;
S_D61B	STA zp6E	; save pointer
	JSR S_E0CE	; get buffer number
	ASL A		; times 2
	TAX
	LDA zp9B,X	; buffer pointer hi
	STA zp8D+1
	LDA zp6E
	STA zp9A,X	; buffer pointer lo, new value
	STA zp8D
	RTS
;$D62D  -------- Close internal channel
L_D62D	LDA #$11	; 17
	STA zp7C
	JSR L_D37D	; close channel
	LDA #$12	; 18
	STA zp7C
	JMP L_D37D	; close channel
	;
	; Set buffer pointer
	;
S_D63B	JSR S_E0CE	; get buffer number
L_D63E	ASL A
	TAX
	LDA zp9B,X	; buffer pointer hi
	STA zp8D+1
	LDA zp9A,X	; buffer pointer lo
	STA zp8D
	RTS

;$D649  -------- Get byte from buffer

S_D649	STA zp70	; pointer lo
	JSR S_E0CE	; get buffer number
	TAX
	LDA V_F123,X	; hi-byte buffer address
	STA zp70+1	; pointer hi
	LDY #$00
	LDA (zp70),Y	; get byte from buffer
	RTS

;$D659  -------- Check track and sector numbers

L_D659	LDA V_025B,X	; command code for disk controller
	AND #$01	; drive number
	ORA V_024D	; plus command code
S_D661	PHA		; save
	STX zp98	; buffer number
	TXA
	ASL A		; times 2
	TAX
	LDA zp09,X	; sector
	STA V_024D	; save
	LDA zp08,X	; track
	BEQ B_D69B	; 66, 'illegal track or sector'
	CMP V_F11A	; 36, highest track number + 1
	BCS B_D69B	; 66, 'illegal track or sector'
	TAX
	PLA		; command code
	PHA
	AND #$F0
	CMP #$90	; code for writing?
	BNE B_D6CB	; no
	PLA
	PHA
	LSR A
	BCS B_D687
	LDA zp5D
	BCC B_D689
B_D687	LDA zp5E
B_D689	BEQ B_D690
	CMP V_F118	; 'A', format marker
	BNE L_D6C3	; 73, 'cbm dos v2.6 tdisk'
B_D690	TXA		; track number
	JSR S_F0B6	; get maximum sector number
	CMP V_024D	; compare with sector number
	BEQ B_D69B	; equal, then error
	BCS B_D6CB	; smaller?
B_D69B	JSR S_D6A3	; get track and sector number
B_D69E	LDA #$66
	JMP S_E781	; 66, 'illegal track or sector'
	;
	; Get track and sector numbers for current job
	;
S_D6A3	LDA zp98	; buffer number
	ASL A		; *2
	TAX		; as index
	LDA zp08,X
	STA zp79	; track
	LDA zp09,X
	STA zp7A	; sector
	RTS

;$D6B0  -------- Check for valid track and sector numbers

S_D6B0	LDA zp79	; track
	BEQ B_D69E	; zero, then error
	CMP V_F11A	; 36, maximum track number + 1
	BCS B_D69E	; 66, 'illegal track and sector number'
	JSR S_F0B6	; get maximum sector number
	CMP zp7A	; sector
	BEQ B_D69E
	BCC B_D69E	; error
	RTS

;$D6C3  -------- DOS mismatch error

L_D6C3	JSR S_D6A3	; get track and sector number
	LDA #$73
	JMP S_E781	; 73, 'cbm dos v2.6 tdisk'
	;
B_D6CB	LDX zp98	; buffer number
	PLA
	STA V_024D	; command code for disk controller
	STA V_025B,X	; write in table
	STA zp02,X	; and in command register
	JMP S_D819
	;
	; Read block
	;
L_D6D9	LDA #$80	; code for read
	BNE B_D6DF	; always jump
	; Write block
L_D6DD	LDA #$90	; code for write
B_D6DF	ORA zp78	; drive number
	LDX zp98	; buffer number
S_D6E3	STA V_024D
L_D6E6	LDA V_024D	; command code
	JSR S_D661	; check track and sector
	; Verify execution
S_D6EC	JSR S_D6F9	; verify execution
	BCS S_D6EC	; wait for end
	PHA
	LDA #$00
	STA V_0298	; erase error flag
	PLA
	RTS
;$D6F9  --------
S_D6F9	LDA zp02,X	; command code (bit 7) still in register?
	CMP #$02	; yes
	BCC B_D713	; error-free execution
	CMP #$08	; 8?
	BEQ B_D70B	; write protect
	CMP #$0B	; 11
	BEQ B_D70B	; ID mismatch
	CMP #$0F	; 15
	BNE B_D715
B_D70B	BIT V_0298
	BMI B_D713
	JMP B_D78A	; create error message
	;
B_D713	CLC		; execution ended
	RTS

;$D715  -------- Additional attempts for read errors

B_D715	TYA
	PHA
	LDA zp78	; drive number
	PHA
	LDA V_025B,X
	AND #$01	; drive number
	STA zp78
	JSR L_F3F7	; set LED flag
	JSR S_D7F0	; read attempt
	CMP #$02
	BCS B_D72E	; not ok?
	JMP L_D7B7	; done
	;
B_D72E	LDA V_025B,X	; command code
	AND #$F0	; isolate
	PHA
	CMP #$90	; code for write
	BNE B_D73F	; no
	LDA zp78	; drive number
	ORA #$B8
	STA V_025B,X
B_D73F	BIT zp69
	BVS B_D77C
	LDA #$00
	STA V_0299	; counter for searches next to track
	STA V_029A
B_D74B	LDY V_0299	; counter
	LDA V_029A
	SEC
	SBC V_F11C + 2,Y	; constants for read attempts
	STA V_029A
	LDA V_F11C + 2,Y
	JSR S_D7C5	; position head next to track
	INC V_0299	; increment counter
	JSR S_D7F0	; read attempt
	CMP #$02	; return message
	BCC B_D770	; smaller than 2, ok?
	LDY V_0299	; load counter
	LDA V_F11C + 2,Y	; get constants
	BNE B_D74B	; not yet zero (table end)?
B_D770	LDA V_029A
	JSR S_D7C5	; position head
	LDA zp02,X
	CMP #$02	; return message
	BCC B_D7A6	; ok?
B_D77C	BIT zp69
	BPL B_D78F
B_D780	PLA		; command code
	CMP #$90	; for writing?
	BNE B_D78A	; no
	ORA zp78	; drive number
	STA V_025B,X	; command code in table
B_D78A	LDA zp02,X	; return message
	JSR L_E746	; set error message
B_D78F	PLA
	BIT V_0298
	BMI L_D7B7
	PHA
	LDA #$C0	; command code for head positioning
	ORA zp78	; drive number
	STA zp02,X	; in command register
	JSR S_D819	; wait for execution
	JSR S_D7F0	; attempt command execution again
	CMP #$02	; return message
	BCS B_D780	; incorrect?
B_D7A6	PLA
	CMP #$90	; command code for writing
	BNE L_D7B7	; no
	ORA zp78	; drive number
	STA V_025B,X	; in table
	JSR S_D7F0	; attempt execution again
	CMP #$02	; return message
	BCS B_D78A	; error?
L_D7B7	PLA
	STA zp78	; get drive number back
	PLA
	TAY
	LDA zp02,X	; error code
	PHA
	JSR S_F3F0
	PLA
	CLC		; end-of-execution flag
	RTS

;$D7C5  -------- Move head by half a track

S_D7C5	CMP #$00
	BEQ B_D7E1
	BMI B_D7D7
B_D7CB	LDY #$01
	JSR S_D7E2	; transmit data for head position
	SEC
	SBC #$01
	BNE B_D7CB
	BEQ B_D7E1
B_D7D7	LDY #$FF
	JSR S_D7E2	; transmit data for head position
	CLC
	ADC #$01
	BNE B_D7D7
B_D7E1	RTS
;$D7E2  -------- Move head one track in or out
S_D7E2	PHA
	TYA
	STA zp54
B_D7E6	CMP zp54	; wait for return message from...
	BEQ B_D7E6
	LDA #$00	; ...disk controller
	STA zp54
	PLA
	RTS

;$D7F0  -------- Attempt command execution multiple times

S_D7F0	LDA zp69	; maximum number of repetitions
	AND #$3F
	TAY
B_D7F5	LDA V_025B,X	; command
	STA zp02,X	; transmit to disk controller
	JSR S_D819	; wait for execution
	CMP #$02	; ok?
	BCC B_D804	; yes
	DEY		; decrement counter
	BNE B_D7F5	; attempt again
B_D804	RTS

;$D805  -------- Transmit param to disk controller

S_D805	JSR S_E0CE	; get buffer number
	;
S_D808	ASL A		; track number
	TAY
	LDA zp79	; track number
	STA $0008,Y	; transmit
	LDA zp7A	; sector number
	STA $0009,Y	; transmit
	LDA zp78	; drive number
	ASL A		; times 2
	TAX
	RTS
;$D819  --------
S_D819	LDA zp02,X	; wait for execution
	BMI S_D819
	RTS

;$D81E  -------- Enter file in dir

S_D81E	LDA zp7C	; secondary address
	PHA
	LDA zp7B	; channel number
	PHA
	LDA zp7A	; sector number
	PHA
	LDA zp79	; track number
	PHA		; save
	LDA #$11	; 17
	STA zp7C	; as secondary address
	JSR S_DF76	; get track and sector number
	LDA V_024A	; file type
	PHA		; save
	LDA zpE3	; drive number
	AND #$01
	STA zp78	; set
	LDX zp98	; buffer number
	EOR V_025B,X
	LSR A
	BCC B_D84F	; equal drive number?
	LDX #$01
	STX V_0292	; pointer in directory
	JSR S_C691	; load dir and find first entry
	BEQ B_D86A	; not found?
	BNE B_D877	; found?
B_D84F	LDA V_0291	; sector number in directory
	BEQ B_D860	; equal zero?
	CMP zp7A	; equal sector number?
	BEQ B_D877	; yes
	STA zp7A	; save sector number
	JSR S_D5B3	; read block
	JMP B_D877
	;
B_D860	LDA #$01
	STA V_0292	; pointer to one
	JSR S_C6FC	; find next entry in directory
	BNE B_D877	; found?
B_D86A	JSR S_D5E0	; write directory block
	LDA zp7A	; sector number
	STA V_0291
	LDA #$02
	STA V_0292	; pointer to 2
B_D877	LDA V_0292
	JSR S_D61B	; set buffer pointer
	PLA
	STA V_024A	; file type
	CMP #$04	; rel-file?
	BNE B_D887	; no
	ORA #$80	; set bit 7
B_D887	JSR S_D10D	; and write in buffer
	PLA
	STA V_0280	; following track
	JSR S_D10D	; in buffer
	PLA
	STA V_0285	; following sector
	JSR S_D10D	; in buffer
	JSR S_E0CE	; get buffer number
	TAY
	LDA V_027A	; pointer to drive number
	TAX
	LDA #$10	; 16, length of filename
	JSR S_C74F	; write filename in buffer
	LDY #$10
	LDA #$00
B_D8A9	STA (zp8D),Y	; fill with zeroes at position 16
	INY
	CPY #$1B	; position 27 already?
	BCC B_D8A9	; no
	LDA V_024A	; file type
	CMP #$04	; rel-file?
	BNE B_D8CA	; no
	LDY #$10
	LDA V_0259	; track
	STA (zp8D),Y
	INY
	LDA V_025A	; and sector
	STA (zp8D),Y	; the side-sectors in directory entry
	INY
	LDA V_0258	; record length
	STA (zp8D),Y	; in directory
B_D8CA	JSR S_D5B7	; write block
	PLA
	STA zp7B	; channel number
	TAX
	PLA
	STA zp7C	; secondary address
	LDA V_0291
	STA zpD9
	STA V_0260,X
	LDA V_0292
	STA zpDE
	STA V_0266,X
	LDA V_024A	; file type
	STA zpE8
	LDA zp78	; drive number
	STA zpE3
	RTS

;$D8EE  -------- OPEN command, secondary addr 15

L_D8EE	LDA zp7C	; secondary address
	STA V_024C
	JSR S_C39D	; get line length, erase flags
	STX V_022A
	LDX V_0200	; first character from buffer
	LDA V_024C	; secondary address
	BNE B_D92A	; not equal 0 (LOAD)?
	; Check '*' Last file
	CPX #$2A	; '*'
	BNE B_D92A
	LDA zp77	; last track number
	BEQ B_D953
	STA zp79	; track number
	LDA V_026E	; last drive number
	STA zp78	; drive number
	STA zpE3
	LDA #$02
	STA zpE8	; set data type to program
	LDA V_026F	; last sector number
	STA zp7A	; sector
	JSR S_DD7D	; allocate buffer, read block
	LDA #$04	; file type
	ORA zp78	; drive number
L_D922	LDX zp7B	; channel number
	STA $00ED,Y	; set flag
	JMP L_C27E	; done
	;
	; Check '$' Directory
	;
B_D92A	CPX #$24	; '$'
	BNE B_D94C	; no
	LDA V_024C	; secondary address
	BNE B_D936	; not equal to zero?
	JMP L_DB8C	; OPEN $
	;
B_D936	JSR S_C2BB	; analyze line to end
	LDA V_F0C3	; 18, directory track
	STA zp79	; track
	LDA #$00
	STA zp7A	; sector 0
	JSR S_DD7D	; allocate buffer, read block
	LDA zp78	; drive number
	ORA #$02
	JMP L_D922	; continue as above
	;
	; Check '#' direct channel
	;
B_D94C	CPX #$23	; "#"
	BNE B_D962
	JMP L_CC76	; open direct access file
	;
B_D953	LDA #$02
	STA V_0296	; file type program
	LDA #$00
	STA zp78
	STA V_028E	; drive 0
	JSR S_D15E	; load BAM
B_D962	JSR S_C2CF	; analyze line
	BNE B_D96B	; colon found?
	LDX #$00
	BEQ B_D977
B_D96B	TXA		; comma found?
	BEQ B_D973	; no
	LDA #$30
	JMP L_C2B2	; 30, 'syntax error'
	;
B_D973	DEY
	BEQ B_D977
	DEY
B_D977	STY V_027A	; pointer to drive number
	LDA #$8D	; shift CR
	JSR S_C352	; check command line to end ???
	INX
	STX V_0278	; comma counter in file name
	JSR S_C3FC	; get drive number
	JSR S_C4B7	; check drive number
	JSR S_C582	; find file entry in directory
	LDX #$00	; default values
	STX V_0258	; record length
	STX V_0297
	STX V_024A	; file type
	INX
	CPX V_0277	; comma before equal sign?
	BCS B_D9AD	; no
	JSR S_DB40	; get file type and control mode
	INX
	CPX V_0277	; additional comma?
	BCS B_D9AD	; no
	CPY #$04
	BEQ B_D9E8
	JSR S_DB40	; get file type and control method
B_D9AD	LDX V_024C
	STX zp7C	; secondary address
	CPX #$02	; greater than 2?
	BCS B_D9C8	; yes
	STX V_0297	; 0 or 1 (LOAD or SAVE)
	LDA #$40
	STA V_02F9
	LDA V_024A	; file type
	BNE B_D9DE	; not deleted
	LDA #$02	; PRG
	STA V_024A	; as file type
B_D9C8	LDA V_024A
	BNE B_D9DE
	LDA zpE8
	AND #$07	; get file type and command line
	STA V_024A
	LDA V_0280	; track number
	BNE B_D9DE	; not equal zero?
	LDA #$01
	STA V_024A	; file type sequential
B_D9DE	LDA V_0297	; control method
	CMP #$01	; 'W'
	BEQ B_D9FD	; yes
	JMP L_DA77
	;
B_D9E8	LDY V_027A,X	; pointer behind second comma
	LDA V_0200,Y	; get value
	STA V_0258	; record length
	LDA V_0280	; track number
	BNE B_D9AD
	LDA #$01	; 'W'
	STA V_0297	; as second method
	BNE B_D9AD
B_D9FD	LDA zpE8	; file type
	AND #$80	; isolate wildcard flag
	TAX
	BNE B_DA18	; wildcard in name
	LDA #$20
	BIT zpE8	; was file closed?
	BEQ B_DA10	; yes
	JSR S_C997	; byte 0 in buffer and write block
	JMP L_DB1A
	;
B_DA10	LDA V_0280	; track number of the first block
	BNE B_DA18	; already existing
	JMP L_DB1A
	;
B_DA18	LDA V_0200	; first character from input buffer
	CMP #$40	; '@'?
	BEQ B_DA2C	; yes
	TXA
	BNE B_DA27	; wildcard set?
	LDA #$63
	JMP L_C2B2	; 63, 'file exists'
	;
B_DA27	LDA #$33
	JMP L_C2B2	; 33, 'syntax error'
	;
	; Open a file with overwriting (@)
	;
B_DA2C	LDA zpE8	; file type
	AND #$07	; isolate
	CMP V_024A
	BNE B_DA9C	; file type different?
	CMP #$04	; rel-file?
	BEQ B_DA9C	; 64, 'file type mismatch'
	JSR L_DE15
	LDA zp7B
	STA V_0270	; save channel number
	LDA #$11
	STA zp7C
	JSR S_D1FB	; open read channel
	LDA V_0294
	JSR S_D61B	; set buffer pointer for directory
	LDY #$00
	LDA (zp8D),Y	; file type
	ORA #$20	; set bit 5, open file
	STA (zp8D),Y
	LDY #$1A
	LDA zp79	; track
	STA (zp8D),Y
	INY
	LDA zp7A	; and sector
	STA (zp8D),Y	; for open with at-sign
	LDX V_0270	; channel number
	LDA zpD9
	STA V_0260,X	; pointer to directory block
	LDA zpDE
	STA V_0266,X
	JSR S_DF76	; get track and sector number
	JSR S_D5B7	; write block
	JMP B_DB26	; prepare track, sector, and drive number
	;
L_DA77	LDA V_0280	; first track number
	BNE B_DA81	; file not erased?
	LDA #$62
	JMP L_C2B2	; 62, 'file not found'
	;
B_DA81	LDA V_0297	; control mode
	CMP #$03	; 'M'
	BEQ B_DA93	; yes, then no test of unclosed file
	LDA #$20	; bit 5
	BIT zpE8	; test in file type
	BEQ B_DA93	; not set, ok
	LDA #$60
	JMP L_C2B2
	;
B_DA93	LDA zpE8
	AND #$07	; isolate file type
	CMP V_024A
	BEQ B_DAA1
B_DA9C	LDA #$64
	JMP L_C2B2	; 64, 'file type mismatch'
	;
B_DAA1	LDY #$00
	STY V_0279
	LDX V_0297	; control mode
	CPX #$02	; 'A', append
	BNE B_DAC7	; no
	CMP #$04	; rel-file?
	BEQ B_DA9C
	LDA (zp8D),Y
	AND #$4F	; "O"
	STA (zp8D),Y
	LDA zp7C
	PHA
	LDA #$11
	STA zp7C	; channel 17
	JSR S_DF76	; get track and sector number
	JSR S_D5B7	; write block
	PLA
	STA zp7C	; get channel number back
B_DAC7	JSR S_DAD7
	LDA V_0297	; control mode
	CMP #$02
	BNE B_DB26
	JSR S_DB61
	JMP L_C27E	; done
	;
	; Open file for reading
	;
S_DAD7	LDY #$13
	LDA (zp8D),Y	; track
	STA V_0259
	INY
	LDA (zp8D),Y	; record length
	STA V_025A
	INY
	LDA (zp8D),Y	; record length
	LDX V_0258	; last record len
	STA V_0258
	TXA
	BEQ B_DAFA
	CMP V_0258
	BEQ B_DAFA
	LDA #$50	; "P"
	JSR L_C2B2	; 50, 'record not present'
B_DAFA	LDX V_0279
	LDA V_0280,X	; track
	STA zp79
	LDA V_0285,X	; sector
	STA zp7A
	JSR S_DD7D
	LDY zp7B
	LDX V_0279
	LDA zpD9,X
	STA V_0260,Y
	LDA zpDE,X
	STA V_0266,Y
	RTS

;$DB1A  -------- Open file for writing

L_DB1A	LDA zpE3	; drive number
	AND #$01
	STA zp78
	JSR L_DE15
	JSR S_D81E
B_DB26	LDA zp7C	; channel number
	CMP #$02
	BCS B_DB3D
	JSR S_DF79
	LDA zp79
	STA zp77
	LDA zp78
	STA V_026E
	LDA zp7A
	STA V_026F
B_DB3D	JMP L_C283
	;
	; Check file type and control mode
	;
S_DB40	LDY V_027A,X	; pointer in command line
	LDA V_0200,Y	; get characters from line
	LDY #$04
B_DB48	DEY
	BMI B_DB53
	CMP V_F0F3,Y	; control modes 'R', 'W', 'A', 'M'
	BNE B_DB48
	STY V_0297	; save
B_DB53	LDY #$05
B_DB55	DEY
	BMI B_DB60
	CMP V_F0F6 + 1,Y	; file types 'D','S','P','U','L'
	BNE B_DB55
	STY V_024A	; save
B_DB60	RTS

;$DB61  -------- Preparation for append

S_DB61	JSR S_CB2E	; open channel to read, get byte
	LDA #$80
	JSR S_DEE1	; last byte?
	BEQ S_DB61	; no
	JSR S_DFD0	; get track and sector number
	LDX zp7A	; sector number
	INX
	TXA
	BNE B_DB79	; not $FF?
	JSR B_D2F9	; close buffer, write block
	LDA #$02
B_DB79	JSR S_D61B	; buffer pointer to 2
	LDX zp7B	; channel number
	LDA #$01
	STA zpF3,X	; set flag for WRITE
	LDA #$80
	ORA zp7B
	LDX zp7C
	STA V_022B,X	; channel number in table
	RTS

;$DB8C  -------- Open directory

L_DB8C	LDA #$0D	; command number 12
	STA V_022A
	LDA #$00
	LDX V_0274
	DEX
	BEQ B_DBA4
	DEX
	BNE B_DBBD
	LDA L_0201	; second character
	JSR S_C4A5	; get drive number
	BMI B_DBBD	; not a plain number?
B_DBA4	STA zpE3
	INC V_0277
	INC V_0278
	INC V_027A
	LDA #$80
	STA zpE8	; set wildcard flag
	LDA #$2A	; '*'
	STA V_0200	; as file name in command buffer
	STA L_0201
	BNE B_DBD5	; absolute jump
B_DBBD	JSR S_C2CF	; test input line to ":"
	BNE B_DBC7	; found?
	JSR S_C3C6	; erase flags
	LDY #$03
B_DBC7	DEY
	DEY
	STY V_027A	; pointer to drive number in command
	JSR S_C2EA	; analyze line
	JSR S_C480	; ascertain file type
	JSR S_C40A	; get drive number
B_DBD5	JSR S_C4B7	; initialize drive if necessary
	JSR S_C898	; prepare disk title
	JSR S_C582	; load directory
	JSR S_EB0B	; create and prepare directory
	JSR S_D247	; get byte from buffer
	LDX zp7B	; channel number
	STA V_023E,X	; byte in output register
	LDA zp78	; drive number
	STA V_028E	; save as last drive number
	ORA #$04
	STA zpED,X	; PRG-flag
	LDA #$00
	STA zpA4	; set pointer back in input buffer
	RTS

;$DBF7  -------- Close routine

S_DBF7	LDA #$00
	STA V_02F9
	LDA zp7C	; secondary address
	BNE B_DC0B	; not zero?
	LDA #$00	; secondary address 0, LOAD
	STA V_0254
	JSR L_D37D	; close channel
B_DC08	JMP L_D62D	; close internal channels 17 & 18
	;
B_DC0B	CMP #$0F	; 15
	BEQ B_DC23	; yes, close all channels
	JSR L_DC39	; close file
	LDA zp7C	; secondary address
	CMP #$02	; smaller than 2?
	BCC B_DC08
	LDA V_026C
	BNE B_DC20
	JMP L_C27E	; termination
	;
B_DC20	JMP L_C297
	;
B_DC23	LDA #$0E	; 14
	STA zp7C	; secondary address
B_DC27	JSR L_DC39	; close file
	DEC zp7C	; next secondary address
	BPL B_DC27
	LDA V_026C
	BNE B_DC36
	JMP L_C27E	; termination
	;
B_DC36	JMP L_C297
	;
	; Close file
	;
L_DC39	LDX zp7C	; secondary address
	LDA V_022B,X	; get channel number
	CMP #$FF	; no channel associated?
	BNE B_DC43
	RTS		; no, then none
;$DC43  --------
B_DC43	AND #$0F	; isolate channel number
	STA zp7B
	JSR S_D235	; check data type
	CMP #$07	; direct access?
	BEQ B_DC5D	; yes
	CMP #$04	; rel-file?
	BEQ B_DC63	; yes
	JSR S_D217	; channel for writing open
	BCS B_DC60	; no file for writing?
	JSR S_DC99	; write last block
	JSR S_DCDC	; write entry in directory and block
B_DC5D	JSR S_ED5F	; write BAM
B_DC60	JMP L_D37D	; close channel
	;
B_DC63	JSR S_DF2C	; get buffer number, write block
	JSR S_CFD4	; change buffer
	JSR S_E306	; get last side-sector
	LDX zp92	; side-sector number
	STX zp72
	INC zp72
	LDA #$00
	STA zp6E+1
	STA zp70
	LDA zp93
	SEC
	SBC #$0E	; minus 14 for pointer
	STA zp70+1
	JSR S_E08C	; calculate block number of file
	LDX zp7B	; channel number
	LDA zp6E+1
	STA zpB6,X	; record number lo
	LDA zp70
	STA zpBC,X	; record number hi
	LDA #$40
	JSR S_DEE1	; bit 6 set?
	BEQ B_DC96	; no
	JSR S_DCDC	; enter in directory
B_DC96	JMP L_D37D	; close channel
	;
	; Write last block
	;
S_DC99	LDX zp7B	; channel number
	LDA zpB6,X	; record number lo
	ORA zpBC,X	; record number hi
	BNE B_DCAD	; not zero?
	JSR S_D63B	; set buffer pointer
	CMP #$02
	BNE B_DCAD	; not 2
	LDA #$0D	; CR
	JSR S_D10D	; in buffer
B_DCAD	JSR S_D63B	; set buffer pointer
	CMP #$02	; now equal to 2?
	BNE B_DCC3	; no
	JSR S_CFD4	; change buffer
	LDX zp7B	; channel number
	LDA zpB6,X	; record number lo
	BNE B_DCBF
	DEC zpBC,X	; decrement block number hi
B_DCBF	DEC zpB6,X	; and block number lo
	LDA #$00
B_DCC3	SEC
	SBC #$01	; set pointer
	PHA
	LDA #$00
	JSR S_D61B	; buffer pointer to zero
	JSR S_D10D	; write zero in buffer
	PLA		; second byte = pointer to end
	JSR S_D10D	; write in buffer
	JSR S_D1D7	; write block to disk
	JSR S_D6EC	; and verify
	JMP S_CFD4	; change buffer
	;
	; Directory entry
	;
S_DCDC	LDX zp7B	; channel number
	STX V_0270	; save
	LDA zp7C	; secondary address
	PHA		; save
	LDA V_0260,X	; sector number in directory
	STA zp7A	; set
	LDA V_0266,X	; pointer in directory
	STA V_0294
	LDA zpED,X
	AND #$01
	STA zp78	; drive number
	LDA V_F0C3	; 18, directory track
	STA zp79	; set
	JSR S_E0CE	; increment buffer number
	PHA
	STA zp98
	JSR S_D5B3	; read directory block
	LDY #$00
	LDA V_F123,X	; buffer address
	STA zp7F+1
	LDA V_0294	; buffer pointer
	STA zp7F
	LDA (zp7F),Y	; file type
	AND #$20	; file closed?
	BEQ B_DD58	; yes
	JSR S_D235	; check file type
	CMP #$04	; rel-file?
	BEQ L_DD60	; yes
	LDA (zp7F),Y
	AND #$8F	; erase bits 4,5, and 6
	STA (zp7F),Y	; in file type
	INY
	LDA (zp7F),Y	; track number
	STA zp79
	STY zp70
	LDY #$1B
	LDA (zp7F),Y	; sector number of the file for
	PHA		; overwriting
	DEY
	LDA (zp7F),Y	; track number for overwriting
	BNE B_DD3D	; set?
	STA zp79	; set track number
	PLA
	STA zp7A	; sector number
	LDA #$67
	JSR S_E781	; 67, 'illegal track or sector'
B_DD3D	PHA
	LDA #$00
	STA (zp7F),Y	; erase track number
	INY
	STA (zp7F),Y	; and sector number of the
	PLA		; substitute file
	LDY zp70
	STA (zp7F),Y
	INY		; set track & sector number of the new file
	LDA (zp7F),Y
	STA zp7A
	PLA
V_DD50	STA (zp7F),Y
	JSR S_C95E	; erase all files
	JMP L_DD60
	;
B_DD58	LDA (zp7F),Y	; get file type
	AND #$0F	; isolate bits 0-3
	ORA #$80	; set bit 7 for closed file
	STA (zp7F),Y
L_DD60	LDX V_0270	; channel number
	LDY #$1C	; block number lo
	LDA zpB6,X	; in directory entry
	STA (zp7F),Y
	INY
	LDA zpBC,X	; and block number hi
	STA (zp7F),Y	; write
	PLA		; buffer number
	TAX
	LDA #$90	; code for 'writing'
	ORA zp78
	JSR S_D6E3	; write block
	PLA
	STA zp7C	; secondary address
	JMP S_D217	; open channel for writing
	;
	; Read block, allocate buffer
	;
S_DD7D	LDA #$01
	JSR S_D338	; find channel and buffer for read
	JSR S_DDED	; set pointer
	LDA V_024A	; file type
	PHA		; save
	ASL A
	ORA zp78	; drive number
	STA zpED,X
	JSR S_D1AB	; read block in buffer
	LDX zp7B	; channel number
	LDA zp79	; track
	BNE B_DD9C	; following track?
	LDA zp7A	; sector
	STA V_0244,X	; as end pointer
B_DD9C	PLA		; file type
	CMP #$04	; rel-file?
	BNE B_DDE0	; no
	LDY zp7C	; secondary address
	LDA V_022B,Y	; channel number
	ORA #$40
	STA V_022B,Y	; set flag for READ and WRITE
	LDA V_0258	; record length
	STA zpC8,X
	JSR S_D3E4	; find buffer for side-sector
	BPL B_DDB8	; found?
	JMP L_D365	; 70, 'no channel'
	;
B_DDB8	LDX zp7B	; channel number
	STA zpCE,X
	LDY V_0259
	STY zp79	; track for side-sector
	LDY V_025A
	STY zp7A	; sector for side-sector
	JSR S_D808	; transmit parameters to disk controller
	JSR S_DFAE	; read block
	JSR S_D6EC	; and verify
L_DDCF	LDX zp7B	; channel number
	LDA #$02
	STA zpC2,X	; pointer for writing
	LDA #$00
	JSR S_D61B	; buffer pointer to zero
	JSR S_E28E	; find next record
	JMP S_DF79	; get track and sector number
	;
B_DDE0	JSR S_D271	; get byte from buffer
	LDX zp7B	; channel number
	STA V_023E,X	; byte in output register
	LDA #$88	; set flag for READ
	STA zpF3,X
	RTS

;$DDED  -------- Reset pointer

S_DDED	LDX zp7B	; channel number
	LDA zpA8,X	; buffer number
	ASL A		; times 2
	BMI B_DDFA
	TAY
	LDA #$02
	STA $009A,Y	; buffer pointer lo
B_DDFA	LDA zpAF,X
	ORA #$80	; set bit 7
	STA zpAF,X
	ASL A
	BMI B_DE09
	TAY
	LDA #$02
	STA $009A,Y	; buffer pointer lo
B_DE09	LDA #$00
	STA zpB6,X	; block number lo
	STA zpBC,X	; block number hi
	LDA #$00
	STA V_0244,X	; end pointer
	RTS

;$DE15  -------- Construct a new block

L_DE15	JSR S_F014	; find free sector in BAM
	LDA #$01
	JSR S_D335	; open channel
	JSR S_D805	; transmit parameter to disk controller
	JSR S_DDED	; reset pointer
	LDX zp7B	; channel number
	LDA V_024A	; file type
	PHA
	ASL A
	ORA zp78	; drive number
	STA zpED,X	; save as flag
	PLA
	CMP #$04	; rel-file?
	BEQ B_DE38	; yes
	LDA #$01
	STA zpF3,X	; set WRITE flag
	RTS
;$DE38  --------
B_DE38	LDY zp7C	; secondary address
	LDA V_022B,Y	; channel number in table
	AND #$3F	; erase the top two bits
	ORA #$40	; set bit 6
	STA V_022B,Y	; READ and WRITE flag
	LDA V_0258	; record length
	STA zpC8,X	; in table
	JSR S_D3E4	; find buffer
	BPL B_DE51	; found?
	JMP L_D365	; 70, 'no channel'
	;
B_DE51	LDX zp7B	; channel number
	STA zpCE,X	; buffer number for side-sector
	JSR S_DFFC	; erase buffer
	JSR S_EF89	; find free block in BAM
	LDA zp79	; track
	STA V_0259	; for side-sector
	LDA zp7A	; sector
	STA V_025A	; for side-sector
	LDX zp7B	; channel number
	LDA zpCE,X	; buffer number
	JSR S_D808	; transmit parameter to disk controller
	LDA #$00
	JSR S_E024	; buffer pointer to zero
	LDA #$00
	JSR S_DEC8
	LDA #$11	; 17
	JSR S_DEC8	; as end pointer in buffer
	LDA #$00	; zero
	JSR S_DEC8	; as side-sector number in buffer
	LDA V_0258	; record length
	JSR S_DEC8	; in buffer
	LDA zp79	; track number of this block
	JSR S_DEC8	; in buffer
	LDA zp7A	; sector number
	JSR S_DEC8	; in buffer
	LDA #$10	; 16
	JSR S_E024	; buffer pointer to 16
	JSR S_DF79	; get track and sector number
	LDA zp79	; track number of the first data block
	JSR S_DEC8	; in buffer
	LDA zp7A	; sector number of the first data block
	JSR S_DEC8	; in buffer
	JSR S_DFA7	; write block to disk
	JSR S_D6EC	; and check
	LDA #$02
	JSR S_D61B	; buffer pointer to 2
	LDX zp7B	; channel number
	SEC
	LDA #$00
	SBC zpC8,X	; record length
	STA zpC2,X	; pointer for writing
	JSR S_E41D	; erase buffer
	JSR S_DF54	; write link bytes in buffer
	JSR S_DF99	; write block to disk
	JSR S_D6EC	; and check
	JSR S_ED5F	; write BAM
	JMP L_DDCF	; and done
	;
	; Write byte in side-sector block
	;
S_DEC8	PHA		; save byte
	LDX zp7B	; channel number
	LDA zpCE,X	; buffer number of the side-sector
	JMP B_D119	; write byte in buffer
	;
	; Manipulate flags
	;
	BCC B_DED8
L_DED2	LDX zp7B	; channel number
	ORA zpED,X	; set flag
	BNE B_DEDE
B_DED8	LDX zp7B	; channel number
	EOR #$FF
	AND zpED,X	; erase flag
B_DEDE	STA zpED,X
	RTS
;$DEE1  --------
S_DEE1	LDX zp7B	; channel number
	AND zpED,X	; test flag
	RTS

;$DEE6  -------- Verify command code for writing

S_DEE6	JSR S_E0CE	; get buffer number
	TAX
	LDA V_025B,X
	AND #$F0	; isolate command code
	CMP #$90	; code for writing?
	RTS
;$DEF2  --------
S_DEF2	LDX #$00
B_DEF4	STX zp70	; counter for secondary address
	LDA V_022B,X	; get channel number from table
	CMP #$FF
	BNE B_DF05	; file open?
B_DEFD	LDX zp70
	INX		; increment counter
	CPX #$10	; smaller than 16?
	BCC B_DEF4
	RTS
;$DF05  --------
B_DF05	STX zp70
	AND #$3F	; isolate channel number
	TAY
	LDA $00ED,Y
	AND #$01	; isolate drive number
	STA zp6E+1
	LDX V_0253
	LDA zpE3,X
	AND #$01	; isolate drive number
	CMP zp6E+1	; same drive?
	BNE B_DEFD	; no
	LDA V_0260,Y	; sector number in directory
	CMP zpD9,X	; same as file?
	BNE B_DEFD	; no
	LDA V_0266,Y
	CMP zpDE,X	; pointer same?
	BNE B_DEFD	; no
	CLC
	RTS

;$DF2C  -------- Write a block of a REL file

S_DF2C	JSR S_E0D9	; get buffer number
	BVC B_DF37	; no rel-file?
	JSR S_DF99	; write block
	JSR S_D6EC	; and verify
B_DF37	RTS

;$DF38  -------- Write bytes for following track

S_DF38	JSR S_DF66	; set buffer pointer
	LDA zp79	; track number
	STA (zp8D),Y	; in buffer
	INY
	LDA zp7A	; sector number
	STA (zp8D),Y	; in buffer
	JMP S_E240	; set rel-flag
	;
	; Get following track and sector numbers
	;
S_DF47	JSR S_DF66	; set buffer pointer
	LDA (zp8D),Y	; following track number
	STA zp79
	INY
	LDA (zp8D),Y	; and get sector number
	STA zp7A
	RTS

;$DF54  -------- Following track for last block

S_DF54	JSR S_DF66	; set buffer pointer
	LDA #$00	; zero
	STA (zp8D),Y	; as track number
	INY
	LDX zp7B	; channel number
	LDA zpC2,X	; pointer in block
	TAX
	DEX		; minus 1
	TXA
	STA (zp8D),Y	; as pointer in block
	RTS
;$DF66  -------- buffer pointer to zero
S_DF66	JSR S_E0CE	; get buffer number
	ASL A		; times 2
	TAX
	LDA zp9B,X	; buffer pointer hi
	STA zp8D+1
	LDA #$00
	STA zp8D	; buffer pointer lo
	LDY #$00
	RTS

;$DF76  -------- Get track and sector

S_DF76	JSR S_D1FB	; get channel number
S_DF79	JSR S_E0CE	; get buffer number
	STA zp98	; save
	ASL A		; times 2
	TAY
	LDA $0008,Y	; get track
	STA zp79
	LDA $0009,Y	; and sector number from disk controller
	STA zp7A
	RTS

;$DF8B  -------- Write

S_DF8B	LDA #$90	; command code for writing
	STA V_024D
	BNE B_DFBA	; jump always

;       --------- Read

S_DF92	LDA #$80	; command code for reading
	STA V_024D
	BNE B_DFBA	; jump always
	; Write
S_DF99	LDA #$90	; command code for writing
	STA V_024D
	BNE B_DFC6	; jump always
	; Read
	LDA #$80	; command code for reading
	STA V_024D
	BNE B_DFC6	; jump always
	; Write
S_DFA7	LDA #$90	; command code for writing
	STA V_024D
	BNE B_DFB0	; jump always
	; Read
S_DFAE	LDA #$80	; command code for reading
B_DFB0	STA V_024D
	LDX zp7B	; channel number
	LDA zpCE,X	; side-sector buffer number
	TAX
	BPL B_DFCD	; buffer associated?
B_DFBA	JSR S_D805	; generate header for disk controller
	JSR S_E0CE	; get buffer number
	TAX
	LDA zp78	; drive number
	STA V_025B,X
B_DFC6	JSR S_E250	; buffer number
	JSR S_E0CE	; get buffer number
	TAX
B_DFCD	JMP L_D659	; write block
	;
	; Get following track and sector from buffer
	;
S_DFD0	LDA #$00
	JSR S_D61B	; buffer pointer to zero
	JSR S_D247	; get byte
	STA zp79	; save as track
	JSR S_D247	; get byte
	STA zp7A	; as sector
	RTS

;$DFE0  -------- Copy buffer contents

S_DFE0	PHA
	LDA #$00
	STA zp6E
	STA zp70
	LDA V_F123,Y	; buffer address Y, hi
	STA zp6E+1
	LDA V_F123,X	; buffer address X, lo
	STA zp70+1
	PLA
	TAY
	DEY
B_DFF4	LDA (zp6E),Y
	STA (zp70),Y
	DEY
	BPL B_DFF4
	RTS

;$DFFC  -------- Erase buffer Y

S_DFFC	TAY		; buffer number
	LDA V_F123,Y	; get hi-address
	STA zp6E+1
	LDA #$00	; lo-address
	STA zp6E
	TAY
B_E007	STA (zp6E),Y	; erase buffer
	INY
	BNE B_E007
	RTS

;$E00D  -------- Get side-sector number

S_E00D	LDA #$00
	JSR S_E017	; buffer pointer to zero
	LDY #$02
	LDA (zp8D),Y	; byte 2 contains the side-sector number
	RTS
;$E017  -------- Set buffer pointer to side-sector
S_E017	STA zp8D	; printer lo
	LDX zp7B	; channel number
	LDA zpCE,X	; buffer number
	TAX
	LDA V_F123,X	; buffer address hi
	STA zp8D+1	; set
	RTS
;$E024  -------- Buffer pointer for side-sector
S_E024	PHA		; pointer in side-sector
	JSR S_E017	; set buffer pointer
	PHA
	TXA		; buffer number
	ASL A		; times 2
	TAX
	PLA
	STA zp9B,X	; buffer pointer hi
	PLA
	STA zp9A,X	; buffer pointer lo
	RTS

;$E033  -------- Get side sector and buffer pointer

S_E033	JSR S_E0A1	; is side-sector in buffer?
	BMI B_E046	; no
	BVC B_E04D	; ok
	LDX zp7B	; channel number
	LDA zpCE,X	; buffer number
	JSR S_E056	; read side-sector
	JSR S_E0A1	; and check if in buffer
	BPL B_E04D	; yes?
B_E046	JSR S_E306	; get last side-sector
	BIT V_F10E + 1	; set V bit
	RTS
;$E04D  --------
B_E04D	LDA zp93	; side-sector and pointer
	JSR S_E024	; set pointer in side-sector
	BIT V_F10E	; erase V bit
	RTS

;$E056  -------- Read side-sector

S_E056	STA zp98	; buffer number
	LDA #$80	; command code for reading
	BNE B_E060
	; Write side-sector
	STA zp98	; buffer number
	LDA #$90	; command code for writing
B_E060	PHA
	LDA zpED,X
	AND #$01	; isolate drive number
	STA zp78
	PLA
	ORA zp78	; command code plus drive number
	STA V_024D	; save
	LDA (zp8D),Y	; track number
	STA zp79
	INY
	LDA (zp8D),Y	; sector number
	STA zp7A
	LDA zp98	; buffer number
	JSR S_D808	; transmit parameter to disk controller
	LDX zp98	; buffer number
	JMP L_D6E6	; transmit command to disk controller
	;
	; Set buffer pointer in side-sector
	;
S_E080	LDX zp7B	; channel number
	LDA zpCE,X	; buffer number
	JMP L_D63E	; set buffer pointer
	;
	; Calculate number of blocks in a REL file
	;
B_E087	LDA #$78	; 120 block pointers per side-sector
	JSR S_E097	; add to $6f/$70
S_E08C	DEX		; side-sector number
	BPL B_E087	; next side-sector?
	LDA zp70+1	; pointer value in last block
	LSR A		; divided by 2
	JSR S_E097	; add to previous sum
	LDA zp72	; number of the side-sector block
S_E097	CLC
	ADC zp6E+1
	STA zp6E+1	; add
	BCC B_E0A0
	INC zp70
B_E0A0	RTS

;$E0A1  -------- Verify side-sector in buffer

S_E0A1	JSR S_E00D	; get side-sector number
	CMP zp92	; = number of necessary block?
	BNE B_E0B6	; no
	LDY zp93	; pointer in side-sector
	LDA (zp8D),Y	; track number
	BEQ B_E0B2
	BIT V_F10E	; erase bits
	RTS
;$E0B2  --------
B_E0B2	BIT V_F10E + 2	; set N-bit
	RTS
;$E0B6  --------
B_E0B6	LDA zp92	; side-sector number
	CMP #$06	; 6 or greater?
	BCS B_E0C6	; yes
	ASL A
	TAY
	LDA #$04
	STA zp8D
	LDA (zp8D),Y	; track number
	BNE B_E0CA
B_E0C6	BIT V_F111	; set N and V bits
	RTS
;$E0CA  --------
B_E0CA	BIT V_F10E + 1	; set V bit
	RTS

;$E0CE  -------- Get buffer number

S_E0CE	LDX zp7B	; channel number
	LDA zpA8,X	; buffer number
	BPL B_E0D6
	LDA zpAF,X	; buffer number from second table
B_E0D6	AND #$BF	; erase V bit
	RTS
;$E0D9  --------
S_E0D9	LDX zp7B	; channel number
	STX V_0257	; save
	LDA zpA8,X	; get buffer number
	BPL B_E0EB	; buffer allocated
	TXA
	CLC
	ADC #$07	; increment number by 7
	STA V_0257	; and save
	LDA zpAF,X	; buffer number from table 2
B_E0EB	STA zp6E+1
	AND #$1F	; erase the highest 3 bits
	BIT zp6E+1
	RTS
;$E0F2  --------
S_E0F2	LDX zp7B	; channel number
	LDA zpA8,X	; buffer number
	BMI B_E0FA	; buffer free?
	LDA zpAF,X	; buffer number from table 2
B_E0FA	CMP #$FF	; free?
	RTS
;$E0FD  --------
S_E0FD	LDX zp7B
	ORA #$80
	LDY zpA8,X
	BPL B_E108
	STA zpA8,X
	RTS
;$E108  --------
B_E108	STA zpAF,X
	RTS

;$E10B  -------- Get next record in REL file

S_E10B	LDA #$20
	JSR B_DED8	; erase bit 5
	LDA #$80
	JSR S_DEE1	; test bit 7
	BNE B_E158	; set?
	LDX zp7B	; channel number
	INC zpB6,X	; increment record number
	BNE B_E11F
	INC zpBC,X	; record number hi
B_E11F	LDX zp7B	; channel number
	LDA zpC2,X	; write pointer
	BEQ B_E153	; zero?
	JSR S_D63B	; set buffer pointer
	LDX zp7B	; channel number
	CMP zpC2,X	; buffer pointer smaller than write pointer
	BCC B_E131	; yes
	JSR S_E177	; write block, read next block
B_E131	LDX zp7B	; channel number
	LDA zpC2,X	; write pointer
	JSR S_D61B	; set buffer pointer = write pointer
	LDA (zp9A,X)	; byte from buffer
	STA zp7E	; put in output register
	LDA #$20
	JSR B_DED8	; erase bit 5
	JSR S_E43F	; add record length to write pointer
S_E144	PHA		; and save
	BCC B_E16F	; not yet in last block?
	LDA #$00
	JSR S_D649	; get track number
	BNE B_E16F	; does block exist?
	PLA		; pointer
	CMP #$02	; = 2
	BEQ B_E165	; yes
B_E153	LDA #$80
	JSR L_DED2	; set bit 7
B_E158	JSR S_D23F	; get byte from buffer
	LDA zp9A,X	; buffer pointer
	STA V_0244,Y	; as end pointer
	LDA #$0D	; CR
	STA zp7E	; in output register
	RTS
;$E165  --------
B_E165	JSR S_E170
	LDX zp7B	; channel number
	LDA #$00
	STA zpC2,X	; write pointer to zero
	RTS
;$E16F  --------
B_E16F	PLA
S_E170	LDX zp7B	; channel number
	STA zpC2,X	; set write pointer
	JMP L_E2A9
	;
	; Write block and read next block
	;
S_E177	JSR S_D329	; get drive number
	JSR S_DFD0	; get track and sector number
	JSR S_E0D9	; get bufer number
	BVC B_E198	; no rel-file?
	JSR S_DF99	; write block
	JSR S_CFD4	; change buffer
	LDA #$02
	JSR S_D61B	; buffer pointer to 2
	JSR S_DEE6	; command code for writing?
	BNE B_E1B6	; no
	JSR S_DF92	; read block
	JMP S_D6EC	; and verify
	;
B_E198	JSR S_CFD4	; change buffer
	JSR S_DEE6	; command code for writing?
	BNE B_E1A6	; no
	JSR S_DF92	; read block
	JSR S_D6EC	; and verify
B_E1A6	JSR S_DFD0	; get track and sector number
	LDA zp79	; track
	BEQ B_E1B6	; no following track
	JSR S_CFD4	; change buffer
	JSR S_DF92	; read block
	JSR S_CFD4	; change buffer
B_E1B6	RTS

;$E1B7  -------- Write a byte in a record

S_E1B7	JSR S_E240
	JSR S_E0CE	; get buffer number
	ASL A		; * 2
	TAX		; as index
	LDA zp7E	; data byte
	STA (zp9A,X)	; write in buffer
	LDY zp9A,X	; buffer pointer
	INY		; increment
	BNE B_E1D1	; not equal zero?
	LDY zp7B	; channel number
	LDA $00C2,Y	; write pointer
	BEQ B_E1D9	; equal zero?
	LDY #$02	; buffer pointer to 2
B_E1D1	TYA
	LDY zp7B	; channel number
	CMP $00C2,Y	; buffer pointer = write pointer?
	BNE B_E1DE	; no
B_E1D9	LDA #$20
	JMP L_DED2	; set bit 5
	;
B_E1DE	INC zp9A,X	; increment buffer pointer
	BNE B_E1E5	; not zero?
	JSR S_E177	; else write block, read next one
B_E1E5	RTS

;$E1E6  -------- Write byte in REL file

L_E1E6	LDA #$A0
	JSR S_DEE1	; test bits 6 & 7
	BNE B_E214	; set?
L_E1ED	LDA zp7E	; data byte
	JSR S_E1B7	; write in record
	LDA zp95	; end?
	BEQ B_E203	; yes
	RTS
;$E1F7  --------
B_E1F7	LDA #$20
	JSR S_DEE1	; test bit 5
	BEQ B_E203	; not set
	LDA #$51	; 51, 'overflow in record'
	STA V_026C	; set error flag
B_E203	JSR L_E22E	; fill remainder with zeroes
	JSR S_E28E
	LDA V_026C	; error flag set?
	BEQ B_E211	; no
	JMP L_C2B2	; set error message
	;
B_E211	JMP L_E7FB	; error free execution
	;
B_E214	AND #$80	; bit 7 set?
	BNE B_E21D	; yes
	LDA zp95
	BEQ B_E1F7	; end?
	RTS
;$E21D  --------
B_E21D	LDA zp7E	; data byte
	PHA
	JSR S_E457	; expand side-sector
	PLA
	STA zp7E
	LDA #$80
	JSR B_DED8	; erase bit 7
	JMP L_E1ED	; write byte in file
	;
	; Fill record with 0s
	;
L_E22E	LDA #$20
	JSR S_DEE1	; test bit 5
	BNE B_E23F	; set?
	LDA #$00
	STA zp7E	; zero as data byte
	JSR S_E1B7	; write in record
	JMP L_E22E	; until record full
	;
B_E23F	RTS

;$E240  -------- Write buffer number in table

S_E240	LDA #$40
	JSR L_DED2	; set bit 6
	JSR S_E0D9	; get buffer number
	ORA #$40	; set bit 6
	LDX V_0257	; channel number + 7
	STA zpA8,X	; write in table
	RTS
;$E250  --------
S_E250	JSR S_E0D9	; get buffer number
	AND #$BF	; erase bit 6
	LDX V_0257	; channel number
	STA zpA8,X	; write in table
	RTS
;$E25B  -------- Get byte from REL file
L_E25B	LDA #$80
	JSR S_DEE1	; test bit 7
	BNE L_E299	; set?
	JSR S_D23F	; get byte from buffer
	LDA zp9A,X	; buffer pointer
	CMP V_0244,Y	; compare to end pointer
	BEQ S_E28E	; equal?
	INC zp9A,X	; increment buffer pointer
	BNE B_E276	; not zero?
	JSR S_E177	; write block, read next one
L_E273	JSR S_D23F	; get byte from buffer
B_E276	LDA (zp9A,X)
L_E278	STA V_023E,Y	; in output register
	LDA #$89
	STA $00F3,Y	; set READ and WRITE flag
	LDA zp9A,X	; buffer pointer
	CMP V_0244,Y	; compare to end pointer
	BEQ B_E288	; same?
	RTS
;$E288  --------
B_E288	LDA #$81
	STA $00F3,Y	; set flag for end
	RTS
;$E28E  --------
S_E28E	JSR S_E10B	; find next record
	JSR S_D23F	; get buffer and channel number
	LDA zp7E	; data byte
	JMP L_E278	; into output register
	;
L_E299	LDX zp7B	; channel number
	LDA #$0D	; CR
	STA V_023E,X	; into output register
	LDA #$81
	STA zpF3,X	; set flag for end
	LDA #$50
	JSR L_C2B2	; 50, 'record not present'
L_E2A9	LDX zp7B	; channel number
	LDA zpC2,X	; write pointer
	STA zp7F+1	; save
	DEC zp7F+1
	CMP #$02	; equal 2?
	BNE B_E2B9	; no
	LDA #$FF
	STA zp7F+1
B_E2B9	LDA zpC8,X	; record length
	STA zp81
	JSR S_D63B	; set buffer pointer
	LDX zp7B	; channel number
	CMP zp7F+1	; buffer pointer > write pointer?
	BCC B_E2DF
	BEQ B_E2DF	; no
	JSR S_CFD4	; change buffer
	JSR S_E2ED
	BCC B_E2D8
	LDX zp7B	; channel number
	STA V_0244,X
	JMP S_CFD4	; change buffer
	;
B_E2D8	JSR S_CFD4	; change buffer
	LDA #$FF
	STA zp7F+1
B_E2DF	JSR S_E2ED
	BCS B_E2E7
	JSR S_D63B	; set buffer pointer
B_E2E7	LDX zp7B	; channel number
	STA V_0244,X	; end pointer
	RTS
;$E2ED  --------
S_E2ED	JSR S_DF66	; buffer pointer to zero
	LDY zp7F+1
B_E2F2	LDA (zp8D),Y	; byte from buffer
	BNE B_E303	; not zero?
	DEY
	CPY #$02
	BCC B_E2FF
	DEC zp81
	BNE B_E2F2
B_E2FF	DEC zp81
	CLC
	RTS
;$E303  --------
B_E303	TYA
	SEC
	RTS

;$E306  -------- Get last side-sector

S_E306	JSR S_E00D	; get number of the side-sector
	STA zp92	; save
	LDA #$04
	STA zp8D	; pointer to side-sectors
	LDY #$0A
	BNE B_E317
B_E313	DEY
	DEY
	BMI B_E33D
B_E317	LDA (zp8D),Y	; track number of the previous block
	BEQ B_E313
	TYA
	LSR A		; divide by 2
	CMP zp92	; = number of the actual block?
	BEQ B_E32A	; yes
	STA zp92	; else save all numbers
	LDX zp7B	; channel number
	LDA zpCE,X	; buffer number
	JSR S_E056	; read block
B_E32A	LDY #$00
	STY zp8D	; buffer pointer
	LDA (zp8D),Y	; track number
	BNE B_E33D	; another block?
	INY
	LDA (zp8D),Y	; sector number = end pointer
	TAY
	DEY
	STY zp93	; save end pointer
	TYA
	JMP S_E024	; set buffer pointer
	;
B_E33D	LDA #$67
	JSR S_E781	; 67, 'illegal track or sector'
	;
	; Perform [P] - Position command
	;
	JSR S_C39D	; verify lines
	LDA L_0201	; secondary address
	STA zp7C
	JSR S_D1FB	; find channel number
	BCC B_E354	; found?
	LDA #$70
	JSR L_C2B2	; 70, 'no block'
B_E354	LDA #$A0
	JSR B_DED8	; erase bits 6 & 7
	JSR S_D235	; verify if 'REL'-file
	BEQ B_E363	; yes
	LDA #$64
	JSR L_C2B2	; 64, 'file type mismatch'
B_E363	LDA zpED,X
	AND #$01
	STA zp78	; drive number
	LDA V_0202	; record number lo
	STA zpB6,X
	LDA V_0203	; record number hi
	STA zpBC,X
	LDX zp7B	; channel number
	LDA #$89
	STA zpF3,X	; READ and WRITE flag
	LDA V_0204	; byte-pointer
	BEQ B_E38E	; zero?
	SEC
	SBC #$01
	BEQ B_E38E
	CMP zpC8,X	; compare with record length
	BCC B_E38E
	LDA #$51
	STA V_026C	; 51, 'overflow in record'
	LDA #$00
B_E38E	STA zp91
	JSR S_CEFD	; calculate pointer in rel-file
	JSR S_E033	; and read appropriate side-sector
	BVC B_E3A0	; does block exist?
	LDA #$80
	JSR L_DED2	; set bit 7
	JMP L_E299	; and 50, 'record not present'
	;
B_E3A0	JSR L_E3B0
	LDA #$80
	JSR S_DEE1	; test bit 7
	BEQ B_E3AD	; not set
	JMP L_E299	; 50, 'record not present'
	;
B_E3AD	JMP L_C27E	; done
	;
L_E3B0	JSR S_E3D7
	LDA zp94	; pointer in rel-file
	JSR S_D61B	; set buffer pointer
	LDX zp7B	; channel number
	LDA zpC8,X	; record length
	SEC
	SBC zp91	; minus position
	BCS B_E3C4	; positive?
	JMP B_E33D	; 67, 'illegal track or sector'
	;
B_E3C4	CLC
	ADC zp94	; add pointer in data block
	BCC B_E3CC	; no overflow
	ADC #$01	; plus 2
	SEC
B_E3CC	JSR S_E144	; set pointer
	JMP L_E273	; get byte from buffer
	;
	LDA #$51
	JSR L_C2B2	; 51, 'overflow in record'
S_E3D7	LDA zp8D	; buffer pointer lo
	STA zp81+1
	LDA zp8D+1	; buffer pointer hi
	STA zp82+1
	JSR S_E40B	; compare track and sector
	BNE B_E3E5	; not equal?
	RTS
;$E3E5  --------
B_E3E5	JSR S_DF2C
	JSR S_DF47
	LDA zp79	; track
	BEQ B_E3FD	; no block following?
	JSR S_E40E	; compare track and sector number
	BNE B_E3FA	; not equal?
	JSR S_CFD4	; change buffer
	JMP L_D42C
	;
B_E3FA	JSR L_D42C
B_E3FD	LDY #$00
	LDA (zp81+1),Y	; track
	STA zp79
	INY
	LDA (zp81+1),Y	; and sector of the next block
	STA zp7A
	JMP L_D1BF	; read block
	;
S_E40B	JSR S_DF79
S_E40E	LDY #$00
	LDA (zp81+1),Y	; track number
	CMP zp79	; compare
	BEQ B_E417
	RTS
;$E417  --------
B_E417	INY
	LDA (zp81+1),Y	; sector number
	CMP zp7A	; compare
	RTS

;$E41D  -------- Divide data blocks into records

S_E41D	JSR S_DF66	; set buffer pointer
	LDY #$02
	LDA #$00
B_E424	STA (zp8D),Y	; erase buffer
	INY
	BNE B_E424
	JSR S_E43F	; set pointer to next record
B_E42C	STA zpC2,X
	TAY
	LDA #$FF
	STA (zp8D),Y	; $FF as 1st character in record
	JSR S_E43F	; set pointer to next record
	BCC B_E42C	; done in this block?
	BNE B_E43E	; block full?
	LDA #$00
	STA zpC2,X	; write pointer to zero
B_E43E	RTS

;$E43F  -------- Set pointer to next record

S_E43F	LDX zp7B	; channel number
	LDA zpC2,X	; write pointer
	SEC
	BEQ B_E453	; equal zero?
	CLC
	ADC zpC8,X	; add record length
	BCC B_E456	; smaller than 256?
	BNE B_E453	; equal 256?
	LDA #$02
	BIT V_F10D
	RTS
;$E453  --------
B_E453	ADC #$01	; add two
	SEC
B_E456	RTS

;$E457  -------- Expand side-sector

S_E457	JSR S_D329	; get drive number
	JSR S_E306	; get last side-sector
	JSR S_E3D7
	JSR S_D09A
	LDA zp93
	STA zp7F+1
	LDA zp92	; side-sector number
	STA zp7F
	LDA #$00
	STA zp81
	LDA #$00
	STA zp91
	JSR S_CEFD	; calculate side-sector number and pointer
L_E476	JSR S_EDB8	; number of free blocks
	LDY zp7B	; channel number
	LDX zpC8,Y	; record length
	DEX
	TXA
	CLC
	ADC zp94	; plus pointer in data block
	BCC B_E490
	INC zp93
	INC zp93	; increment pointer to end by 2
	BNE B_E490
	INC zp92	; increment side-sector number
	LDA #$10
	STA zp93	; set pointer to 16
B_E490	LDA zp7F+1
	CLC
	ADC #$02
	JSR S_E024	; set buffer pointer for side-sector
	LDA zp92	; side-sector number
	CMP #$06
	BCC B_E4A3	; smaller than 6?
B_E49E	LDA #$52
	JSR L_C2B2	; 52, 'file too large'
B_E4A3	LDA zp93	; end pointer
	SEC
	SBC zp7F+1	; minus last end pointer
	BCS B_E4AD
	SBC #$0F	; minus 16
	CLC
B_E4AD	STA zp70+1
	LDA zp92	; side-sector number
	SBC zp7F	; minus last side-sector number
	STA zp72	; save
	LDX #$00
	STX zp6E+1	; erase sum for calculation
	STX zp70
	TAX
	JSR S_E08C	; calculate block # of rel-file
	LDA zp70
	BNE B_E4CA
	LDX zp6E+1
	DEX
	BNE B_E4CA
	INC zp81
B_E4CA	CMP V_0273	; block number of rel-file
	BCC B_E4D8	; greater than free blocks on disk?
	BNE B_E49E	; 52, 'file too large'
	LDA V_0272
	CMP zp6E+1
	BCC B_E49E	; 52, 'file too large'
B_E4D8	LDA #$01
	JSR S_D649	; get byte from buffer
	CLC
	ADC #$01	; plus 1
	LDX zp7B
	STA zpC2,X	; as write pointer
	JSR S_EF89	; find free block in BAM
	JSR S_DF38	; track and sector in buffer
	LDA zp81
	BNE B_E503	; only one block needed?
	JSR S_DF99	; write block
B_E4F1	JSR S_CFD4	; change buffer
	JSR S_D805	; transmit parameter to disk controller
	JSR S_EF89	; find free block in BAM
	JSR S_DF38	; track and sector in buffer
	JSR S_E41D	; erase buffer
	JMP L_E50F
	;
B_E503	JSR S_CFD4	; change buffer
	JSR S_D805	; transmit parameter to disk controller
	JSR S_E41D	; erase buffer
	JSR S_DF54	; zero byte and end pointer in buffer
L_E50F	JSR S_DF99	; write block
	JSR S_DF47	; get track and sector
	LDA zp79	; track
	PHA
	LDA zp7A	; and sector
	PHA		; save
	JSR S_DF79	; get track and sector from disk
	LDA zp7A	; controller
	PHA
	LDA zp79	; save track and sector
	PHA
	JSR S_E080	; set buffer pointer for side-sector
	TAX
	BNE B_E534	; pointer not zero?
	JSR S_E589	; write side-sector
	LDA #$10
	JSR S_E024	; buffer pointer to 16
	INC zp7F	; increment side-sector number
B_E534	PLA
	JSR S_DEC8	; track in side-sector
	PLA
	JSR S_DEC8	; sector in side-sector
	PLA
	STA zp7A	; sector
	PLA
	STA zp79	; and get track back
	BEQ B_E553	; no more blocks?
	LDA zp7F	; side-sector number
	CMP zp92	; changed?
	BNE B_E4F1	; yes
	JSR S_E080	; set buffer pointer in side-sector
	CMP zp93	; end pointer
	BCC B_E4F1	; smaller?
	BEQ B_E503	; same
B_E553	JSR S_E080	; set buffer pointer in side-sector
	PHA
	LDA #$00
	JSR S_E017	; buffer pointer to zero
	LDA #$00
	TAY
	STA (zp8D),Y	; zero as track number
	INY
	PLA		; end pointer
	SEC
	SBC #$01	; minus one
	STA (zp8D),Y	; as sector
	JSR S_DFA7	; write block
	JSR S_D6EC	; and verify
	JSR S_ED5F	; update BAM
	JSR S_CEFD	; update pointer for rel-file
	JSR S_CFD4	; change buffer
	JSR S_E033	; right side-sector?
	BVS B_E57F	; no
	JMP L_E3B0
	;
B_E57F	LDA #$80
	JSR L_DED2	; set bit 7
	LDA #$50
	JSR L_C2B2	; 50, 'record not present'
	;
	; Write side-sector and allocate new
	;
S_E589	JSR S_EF89	; find free block in BAM
	JSR S_CFD4	; change buffer
	JSR S_DF2C	; write block
	JSR S_E0CE	; get buffer number
	PHA
	JSR S_DFFC	; erase buffer
	LDX zp7B	; channel number
	LDA zpCE,X	; buffer number
	TAY
	PLA
	TAX
	LDA #$10	; 16 bytes of the side-sector
	JSR S_DFE0	; copy in buffer
	LDA #$00
	JSR S_E017	; buffer pointer to 0, old side-sector
	LDY #$02
	LDA (zp8D),Y	; side-sector number
	PHA
	LDA #$00
	JSR S_D61B	; buffer pointer to 0, new side-sector
	PLA
	CLC
	ADC #$01	; increment side-sector number
	STA (zp8D),Y	; and in buffer
	ASL A		; times 2
	ADC #$04	; plus 4
	STA zp81+1
	TAY
	SEC
	SBC #$02	; minus 2
	STA zp82+1	; same pointer to old side-sector
	LDA zp79	; track
	STA zp7F+1
	STA (zp8D),Y	; in buffer
	INY
	LDA zp7A	; sector
	STA zp81
	STA (zp8D),Y	; in buffer
	LDY #$00
	TYA
	STA (zp8D),Y	; zero in buffer
	INY
	LDA #$11	; 17
	STA (zp8D),Y	; number of bytes in block
	LDA #$10	; 16
B_E5DE	JSR S_D61B	; buffer pointer to 16
	JSR S_DF8B	; write block
	JSR S_D6EC	; and verify
	LDX zp7B	; channel number
	LDA zpCE,X	; buffer number of the side-sector
	PHA
	JSR S_E0D9	; get buffer number
	LDX zp7B	; channel number
	STA zpCE,X	; write in table
	PLA
	LDX V_0257	; channel number + 7
	STA zpA8,X	; in table
	LDA #$00
	JSR S_D61B	; buffer pointer to zero
	LDY #$00
	LDA zp79	; track
	STA (zp8D),Y	; in buffer
	INY
	LDA zp7A	; sector
	STA (zp8D),Y	; in buffer
	JMP L_E619
	;
B_E60C	JSR S_E0CE	; get buffer number
	LDX zp7B	; channel number
	JSR S_E056	; read block
	LDA #$00
	JSR S_D61B	; buffer pointer to zero
L_E619	DEC zp82+1
	DEC zp82+1	; counter for side-sector blocks
	LDY zp81+1
	LDA zp7F+1	; track number
	STA (zp8D),Y	; in buffer
	INY
	LDA zp81	; sector number
	STA (zp8D),Y	; in buffer
	JSR S_DF99	; write block
	JSR S_D6EC	; and verify
	LDY zp82+1	; counter for side-sector blocks
	CPY #$03
	BCS B_E60C	; greater than or equal to 3?
	JMP S_CFD4	; change buffer
	;
	; Error codes and messages
	;
	DB $00
	DB $A0,"OK"
	DB $20,$21,$22,$23,$24,$27
	DB $D2,$45,$41,$44
	DB $89
; $E646
	DB $52
; $E647
	DB $83
	DB " TOO LARGe"
	DB $50
	DB $8B
	DB $06
	DB "oVERFLOW"
	DB " IN"
	DB $8B
	DB $25,$28
	DB $8A
	DB $89
	DB $26
	DB $8A
	DB " PROTECT On"
	DB $29
	DB $88
	DB " ID"
	DB $85
	DB $30,$31,$32,$33,$34
	DB $D3,$59,$4E,$54,$41,$58 ; "Syntax"
	DB $89
	DB $60
	DB $8A
; $E68F
	DB $03
	DB $84
; $E691
	DB $63
	DB $83
	DB " EXISTs"
	DB $64
	DB $83
	DB " TYPE"
	DB $85
	DB $65
	DB "nO BLOCK"
	DB $66,$67
	DB "iLLEGAL TRACK OR SECTOR"
	DB $61
; $E6C5
	DB $83,$06
	STY zp39
; $E6C9
	DB "b"
; $E6CA
	DB $83,$06
; $E6CC
	DB $87,$01
; $E6CE
	DB $83,"S"
	JSR S_4353
; $E6D3
	DB "R"
	EOR (zp54,X)
; $E6D6
	DB "CH"
	EOR zpC4
	BVS B_E6AA
; $E6DC
	DB "O C"
	PHA
	EOR (zp4E,X)
	LSR V_CC45
B_E6E5	ADC (zpC4),Y
	EOR #$52	; "R"
; $E6E9
	DB $89,$72
	DEY
	JSR S_5546
	JMP L_73CC
	;
; $E6F2
	DB $C3,"B"
	EOR V_4420
; $E6F7
	DB "OS "
	LSR zp32,X
	ROL V_2036
; $E6FF
	DB "T"
V_E700	DB "D"
	EOR #$53	; "S"
	DB $CB,$74
	CPY zp52
	EOR #$56	; "V"
	EOR zp06
	JSR S_4552
	EOR (zp44,X)
	CMP V_C508 + 1,Y
; $E713
	DB "R"
; $E714
	DB "R"
; $E715
	DB "O",$D2,$0A
; $E718
	DB $D7,"R"
	EOR #$54	; "T"
	CMP zp03
	DEC zp49
	JMP L_04C5
	;
; $E723
	DB $CF,"PE"
	DEC V_CD05
	EOR #$53	; "S"
	EOR V_5441
; $E72E
	DB "C",$C8
	ASL zpCE
; $E732
	DB $4F,$D4,$07
	DEC zp4E+1
	EOR zp4E,X
	CPY zp08
	CPY zp49
; $E73D
	DB "S",$CB
; $E73F
	DB $0B,$D2
	EOR zp43
; $E743
	DB "OR",$C4
	;
	; Prepare error number and message
	;
L_E746	PHA		; save error code
	STX zp98	; drive number
	TXA
	ASL A		; times 2
	TAX		; as pointer
	LDA zp08,X
	STA zp79	; get track
	LDA zp09,X
	STA zp7A	; and sector number
	PLA		; get error code back
	AND #$0F	; isolate bits 0-3
	BEQ B_E761	; zero, then 24, 'read error'
	CMP #$0F	; 15?
	BNE B_E763
	LDA #$74	; 74, 'drive not ready'
	BNE B_E769	; 6
B_E761	LDA #$06
B_E763	ORA #$20	; add $20
	TAX
	DEX
	DEX		; subtract two (= 36)
	TXA
B_E769	PHA		; save error number
	LDA V_022A	; number of the disk command
	CMP #$00	; OPEN or VALIDATE?
	BNE B_E780	; no
	LDA #$FF
	STA V_022A
	PLA		; get error number back
	JSR S_E806	; generate error message
	JSR S_D15E	; load BAM
	JMP S_E784	; set error message
	;
B_E780	PLA
	;
	; Print error message into error buffer
	;
S_E781	JSR S_E806	; set error message
	;
S_E784	JSR S_C2A7	; erase input buffer
	LDA #$00
	STA V_02F9	; erase error flag
	JSR L_F3F7	; turn LED off
	JSR L_D62D	; close channels 17 and 18
	LDA #$00
	STA zpA4	; input buffer pointer to zero
	LDX #$FF
	TXS		; initialize stack pointer
	LDA zp7D	; secondary address
	AND #$0F
	STA zp7C
	CMP #$0F	; 15?
	BEQ B_E7D4	; yes, command channel
	LDA zp5C	; LISTEN active?
	BNE B_E7C4	; yes
	LDA zp5B	; TALK active?
	BNE B_E7BB	; yes
	LDX zp7C	; channel number
	LDA V_022B,X	; open channel to this secondary addr
	CMP #$FF
	BEQ B_E7D4	; no
	AND #$0F
	STA zp7B	; channel
	JMP L_E7CA
	;
	; TALK
	;
B_E7BB	JSR S_D1FB
	JSR S_C1CD
	JMP L_E7CA
	;
	; LISTEN
	;
B_E7C4	JSR S_D217
	JSR S_C1D8
	;
L_E7CA	JSR S_D235	; verify file type
	CMP #$04	; file type REL?
	BCS B_E7D4	; yes
	JSR L_D37D	; close channel
	;
B_E7D4	LDX #$FF	; reset stack pointer
	TXS
	JMP L_EABD	; jump to main loop
	;
	; Convert BIN to 2-Ascii (error message buffer)
	;
S_E7DA	TAX
	LDA #$00
	SED
L_E7DE	CPX #$00
	BEQ B_E7E9	; convert hex to BCD
	CLC
	ADC #$01
	DEX
	JMP L_E7DE
	;
B_E7E9	CLD
	;
	; Convert BCD to 2-Ascii (error message buffer)
	;
S_E7EA	TAX
	LSR A
	LSR A		; shift hi-nibble down
	LSR A
	LSR A
	JSR S_E7F3	; convert to ASCII
	TXA
S_E7F3	AND #$0F	; erase top 4 bits
	ORA #$30	; add '0'
	STA (zpA6),Y	; write in buffer
	INY		; increment buffer pointer
	RTS

;$E7FB  -------- Write OK in buffer

L_E7FB	JSR S_F3F0	; erase error flag
	LDA #$00	; error number 0
	;
	; Print error on track 00,00 to error buffer
	;
S_E800	LDY #$00
	STY zp79	; track 0
	STY zp7A	; sector 0
S_E806	LDY #$00	; buffer pointer
	LDX #$D5
	STX zpA6	; pointer $A5/$A6 to $2D5
	LDX #$02
	STX zpA6+1
	JSR S_E7EA	; error number to ASCII and in buffer
	LDA #$2C	; ',' comma
	STA (zpA6),Y	; write in buffer
	INY		; increment buffer pointer
	LDA V_02D5	; first digit of the disk status
	STA V_0243	; in output register
	TXA		; error number in accumulator
	JSR S_E845	; error message in buffer
	LDA #$2C	; ',' comma
	STA (zpA6),Y	; write in buffer
	INY		; and increment buffer pointer
	LDA zp79	; track number
	JSR S_E7DA	; to ASCII and in buffer
	LDA #$2C	; ',' comma
	STA (zpA6),Y	; write in buffer
	INY		; increment buffer pointer
	LDA zp7A	; sector
	JSR S_E7DA	; convert to ASCII and in buffer
	DEY
	TYA
	CLC
	ADC #$D5
	STA V_0249	; end pointer
	INC zpA6
	LDA #$88	; set READ flag
	STA zpF8
	RTS

;$E845  -------- Write error message string to buffer

S_E845	TAX		; error code to X
	LDA zp7F
	PHA
	LDA zp7F+1	; preserve pointer $7f/$80
	PHA
	LDA #$37
	STA zp7F
	LDA #$E6	; start of the error messages
	STA zp7F+1	; E637
	TXA		; error number in accumulator
	LDX #$00
L_E857	CMP (zp7F,X)	; compare with error number in table
	BEQ B_E87C
	PHA
	JSR S_E8B4	; bit 7 into carry and erase
	BCC B_E866	; not set?
B_E861	JSR S_E8B4	; bit 7 into carry
	BCC B_E861	; wait for character with bit 7 set
B_E866	LDA zp7F+1
	CMP #$E7
	BCC B_E874	; $E746 ...
	BNE B_E878
	LDA #$46	; ...  check to end of table
	CMP zp7F
	BCC B_E878
B_E874	PLA
	JMP L_E857	; no, continue
	;
B_E878	PLA
	JMP L_E88C	; done
	;
B_E87C	JSR S_E8A6	; get a character, bit 7 in carry
	BCC B_E87C	; wait for character with bit 7 set
B_E881	JSR S_E893	; and write in buffer
	JSR S_E8A6	; get next character
	BCC B_E881	; wait for character with bit 7 set
	JSR S_E893	; put character in buffer
L_E88C	PLA
	STA zp7F+1
	PLA		; get pointer $7f/$80 back
	STA zp7F
	RTS

;$E893  -------- Get character and in buffer

S_E893	CMP #$20	; ' ' blank
	BCS B_E8A2	; greater, then write in buffer
	TAX		; save code
	LDA #$20	; blank
	STA (zpA6),Y	; write in buffer
	INY		; increment buffer pointer
	TXA		; code in accumulator
	JSR S_E845	; output previous text
	RTS
;$E8A2  --------
B_E8A2	STA (zpA6),Y	; write character in buffer
	INY		; and increment pointer
	RTS

;$E8A6  -------- Get a char of the error message

S_E8A6	INC zp7F
	BNE S_E8AC	; increment pointer
	INC zp7F+1
S_E8AC	LDA (zp7F,X)	; get character
	ASL A		; bit 7 into carry
	LDA (zp7F,X)	; get character
	AND #$7F	; erase bit 7
	RTS
;$E8B4  --------
S_E8B4	JSR S_E8AC	; bit 7 into carry
	INC zp7F
	BNE B_E8BD	; increment pointer
	INC zp7F+1
B_E8BD	RTS
;$E8BE  -------- Dummy subroutine
L_E8BE	RTS
;$E8BF  --------
	JMP L_E8BE
	;
	CLI
	INC V_0278
	INC V_0274
	LDA #$2A
	STA V_0200
	JMP L_E8D9
	;
	LDA #$01
	STA V_027A
	JSR S_C3FC
L_E8D9	LDA V_0278
	PHA
	LDA #$01
	STA V_0278
V_E8E2	LDA #$FF
	STA zp7F
	JSR S_C53A
	LDA V_0280
	BNE B_E8F3
	LDA #$39
	JSR L_C2B2
B_E8F3	PLA
	STA V_0278
	LDA V_0280
	STA zp79
	LDA V_0285
	STA zp7A
	LDA #$03
	JSR S_D5CA
B_E906	LDA #$00
	STA zp7F+1	; erase checksum
	JSR S_E967	; get byte from file
	STA zp81	; save as start address lo
	JSR S_E979	; from checksum
	JSR S_E967	; get byte from file
	STA zp81+1	; as start address hi
	JSR S_E979	; form checksum
	LDA zp7F
	BEQ B_E928
	LDA zp81
	PHA		; save program start address
	LDA zp81+1
	PHA
	LDA #$00
	STA zp7F
B_E928	JSR S_E967	; get byte from file
	STA zp82+1	; save as counter
	JSR S_E979	; form checksum
B_E930	JSR S_E967	; get byte from file
	LDY #$00
	STA (zp81),Y	; save as program bytes
	JSR S_E979	; form checksum
	LDA zp81
	CLC
	ADC #$01
	STA zp81	; increment $88/$89
	BCC B_E945
	INC zp81+1
B_E945	DEC zp82+1	; decrement pointer
	BNE B_E930
	JSR S_CB2A	; get next byte
	LDA zp7E	; data byte
	CMP zp7F+1	; equal to checksum?
	BEQ B_E95A	; yes
	JSR S_DF79	; transmit parameter to disk controller
	LDA #$50	;
	JSR S_E781	; 50, 'record not present'
B_E95A	LDA zp95	; end?
	BNE B_E906	; no, next data block
	PLA
	STA zp81+1
	PLA		; get program start address back
	STA zp81
	JMP ($0081)	; *** Indirect jump to program
	;
S_E967	JSR S_CB2A	; get byte from file
	LDA zp95	; end?
	BNE B_E976	; no
	JSR S_DF79	; transmit parameter to disk controller
	LDA #$51
	JSR S_E781	; 51, 'overflow in record'
B_E976	LDA zp7E	; data byte
	RTS

;$E979  -------- Generate checksum

S_E979	CLC
	ADC zp7F+1
	ADC #$00
	STA zp7F+1
	RTS

;$E981  -------- Blink LED and loop

L_E981	LDX #$00
	DB $2C		; BIT $xxxx
L_E984	LDX zp6E	;
	TXS		; load X to stack pointer
B_E987	TSX		; read X from stack pointer
B_E988	LDA #$6F
	STA zp00	; set direction of processor port to default
	AND #$60	; drive LED on
	STA zp01	; store #$60 to processor port
	TYA
B_E991	CLC
B_E992	ADC #$01
	BNE B_E992
	DEY
	BNE B_E991	; delay (WAIT)
	LDA #$68
	STA zp01	; drive LED off
B_E99D	TYA
B_E99E	CLC
B_E99F	ADC #$01
	BNE B_E99F
	DEY
	BNE B_E99E	; delay (WAIT)
	DEX
	BPL B_E988	; flash LED
	CPX #$F4
	BNE B_E99D
	BEQ B_E987
L_E9AF	JMP L_E984
	;
B_E9B2	JMP L_E981
	;
	; Drive RESET
	;
	SEI
	CLD
	LDY #$00
	LDX #$02	; memory test on zero lap ($02-$FF)
B_E9BB	TXA
	STA zp00,X
	INX
	BNE B_E9BB
	LDX #$02
B_E9C3	TXA
	CMP zp00,X
	BNE B_E9B2
B_E9C8	INC zp00,X
	INY
	BNE B_E9C8
	CMP zp00,X
	BNE B_E9B2	; memory test failure (x will be the RAM page nr)?
	STY zp00,X	; clear to 0 (zero)
	LDA zp00,X	; check
	BNE B_E9B2	; memory test failed...
	INX
	BNE B_E9C3	; loop
	INC zp6E	; increase blink count
	STX zp74+1
	LDA #$00	; ROM checksumgeneration begins
	STA zp74
	TAY		; Y = A (0)
	LDX #$40
	CLC
B_E9E6	DEC zp74+1
B_E9E8	ADC (zp74),Y
	INY
	BNE B_E9E8
	DEX
	BNE B_E9E6
	STA zp61	; reset count
	ADC #$FF
	BNE L_E9AF	; ROM checksum correct?
	LDA #$01
	STA zp74+1
	INC zp6E
	LDX #$07
B_E9FE	TYA
	CLC
	ADC zp74+1
	STA (zp74),Y
	INY
	BNE B_E9FE
	INC zp74+1
	DEX
	BNE B_E9FE
	LDX #$07
B_EA0E	DEC zp74+1
B_EA10	DEY
	TYA
	CLC
	ADC zp74+1
	CMP (zp74),Y
	BNE B_EA2B
	EOR #$FF	; reverse all bits
	STA (zp74),Y
	EOR (zp74),Y	; check
	STA (zp74),Y
	BNE B_EA2B	; not equal, then jump
	TYA
	BNE B_EA10
	DEX
	BNE B_EA0E
	BEQ B_EA2E	; always jump
B_EA2B	JMP L_E9AF
	;
B_EA2E	LDX #$FF
	STX zp95
	TXS		; clear stack pointer
	JSR S_C3C6	; DOS init
	JSR S_F13D	; FDC init
	LDA #$11
	STA zp68
	LDA #$05
	STA zp69
	LDX #$00
	LDY #$00
B_EA45	LDA #$00
	STA zp9A,X
	INX
	LDA V_F123,Y
	STA zp9A,X
	INX
	INY
	CPY #$05
	BNE B_EA45
	LDA #$00
	STA zp9A,X
	INX
	LDA #$02
	STA zp9A,X
	INX
	LDA #$D5
	STA zp9A,X
	INX
	LDA #$02
	STA zp9A,X
	LDA #$FF
	LDX #$12
B_EA6C	STA V_022B,X
	DEX
	BPL B_EA6C
	LDX #$05
B_EA74	STA zpA8,X
	STA zpAF,X
	STA zpCE,X
	DEX
	BPL B_EA74
	LDA #$05
	STA zpAC
	LDA #$06
	STA zpAD
	LDA #$FF
	STA zpAE
	STA zpB5
	LDA #$05
	STA V_023B
	LDA #$84
	STA V_023A
	LDA #$0F
	STA V_0256
	LDA #$01
	STA zpF7
	LDA #$88
	STA zpF8
	LDA #$E0
	STA V_024F
	LDA #$FF
	STA V_0250
	LDA #$01
	STA zp22
	STA zp23
	JSR S_CC55
	JSR S_CFB0
	LDA #$73
	JSR S_E800
	;
	; Main wait loop
	;
L_EABD	INC zp61	; count
	BNE B_EAC4	; if not zero, skip next call
	JSR S_EADC
B_EAC4	LDA V_4000	; read I/O port from computer
	BPL B_EACC	; 7th bit set?
	JSR S_C022	; yes, then jump
B_EACC	LDA V_0255	; waiting for command?
	BEQ L_EABD	; no...
	LDA #$00	; yes
	STA V_0255	; clear command flag
	JSR S_C230	; analyze and execute command
	JMP L_EABD	; back to main loop
	;
	;
	;
S_EADC	LDA #$0E	; 14
	STA zp63	; as secondary address
	LDA #$00
	STA zp62	; job counter
B_EAE4	LDX zp63
	LDA V_022B,X	; secondary address
	CMP #$FF	; channel associated?
	BEQ B_EAEF	; no
	INC zp62
B_EAEF	DEC zp63
	BPL B_EAE4
	LDA zp62
	BEQ B_EAFE
	LDA zp22
	BEQ B_EAFE
	JSR S_D465
B_EAFE	LDX V_026C
	BEQ B_EB06
	JMP L_F3F7	; set LED flag
	;
B_EB06	LDA zp62
	STA zp96
	RTS
;$EB0B  --------
S_EB0B	LDA #$00
	STA zp7C
	LDA #$01
	JSR S_D338
	LDA #$00
	JSR S_D61B
	LDX zp7B
	LDA #$00
	STA V_0244,X
	JSR S_E0CE
	TAX
	LDA zp78
	STA V_025B,X
	LDA #$01
	JSR S_D10D
	LDA #$04
	JSR S_D10D
	LDA #$01
	JSR S_D10D
	JSR S_D10D
	LDA V_0272
	JSR S_D10D
	LDA #$00
	JSR S_D10D
	JSR S_EBC6
	JSR S_E0CE
	ASL A
	TAX
	DEC zp9A,X
	DEC zp9A,X
	LDA #$00
	JSR S_D10D
B_EB57	LDA #$01
	JSR S_D10D
	JSR S_D10D
	JSR S_C7AF
	BCC B_EB90
	LDA V_0272
	JSR S_D10D
	LDA V_0273
	JSR S_D10D
	JSR S_EBC6
	LDA #$00
	JSR S_D10D
	BNE B_EB57
L_EB7A	JSR S_E0CE
	ASL A
	TAX
	LDA #$00
	STA zp9A,X
	LDA #$88
	LDY zp7B
	STA V_0254
	STA $00F3,Y
	LDA zp7E
	RTS
;$EB90  --------
B_EB90	LDA V_0272	; block number lo
	JSR S_D10D	; write in buffer
	LDA V_0273	; block number hi
	JSR S_D10D	; in buffer
	JSR S_EBC6	; 'blocks free.' in buffer
	JSR S_E0CE	; get buffer number
	ASL A
	TAX
	DEC zp9A,X
	DEC zp9A,X	; buffer pointer minus 2
	LDA #$00
	JSR S_D10D
	JSR S_D10D	; three zeroes as program end
	JSR S_D10D
	JSR S_E0CE	; get buffer number
	ASL A		; times 2
	TAY
	LDA $009A,Y	; buffer pointer
	LDX zp7B
	STA V_0244,X	; as end marker
	DEC V_0244,X
	JMP L_EB7A
	;
	; Transmit dir line
	;
S_EBC6	LDY #$00
B_EBC8	LDA V_02B1,Y	; character from buffer
	JSR S_D10D	; write in output buffer
	INY
	CPY #$1B	; 27 characters?
	BNE B_EBC8
	RTS
;$EBD4  -------- Get byte from buffer
S_EBD4	JSR S_D247	; get byte
	BEQ B_EBDA	; buffer pointer zero?
	RTS
;$EBDA  --------
B_EBDA	STA zp7E	; save data byte
	LDY zp7B	; channel number
	LDA V_0244,Y	; set end marker
	BEQ B_EBEB	; zero (LOAD $)?
	LDA #$80
	STA $00F3,Y	; set READ flag
	LDA zp7E	; data byte
	RTS
;$EBEB  --------
B_EBEB	PHA
	JSR B_EB57	; create directory line in buffer
	PLA
	RTS

;$EBF1  -------- Perform [V] - Validate command

	JSR S_C2BB	; find drive number in input line
	JSR S_D15E	; load BAM
	LDA #$40
	STA V_02F9
	JSR S_ED22	; create new BAM in buffer
	LDA #$00
	STA V_0292
	JSR S_C691	; load directory, find 1st flag
	BNE B_EC46	; found?
B_EC09	LDA #$00
	STA zp7A	; sector 0
	LDA V_F0C3	; 18
	STA zp79	; track 18 for BAM
	JSR S_EC52	; mark directory blocks as allocated
	LDA #$00
	STA V_02F9
	JSR S_ED6A	; write BAM back to disk
	JMP L_C27E	; done, prepare disk status
	;
B_EC20	INY
	LDA (zp8D),Y	; save track
	PHA
	INY
	LDA (zp8D),Y	; and sector
	PHA
	LDY #$13	; pointer to side-sector block
	LDA (zp8D),Y
	BEQ B_EC38	; no track following?
	STA zp79	; track and
	INY
	LDA (zp8D),Y
	STA zp7A	; sector of 1st side-sector block
	JSR S_EC52	; mark side-sector block as
B_EC38	PLA		; allocated
	STA zp7A
	PLA		; get track and sector back
	STA zp79
	JSR S_EC52	; mark blocks of file as allocated
L_EC41	JSR S_C6E9	; read next entry in directory
	BEQ B_EC09	; end of directory?
B_EC46	LDY #$00
	LDA (zp8D),Y	; file type
	BMI B_EC20	; bit 7 set, file closed?
	JSR S_C997	; file type to zero and write BAM
	JMP L_EC41
	;
	; Allocate file blocks in BAM
	;
S_EC52	JSR S_D6B0	; check track and sector number
	JSR S_EDFB	; allocate block in BAM
	JSR S_D5C8	; read next block
L_EC5B	LDA #$00
	JSR S_D61B	; buffer pointer zero
	JSR S_D247	; get byte from buffer
	STA zp79	; track
	JSR S_D247	; get byte from buffer
	STA zp7A	; sector
	LDA zp79	; another block?
	BNE B_EC71	; yes
	JMP L_D37D	; close channel
	;
B_EC71	JSR S_EDFB	; allocate block in BAM
	JSR S_D5A0	; read next block
	JMP L_EC5B	; continue
	;
	; Perform [N] - New (Format) command
	;
	JSR S_C3FC	; get drive number
	LDA zpE3	; drive number
	BPL B_EC86	; not clear?
	LDA #$33
	JMP L_C2B2	; 33, 'syntax error'
	;
B_EC86	AND #$01
	STA zp78	; drive number
	TAX
	LDY #$00
	STY zp5F,X
	ASL A		; times 2
	TAX
	LDY V_027B	; comma position
	CPY V_0274	; compare with end name
	BEQ B_ECB3	; format without ID
	LDA V_0200,Y	; first character of ID
	STA zp14,X	; save
	LDA L_0201,Y	; second character
	STA zp15,X
	JSR S_D459	; close all channels
	LDA #$01
	STA zp79	; track 1
	JSR S_C9A7	; format disk
	JSR S_EE70	; erase buffer
	JMP L_ECC2	; continue as below
	;
B_ECB3	JSR S_D15E	; load BAM
	LDX zp78	; drive number
	LDA zp5D,X
	CMP V_F118	; 'A', marker for 1541 format
	BEQ L_ECC2	; ok
	JMP L_D6C3	; 73, 'cbm dos v2.6 tdisk'
	;
L_ECC2	JSR S_ED22	; create BAM
	LDA zp98	; buffer number
	TAY
	ASL A
	TAX
	LDA V_F0C6	; $90, start of disk name
	STA zp9A,X	; buffer pointer to name
	LDX V_027A
	LDA #$1B	; 27
	JSR S_C74F	; write filenames in buffer
	LDY #$12	; position 18
	LDX zp78	; drive number
	LDA V_F118	; 'A', 1541 format
	STA zp5D,X
	TXA
	ASL A	 	; times 2
	TAX
	LDA zp14,X	; ID, first character
	STA (zp8D),Y	; in buffer
	INY
	LDA zp15,X	; and second character
	STA (zp8D),Y	; in buffer
	INY
	INY
	LDA #$32	; '2'
	STA (zp8D),Y	; in buffer
	INY
	LDA V_F118	; 'A' 1541 format
	STA (zp8D),Y	; in buffer
	LDY #$02
	STA (zp6C),Y	; and at position 2
	LDA V_F0C3	; 18
	STA zp79	; track number
	JSR S_EDFE	; mark block as allocated
	LDA #$01	; 1
	STA zp7A	; sector number
	JSR S_EDFE	; mark block as allocated
	JSR S_ED6A	; write BAM
	JSR S_EE70	; pointer $6D/$6E to buffer, erase buffer
	LDY #$01
	LDA #$FF
	STA (zp6C),Y	; track following is zero
	JSR S_D5B7	; write BAM
	DEC zp7A	; decrement sector number, 0
	JSR S_D5B3	; read block
	JMP L_C27E	; prepare disk status
	;
	; Create BAM
	;
S_ED22	JSR S_EF3C
	LDY #$00
	LDA #$12	; 18
	STA (zp6C),Y	; pointer to directory track
	INY
	TYA		; 1
	STA (zp6C),Y	; pointer to directory sector
	INY
	INY
	INY
B_ED32	LDA #$00
	STA zp6E
	STA zp6E+1	; 3 bytes = 24 bits for sectors
	STA zp70
	TYA		; byte position
	LSR A
	LSR A		; divided by 4 = track number
	JSR S_F0B6	; get number of sectors
	STA (zp6C),Y	; and in BAM
	INY
	TAX
B_ED44	SEC
	ROL zp6E
	ROL zp6E+1	; create bit model
	ROL zp70
	DEX
	BNE B_ED44
B_ED4E	LDA zp6E,X	; 3 bytes
	STA (zp6C),Y	; the BAM in buffer
	INY
	INX
	CPX #$03
	BCC B_ED4E
	CPY #$90	; position 144?
	BCC B_ED32	; no, next track
	JMP L_D185	; calculate number of free blocks
	;
	; Write BAM if needed
	;
S_ED5F	JSR S_E0CE	; get buffer number
	TAX
	LDA V_025B,X	; command for disk controller
	AND #$01
	STA zp78	; isolate drive number
S_ED6A	LDY zp78
	LDA V_0251,Y	; BAM-changed flag set?
	BNE B_ED72	; yes
	RTS
;$ED72  --------
B_ED72	LDA #$00
	STA V_0251,Y	; reset BAM-changed flag
	JSR S_EDA5	; set buffer pointer for BAM
	LDA zp78	; drive number
	ASL A		; times 2
	PHA
	JSR S_EF10	; verify BAM entry
	PLA
	CLC
	ADC #$01	; inrement track number
	JSR S_EF10	; verify BAM entry
	LDA zp79	; track
	PHA
	LDA #$01	; track 1
	STA zp79
B_ED8F	ASL A
	ASL A		; times 4
	STA zp6C
	JSR S_F08B	; verify BAM
	INC zp79	; increment track number
	LDA zp79
	CMP V_F11A	; and compare with max val + 1 = 36
	BCC B_ED8F	; ok, next track
	PLA
	STA zp79	; get track number back
	JMP L_D6DD	; write BAM to disk
	;
	; Set buffer pointer for BAM
	;
S_EDA5	JSR S_EF7A	; get 6 for drive 0
	TAX
	JSR S_EF4A	; allocate buffer
	LDX zp98	; buffer number
	LDA V_F123,X	; buffer address, hi byte
	STA zp6C+1
	LDA #$00	; lo byte
	STA zp6C	; pointer to $6D/$6E
	RTS

;$EDB8  -------- Get number of free blocks for dir

S_EDB8	LDX zp78	; drive number
	LDA V_02FA,X	; number of blocks, lo
	STA V_0272
	LDA V_02FC,X	; number of blocks, hi
	STA V_0273	; in buffer for directory
	RTS

;$EDC7  -------- Mark block as free

	JSR S_EE5B + 1	; set buffer pointer
S_EDCA	JSR S_EE3A	; erase bit for sector in BAM
	SEC
	BNE B_EDF2	; block already free, then done
	LDA (zp6C),Y	; bit model of BAM
	ORA V_EE54,X	; set bit X, marker for free
	STA (zp6C),Y
	JSR S_EDF3	; set flag for BAM changed
	LDY zp6E
	CLC
	LDA (zp6C),Y
	ADC #$01	; increment number of free blocks/track
	STA (zp6C),Y
	LDA zp79	; track
	CMP V_F0C3	; equal to 18?
	BEQ B_EE25	; then skip
	INC V_02FA,X	; increment number of free blocks in disk
	BNE B_EDF2
	INC V_02FC,X	; increment number of blocks hi
B_EDF2	RTS

;$EDF3  -------- Set flag for BAM changed

S_EDF3	LDX zp78	; drive number
	LDA #$01
	STA V_0251,X	; flag = 1
	RTS

;$EDFB  -------- Mark block as allocated

S_EDFB	JSR S_EE5B + 1	; set buffer pointer
S_EDFE	JSR S_EE3A	; erase bit for sector in BAM
	BEQ B_EE39	; already allocated, then done
	LDA (zp6C),Y
	EOR V_EE54,X	; erase bit for block
	STA (zp6C),Y
	JSR S_EDF3	; set flag for BAM changed
	LDY zp6E
	LDA (zp6C),Y
	SEC
	SBC #$01	; decrement number of blocks per track
	STA (zp6C),Y
	LDA zp79	; track
	CMP V_F0C3	; 18?
	BEQ B_EE28
	LDA V_02FA,X	; number of free blocks lo
	BNE B_EE25
	DEC V_02FC,X	; decrement number of free blocks
B_EE25	DEC V_02FA,X
B_EE28	LDA V_02FC,X	; number of free blocks hi
	BNE B_EE39	; more than 255 blocks free?
	LDA V_02FA,X	; free blocks lo
	CMP #$03
	BCS B_EE39	; smaller than 3?
	LDA #$72
	JSR S_E806	; 72, 'disk full'
B_EE39	RTS

;$EE3A  -------- Erase bit for sector in BAM entry

S_EE3A	JSR S_EE7C	; find BAM field for this track
	TYA
	STA zp6E
S_EE40	LDA zp7A	; sector
	LSR A
	LSR A		; divide by 8
	LSR A
	SEC
	ADC zp6E
	TAY		; byte number in BAM entry
	LDA zp7A	; sector number
	AND #$07
	TAX		; bit number in BAM entry
	LDA (zp6C),Y	; byte in BAM
	AND V_EE54,X	; erase bit for corresponding sector
	RTS
;$EE54  -------- Powers of 2
V_EE54	DB $01,$02,$04,$08,$10,$20,$40,$80
;$EE5C  -------- Write BAM after change
S_EE5C	LDA #$FF
	BIT $02F9
	BEQ B_EE6F
	BPL B_EE6F
	BVS B_EE6F
	LDA #$00
	STA V_02F9	; reset flag
	JMP L_D6DD	; write block
	;
B_EE6F	RTS
;$EE70  -------- Erase BAM buffer
S_EE70	JSR S_EDA5	; pointer $6c/$6d to BAM buffer
	LDY #$00
	TYA
B_EE76	STA (zp6C),Y	; erase BAM buffer
	INY
B_EE79	BNE B_EE76
	RTS
;$EE7C  --------
S_EE7C	LDA zp6E
	PHA
	LDA zp6E+1
	PHA
	LDX zp78	; drive number
	LDA zp5F,X
	BEQ B_EE8D	; drive zero?
	LDA #$74
	JSR S_E784	; 'drive not ready'
B_EE8D	JSR S_EF7A	; get buffer number for BAM
	STA zp6E
	TXA
	ASL A
	STA zp6E+1
	TAX
	LDA zp79	; track
	CMP V_029D,X
	BEQ B_EEA9
	INX
	STX zp6E+1
	CMP V_029D,X
	BEQ B_EEA9
	JSR S_EEC6
B_EEA9	LDA zp6E+1
	LDX zp78	; drive number
	STA V_029B,X
	ASL A
	ASL A		; times 4
	CLC
	ADC #$A1
	STA zp6C
	LDA #$02
	ADC #$00
	STA zp6C+1
	LDY #$00
	PLA
	STA zp6E+1
	PLA
	STA zp6E
	RTS
;$EEC6  --------
S_EEC6	LDX zp6E
	JSR S_EF4A
	LDA zp78	; drive number
	TAX
	ASL A
	ORA V_029B,X
	EOR #$01
	AND #$03
	STA zp6E+1
	JSR S_EF10
	LDA zp98	; buffer number
	ASL A
	TAX
	LDA zp79	; track
	ASL A
	ASL A		; times 4
	STA zp9A,X	; equal pointer in BAM field
	LDA zp6E+1
	ASL A
	ASL A
	TAY
B_EEEA	LDA (zp9A,X)
	STA V_02A1,Y
	LDA #$00
	STA (zp9A,X)	; zero in buffer
	INC zp9A,X	; increment buffer pointer
	INY
	TYA
	AND #$03
	BNE B_EEEA
	LDX zp6E+1
	LDA zp79	; track
	STA V_029D,X
	LDA V_02F9
	BNE B_EF0A
	JMP L_D6DD	; write block
	;
B_EF0A	ORA #$80
	STA V_02F9
	RTS
;$EF10  --------
S_EF10	TAY
	LDA V_029D,Y
	BEQ B_EF3B
	PHA
	LDA #$00
	STA V_029D,Y
	LDA zp98	; buffer number
	ASL A		; times 2
	TAX
	PLA
	ASL A
	ASL A
	STA zp9A,X
	TYA
	ASL A
	ASL A
	TAY
B_EF29	LDA V_02A1,Y
	STA (zp9A,X)	; write in buffer
	LDA #$00
	STA V_02A1,Y
	INC zp9A,X	; increment buffer pointer
	INY
	TYA
	AND #$03
	BNE B_EF29
B_EF3B	RTS

;$EF3C  -------- Clear BAM

S_EF3C	LDA zp78	; drive number
	ASL A		; * 2
	TAX		; index
	LDA #$00
	STA V_029D,X
	INX
	STA V_029D,X
	RTS
;$EF4A  --------
S_EF4A	LDA zpA8,X
	CMP #$FF
	BNE B_EF75
	TXA
	PHA
	JSR S_D3E4
	TAX
	BPL B_EF5D
	LDA #$70
	JSR L_C2B2	; 70, 'no channel'
B_EF5D	STX zp98
	PLA
	TAY
	TXA
	ORA #$80
	STA $00A8,Y
	ASL A
	TAX
	LDA V_F0C3	; 18, directory track
	STA zp08,X	; save
	LDA #$00	; 0
	STA zp09,X	; as sector
	JMP L_D6D9	; write block
	;
B_EF75	AND #$0F
	STA zp98	; buffer number
	RTS
;$EF7A  -------- Get buffer number for BAM
S_EF7A	LDA #$06
	LDX zp78	; drive number
	BNE B_EF83
	CLC
	ADC #$07	; gives 13 for drive 0
B_EF83	RTS
;$EF84  -------- Buffer number for BAM
S_EF84	JSR S_EF7A	; get buffer number
	TAX
	RTS
;$EF89  -------- Find and allocate free block
S_EF89	JSR S_DF79	; get track and sector number
	LDA #$03
	STA zp6E	; counter
	LDA #$01
	ORA V_02F9
	STA V_02F9
S_EF98	LDA zp6E	; save counter
	PHA
	JSR S_EE7C	; find BAM field for this track
	PLA
	STA zp6E	; get counter back
	LDA (zp6C),Y	; number of free blocks in track
	BNE B_EFDE	; blocks still free?
	LDA zp79	; track
	CMP V_F0C3	; 18, directory track?
	BEQ B_EFC5	; yes, 'disk full'
	BCC B_EFCA	; smaller, then next lower track
	INC zp79	; increment track number
	LDA zp79
	CMP V_F11A	; 36, highest track number plus one
	BNE S_EF98	; no, continue searching this track
	LDX V_F0C3	; 18, directory track
	DEX		; decrement
	STX zp79	; save as track number
	LDA #$00
	STA zp7A	; begin with sector number zero
	DEC zp6E	; decrement counter
	BNE S_EF98	; not yet zero, then continue
B_EFC5	LDA #$72
	JSR L_C2B2	; 72, 'disk full'
B_EFCA	DEC zp79	; decrement track number
	BNE S_EF98	; not yet 0, continue in this track
	LDX V_F0C3	; 18, directory track
	INX		; increment
	STX zp79	; save as track number
	LDA #$00
	STA zp7A	; begin with sector zero
	DEC zp6E	; decrement counter
	BNE S_EF98	; not yet zero, then continue
	BEQ B_EFC5	; else 'disk full'
B_EFDE	LDA zp7A	; sector number
	CLC
	ADC zp68	; plus step width (10)
	STA zp7A	; as new number
	LDA zp79	; track number
	JSR S_F0B6	; get maximum sector number
	STA V_024E
	STA V_024D	; and save
	CMP zp7A	; greater than selected sector number?
	BCS B_F000	; yes
	SEC		; else
	LDA zp7A	; sector number
	SBC V_024E	; minus maximum sector number
	STA zp7A	; save as new sector number
	BEQ B_F000	; zero?
	DEC zp7A	; else decrement sector number by one
B_F000	JSR S_F065	; check BAM, find free sector
	BEQ B_F008	; not found?
B_F005	JMP S_EDFB	; allocate block in BAM
	;
B_F008	LDA #$00
	STA zp7A	; sector zero
	JSR S_F065	; find free sector
	BNE B_F005	; found?
	JMP L_F060	; no, 'dir sector'
	;
	; Find free sector and allocate
	;
S_F014	LDA #$01
	ORA V_02F9
	STA V_02F9
	LDA zp7F
	PHA
	LDA #$01	; track counter
	STA zp7F
B_F023	LDA V_F0C3	; 18, directory track
	SEC
	SBC zp7F	; minus counter
	STA zp79	; save as track number
	BCC B_F036	; result <= zero?
	BEQ B_F036	; then try top half of directory
	JSR S_EE7C	; find BAM field for this track
	LDA (zp6C),Y	; number of free blocks in this track
	BNE B_F051	; free blocks exist
B_F036	LDA V_F0C3	; 18, directory track
	CLC
	ADC zp7F	; plus counter
	STA zp79	; save as track number
	INC zp7F	; increment counter
	CMP V_F11A	; 36, max track number plus one
	BCC B_F04A	; smaller, then ok
	LDA #$67
	JSR S_E781	; 67, 'illegal track or sector'
B_F04A	JSR S_EE7C	; find BAM field for this track
	LDA (zp6C),Y	; number of free blocks?
	BEQ B_F023	; no more free blocks?
B_F051	PLA
	STA zp7F
	LDA #$00
	STA zp7A	; sector 0
	JSR S_F065	; find free sector
	BEQ L_F060	; not found?
	JMP S_EDFB	; allocate block in BAM
	;
L_F060	LDA #$71
	JSR S_E781	; 71, 'dir error'
	; Find free sectors in current track
S_F065	JSR S_EE7C	; find BAM field for this track
	TYA		; point to number of free blocks
	PHA
	JSR S_F08B	; verify BAM
	LDA zp79	; track
	JSR S_F0B6	; get max number of sectors of the track
	STA V_024E	; save
	PLA
	STA zp6E	; save pointer
B_F078	LDA zp7A	; compare sector
	CMP V_024E	; with maximum number
	BCS B_F088	; greater than or equal to?
	JSR S_EE40	; get bit number of sector
	BNE B_F08A	; sector free?
	INC zp7A	; increment sector number
	BNE B_F078	; and check if free
B_F088	LDA #$00	; no sectors free
B_F08A	RTS

;$F08B  -------- Verify number of free blocks in BAM

S_F08B	LDA zp6E
	PHA
	LDA #$00
	STA zp6E	; counter to zero
	LDY V_F0C4	; 4, number of bytes per track in BAM
	DEY
B_F096	LDX #$07
B_F098	LDA (zp6C),Y
	AND V_EE54,X	; isolate bit
	BEQ B_F0A1
	INC zp6E	; increment counter of free sectors
B_F0A1	DEX
	BPL B_F098
	DEY
	BNE B_F096
	LDA (zp6C),Y	; compare with number on diskette
	CMP zp6E
	BNE B_F0B1	; not equal, then error
	PLA
	STA zp6E
	RTS
;$F0B1  --------
B_F0B1	LDA #$71
	JSR S_E781	; 71, 'dir error'
	; Establish number of sectors per track
S_F0B6	LDX V_F118 + 1	; 4 different values
B_F0B9	CMP V_F118 + 1,X	; track number
	DEX
	BCS B_F0B9	; not greater?
V_F0BF	LDA V_F114,X	; get number of sectors
	RTS		; Dummy subroutine
;$F0C3  --------
; $F0C3
V_F0C3	DB "R"-64
; $F0C4
V_F0C4	DB "D"-64,"D"-64
V_F0C6	BCC B_F0EC + 1
	LSR zp49,X
; $F0CA
	DB "DM"
; $F0CC
	DB "B"
	EOR zp50,X
	ROL zp43
; $F0D1
	DB "R"
; $F0D2
	DB "SN"
V_F0D4	CMP V_21F1,X
	LDX #$ED
	ORA V_424E
	CMP (zpE5),Y
	ADC V_7A04,X
V_F0E1	CMP (zpEB,X)
	CMP (zpC9),Y
V_F0E5	DB $CB,$CD
	CPY V_E8E2 + 1
	CMP #$CB
B_F0EC	CMP #$EC
	EOR (zpDD),Y
; $F0F0
	DB $1C,$9E,$1C
; $F0F3
V_F0F3	DB "R"
; $F0F4
	DB "WA"
V_F0F6	EOR L_5344
	BVC B_F14F + 1
V_F0FB	JMP L_5344	; *** Self mod. indirect jump!
	;
	BVC B_F154 + 1
; $F100
V_F100	DB "R"
V_F101	EOR zp45
; $F103
	DB "R"
; $F104
	DB "SE"
V_F106	JMP L_4751
	;
; $F109
	DB "R"
	JMP L_0201
	;
V_F10D	DB $00
; $F10E
V_F10E	DB $3F
V_F10F	DB $7F
V_F110	DB $BF
; $F111
V_F111	DB $FF,"E"-64,"F"-64
V_F114	ORA (zp12),Y
; $F116
	DB "S"-64,"U"-64
V_F118	EOR (zp04,X)
V_F11A	BIT zp1E+1
V_F11C	ORA V_0112,Y
; $F11F
	DB $FF,$FF,$01
	BRK
; $F123
V_F123	DB "C"-64,"D"-64
	ORA zp06
; $F127
	DB "G"-64,"G"-64
V_F129	AND (zp22,X)
; $F12B
	DB $23,$24
	AND zp26
; $F12F
	DB $27,$28
V_F131	AND #$02
; $F133
	DB "B"-64
; $F134
	DB "D"-64,"F"-64
	PHP
	PHP
; $F138
	DB "K"-64,"S"-64
	ASL zp58,X
	RTS
;$F13D  -------- Init drive
S_F13D	LDA #$6F
	STA zp00	; set data direction register
	AND #$68
	STA zp01	; peripheral control defaults
	LDX #$14
	STX V_4002
	LDX #$1F
	STX V_4005
B_F14F	LDA V_4002
	AND #$20
B_F154	BNE B_F159
	LDA #$08
	DB $2C
B_F159	LDA #$09
	STA zp66
	JSR S_C20D
	LDA #$FF
	STA zp31
	STA zp40
	LDA #$01
	STA zp22
	STA zp23
	LDA #$00
	STA zp4D
	LDY #$12	; Y = 18
	LDA #$01
B_F174	STA $0002,Y	; empty job code buffers
	DEY
	BPL B_F174
	LDA #$00
	STA V_4003	; port A to input (listening to machine...)
	LDA V_4002
	ORA #$08
	AND #$FC
	STA V_4002
	AND #$F7
	STA V_4002
	ORA #$08
	STA V_4002
	CLI		; enable IRQ
	RTS
;
;$F195  -------- IRQ routine
;
; An IRQ signal is generated by an 555 astable multivibrator
; every 16650 cycles for approx. 14 cycles long
;
	PHA
	TXA
	PHA
	TYA
	PHA
	TSX
	STX zp3A	; save stack pointer
L_F19D	LDY #$05
B_F19F	LDA $0002,Y	; check job queue for all DOS channels
	BMI B_F1CB	; job found?
	DEY
	BPL B_F19F
	LDA zp76	; drive LED flashing?
	BNE B_F1BA	; yes...
	LDA zp01
	ORA #$08	; drive LED off
	LDY zp96	; counter for drive led
	BEQ B_F1B5	; timeout?
	AND #$F7	; not, then set drive LED back on
B_F1B5	STA zp01
	JMP L_F1C8
	;
B_F1BA	DEC zp55	; decrease flash counter
	BPL L_F1C8	; timeout?
	LDA #$1E	; reset flash counter
	STA zp55
	LDA zp01
	EOR #$08	; toggle drive LED
	STA zp01
L_F1C8	JMP L_FA41
	;
B_F1CB	AND #$01
	TAX
	CMP zp31
	BEQ B_F1ED
	STA zp31
	AND #$01
	STA zp32
	ROR A
	ROR A
	ROR A
	STA zp38
	LDA V_4002
	AND #$3F
	ORA zp38
	STA V_4002
	JSR S_FA27
	JMP L_FA41
	;
B_F1ED	LDA zp2B
	BMI B_F1F4
	ASL A
	BPL B_F1F7
B_F1F4	JMP L_FA41
	;
B_F1F7	LDA #$20
	STA zp2B
	LDA zp01
	AND #$F7
	STA zp01
	LDY #$05
	STY zp32+1
B_F205	JSR S_F284
	BMI B_F224
L_F20A	DEC zp32+1
	BPL B_F205
	LDY zp34
	JSR S_F286
	LDA zp34+1
	STA zp3B
	ASL zp3B
	LDA #$60
	STA zp2B
	LDA (zp20),Y
	STA zp29
	JMP L_FA41
	;
B_F224	AND #$01
	CMP zp31
	BNE L_F20A
	LDA zp29
	BEQ B_F23E
	SEC
	LDA (zp20),Y
	SBC zp29
	BEQ B_F23E
	STA zp34+1
	LDA zp32+1
	STA zp34
	JMP L_F20A
	;
B_F23E	LDX #$04
	LDA (zp20),Y
	STA zp56
B_F244	CMP V_F118 + 1,X
	DEX
	BCS B_F244
	LDA V_F114,X
	STA zp57
	TXA
	ASL A
	ASL A
	ASL A
	ASL A
	ASL A
	STA zp38
	LDA zp01
	AND #$9F
	ORA zp38
	STA zp01
	LDA zp1D
	CMP #$40
	BEQ B_F26F
	CMP #$70
	BEQ B_F26C
	JMP L_F2A6
	;
B_F26C	JMP L_FB7A
	;
B_F26F	LDA zp01
	AND #$FC
	STA zp01
	LDA #$60
	STA zp2B
	LDA #$A4
	STA zp3B
	LDA #$01
	STA zp29
	JMP L_FA12
	;
S_F284	LDY zp32+1
S_F286	LDA $0002,Y
	PHA
	BPL B_F2A0
	AND #$78
	STA zp1D
	TYA
	ASL A
	ADC #$08
	STA zp20
	LDA #$00
	STA zp20+1
	TYA
	CLC
	ADC #$03
	STA zp27+1
B_F2A0	LDY #$00
	STY zp27
	PLA
	RTS
;$F2A6  --------
L_F2A6	LDA #$5A
	STA zp3C
B_F2AA	JSR L_F560
B_F2AD	BIT zp01
	BPL B_F2AD
	BIT V_4000
	LDA V_4001
	CMP #$52	; "R"
	BNE B_F2FD
	LDY #$00
	STA V_0111,Y
	INY
B_F2C1	BIT zp01
	BPL B_F2C1
	BIT V_4000
	LDA V_4001
	STA V_0111,Y
	INY
	CPY #$08
	BNE B_F2C1
	JSR S_F388
	LDY #$04
	LDA #$00
B_F2DA	EOR $0018,Y
	DEY
	BPL B_F2DA
	CMP #$00
	BNE B_F314
	LDA zp1A
	STA zp29
	LDA zp1D
	CMP #$30
	BEQ B_F306
	LDA zp14
	CMP zp18
	BNE B_F311
	LDA zp15
	CMP zp19
	BNE B_F311
	JMP L_F319
	;
B_F2FD	DEC zp3C
	BNE B_F2AA
	LDA #$02
	JSR L_FA12
B_F306	LDA zp18
	STA zp14
	LDA zp19
	STA zp15
L_F30E	LDA #$01
	DB $2C
B_F311	LDA #$0B
	DB $2C
B_F314	LDA #$09
	JMP L_FA12
	;
L_F319	LDA #$7F
	STA zp3D
	LDA zp1B
	CLC
	ADC #$02
	CMP zp57
	BCC B_F328
	SBC zp57
B_F328	STA zp3E
	LDX #$05
	STX zp32+1
	LDX #$FF
B_F330	JSR S_F284
	BPL B_F374
	STA zp38
	AND #$01
	CMP zp31
	BNE B_F374
	LDY #$00
	LDA (zp20),Y
	CMP zp56
	BNE B_F374
	LDY #$01
	SEC
	LDA (zp20),Y
	SBC zp3E
	BPL B_F351
	CLC
	ADC zp57
B_F351	CMP zp3D
	BCS B_F374
	PHA
	LDA zp1D
	BEQ B_F36F
	PLA
	CMP #$09
	BCC B_F374
	CMP #$0C
	BCS B_F374
B_F363	STA zp3D
	LDA zp32+1
	TAX
	CLC
	ADC #$03
	STA zp27+1
	BNE B_F374
B_F36F	PLA
	CMP #$06
	BCC B_F363
B_F374	DEC zp32+1
	BPL B_F330
	TXA
	BPL B_F37E
	JMP L_FA41
	;
B_F37E	STX zp32+1
	JSR S_F284
	LDA zp1D
	JMP L_F3FC
	;
S_F388	LDA zp27
	PHA
	LDA zp27+1
	PHA
	LDA #$11
	STA zp27
	LDA #$01
	STA zp27+1
	LDA #$00
	STA zp2D
	JSR S_F928
	LDA zp44
	STA zp1A
	LDA zp43
	STA zp1B
	LDA zp42
	STA zp1C
	JSR S_F928
	LDA zp41
	STA zp19
	LDA zp42
	STA zp18
	PLA
	STA zp27+1
	PLA
	STA zp27
	RTS
;$F3BB  --------
S_F3BB	LDA zp27+1
	STA zp1E+1
	LDA #$01
	STA zp27+1
	LDA #$11
	STA zp2D
	LDA #$08
	STA zp41
	LDA zp1C
	STA zp42
	LDA zp1B
	STA zp43
	LDA zp1A
	STA zp44
	JSR S_F80C
	LDA zp19
	STA zp41
	LDA zp18
	STA zp42
	LDA #$00
	STA zp43
	STA zp44
	JSR S_F80C
	LDA zp1E+1
	STA zp27+1
	RTS
;$F3F0  --------
S_F3F0	LDA #$00
	STA V_026C
	BEQ B_F3F9
	;
	; Set LED flag
	;
L_F3F7	LDA #$E0
	; Set LED flag to accu
B_F3F9	STA zp76	; drive LED flag for IRQ routine
	RTS
;$F3FC  --------
L_F3FC	CMP #$00
	BEQ B_F403
	JMP L_F57D
	;
B_F403	JSR S_F513
B_F406	BIT zp01
	BPL B_F406
	LDA V_4001
	STA zpFA
	AND #$F8
	TAX
	LDA V_F70C,X
	STA zpF9
	LDA zpFA
	AND #$07
	STA zpFA
B_F41D	BIT zp01
	BPL B_F41D
	LDA V_4001
	STA zpFB
	AND #$C0
	ORA zpFA
	TAX
	LDA V_F70C,X
	ORA zpF9
	PHA
	BNE B_F464
	BEQ B_F464
B_F435	BIT zp01
	BPL B_F435
	LDA V_4001
	STA zpFA
	AND #$F8
	TAX
	LDA V_F70C,X
	STA zpF9
	LDA zpFA
	AND #$07
	STA zpFA
B_F44C	BIT zp01
	BPL B_F44C
	LDA V_4001
	STA zpFB
	AND #$C0
	ORA zpFA
	TAX
	LDA V_F70C,X
	ORA zpF9
	STA (zp27),Y
	INY
	BEQ B_F4D9
B_F464	LDA zpFB
	AND #$3E
	TAX
	LDA V_F70C,X
	STA zpF9
	LDA zpFB
	AND #$01
	STA zpFB
B_F474	BIT zp01
	BPL B_F474
	LDA V_4001
	STA zpFC
	AND #$F0
	ORA zpFB
	TAX
	LDA V_F70C + 2,X
	ORA zpF9
	STA (zp27),Y
	INY
	LDA zpFC
	AND #$0F
	STA zpFC
B_F490	BIT zp01
	BPL B_F490
	LDA V_4001
	STA zpFD
	AND #$80
	ORA zpFC
	TAX
	LDA V_F71C,X
	STA zpF9
	LDA zpFD
	AND #$7C
	TAX
	LDA V_F70C + 1,X
	ORA zpF9
	STA (zp27),Y
	INY
	LDA zpFD
	AND #$03
	STA zpFD
B_F4B6	BIT zp01
	BPL B_F4B6
	LDA V_4001
	STA zpFA
	AND #$E0
	ORA zpFD
	TAX
	LDA V_F729,X
	STA zpF9
	LDA zpFA
	AND #$1F
	TAX
	LDA V_F6FF,X
	ORA zpF9
	STA (zp27),Y
	INY
	JMP B_F435
	;
B_F4D9	LDA zpFB
	AND #$3E
	TAX
	LDA V_F70C,X
	STA zpF9
	LDA zpFB
	AND #$01
	STA zpFB
B_F4E9	BIT zp01
	BPL B_F4E9
	LDA V_4001
	AND #$F0
	ORA zpFB
	TAX
	LDA V_F70C + 2,X
	ORA zpF9
	STA zpFA
	PLA
	CMP #$07
	BNE B_F50B
	JSR S_F60A
	CMP zpFA
	BEQ B_F50E
	LDA #$05
	DB $2C
B_F50B	LDA #$04
	DB $2C
B_F50E	LDA #$01
	JMP L_FA12
	;
S_F513	JSR S_F519
	JMP L_F560
	;
S_F519	LDA zp14
	STA zp18
	LDA zp15
	STA zp19
	LDY #$00
	LDA (zp20),Y
	STA zp1A
	INY
	LDA (zp20),Y
	STA zp1B
	LDA #$00
	EOR zp18
	EOR zp19
	EOR zp1A
	EOR zp1B
	STA zp1C
	JSR S_F3BB
	LDA #$5A
	STA zp3C
B_F53F	JSR L_F560
B_F542	LDA V_0111,Y
B_F545	BIT zp01
	BPL B_F545
	CMP V_4001
	BNE B_F554
	INY
	CPY #$08
	BNE B_F542
	RTS
;$F554  --------
B_F554	DEC zp3C
	BNE B_F53F
	LDA #$02
	DB $2C
L_F55B	LDA #$03
	JMP L_FA12
	;
L_F560	LDY #$12
B_F562	LDX #$FF
B_F564	LDA V_4002
	AND #$40
	BEQ B_F574
	DEX
	BNE B_F564
	DEY
	BNE B_F562
	JMP L_F55B
	;
B_F574	LDA V_4001
	BIT V_4000
	LDY #$00
	RTS
;$F57D  --------
L_F57D	CMP #$10
	BEQ B_F584
	JMP L_F6BA
	;
B_F584	JSR S_F60A
	LDA zp01
	AND #$10
	BNE B_F592
	LDA #$08
	JMP L_FA12
	;
B_F592	JSR S_F8CD + 2
	JSR S_F519
	LDY #$09
B_F59A	BIT zp01
	BPL B_F59A
	BIT V_4000
	DEY
	BNE B_F59A
	LDA #$FF
	STA V_4004
	LDA V_4002
	AND #$EF
	STA V_4002
	LDA #$FF
	LDY #$05
	STA V_4001
	BIT V_4000
B_F5BB	BIT zp01
	BPL B_F5BB
	BIT V_4000
	DEY
	BNE B_F5BB
	LDY #$BB
B_F5C7	LDA $0060,Y
B_F5CA	BIT zp01
	BPL B_F5CA
	BIT V_4000
	STA V_4001
	INY
	BNE B_F5C7
B_F5D7	LDA (zp27),Y
B_F5D9	BIT zp01
	BPL B_F5D9
	BIT V_4000
	STA V_4001
	INY
	BNE B_F5D7
B_F5E6	BIT zp01
	BPL B_F5E6
	BIT V_4000
	LDA V_4002
	ORA #$10
	STA V_4002
	LDA #$00
	STA V_4004
	JSR S_F618
	LDY zp32+1
	LDA $0002,Y
	EOR #$30
	STA $0002,Y
	JMP L_F2A6
	;
S_F60A	LDY #$00
	STY zp30
B_F60E	LDA (zp27),Y
	EOR zp30
	STA zp30
	INY
	BNE B_F60E
	RTS
;$F618  --------
S_F618	LDA #$60
	STA zp27
	LDA zp27+1
	STA zp36
	LDA #$00
	STA zp27+1
	STA zp37
	LDA #$BB
	STA zp2D
	STA zp2E
	JSR S_F928
	LDA zp41
	STA zp2F
	LDY zp2E
	LDA zp42
	STA $0060,Y
	INY
	LDA zp43
	STA $0060,Y
	INY
	LDA zp44
	STA $0060,Y
	INY
	STY zp2E
B_F649	JSR S_F928
	LDY zp2E
	LDA zp41
	STA $0060,Y
	INY
	LDA zp42
	STA $0060,Y
	INY
	BEQ B_F66C
	LDA zp43
	STA $0060,Y
	INY
	LDA zp44
	STA $0060,Y
	INY
	STY zp2E
	BNE B_F649
B_F66C	LDA zp43
	STA (zp27),Y
	INY
	LDA zp44
	STA (zp27),Y
	INY
	STY zp2E
B_F678	JSR S_F928
	LDY zp2E
	LDA zp41
	STA (zp27),Y
	INY
	LDA zp42
	STA (zp27),Y
	INY
	LDA zp43
	STA (zp27),Y
	INY
	LDA zp44
	STA (zp27),Y
	INY
	STY zp2E
	CPY #$BB
	BCC B_F678
	LDA #$45	; "E"
	STA zp1E
	LDA zp27+1
	STA zp1E+1
	LDY #$BA
B_F6A1	LDA (zp27),Y
	STA (zp1E),Y
	DEY
	BNE B_F6A1
	LDA (zp27),Y
	STA (zp1E),Y
	LDX #$BB
B_F6AE	LDA V_011B,Y
	STA (zp27),Y
	INY
	INX
	BNE B_F6AE
	STX zp3F
	RTS
;$F6BA  --------
L_F6BA	CMP #$20
	BEQ B_F6C1
	JMP L_F6F9
	;
B_F6C1	JSR S_F60A
	JSR S_F8CD + 2
	JSR S_F513
	LDY #$BB
B_F6CC	LDA $0060,Y
B_F6CF	BIT zp01	; wait for byte-ready
	BPL B_F6CF
	BIT V_4000	; reset byte-ready signal
	EOR V_4001	; read and ...
	BNE B_F6F4	; ... verify with buffer contents
	INY
	BNE B_F6CC
B_F6DE	LDA (zp27),Y
B_F6E0	BIT zp01	; wait for byte-ready
	BPL B_F6E0
	BIT V_4000	; reset byte-ready signal
	EOR V_4001	; read and ...
	BNE B_F6F4	; ... verify with buffer contents
	INY
	CPY #$FD	; repeat $FC (252) times
	BNE B_F6DE
	JMP L_F30E
	;
B_F6F4	LDA #$07
	JMP L_FA12
	;
L_F6F9	JSR S_F519
	JMP L_F30E
	;
; $F6FF
V_F6FF	DB $FF
V_F700	DB $FF,$FF
; $F702
	DB $FF,$FF,$FF
; $F705
	DB $FF,$FF,$FF
	PHP
	BRK
	ORA (zpFF,X)
; $F70C
V_F70C	DB "L"-64
V_F70D	DB "D"-64
V_F70E	DB "E"-64
; $F70F
	DB $FF,$FF,"B"-64
; $F712
	DB "C"-64,$FF
; $F714
	DB "O"-64,"F"-64,"G"-64
; $F717
	DB $FF,"I"-64,"J"-64
; $F71A
	DB "K"-64,$FF
V_F71C	ORA V_800E
; $F71F
	DB $FF,$00,$00
	BPL B_F761 + 3
; $F724
	DB $FF,$20,$C0
	RTS
;$F728  --------
	RTI
;$F729  --------
V_F729	LDY #$50	; "P"
	CPX #$FF
; $F72D
	DB $FF,$FF,$02
	JSR S_3008
; $F733
	DB $FF,$FF,$00
B_F736	BEQ B_F736 + 1
	RTS
;$F739  --------
B_F739	ORA (zp70,X)
; $F73B
	DB $FF,$FF,$FF
	BCC B_F742 + 1
	LDY #$0C
B_F742	BCS B_F742 + 1
; $F744
	DB $FF,$04,$D0
; $F747
B_F747	DB $FF,$E0,$05
; $F74A
	DB $80,$FF
B_F74C	BCC B_F74C + 1
	PHP
; $F74F
	DB "L"-64,$FF,"O"-64
	ORA #$0D
; $F754
	DB $80,$02
; $F756
	DB $FF,$FF,$FF
; $F759
	DB $03,$FF
; $F75B
	DB $FF,$00,$FF
; $F75E
	DB $FF,$0F,$FF
; $F761
B_F761	DB $0F,$FF,$FF
B_F763 + 1	BPL B_F76B + 1
; $F766
	DB $FF,$FF,$FF
; $F769
	DB $07,$00
B_F76B	JSR S_FF9F + 1	; *** Self mod. indirect jump!
; $F76E
	DB $FF,$06,$FF
	ORA #$FF
; $F773
	DB $FF,$C0,$0A
; $F776
	DB $FF,$FF,$FF
; $F779
	DB $0B,$FF
; $F77B
B_F77B	DB $FF,$40,$FF
; $F77E
	DB $FF,$07,$FF
	ORA $FFFF	;
	BVC B_F793 + 1
; $F786
	DB $FF,$FF,$FF
; $F789
	DB $FF,$10,$30
B_F78C	BCS B_F78C + 1
	BRK
; $F78F
	DB "D"-64,"B"-64
	ASL zp0A
B_F793	ASL $FF7E + 2	;
; $F796
B_F796	DB $FF,$FF,$FF
; $F799
	DB $FF,$FF,$FF
	JSR S_08FF	;
	ORA #$80
	BPL B_F763
	BVC B_F7D4 + 1
	BMI B_F797
	BVS B_F739
	BCS B_F77B
; $F7AB
	DB $FF,$FF,$FF
	BRK
	ASL A
; $F7B0
	DB $FF,$FF,$FF
; $F7B3
	DB $FF,$F0,$FF
; $F7B6
	DB $FF,$FF,$FF
; $F7B9
	DB $FF,$FF,$FF
	RTS
;$F7BD  --------
; $F7BD
	DB $FF,"A"-64,"K"-64
; $F7C0
	DB $FF,$FF,$FF
; $F7C3
	DB $FF,$70,$FF
; $F7C6
	DB $FF,$FF,$FF
; $F7C9
	DB $FF,$C0,$F0
B_F7CC	BNE B_F7CC + 1
	ORA (zp05,X)
; $F7D0
	DB "C"-64,"G"-64
; $F7D2
	DB "K"-64,$FF
B_F7D4	BCC B_F7D4 + 1
; $F7D6
	DB $FF,$FF,$FF
; $F7D9
	DB $FF,$FF,$FF
	LDY #$FF
; $F7DE
	DB "L"-64,"M"-64,$FF
; $F7E1
	DB $FF,$FF,$FF
B_F7E4	BCS B_F7E4 + 1
; $F7E6
	DB $FF,$FF,$FF
; $F7E9
	DB $FF,$40,$60
	CPX #$FF
; $F7EE
	DB "D"-64,"N"-64
; $F7F0
	DB $FF,$FF,$FF
; $F7F3
	DB $FF,$D0,$FF
; $F7F6
	DB $FF,$FF,$FF
; $F7F9
	DB $FF,$FF,$FF
	CPX #$FF
	ORA zpFF
; $F800
V_F800	DB $FF,$FF,$FF
; $F803
	DB $FF,$FF,$FF
; $F806
	DB $FF,$FF,$FF
; $F809
	DB $FF,"Pp"
	;
	; Convert 4 binary bytes to 5 GCR bytes
	;
S_F80C	LDA #$00
	STA zp45+1
	STA zp49
	LDY zp2D
	LDA zp41
	AND #$F0	; isolate hi-nibble
	LSR A
	LSR A
	LSR A
	LSR A		; and rotate to lower nibble
	TAX		; use as index in table
	LDA V_F8BF,X
	ASL A
	ASL A
	ASL A		; times 8
	STA zp45
	LDA zp41
	AND #$0F	; isolate lower nibble
	TAX		; as index in table
	LDA V_F8BF,X
	ROR A
	ROR zp45+1
	ROR A
	ROR zp45+1
	AND #$07
	ORA zp45
	STA (zp27),Y	; in buffer
	INY		; increment buffer
	LDA zp42
	AND #$F0	; isolate upper nibble
	LSR A
	LSR A
	LSR A
	LSR A		; shift to upper nibble
	TAX		; as index in table
	LDA V_F8BF,X
	ASL A
	ORA zp45+1
	STA zp45+1
	LDA zp42
	AND #$0F	; lower nibble
	TAX		; as index
	LDA V_F8BF,X
	ROL A
	ROL A
	ROL A
	ROL A
	STA zp47
	ROL A
	AND #$01
	ORA zp45+1
	STA (zp27),Y	; in buffer
	INY		; increment buffer
	LDA zp43
	AND #$F0	; isolate hi-nibble
	LSR A
	LSR A
	LSR A
	LSR A
	TAX
	LDA V_F8BF,X
	CLC
	ROR A
	ORA zp47
	STA (zp27),Y	; in buffer
	INY		; increment buffer pointer
	ROR A
	AND #$80
	STA zp48
	LDA zp43
	AND #$0F	; lower nibble
	TAX		; as index
	LDA V_F8BF,X
	ASL A
	ASL A
	AND #$7C
	ORA zp48
	STA zp48
	LDA zp44
	AND #$F0	; isolate hi-nibble
	LSR A
	LSR A
	LSR A
	LSR A		; shift to lower nibble
	TAX		; as index in table
	LDA V_F8BF,X
	ROR A
	ROR zp49
	ROR A
	ROR zp49
	ROR A
	ROR zp49
	AND #$03
	ORA zp48
	STA (zp27),Y	; in buffer
	INY		; increment buffer pointer
	BNE B_F8AF
	LDA zp1E+1
	STA zp27+1
	LDA #$00
	STA zp27
B_F8AF	LDA zp44
	AND #$0F	; lower nibble
	TAX		; as index
	LDA V_F8BF,X
	ORA zp49
	STA (zp27),Y	; in buffer
	INY		; increment buffer pointer
	STY zp2D	; and save
	RTS
;$F8BF  -------- GCR (5-bit) nybble table
V_F8BF	DB $0A,$0B,$12,$13,$0E,$0F,$16,$17
	DB $09,$19,$1A,$1B,$0D,$1D,$1E,$15
	;
	; Convert 260 bytes to 325 bytes group code
	;
	LDA #$00
	STA zp1E
	STA zp2E
	LDA #$60
	STA zp27
	LDA #$BB
	STA zp2D
	STA zp3F
	LDA zp27+1
	STA zp1E+1
	LDA #$00
	STA zp27+1
	LDA #$07
	STA zp41
	LDY zp2E
	LDA (zp1E),Y
	STA zp42
	INY
	LDA (zp1E),Y
	STA zp43
	INY
	LDA (zp1E),Y
	STA zp44
	INY
B_F8FC	STY zp2E
	JSR S_F80C
	LDY zp2E
	LDA (zp1E),Y
	STA zp41
	INY
	BEQ B_F91B
	LDA (zp1E),Y
	STA zp42
	INY
	LDA (zp1E),Y
	STA zp43
	INY
	LDA (zp1E),Y
	STA zp44
	INY
	BNE B_F8FC
B_F91B	LDA zp30
	STA zp42
	LDA #$00
	STA zp43
	STA zp44
	JMP S_F80C
	;
	; Convert 5 GCR bytes to 4 binary bytes
	;
S_F928	LDY zp2D
	LDA (zp27),Y
	TAX
	AND #$F8
	STA zp45
	TXA
	AND #$07
	STA zp45+1
	INY
	BNE B_F93F
	LDA zp36
	STA zp27+1
	LDY zp37
B_F93F	LDA (zp27),Y
	TAX
	AND #$C0
	ORA zp45+1
	STA zp45+1
	TXA
	AND #$3E
	STA zp47
	TXA
	AND #$01
	STA zp48
	INY
	LDA (zp27),Y
	TAX
	AND #$F0
	ORA zp48
	STA zp48
	TXA
	AND #$0F
	STA zp49
	INY
	LDA (zp27),Y
	TAX
	AND #$80
	ORA zp49
	STA zp49
	TXA
	AND #$7C
	STA zp49+1
	TXA
	AND #$03
	STA zp4B
	INY
	BNE B_F980
	LDA zp36
	STA zp27+1
	LDY zp37
	STY zp27
B_F980	LDA (zp27),Y
	TAX
	AND #$E0
	ORA zp4B
	STA zp4B
	TXA
	AND #$1F
	STA zp4C
	INY
	STY zp2D
	LDX zp45
	LDA V_F70C,X
	LDX zp45+1
	ORA V_F70C,X
	STA zp41
	LDX zp47
	LDA V_F70C,X
	LDX zp48
	ORA V_F70E,X
	STA zp42
	LDX zp49
	LDA V_F71C,X
	LDX zp49+1
	ORA V_F70D,X
	STA zp43
	LDX zp4B
	LDA V_F729,X
	LDX zp4C
	ORA V_F6FF,X
	STA zp44
	RTS
;$F9C2  --------
	LDA #$00
	STA zp2D
	STA zp1E
	STA zp2E
	LDA #$01
	STA zp36
	LDA #$1B
	STA zp37
	LDA zp27+1
	STA zp1E+1
	JSR S_F928
	LDA zp41
	STA zp2F
	LDY zp2E
	LDA zp42
	STA (zp1E),Y
	INY
	LDA zp43
	STA (zp1E),Y
	INY
	LDA zp44
	STA (zp1E),Y
	INY
B_F9EE	STY zp2E
	JSR S_F928
	LDY zp2E
	LDA zp41
	STA (zp1E),Y
	INY
	BEQ B_FA0D
	LDA zp42
	STA (zp1E),Y
	INY
	LDA zp43
	STA (zp1E),Y
	INY
	LDA zp44
	STA (zp1E),Y
	INY
	BNE B_F9EE
B_FA0D	LDA zp1E+1
	STA zp27+1
	RTS
;$FA12  --------
L_FA12	LDY zp32+1
	STA $0002,Y
	LDA zp3F
	BEQ B_FA1E
	JSR S_F618
B_FA1E	JSR S_FA36
	LDX zp3A
	TXS
	JMP L_F19D
	;
S_FA27	LDA #$A0
	STA zp2B
	LDA zp01
	ORA #$04
	STA zp01
	LDA #$A7
	STA zp39
	RTS
;$FA36  --------
S_FA36	LDA zp2B
	ORA #$10
	STA zp2B
	LDA #$FF
	STA zp39
	RTS
;$FA41  --------
L_FA41	LDA zp01	;
	AND #$10	; set write mode
	CMP zp24	; check previous mode, changed?
	STA zp24	;
	BNE B_FA51	; changed...
	LDA zpFE
	BNE B_FA61
	BEQ B_FA71
B_FA51	LDA #$FF
	STA zpFE
	LDA zp01
	ORA #$04	; set drive motor on
	STA zp01
	LDA #$01
	STA zp22
	BNE B_FA71
B_FA61	DEC zpFE
	BNE B_FA71
	LDA zp2B
	CMP #$00
	BNE B_FA71
	LDA zp01
	AND #$FB
	STA zp01
B_FA71	LDA zp54
	BEQ B_FA88
	CMP #$02
	BNE B_FA7F
	LDA #$00
	STA zp54
	BEQ B_FA88
B_FA7F	STA zp3B
	LDA #$02
	STA zp54
	JMP L_FAC5
	;
B_FA88	LDX zp31
	BMI B_FA93
	LDA zp2B
	TAY
	CMP #$20
	BNE B_FA96
B_FA93	JMP L_FB00
	;
B_FA96	DEC zp39
	BNE B_FAB5
	TYA
	BPL B_FAA1
	AND #$7F
	STA zp2B
B_FAA1	AND #$10
	BEQ B_FAB5
	LDA zp01
	AND #$FB
	STA zp01
	LDA #$FF
	STA zp31
	LDA #$00
	STA zp2B
	BEQ B_FA93
B_FAB5	TYA
	AND #$40
	BNE B_FABD
	JMP L_FB00
	;
B_FABD	LDA zp4D
	BNE B_FADC
	LDA zp3B
	BEQ B_FAD3
L_FAC5	LDA zp3B
	BPL B_FAED
	INC zp3B
	LDA zp01
	SEC
	SBC #$01
	JMP L_FAF4
	;
B_FAD3	LDA #$02
	STA zp39
	STA zp4D
	JMP L_FB00
	;
B_FADC	DEC zp39
	BNE L_FB00
	LDA zp2B
	AND #$BF
	STA zp2B
	LDA #$00
	STA zp4D
	JMP L_FB00
	;
B_FAED	DEC zp3B
	LDA zp01
	CLC
	ADC #$01
L_FAF4	AND #$03
	STA zp3C	; note drive head control state
	LDA zp01
	AND #$FC
	ORA zp3C
	STA zp01	; step motor
L_FB00	PLA
	TAY
	PLA
	TAX
	PLA
	RTI		; return from interrupt
;$FB06  --------
S_FB06	LDA #$05
	STA V_0100
B_FB0B	LDX #$1C
	JSR $FD87	; write $1c * 256 GCR gap bytes
	LDX #$14	; counter for repeat, exactly half of the 1541...
	LDY #$00	; .. due to 2x CPU clock frequency
	LDA #$FF
	STA V_4001	; $FF to write head
B_FB19	BIT zp01	; wait for byte-ready
	BPL B_FB19
	BIT V_4000	; delete byte-ready signal
	DEY
	BNE B_FB19
	DEX
	BNE B_FB19	; repeat 10240 / 2 times (1541 has X = #$28 !)
	JSR $FD79
	LDY #$FF
B_FB2B	LDX #$FF
B_FB2D	LDA V_4002
	AND #$40
	BEQ B_FB44
	DEX
	BNE B_FB2D
	DEY
	BNE B_FB2B
B_FB3A	DEC V_0100
	BNE B_FB0B
	LDA #$02
	JMP $FD6F
	;
B_FB44	LDY #$00
	LDX #$00
B_FB48	LDA V_4002
	AND #$40	; check SYNC
	BEQ B_FB48	; not encountered yet?
B_FB4F	LDA V_4002	; read SYNC
	INY
	BNE B_FB56	; Y not zero yet?
	INX
B_FB56	AND #$40	; check SYNC
	BNE B_FB4F	; no SYNC found, back
	STX V_0102	; found SYNC, note X and Y count
	STY V_0101
	LDA #$00
	STA zpFF
	LDX #$08
B_FB66	LDA V_F129,X
	CMP V_0102
	BEQ B_FB73
	DEX
	BPL B_FB66
	BMI B_FB3A
B_FB73	LDA V_F131 + 1,X
	STA V_0103
	RTS
;$FB7A  --------
L_FB7A	LDA zp40
	BPL B_FB99
	LDA #$60
	STA zp2B
	LDA #$01
	STA zp29
	STA zp40
	LDA #$A4
	STA zp3B
	LDA zp01
	AND #$FC	; drive motor off
	STA zp01
	LDA #$0A
	STA zp51
	JMP L_FA41
	;
B_FB99	LDY #$00
	LDA (zp20),Y
	CMP zp40
	BEQ B_FBA8
	LDA zp40
	STA (zp20),Y
	JMP L_FA41
	;
B_FBA8	LDA zp01
	AND #$10	; check write protect sensor
	BNE B_FBB3	; not protected...
	LDA #$08
	JMP $FD68
	;
B_FBB3	LDA zpFF
	BPL B_FBBA
	JSR S_FB06
B_FBBA	LDA V_0103
	STA zp4E
	CLC
	LDA #$03
	STA zp20+1
	LDA #$00
	STA zp20
	STA zp53
	LDY #$00
B_FBCC	LDA #$08
	STA (zp20),Y
	INY
	LDA #$00
	STA (zp20),Y
	INY
	LDA zp53
	STA (zp20),Y
	INY
	LDA zp40
	STA (zp20),Y
	INY
	LDA zp15
	STA (zp20),Y
	INY
	LDA zp14
	STA (zp20),Y
	INY
	LDA #$0F
	STA (zp20),Y
	INY
	STA (zp20),Y
	INY
	TYA
	PHA
	LDX #$07
	LDA #$00
	STA zp30
B_FBFA	DEY
	LDA (zp20),Y
	EOR zp30
	STA zp30
	DEX
	BNE B_FBFA
	STA (zp20),Y
	PLA
	TAY
	INC zp53
	LDA zp53
	CMP zp57
	BCC B_FBCC
	JSR $FDA9
	LDY #$BA
B_FC15	LDA (zp20),Y
	LDX #$45	; "E"
	STX zp20
	STA (zp20),Y
	LDX #$00
	STX zp20
	DEY
	CPY #$FF
	BNE B_FC15
	LDY #$44	; "D"
B_FC28	LDA V_011B,Y
	STA (zp20),Y
	DEY
	BPL B_FC28
	CLC
	LDA #$03
	ADC #$02
	STA zp27+1
	LDA #$00
	TAY
B_FC3A	STA (zp27),Y
	INY
	BNE B_FC3A
	JSR S_F60A
	JSR S_F8CD + 2
	LDA #$00
	STA zp4E+1
	LDX #$03
	JSR $FD87	; write 3 * 256 GCR gap bytes
L_FC4E	LDA #$FF
	STA V_4001	; $FF to write head
	LDY #$05	; write 5 pieces of $FF (sync) bytes
B_FC55	BIT zp01	; wait on byte-ready
	BPL B_FC55
	BIT V_4000	; clear byte-ready signal
	DEY
	BNE B_FC55	; repeat
	LDA #$0A
	STA zp50
	LDY zp4E+1
B_FC65	BIT zp01	; wait on byte-ready
	BPL B_FC65
	BIT V_4000	; clear byte-ready signal
	LDA (zp20),Y
	STA V_4001
	INY
	DEC zp50	; repeat 10 times
	BNE B_FC65
	LDY #$09
B_FC78	BIT zp01	; wait on byte-ready
	BPL B_FC78
	BIT V_4000	; clear byte-ready signal
	LDA #$55	; GCR code for inter-sector gap
	STA V_4001	; write to disk
	DEY
	BNE B_FC78	; repeat this 9 times
	LDA #$FF
	LDY #$05
B_FC8B	BIT zp01	; wait on byte-ready
	BPL B_FC8B
	BIT V_4000	; clear byte-ready signal
	STA V_4001	; write 5 sync bytes to disk
	DEY
	BNE B_FC8B
	LDY #$BB
B_FC9A	BIT zp01
	BPL B_FC9A	; wait on byte-ready
	BIT V_4000	; clear byte-ready signal
	LDA $0060,Y
	STA V_4001	; write buffer contents to disk
	INY
	BNE B_FC9A	; repeat $BB (187) times
B_FCAA	BIT zp01
	BPL B_FCAA	; wait on byte-ready
	BIT V_4000	; clear byte-ready signal
	LDA (zp27),Y
	STA V_4001	; write buffer contents to disk
	INY
	BNE B_FCAA
	LDA #$55	; GAP
	LDY zp4E
B_FCBD	BIT zp01
	BPL B_FCBD	; wait on byte-ready
	BIT V_4000	; clear byte-ready signal
	STA V_4001	; write GCR GAP
	DEY
	BNE B_FCBD
	LDA zp4E+1
	CLC
	ADC #$0A	; add 10 (interleave)
	STA zp4E+1
	DEC zp53
	BEQ B_FCD8
	JMP L_FC4E
	;
B_FCD8	BIT zp01	; wait on byte-ready
	BPL B_FCD8
	BIT V_4000	; clear byte-ready signal
B_FCDF	BIT zp01
	BPL B_FCDF	; wait on byte-ready
	BIT V_4000	; clear byte-ready signal
	JSR $FD79
	LDA #$C8
	STA zp52
B_FCED	LDA #$00
	STA zp4E+1
	LDA zp57
	STA zp53
B_FCF5	LDA #$0A
	STA zp50
	JSR L_F560
	LDY zp4E+1
B_FCFE	LDA (zp20),Y
B_FD00	BIT zp01	; wait on byte-ready
	BPL B_FD00
	BIT V_4000	; clear byte-ready signal
	CMP V_4001	; verify
	BNE $FD1B
	INY
	DEC zp50
	BNE B_FCFE
	CLC
	LDA zp4E+1
	ADC #$0A
	STA zp4E+1
	JMP $FD24
	;
$FD1B	DEC zp52
	BNE B_FCED
	LDA #$06
	JMP $FD68
	;
$FD24	JSR L_F560
	LDY #$BB
$FD29	LDA $0060,Y
$FD2C	BIT zp01	; wait on byte-ready
	BPL $FD2C
	BIT V_4000	; clear byte-ready signal
	CMP V_4001	; verify what's read
	BNE $FD1B
	INY
	BNE $FD29
$FD3B	LDA (zp27),Y
$FD3D	BIT zp01	; wait on byte-ready
	BPL $FD3D
	BIT V_4000	; clear byte-ready signal
	CMP V_4001	; verify
	BNE $FD1B
	INY
	BNE $FD3B
	DEC zp53
	BNE B_FCF5
	INC zp40
	LDA zp40
	CMP #$24
	BCS $FD5B
	JMP L_FA41
	;
$FD5B	LDA #$FF
	STA zp40
	LDA #$00
	STA zp3F
	LDA #$01
	JMP L_FA12
	;
$FD68	DEC zp51
	BEQ $FD6F
	JMP L_FA41
	;
$FD6F	LDY #$FF
	STY zp40
	INY
	STY zp3F
	JMP L_FA12
	;
	; Initialise read mode
	;
$FD79	LDA V_4002
	ORA #$10
	STA V_4002	; set head to read mode
	LDA #$00	; TIA port B to input
	STA V_4004
	RTS

;$FD87  -------- Write GCR gap bytes ($55) to - erase - current track

$FD87	LDA V_4002
	AND #$EF
	STA V_4002	; set head to write mode
	LDA #$FF
	STA V_4004	; TIA port B to output
	LDA #$55	; GCR gap byte
	STA V_4001	; write...
	LDY #$00
$FD9B	BIT zp01	; wait on byte-ready
	BPL $FD9B
	BIT V_4000	; clear byte-ready signal
	DEY
	BNE $FD9B
	DEX
	BNE $FD9B	; repeat this 256 * X times
	RTS

;$FDA9  -------- Convert header in buffer 0 to GCR code

$FDA9	LDA #$00
	STA zp27+1
	STA zp1E
	STA zp2E
	LDA #$BB
	STA zp2D
	LDA #$60
	STA zp27
	CLC
	LDA #$03
	STA zp1E+1	; source buffer is at $1E/$1F
$FDBE	LDY zp2E
	LDA (zp1E),Y	; read 4 normal bytes to $41,$42,$43,$44
	STA zp41
	INY
	LDA (zp1E),Y
	STA zp42
	INY
	LDA (zp1E),Y
	STA zp43
	INY
	LDA (zp1E),Y
	STA zp44
	INY
	BEQ $FDDE
	STY zp2E
	JSR S_F80C
	JMP $FDBE
	;
$FDDE	JMP S_F80C
	;
	STA (zpFF,X)
; $FDE3
	DB $FF,$FF,$FF
; $FDE6
	DB $FF,$FF,$FF
; $FDE9
	DB $FF,$FF,$FF
; $FDEC
	DB $FF,$FF,$FF
; $FDEF
	DB $FF,$FF,$FF
; $FDF2
	DB $FF,$FF,$FF
; $FDF5
	DB $FF,$FF,$FF
; $FDF8
	DB $FF,$FF,$FF
; $FDFB
	DB $FF,$FF,$FF
; $FDFE
	DB $FF,$FF
V_FE00	DB $FF
; $FE01
	DB $FF,$FF,$FF
; $FE04
	DB $FF,$FF,$FF
; $FE07
	DB $FF,$FF,$FF
; $FE0A
	DB $FF,$FF,$FF
; $FE0D
	DB $FF,$FF,$FF
; $FE10
	DB $FF,$FF,$FF
; $FE13
	DB $FF,$FF,$FF
; $FE16
	DB $FF,$FF,$FF
; $FE19
	DB $FF,$FF,$FF
; $FE1C
	DB $FF,$FF,$FF
; $FE1F
	DB $FF,$FF,$FF
; $FE22
	DB $FF,$FF,$FF
; $FE25
	DB $FF,$FF,$FF
; $FE28
	DB $FF,$FF,$FF
; $FE2B
	DB $FF,$FF,$FF
; $FE2E
	DB $FF,$FF,$FF
; $FE31
	DB $FF,$FF,$FF
; $FE34
	DB $FF,$FF,$FF
; $FE37
	DB $FF,$FF,$FF
; $FE3A
	DB $FF,$FF,$FF
; $FE3D
	DB $FF,$FF,$FF
; $FE40
	DB $FF,$FF,$FF
; $FE43
	DB $FF,$FF,$FF
; $FE46
	DB $FF,$FF,$FF
; $FE49
	DB $FF,$FF,$FF
; $FE4C
	DB $FF,$FF,$FF
; $FE4F
	DB $FF,$FF,$FF
; $FE52
	DB $FF,$FF,$FF
; $FE55
	DB $FF,$FF,$FF
; $FE58
	DB $FF,$FF,$FF
; $FE5B
	DB $FF,$FF,$FF
; $FE5E
	DB $FF,$FF,$FF
; $FE61
	DB $FF,$FF,$FF
; $FE64
	DB $FF,$FF,$FF
; $FE67
	DB $FF,$FF,$FF
; $FE6A
	DB $FF,$FF,$FF
; $FE6D
	DB $FF,$FF,$FF
; $FE70
	DB $FF,$FF,$FF
; $FE73
	DB $FF,$FF,$FF
; $FE76
	DB $FF,$FF,$FF
; $FE79
	DB $FF,$FF,$FF
; $FE7C
	DB $FF,$FF,$FF
; $FE7F
	DB $FF,$FF,$FF
; $FE82
	DB $FF,$FF,$FF
; $FE85
	DB $FF,$FF,$FF
; $FE88
	DB $FF,$FF,$FF
; $FE8B
	DB $FF,$FF,$FF
; $FE8E
	DB $FF,$FF,$FF
; $FE91
	DB $FF,$FF,$FF
; $FE94
	DB $FF,$FF,$FF
; $FE97
	DB $FF,$FF,$FF
; $FE9A
	DB $FF,$FF,$FF
; $FE9D
	DB $FF,$FF,$FF
; $FEA0
	DB $FF,$FF,$FF
; $FEA3
	DB $FF,$FF,$FF
; $FEA6
	DB $FF,$FF,$FF
; $FEA9
	DB $FF,$FF,$FF
; $FEAC
	DB $FF,$FF,$FF
; $FEAF
	DB $FF,$FF,$FF
; $FEB2
	DB $FF,$FF,$FF
; $FEB5
	DB $FF,$FF,$FF
; $FEB8
	DB $FF,$FF,$FF
; $FEBB
	DB $FF,$FF,$FF
; $FEBE
	DB $FF,$FF,$FF
; $FEC1
	DB $FF,$FF,$FF
; $FEC4
	DB $FF,$FF,$FF
; $FEC7
	DB $FF,$FF,$FF
; $FECA
	DB $FF,$FF,$FF
; $FECD
	DB $FF,$FF,$FF
; $FED0
	DB $FF,$FF,$FF
; $FED3
	DB $FF,$FF,$FF
; $FED6
	DB $FF,$FF,$FF
; $FED9
	DB $FF,$FF,$FF
; $FEDC
	DB $FF,$FF,$FF
; $FEDF
	DB $FF,$FF,$FF
; $FEE2
	DB $FF,$FF,$FF
; $FEE5
	DB $FF,$FF,$FF
; $FEE8
	DB $FF,$FF,$FF
; $FEEB
	DB $FF,$FF,$FF
; $FEEE
	DB $FF,$FF,$FF
; $FEF1
	DB $FF,$FF,$FF
; $FEF4
	DB $FF,$FF,$FF
; $FEF7
	DB $FF,$FF,$FF
; $FEFA
	DB $FF,$FF,$FF
; $FEFD
	DB $FF,$FF,$FF
; $FF00
V_FF00	DB $FF,$FF,$FF
; $FF03
	DB $FF,$FF,$FF
; $FF06
	DB $FF,$FF,$FF
; $FF09
	DB $FF,$FF,$FF
; $FF0C
	DB $FF,$FF,$FF
; $FF0F
	DB $FF,$FF,$FF
; $FF12
	DB $FF,$FF,$FF
; $FF15
	DB $FF,$FF,$FF
; $FF18
	DB $FF,$FF,$FF
; $FF1B
	DB $FF,$FF,$FF
; $FF1E
	DB $FF,$FF,$FF
; $FF21
	DB $FF,$FF,$FF
; $FF24
	DB $FF,$FF,$FF
; $FF27
	DB $FF,$FF,$FF
; $FF2A
	DB $FF,$FF,$FF
; $FF2D
	DB $FF,$FF,$FF
; $FF30
	DB $FF,$FF,$FF
; $FF33
	DB $FF,$FF,$FF
; $FF36
	DB $FF,$FF,$FF
; $FF39
	DB $FF,$FF,$FF
; $FF3C
	DB $FF,$FF,$FF
; $FF3F
	DB $FF,$FF,$FF
; $FF42
	DB $FF,$FF,$FF
; $FF45
	DB $FF,$FF,$FF
; $FF48
	DB $FF,$FF,$FF
; $FF4B
	DB $FF,$FF,$FF
; $FF4E
	DB $FF,$FF,$FF
; $FF51
	DB $FF,$FF,$FF
; $FF54
	DB $FF,$FF,$FF
; $FF57
	DB $FF,$FF,$FF
; $FF5A
	DB $FF,$FF,$FF
; $FF5D
	DB $FF,$FF,$FF
; $FF60
	DB $FF,$FF,$FF
; $FF63
	DB $FF,$FF,$FF
; $FF66
	DB $FF,$FF,$FF
; $FF69
	DB $FF,$FF,$FF
; $FF6C
	DB $FF,$FF,$FF
; $FF6F
	DB $FF,$FF,$FF
; $FF72
	DB $FF,$FF,$FF
; $FF75
	DB $FF,$FF,$FF
; $FF78
	DB $FF,$FF,$FF
; $FF7B
	DB $FF,$FF,$FF
; $FF7E
	DB $FF,$FF,$FF
; $FF81
	DB $FF,$FF,$FF
; $FF84
	DB $FF,$FF,$FF
; $FF87
	DB $FF,$FF,$FF
; $FF8A
	DB $FF,$FF,$FF
; $FF8D
	DB $FF,$FF,$FF
; $FF90
	DB $FF,$FF,$FF
; $FF93
	DB $FF,$FF,$FF
; $FF96
	DB $FF,$FF,$FF
; $FF99
	DB $FF,$FF,$FF
; $FF9C
	DB $FF,$FF,$FF
; $FF9F
S_FF9F	DB $FF,$FF,$FF
; $FFA2
	DB $FF,$FF,$FF
; $FFA5
	DB $FF,$FF,$FF
; $FFA8
	DB $FF,$FF,$FF
; $FFAB
	DB $FF,$FF,$FF
; $FFAE
	DB $FF,$FF,$FF
; $FFB1
	DB $FF,$FF,$FF
; $FFB4
	DB $FF,$FF,$FF
; $FFB7
	DB $FF,$FF,$FF
; $FFBA
	DB $FF,$FF,$FF
; $FFBD
	DB $FF,$FF,$FF
; $FFC0
	DB $FF,$FF,$FF
; $FFC3
	DB $FF,$FF,$FF
; $FFC6
	DB $FF,$FF,$FF
; $FFC9
	DB $FF,$FF,$FF
; $FFCC
	DB $FF,$FF,$FF
; $FFCF
	DB $FF,$FF,$FF
; $FFD2
	DB $FF,$FF,$FF
; $FFD5
	DB $FF,$FF,$FF
; $FFD8
	DB $FF,$FF,$FF
; $FFDB
	DB $FF,$FF,$FF
; $FFDE
	DB $FF,$FF,$FF
; $FFE1
	DB $FF,$FF,$FF
; $FFE4
	DB $FF,$FF,$A7,$C9,$3B,$F1,$51,$CE,$8B,$CE,$00,$05
	DB $03,$05,$06,$05,$09,$05,$0C,$05,$0F,$05,$39,$EA,$B5,$E9,$95,$F1
; EOF

 

Letzte Änderung: 2019-01-02 21:40:05
  Rubrik:  Floppy
Rubriken-Übersicht
 16 Besucher online 

Valid XHTML 1.0 Transitional Valid CSS!