; Disassembly of Opus EDOS 0.4 patched by EDOSPAT 4.51 (U)
; Last updated 7/Mar/2008
; Created with EXMON II and edited by Steven Bass
; Acorn Latch modified by Steven Bass to work on Master 128
; Comments by Greg Cook.
; Notes all done except Tube host code
; for which a commentary by J.G.Harston can be found at:
; http://mdfs.net/Software/Tube/BBC/Host.lst
; Comments beginning with capital letters are entry points
;
;
;
; ZERO PAGE WORKSPACE
; *******************
;
;00A0..A1  Pointer to user's OSWORD &7F block
;00A0	   Temporary for A in NMI service routines
;00A1	   No. bytes to fetch in Read ID NMI service routine
;00A2..A3  CHRN block address from O7F 1..2 for Format command
;00A4	   No. sectors to read
;00A8..A9  Pointer to CHRN table in *FORMAT
;00A8..A9  Pointer to private page when stowing/restoring workspace
;00AA..AB  Pointer to extended vector table while setting up FS
;00B0	   contains address of parameter block for OSWORD and OS calls
;00B1	   contains address of parameter block for OSWORD and OS calls
;00B2..B3  Pointer to hex word in print-absolute
;00B8	   Temp for high bits when packing catalogue entry
;00B8	   Uppercased character to compare with names of open handles
;00B9	   Counter to compare filename with names of open handles
;00BA..BB  Target absolute sector when advancing PTR
;00BA..BB  Temporary during OSGBPB sector operations
;00BC..BD  Pointer to user memory in OSGBPB
;00BE..BF  Pointer to user's OSGBPB block
;00C0..C6  Immediate file name
;00C7	   Immediate dir (ASCII)
;00C8	   Immediate volume (ASCII)
;00C9	   Immediate drive (ASCII)
;00CA..CB  Pointer to buffer of open file (CB=file handle)
;00CC	   Pointer to file entry in catalogue
;00CD	   Microcode shift register in OSGBPB etc.
;00CE	   ambiguous file spec flag
;00CF	   was used in Master version 'S' in Convert DDOS latch routine
;
;
;00EF	   OSWORD/OSBYTE accumulator value
;00F0	   OSWORD/OSBYTE X register value
;00F1	   OSWORD/OSBYTE Y register value

cliptrl	     = &F2			;string address for GSINIT + offset in Y
cliptrh	     = &F3			;string address for GSINIT + offset in Y
rmslrg	     = &F4			;copy of ROM select register
;
;
;
; SHEILA MEMORY MAPPED ADDRESSES
; ******************************
;
io_page	  = &FE00			;base address of SHEILA
fdc_base  = &FE24
fdc_cntrl = &FE24
fdc_stat  = &FE28
fdc_comm  = &FE28
fdc_trck  = &FE29
fdc_sect  = &FE2A
fdc_data  = &FE2B
romselr	  = &FE30			;Paged ROM select register
acccon	  = &FE34			;Memory access control register
;
;
; STANDARD MOS CALLS & VECTORS USED BY THIS CODE
; **********************************************
;
osfcv  = &021E				; The filing control vector
oswrsc = &FFB3
osrdsc = &FFB9
oseven = &FFBF
gsinit = &FFC2
gsread = &FFC5
nvrdch = &FFC8
nvwrch = &FFCB
osfind = &FFCE				; open/close file
osgbpb = &FFD1				; read/write open file
osbput = &FFD4
osbget = &FFD7
osargs = &FFDA
osfile = &FFDD
osrdch = &FFE0
osacii = &FFE3
osnewl = &FFE7
oswrch = &FFEE
osword = &FFF1
osbyte = &FFF4
oscli  = &FFF7
;
;
; THE TUBE STATUS AND DATA REGISTERS
; **********************************
tubeR1stat = &FFF0		;Register 1 status
tubeR1data = &FEE1		;Register 1 data
tubeR2stat = &FEE2		;Register 2 status
tubeR2data = &FEE3		;Register 2 data
tubeR3stat = &FEE4		;Register 3 status
tubeR3data = &FEE5		;Register 3 data
tubsR4stat = &FEE6		;Register 4 status
tubeR4data = &FEE7		;Register 4 data
;
;
;
; Paged ROM header

8000 4C B5 80  JMP language		;Language entry (RTS)

8003 4C 3D 80  JMP service		;Service entry

EQUB EQUB &82				; rom type: service only
8007 EQUB &26				; Copyright offset pointer
.P008
8008 EQUS "W"				; Version No.
8009 EQUS "OPUS EDOS "			; title
8013 EQUB &00				; terminator byte
8014 EQUS "0.40 (20 Feb 2009)"		; version string
8026 EQUB &00				; terminator byte
8027 EQUS "(C)1984 Alan Williams"	; copyright pointer validated by MOS prior to accepting ROM
803C EQUB &00				; terminator byte


;Paged ROM service
.service				;ROM service.
803D 20 03 B7  JSR S703			;call monitor
8040 C9 01     CMP #&01			;request absolute workspace
8042 F0 29     BEQ P06D
8044 C9 02     CMP #&02			;request private workspace
8046 F0 2C     BEQ P074
8048 C9 03     CMP #&03			;boot
804A F0 45     BEQ boot
804C C9 04     CMP #&04			;unrecognised OSCLI
804E F0 47     BEQ P097
8050 C9 08     CMP #&08			;unrecognised OSWORD
8052 F0 49     BEQ P09D
8054 C9 09     CMP #&09			;*HELP
8056 F0 4B     BEQ help
8058 C9 0A     CMP #&0A			;claim absolute workspace
805A F0 4D     BEQ P0A9
805C C9 0F     CMP #&0F			;vectors claimed
805E F0 49     BEQ P0A9
8060 C9 12     CMP #&12			;initialise filing system
8062 F0 48     BEQ P0AC
8064 C9 FE     CMP #&FE			;tube post initialisation
8066 F0 4E     BEQ P0B6
8068 C9 FF     CMP #&FF			;tube main initialisation
806A F0 54     BEQ P0C0
806C 60        RTS

.P06D					;request absolute workspace
806D C0 16     CPY #&16
806F B0 02     BCS P073			;request private workspace
8071 A0 16     LDY #&16			;we need 8 pages 0E..15 incl
.P073
8073 60        RTS

; SVCE CALL 2 - CLAIM PRIVATE WORK SPACE
; A = SVCE CALL No., X = ROM No., Y = value of first free page.
.P074					;request private workspace
8074 48        PHA			;save on stack
8075 98        TYA			;save our page number in the
8076 9D F0 0D  STA &0DF0,X		;OS ROM table
8079 85 A9     STA &A9			;and in high byte of pointer
807B 18        CLC			;claim one page
807C 69 01     ADC #&01
807E A8        TAY
807F 68        PLA			;restore ROM call number
8080 20 00 92  JSR Q200			;save AXY
8083 AD 8D 02  LDA &028D		;get last reset type
8086 F0 08     BEQ P090			;if not 0 soft break
8088 A0 00     LDY #&00			;then low byte of pointer =0
808A 84 A8     STY &A8			;clear workspace flag in
808C A0 0D     LDY #&0D			;byte &D of private page
808E 91 A8     STA (&A8),Y		;marking it uninitialised.
.P090
8090 60        RTS

.boot
8091 20 C6 80  JSR P0C6			;test boot key
8094 B0 1A     BCS P0B0			;if okay boot the disc
8096 60        RTS

; SVCE CALL 4 - UNRECOGNISED * COMMAND
; On entry &F2 and &F3 point to the start of the string
.P097					; Unrecognised OSCLI
8097 20 03 81  JSR P103			;scan it
809A B0 17     BCS P0B3			;if we ran it break out
809C 60        RTS

.P09D					;unrecognised OSWORD
809D 20 00 BA  JSR SA00			;compare OSWORD
80A0 B0 11     BCS P0B3			;with our codes && break out
80A2 60        RTS

.help					;*HELP
80A3 20 06 81  JSR P106			;search our topics
80A6 B0 0B     BCS P0B3			;if specific to us break out
80A8 60        RTS

.P0A9					;claim absolute workspace
80A9 4C 06 96  JMP Q606			;Wksp claim/vectors changed.

.P0AC					;Initialise FS
80AC C0 04     CPY #&04			;our FS ID = 4
80AE D0 05     BNE language
.P0B0
80B0 20 03 96  JSR Q603
.P0B3					;Break out of ROM call chain
80B3 A9 00     LDA #&00
.language
80B5 60        RTS

.P0B6					;Post-initialise Tube
80B6 C0 00     CPY #&00
80B8 F0 FB     BEQ language		;edos ignores if Y=0
80BA 20 03 A0  JSR R003			;otherwise it does post-init
80BD A9 00     LDA #&00			;and consumes the call.
80BF 60        RTS

.P0C0					;Tube main init
80C0 20 00 A0  JSR R000
80C3 A9 00     LDA #&00			;edos consumes this call
80C5 60        RTS

.P0C6					;Test boot key
80C6 20 00 92  JSR Q200			;Save AXY
80C9 A9 7A     LDA #&7A
80CB 20 F4 FF  JSR osbyte		;scan keyboard from code &10
80CE 8A        TXA
80CF 30 09     BMI P0DA			;if no keypress C=1, allow boot
80D1 C9 32     CMP #&32			;if key is not "D" disallow boot
80D3 D0 07     BNE P0DC			;return C=0 disallow boot
80D5 A9 78     LDA #&78			;else
80D7 20 F4 FF  JSR osbyte		;register keypress for 2KR
.P0DA
80DA 38        SEC			;return C=1 allow boot
80DB 60        RTS

.P0DC
80DC 18        CLC			;return C=0 disallow boot
80DD 60        RTS



.P100					;Keyword recognition and help subsystem
8100 4C 0C 81  JMP P10C			;OSFSC 3

.P103
8103 4C 1A 81  JMP P11A			;OSCLI

.P106
8106 4C 13 81  JMP P113			;*HELP

.P109
8109 4C 70 81  JMP P170			;Print syntax for command

;OSFSC 3 pt2
.P10C					;scan DFS commands
810C 20 00 92  JSR Q200			;Save AXY etc
810F A2 2C     LDX #&2C			;X=table offset=&2C
8111 D0 0C     BNE P11F
.P113					;scans help keywords
8113 20 00 92  JSR Q200			;Save AXY etc
8116 A2 E0     LDX #&E0			;X=table offset=&E0
8118 D0 05     BNE P11F
.P11A					;OSCLI. scans UTILS commands
811A 20 00 92  JSR Q200			;Save AXY etc
811D A2 00     LDX #&00			;X=table offset=&00
.P11F					;Scan
811F 20 C2 FF  JSR gsinit		;call GSINIT on keyword
.P122
8122 8A        TXA			;X = table offset.
8123 48        PHA			;save table offset
8124 98        TYA			;Y = GSINIT offset
8125 48        PHA			;save GSINIT offset
.P126
8126 BD 1B 82  LDA P21B,X		;get character from table
8129 F0 41     BEQ P16C			;if NUL then exit C=0
812B 30 1F     BMI P14C			;if terminator test completeness
812D 51 F2     EOR (&F2),Y		;else compare with command char
812F 29 DF     AND #&DF			;make test case insensitive
8131 D0 04     BNE P137			;if unequal test if abbreviated
8133 E8        INX			;else increment table offset
8134 C8        INY			;increment command offset
8135 D0 EF     BNE P126			;and loop.
.P137
8137 E8        INX
8138 BD 1B 82  LDA P21B,X		;search tbl for next terminator
813B 10 FA     BPL P137			;if unequal test if abbreviated
813D B1 F2     LDA (&F2),Y		;get char where search stopped
813F C8        INY			;increment command offset
8140 C9 2E     CMP #&2E			;was it a dot?
8142 F0 14     BEQ P158			;if so accept the abbreviation
.P144
8144 68        PLA			;else restore command offset
8145 A8        TAY			;to start
8146 68        PLA			;discard old table offset
8147 E8        INX			;increment table offset by 3 to
8148 E8        INX			;skip syntax and action address
8149 E8        INX
814A D0 D6     BNE P122			;and compare with next keyword.
.P14C
814C B1 F2     LDA (&F2),Y		;get character after command
814E 29 DF     AND #&DF			;convert to uppercase
8150 C9 41     CMP #&41			;is it less than "A"?
8152 90 04     BCC P158			;then accept the command
8154 C9 5B     CMP #&5B			;is it less than "Z"?
8156 90 EC     BCC P144			;then table entry was too short!
.P158
8158 BD 1C 82  LDA P21B+1,X		;else accept command.
815B 85 A8     STA &A8			;get action address
815D BD 1D 82  LDA P21B+2,X		;store in temp pointer
8160 85 A9     STA &A9
8162 18        CLC
8163 20 C2 FF  JSR gsinit		;call GSINIT on command tail
8166 68        PLA			;discard old GSINIT offset
8167 68        PLA			;get tbl offset of this command
8168 AA        TAX			;place in X
8169 6C A8 00  JMP (&00A8)		;and jump to the action address.

.P16C
816C 68        PLA			;command not found.
816D 68        PLA			;discard offsets
816E 18        CLC			;offer command to lower ROMs
816F 60        RTS			;exit

.P170					;Print syntax for command
8170 20 18 90  JSR Q018			;Print Syntax:
8173 EQUB &08				;X=offset to help entry
8174 EQUB &DC				;error 220, "Syntax"
8175 EQUS "Syntax:"
817C EQUB &00				;terminator byte
817D 20 F1 81  JSR P1F1			;print help entry
8180 20 09 90  JSR Q009			;display error (never returns)
.P183
8183 A9 02     LDA #&02			;*HELP
;8185 A2 EA     LDX #&EA		;one column. point to keywd table
8185 A2 E3     LDX #&E3			;one column.point to keywd table
8187 20 94 81  JSR P194			;print help keywords
818A 18        CLC			;pass call to lower ROMs
818B 60        RTS			;exit

.P18C					;*HELP DFS
818C A2 2C     LDX #&2C			;offset to point to DFS table
818E D0 02     BNE P192
.P190					;*HELP UTILS
8190 A2 00     LDX #&00			;point to UTILS table
.P192
8192 A9 01     LDA #&01			;Print help table, two columns:
.P194
8194 85 AA     STA &AA			;Print help table.
;8196 20 00 96  JSR Q600		;print EDOS banner
8196 20 C8 83  JSR P3C8			;print EDOS banner
.P199
8199 20 F1 81  JSR P1F1			;print help entry
819C E8        INX			;skip syntax and action address
819D E8        INX
.P19E
819E E8        INX
819F BD 18 82  LDA P218,X		;search keyword just printed
81A2 10 FA     BPL P19E			;until terminator found
81A4 BD 1B 82  LDA P21B,X		;test first char of next keyword
81A7 F0 16     BEQ P1BF			;if NUL print newline and exit
81A9 A5 AA     LDA &AA			;else toggle b0 of column flag
81AB 49 01     EOR #&01			;00000001
81AD 85 AA     STA &AA
81AF F0 06     BEQ P1B7			;if any bit is set
81B1 20 09 90  JSR Q009			;print newline
81B4 4C 99 81  JMP P199			;and loop

.P1B7
81B7 A9 28     LDA #&28			;else
81B9 20 06 90  JSR Q006			;Tab to column 40
81BC 4C 99 81  JMP P199			;and loop.

.P1BF
81BF 20 09 90  JSR Q009			;print newline
81C2 38        SEC			;break out of ROM call
81C3 60        RTS			;exit

.P1C4					;*HELP EDOS
;81C4 20 00 96  JSR Q600		;Print EDOS banner
81C4 20 C8 83  JSR P3C8			;Tab to column in A
81C7 20 18 90  JSR Q018			;prints banner
;EDOSPAT version number, target controller and EDOSPAT author
81CA EQUB &02
81CB EQUS "EDOSPAT 4.60 (W) Master 1770:G.Cook"
81EE EQUB &00
81EF 38		SEC
81F0 60		RTS

.P1F1					;Print help entry, X=offset.
81F1 20 00 92  JSR Q200			;Save AXY
81F4 A9 02     LDA #&02			;tab to column 2 or more
81F6 20 06 90  JSR Q006			;returning current POS in A
81F9 48        PHA			;save POS
.P1FA
81FA BD 1B 82  LDA P21B,X		;get character from table of UTILS commands
81FD 30 06     BMI P205			;if not the terminator
81FF 20 00 90  JSR Q000			;print the character in A
8202 E8        INX			;advance offset
8203 D0 F5     BNE P1FA			;and loop
.P205
8205 29 7F     AND #&7F			;else mask terminator
8207 AA        TAX			;to get offset of syntax
8208 68        PLA			;get back POS
8209 18        CLC
820A 69 09     ADC #&09			;add 9
820C 20 06 90  JSR Q006			;tab to 9 places after command
.P20F
820F BD 14 83  LDA P314,X		;get character from syntax
8212 F0 06     BEQ P21A			;if NUL then exit
8214 20 00 90  JSR Q000			;else print the character in A
8217 E8        INX			;advance offset
.P218
8218 D0 F5     BNE P20F			;and loop.
.P21A
821A 60        RTS

.P21B					;Table of UTILS commands
821B EQUS "BUILD"			;*BUILD fsp P400
8220 EQUB &BA				;Syntax fsp (b7 set)
8221 EQUW &00,&84			;Action address &8400

8223 EQUS "DISC"			;*DISC I, P403
8227 EQUB &B8				;Syntax I (b7 set)
8228 EQUW &03,&84			;Action address &8403

822A EQUS "DISK"			;*DISK I, P403
822E EQUB &B8				;Syntax I (b7 set)
822F EQUW &03,&84			;Action address &8403

8231 EQUS "DUMP"			;*DUMP fsp, P406
8235 EQUB &BA				;Syntax fsp (b7 set)
8236 EQUW &06,&84			;Action address &8406

8238 EQUS "LIST"			;*LIST fsp, P409
823C EQUB &BA				;Syntax fsp (b7 set)
823D EQUW &09,&84			;Action address &8409

823F EQUS "TYPE"			;*TYPE fsp, P40C
8243 EQUB &BA				;Syntax fsp (b7 set)
8244 EQUW &0C,&84			;Action address &840C
8246 EQUW &00				;terminator byte

;Table of DFS commands
8247 EQUS "ACCESS"			;*ACCESS fsp L, P600
824D EQUB &80				;Syntax fsp L
824E EQUW &00,&86			;Action address &8600

8250 EQUS "BACKUP"			;*BACKUP drv drv, PA00
8256 EQUB &88				;Syntax drv drv
8257 EQUW &00,&8A			;Action address &8A00

8259 EQUS "CATGEN"			;*CATGEN vol ..., R903
825F EQUB &E1				;Syntax vol ...
8260 EQUW &03,&A9			;Action address &A903

8262 EQUS "COMPACT"			;*COMPACT vol, PA03
8269 EQUB &9B				;Syntax vol
826A EQUW &03,&8A			;Action address &8A03

826C EQUS "COPY"			;*COPY vol vol afsp, PA06
8270 EQUB &9F				;Syntax vol vol afsp
8271 EQUW &06,&8A			;Action address &8A06

8273 EQUS "DELETE"			;*DELETE fsp, P606
8279 EQUB &BA				;Syntax fsp (b7 set)
827A EQUW &06,&86			;Action address &8606

827C EQUS "DESTROY"			;*DESTROY afsp, P609
8283 EQUB &B3				;Syntax afsp
8284 EQUW &09,&86			;Action address &8609

8286 EQUS "DIR"				;*DIR dir, P60C
8289 EQUB &BE				;Syntax dir
828A EQUW &0C,&86			;Action address &860C

828C EQUS "DRIVE"			;*DRIVE drv, PB27
8291 EQUB &9B				;Syntax drv
8292 EQUW &27,&86			;Action address &9B27

8294 EQUS "ENABLE"			;*ENABLE, PA09
829A EQUB &B7				;Syntax
829B EQUW &09,&8A			;Action address &8A09

829D EQUS "FCOPY"			;*FCOPY fsp name, PA12
82A2 EQUB &C2				;Syntax fsp name
82A3 EQUW &12,&8A			;Action address &8A12

82A5 EQUS "FORMAT"			;*FORMAT drv ..., R900
82AB EQUB &F5				;Syntax drv ...
82AC EQUW &00,&A9			;Action address &A900

82AE EQUS "INFO"			;*INFO afsp, P612
82B2 EQUB &B3				;Syntax afsp
82B3 EQUW &12,&86			;Action address &8612

82B5 EQUS "LIB"				;*LIB dir, P615
82B8 EQUB &BE				;Syntax dir
82B9 EQUW &15,&86			;Action address &8615

82BB EQUS "LOCK"			;*LOCK afsp, P621
82BF EQUB &B3				;Syntax afsp
82C0 EQUW &21,&86			;Action address &8621

82C2 EQUS "RENAME"			;*RENAME fsp name, P618
82C8 EQUB &C2				;Syntax fsp name
82C9 EQUW &18,&86			;Action address &8618

82CB EQUS "SCOPY"			;*SCOPY vol vol afsp, PA0F
82D0 EQUB &9F				;Syntax vol vol afsp
82D1 EQUW &0F,&8A			;Action address &8A0F

82D3 EQUS "TITLE"			;*TITLE title, P61B
82D8 EQUB &DB				;Syntax title
82D9 EQUW &1B,&86			;Action address &861B

82DB EQUS "UNLOCK"			;*UNLOCK afsp, P624
82E1 EQUB &B3				;Syntax afsp
82E2 EQUW &24,&86			;Action address &8624

82E4 EQUS "VERIFY"			;*VERIFY drv, R906
82EA EQUB &F1				;Syntax drv
82EB EQUW &06,&A9			;Action address &A906

82ED EQUS "VOL"				;*VOL vol, P627
82F0 EQUB &9B				;Syntax vol
82F1 EQUW &27,&86			;Action address &8627

82F3 EQUS "WIPE"			;*WIPE afsp, P61E
82F7 EQUB &B3				;Syntax afsp
82F8 EQUW &1E,&86			;Action address &861E
82FA EQUW &00				;terminator byte

;Help keywords
82FB EQUB &B7				;*HELP, P3DA
;82FC EQUW &D4,&83			;Action address &83D4
82FC EQUW &DA,&83			;Action address &83DA

82FE EQUS "EDOS"			;*HELP EDOS, P1C4
8302 EQUB &B7				;Syntax
8303 EQUW &C4,&81			;Action address &81C4

8305 EQUS "DFS"				;*HELP DFS, P18C
8308 EQUB &B7				;Syntax
8309 EQUW &8C,&81			;Action address &818C

830B EQUS "UTILS"			;*HELP UTILS, P190
8310 EQUB &B7				;Syntax
8311 EQUW &90,&81			;Action address &8190
8313 EQUB &00				;terminator byte

.P314					;Syntax particles
8314 EQUS "afsp  L"
831B EQUW &00				;terminator byte

831C EQUS "src drv   dest drv"
832E EQUB &00				;terminator byte

832F EQUS "vol"
8332 EQUB &00				;terminator byte

8333 EQUS "src vol   dest vol  afsp"
834B EQUB &00				;terminator byte

834C EQUS "I"
834D EQUB &00				;terminator byte

834E EQUS "fsp"
8351 EQUB &00				;terminator byte

8352 EQUS "dir"
8355 EQUB &00				;terminator byte

8356 EQUS "old fsp   new entry name"
836E EQUB &00				;terminator byte

836F EQUS "title"
8374 EQUB &00				;terminator byte

8375 EQUS "drv   vol specs"
8384 EQUB &00				;terminator byte

8385 EQUS "drv"
8388 EQUB &00				;terminator byte

8389 EQUS "drv  S  D  40  80  40-80  Oo"
83A5 EQUB &00				;terminator byte

83A6 EQUW &00,&00
83A8 EQUD &00,&00,&00,&00
83AC EQUD &00,&00,&00,&00
83B0 EQUD &00,&00,&00,&00
83B4 EQUD &00,&00,&00,&00
83B8 EQUD &00,&00,&00,&00
83BC EQUD &00,&00,&00,&00
83C0 EQUD &00,&00,&00,&00
83C4 EQUD &00,&00,&00,&00
;83C8 EQUD &00,&00,&00,&00
;83CC EQUW &00,&00

;;EDOSPAT extensions, block 1
;.P3CE					;get byte from stack page
;83CE B9 00 01  LDA &0100,Y		;get character from *DUMP row
;83D1 C9 7F     CMP #&7F		;exit C=1 if DEL or higher
;83D3 60        RTS
;
;.P3D4
;83D4 18        CLC			;*HELP with empty keyword:
;83D5 20 C2 FF  JSR gsinit		;call GSINIT on current position
;83D8 F0 15     BEQ P3EF		;if end-of-string then scan kywd
;83DA C9 2E     CMP #&2E		;else test if first char is dot
;83DC D0 0F     BNE P3ED		;if not then ignore call, else:
;83DE 20 C4 81  JSR P1C4		;*HELP DDOS
;83E1 20 09 90  JSR Q009		;do *HELP EDOS, print newline
;83E4 20 8C 81  JSR P18C		;do *HELP DFS
;83E7 20 09 90  JSR Q009		;print newline

;EDOSPAT extensions, block 1
.P3C8
83C8 20 09 90  JSR Q009			;Display error message/newline
83CB 4C 00 96  JMP Q600			;Print EDOS banner and exit

.P3CE					;print EDOS banner w/2 newlines and display error message
83CE 20 00 96  JSR Q600			;Print EDOS banner
83D1 4C 09 90  JMP Q009			;Display error message/newline and exit

.P3D4					;get character from *DUMP row
83D4 B9 00 01  LDA &0100,Y		;get byte from stack page
83D7 C9 7F     CMP #&7F			;if DEL or higher
83D9 60        RTS			;exit C=1

.P3DA					;*HELP with empty keyword:
83DA 18        CLC			;clear carry
83DB 20 C2 FF  JSR gsinit		;call GSINIT on current position
83DE F0 0F     BEQ P3EF			;if end-of-string then scan kyw
83E0 C9 2E     CMP #&2E			;else test if first char is dot
83E2 D0 09     BNE P3ED			;if not then ignore call, else:
83E4 20 C4 81  JSR P1C4			;*HELP DDOS
83E7 20 8C 81  JSR P18C			;do *HELP DFS
83EA 20 90 81  JSR P190			;do *HELP UTILS
.P3ED
83ED 18        CLC			;and pass *HELP . to lower ROMs.
83EE 60        RTS

.P3EF
83EF 98        TYA			;scan for end of keyword:
83F0 F0 0B     BEQ P3FD			;if start-of-string then *HELP
83F2 88        DEY			;else step back one character
83F3 B1 F2     LDA (&F2),Y		;fetch it
83F5 C9 20     CMP #&20			;if space then keep scanning
83F7 F0 F6     BEQ P3EF
83F9 C9 22     CMP #&22			;if double quotes
83FB F0 F0     BEQ P3ED			;then ignore the call
.P3FD
83FD 4C 83 81  JMP P183			;if anything else then *HELP



;Utilities
.P400
8400 4C 0F 84  JMP P40F			;*BUILD fsp

.P403
8403 4C 71 84  JMP P471			;*DISC, *DISK

.P400
8406 4C 82 84  JMP P482			;*DUMP

.P409
8409 4C F4 84  JMP P4F4			;*LIST

.P40C
840C 4C 1F 85  JMP P51F			;*TYPE

.P40F					;*BUILD
840F A9 80     LDA #&80
8411 20 3B 85  JSR P53B			;open file for writing
8414 20 67 84  JSR P467			;flush all open files
.P417
8417 20 73 85  JSR P573			;increment line number
841A 20 8B 85  JSR P58B			;print line number
841D 20 44 84  JSR P444			;input line
.P420
8420 A6 AA     LDX &AA			;get low byte of pointer
8422 E4 AF     CPX &AF			;compare with line length
8424 F0 0B     BEQ P431			;if equal input next line
8426 A2 00     LDX #&00			;else get char at pointer
8428 A1 AA     LDA (&AA,X)
842A 20 D4 FF  JSR osbput		;call OSBPUT
842D E6 AA     INC &AA			;advance pointer
842F D0 EF     BNE P420			;loop until end of buffer
.P431
8431 24 FF     BIT &FF			;test escape flag
8433 10 E2     BPL P417			;if clear input next line
8435 98        TYA			;else save file handle
8436 48        PHA
8437 A9 7E     LDA #&7E			;acknowledge Escape
8439 20 F4 FF  JSR osbyte
843C 68        PLA			;restore file handle
843D A8        TAY
843E 20 E7 FF  JSR osnewl		;print newline
8441 4C 6C 85  JMP P56C			;close file and exit.

.P444					;Input line
8444 20 00 92  JSR Q200			;Save AXY
8447 88        DEY			;Y=handle, point to previous
8448 C0 11     CPY #&11			;buffer. If buffer was &11
844A B0 02     BCS P44E			;or less, point to next
844C C8        INY			;buffer.
844D C8        INY
.P44E
844E 84 AB     STY &AB			;store high byte of pointer
8450 A0 FF     LDY #&FF
8452 84 AC     STY &AC			;maximum line length = 255
8454 84 AE     STY &AE			;maximum ASCII value = 255
8456 C8        INY			;set Y=0
8457 84 AA     STY &AA			;clear low byte of pointer
8459 84 AD     STY &AD			;minimum ASCII value = 0
845B 98        TYA			;set A=0
845C A2 AA     LDX #&AA			;point XY to parameter block
845E 20 F1 FF  JSR osword		;call OSWORD to input line
8461 B0 01     BCS P464			;if user did not Escape
8463 C8        INY			;add 1 for the CR character
.P464
8464 84 AF     STY &AF			;return length of line in &AF
8466 60        RTS

.P467
8467 20 00 92  JSR Q200			;Save AXY;Flush all open files
846A A9 FF     LDA #&FF
846C A0 00     LDY #&00
846E 4C DA FF  JMP osargs

.P471					;*DISC, *DISK
8471 20 C5 FF  JSR gsread
8474 A0 01     LDY #&01			;call GSREAD for next char
8476 B0 05     BCS P47D			;if EOS init EDOS, Y=1 no boot
8478 C9 49     CMP #&49			;else is character "I"?
847A D0 01     BNE P47D			;if not init EDOS, Y=1 no boot
847C 88        DEY			;else Y=0 to boot default drive
.P47D
847D 20 03 96  JSR Q603			;initialise EDOS
8480 38        SEC			;C=1, exit and break ROM call
8481 60        RTS

.P482					;*DUMP
8482 20 39 85  JSR P539			;Open file for reading
8485 AE 55 03  LDX &0355		;open file, get current MODE
8488 BD EC 84  LDA P4EC,X		;get ASCII column tab for MODE
848B 85 AA     STA &AA			;store in temp
848D BD E4 84  LDA P4E4,X		;get bytes per row for MODE
8490 85 AF     STA &AF			;store in temp
.P492
8492 20 93 85  JSR P593			;BGET byte
8495 B0 27     BCS P4BE			;if EOF close file
8497 20 8A 85  JSR P58A			;else print file offset+space
849A 20 79 85  JSR P579			;add bytes/row to file offset
849D A6 AF     LDX &AF			;X=bytes per row
.P49F
849F 24 AA     BIT &AA			;if b7 of tab clear
84A1 30 03     BMI P4A6
84A3 20 03 90  JSR Q003			;then print space.
.P4A6
84A6 38        SEC			;permit leading zero
84A7 20 0F 90  JSR Q00F			;print hex byte
84AA 9D 00 01  STA &0100,X		;store byte for ASCII column
84AD CA        DEX			;decrement column counter
84AE D0 06     BNE P4B6			;if no more columns
84B0 20 C1 84  JSR P4C1			;print ASCII column
84B3 4C 92 84  JMP P492			;and loop for next row.

.P4B6
84B6 20 93 85  JSR P593			;else BGET next byte
84B9 90 E4     BCC P49F			;if no EOF print it and loop
84BB 20 C1 84  JSR P4C1			;else flush ASCII column
.P4BE
84BE 4C 6C 85  JMP P56C			;close file and exit.

.P4C1
84C1 20 00 92  JSR Q200			;Save AXY;Print ASCII column
84C4 A5 AA     LDA &AA			;X=no.chars not to print
84C6 29 7F     AND #&7F			;mask print-space bit off tab
84C8 20 06 90  JSR Q006			;tab to screen column
84CB A4 AF     LDY &AF			;Y=bytes per row
.P4CD
;84CD 20 CE 83  JSR P3CE		;get byte from stack page
84CD 20 D4 83  JSR P3D4			;get byte from stack page
84D0 B0 04     BCS P4D6			;if >=&7F print a dot
84D2 C9 20     CMP #&20			;else if >=&20 print character
84D4 B0 02     BCS P4D8
.P4D6
84D6 A9 2E     LDA #&2E			;else print a dot
.P4D8
84D8 20 00 90  JSR Q000			;Print character in A
84DB 88        DEY			;decrement byte pointer
84DC E8        INX			;increment bytes not to print
84DD E4 AF     CPX &AF			;if result <> bytes per column
84DF D0 EC     BNE P4CD			;then loop for next character
84E1 4C E7 FF  JMP osnewl		;else print newline and exit.

.P4E4
84E4 10 08     BPL P4EE			;*DUMP bytes/row in MODEs [0..7]
84E6 04
84E7 10 08     BPL P4F1
84E9 04
84EA 08        PHP
84EB 08        PHP

.P4EC
84EC EQUW &37,&1F			;*DUMP ASCII tab in MODEs [0..7]

.P4EE
84EE 8E 37 1F  STX &1F37
.P4F1
84F1 8E 1F 1F  STX &1F1F
.P4F4					;*LIST
84F4 20 39 85  JSR P539			;Open file for reading
.P4F7
84F7 20 93 85  JSR P593			;open file, BGET char
84FA B0 70     BCS P56C			;if EOF close file
84FC 20 73 85  JSR P573			;else increment line number
84FF 20 8B 85  JSR P58B			;print line number
.P502
8502 20 E3 FF  JSR osacii		;call OSASCI to print char
.P505
8505 C9 0D     CMP #&0D			;was it CR?
8507 F0 EE     BEQ P4F7			;if so start next line
8509 C9 0A     CMP #&0A			;else, was it LF?
850B F0 07     BEQ P514			;if so BGET+OSWRCH next char
850D 20 93 85  JSR P593			;else BGET next character
8510 B0 5A     BCS P56C			;if EOF close file
8512 90 EE     BCC P502			;else print char and loop.
.P514
8514 20 93 85  JSR P593			;test Escape and BGET char
8517 B0 53     BCS P56C			;if EOF close file
8519 20 EE FF  JSR oswrch		;else call OSWRCH to print
851C 4C 05 85  JMP P505			;interpret char and loop.

.P51F					;*TYPE
851F 20 39 85  JSR P539			;Open file for reading
.P522
8522 20 93 85  JSR P593			;open file, BGET char
8525 B0 45     BCS P56C			;if EOF close file
8527 20 E3 FF  JSR osacii		;else print char with OSASCI
P52A
852A C9 0A     CMP #&0A			;was it LF?
852C D0 F4     BNE P522			;if not loop for next char
852E 20 93 85  JSR P593			;else BGET next char
8531 B0 39     BCS P56C			;if EOF close file
8533 20 EE FF  JSR oswrch		;else call OSWRCH to print
8536 4C 2A 85  JMP P52A			;interpret char and loop.

;Open file for reading
8539 A9 40     LDA #&40
.P53B					;Open file
853B 20 00 92  JSR Q200			;Save AXY
853E 48        PHA			;save A
853F 98        TYA			;GSREAD pointer (&F2),Y
8540 18        CLC			;points to filename.
8541 65 F2     ADC &F2			;calculate XY = &F2,3 + Y
8543 AA        TAX			;X = Y + &F2
8544 A9 00     LDA #&00			;A = 0
8546 85 A8     STA &A8			;as side effect line no.=0
8548 85 A9     STA &A9			;Y = 0 + &F3 + carry
854A 65 F3     ADC &F3
854C A8        TAY
854D 68        PLA			;restore A file open mode
854E 20 CE FF  JSR osfind		;call OSFIND to open file
8551 BA        TSX			;return handle in Y
8552 9D 03 01  STA &0103,X
8555 AA        TAX			;if handle = 0
8556 D0 1A     BNE P572
8558 20 18 90  JSR Q018			;Print "File not found" error.
855B EQUB &0A				;LF
855C EQUB &D6
855D EQUS "File not found"
856B EQUB &00				;terminator byte
.P56C					;Close file
856C A9 00     LDA #&00
856E 20 CE FF  JSR osfind		;break unrecognised OSCLI
.P571
8571 38        SEC
.P572
8572 60        RTS			;ROM call and exit

.P573
8573 48        PHA
8574 F8        SED
8575 A9 01     LDA #&01			;Increment line number
8577 D0 03     BNE P57C
.P579
8579 48        PHA			;Add bytes/row to file offset
857A A5 AF     LDA &AF
.P57C
857C 18        CLC
857D 65 A8     ADC &A8
857F 85 A8     STA &A8
8581 A9 00     LDA #&00
8583 65 A9     ADC &A9
8585 85 A9     STA &A9
8587 D8        CLD
8588 68        PLA
8589 60        RTS

.P58A
858A 38        SEC			;Print offset w/leading zeroes
.P58B
858B 20 15 90  JSR Q015			;Print BCD line no at &00A8
858E EQUB &A8
858F EQUB &00				;terminator byte
8590 4C 03 90  JMP Q003			;print space and exit

.P593
8593 24 FF     BIT &FF			;Test Escape and BGET
8595 30 DA     BMI P571
8597 4C D7 FF  JMP osbget


;'Light' DFS commands
.P600
8600 4C 2A 86  JMP P62A			;*ACCESS

.P603
8603 4C 74 86  JMP P674			;*CAT

.P606
8606 4C BC 87  JMP P7BC			;*DELETE

.P609
8609 4C CD 87  JMP P7CD			;*DESTROY

.P60C
860C 4C 0E 88  JMP &880E		;*DIR

.P60F
860F 4C 28 88  JMP P828			;*DRIVE

.P612
8612 4C 42 88  JMP P842			;*INFO

.P615
8615 4C 35 88  JMP P835			;*LIB

.P618
8618 4C 54 88  JMP P854			;*RENAME

.P61B
861B 4C 91 88  JMP P891			;*TITLE

.P61E
861E 4C B9 88  JMP P8B9			;*WIPE

.P621
8621 4C 3E 86  JMP P63E			;*LOCK

.P624
8624 4C 4C 86  JMP P64C			;*UNLOCK

.P627
8627 4C 1B 88  JMP P81B			;*VOL

.P62A					;*ACCESS
862A 20 15 93  JSR Q315			;Get ambiguous file spec?
862D 20 C5 FF  JSR gsread		;get afsp, call GSREAD
8630 B0 1D     BCS P64F			;if end of string unlock file
8632 C9 4C     CMP #&4C			;else is character "L"?
8634 D0 05     BNE P63B			;if not print syntax and exit
8636 20 C5 FF  JSR gsread		;call GSREAD for next char
8639 B0 06     BCS P641			;if end of string lock file
863B 4C 09 81  JMP P109			;else print syntax and exit

.P63E					;*LOCK
863E 20 15 93  JSR Q315			;Get ambiguous file spec?
.P641
8641 20 6A 86  JSR P66A			;select file, dir in A
.P644
8644 09 80     ORA #&80			;set attribute bit
8646 20 5A 86  JSR P65A			;update file, select next
8649 90 F9     BCC P644			;loop until no more files
864B 60        RTS

P64C					;*UNLOCK
864C 20 15 93  JSR Q315			;Get ambiguous file spec?
.P64F
864F 20 6A 86  JSR P66A			;select file, dir in A
.P652
8652 29 7F     AND #&7F			;clear attribute bit
8654 20 5A 86  JSR P65A			;update file, select next
8657 90 F9     BCC P652			;loop until no more files
8659 60        RTS

.P65A					;Update file entry
865A 8D 47 10  STA &1047		;store dir
865D 20 06 A6  JSR R606			;pack catalogue entry
8660 20 0F A5  JSR R50F			;find next match of afsp
8663 90 08     BCC P66D			;if more matches select next
8665 20 03 9B  JSR QB03			;else write catalogue
8668 38        SEC			;set carry
8669 60        RTS			;and exit

.P66A
866A 20 83 89  JSR P983			;Select file from afsp
. P66D
866D 20 03 A6  JSR R603			;?, unpack catalogue entry
8670 AD 47 10  LDA &1047		;return directory and attribute
8673 60        RTS

.P674					;*CAT
8674 20 06 93  JSR Q306			;get drv/vol spec,
8677 20 0C 9B  JSR QB0C			;softmount disc
867A 20 6E 89  JSR P96E			;reset column COUNT = 0
867D 20 18 90  JSR Q018			;Print "Defs"
8680 EQUB &00
8681 EQUS "Defs"
8685 EQUB &00				;terminator byte
8686 A2 00     LDX #&00			;x=0 for default path
8688 20 E9 88  JSR P8E9			;print " :"+path
868B A9 2E     LDA #&2E			;start with a dot
.P68D
868D 20 00 90  JSR Q000			;print character in A
8690 BD 00 10  LDA &1000,X		;get character of def filename
8693 E8        INX			;increment index
8694 E0 08     CPX #&08			;have we loaded 7 characters?
8696 D0 F5     BNE P68D			;if not then loop
8698 20 73 89  JSR P973			;else tab to next 20-column
869B 20 18 90  JSR Q018			;print "Lib"
869E EQUB &00
869F EQUS "Lib"
86A2 EQUB &00				;terminator byte
86A3 A2 03     LDX #&03			;X = 3 for library path
86A5 20 E9 88  JSR P8E9			;print " :"+path
86A8 20 73 89  JSR P973			;tab to next 20-column
86AB A5 C9     LDA &C9			;get immediate (*CAT) drive, A = current drive
86AD 20 18 90  JSR Q018			;print "Drive "+number
86B0 EQUB &C0
86B1 EQUS "Drive "
86B7 EQUB &00				;terminator byte
86B8 AA        TAX			;drive number to X register
86B9 BD F8 0F  LDA &0FF8,X		;get track stepping status
86BC D0 09     BNE P6C7			;if enabled skip forward
86BE BD F4 0F  LDA &0FF4,X		;else get no. tracks
86C1 20 04 89  JSR P904			;"Print "n tracks"
86C4 4C D3 86  JMP P6D3			;skip forward.

.P6C7
86C7 20 18 90  JSR Q018			;Print " 40-80"
86CA EQUB &00
86CB EQUS "  40-80"
86D2 EQUB &00				;terminator byte
.P6D3
86D3 20 73 89  JSR P973			;tab to next 20-column
86D6 BD F0 0F  LDA &0FF0,X		;get density flag
86D9 4A        LSR A
86DA 4A        LSR A
86DB 4A        LSR A			;divide by 8 (SD=1 DD=2)
86DC 20 18 90  JSR Q018			;Print "Density "
86DF EQUB &80
86E0 EQUS "Density "
86E8 EQUB &00				;terminator byte
86E9 BD FC 0F  LDA &0FFC,X		;get number of volumes
86EC F0 32     BEQ P720			;if DFS skip volume list
86EE 20 03 90  JSR Q003			;else print a space
86F1 A0 41     LDY #&41			;start with "A"
.P6F3
86F3 B9 EF 0F  LDA &0FEF,Y		;get no. tracks in 1030..7
86F6 F0 04     BEQ &86FC		;if none volume not present
86F8 98        TYA			;else print volume letter
86F9 20 00 90  JSR Q000			;Print character in A
86FC C8        INY			;increment volume letter
86FD C0 49     CPY #&49			;is it before "I"?
86FF D0 F2     BNE P6F3			;if so loop.
8701 A4 C8     LDY &C8			;get immediate (*CAT) volume, Y = Immediate volume
8703 D0 18     BNE P71D			;if undefined then
8705 20 6B 89  JSR P96B			;cat all vols: print newline
8708 A0 41     LDY #&41			;set immediate volume = "A"
.P70A
870A 84 C8     STY &C8			;Y -> &00C8 = Immediate volume
870C B9 EF 0F  LDA &0FEF,Y		;get no. tracks in volume
870F F0 06     BEQ P717			;if volume is present
8711 20 00 9B  JSR QB00			;then read volume catalogue
8714 20 23 87  JSR P723			;and list its contents.
.P717					;increment volume letter
8717 C8        INY			;if now less than "I"
8718 C0 49     CPY #&49			;then loop over volumes
871A D0 EE     BNE P70A			;else exit.
871C 60        RTS

.P71D
871D 20 09 9B  JSR QB09			;load volume catalogue
.P720
8720 20 6B 89  JSR P96B			;print newline, reset count
.P723
8723 20 00 92  JSR Q200			;save AXY
8726 20 6B 89  JSR P96B			;print newline, reset count
8729 A2 00     LDX #&00			;print first 8 characters
.P72B
872B BD 00 0E  LDA &0E00,X		;of title in sector 0
872E 20 00 90  JSR Q000			;Print character in A
8731 E8        INX
8732 E0 08     CPX #&08
8734 D0 F5     BNE P72B
8736 A2 00     LDX #&00			;print last 4 characters
.P738
8738 BD 00 0F  LDA &0F00,X		;of title in sector 1
873B 20 00 90  JSR Q000			;Print character in A
873E E8        INX
873F E0 04     CPX #&04
8741 D0 F5     BNE P738
8743 AD 04 0F  LDA &0F04		;get cycle number
8746 20 18 90  JSR Q018			;print " ("+hex byte
8749 40        RTI
874A 20 28 00  JSR &0028
874D A9 29     LDA #&29
874F 20 00 90  JSR Q000			;print ")"
8752 A6 C9     LDX &C9			;X = current drive
8754 BD FC 0F  LDA &0FFC,X		;X=*CAT drive number
8757 F0 18     BEQ P771			;get number of volumes
8759 20 73 89  JSR P973			;if not a DFS disc
875C 20 73 89  JSR P973			;then tab to next 20-column
875F A4 C8     LDY &C8			;and again, Y = Immediate volume
8761 98        TYA			;get *CAT volume letter, Y -> A = Immediate volume
8762 20 18 90  JSR Q018			;print "Vol " +letter?
8765 EQUB &C0
8766 EQUS "Vol "
876A EQUB &00				;terminator byte
876B B9 EF 0F  LDA &0FEF,Y		;get number of tracks in volume
876E 20 04 89  JSR P904			;print "n tracks"
.P771
8771 20 73 89  JSR P973			;tab to next 20-field
8774 20 1B A6  JSR R61B			;get free space on volume
8777 20 09 A4  JSR R409			;print decimal word
877A 20 18 90  JSR Q018			;Print "free/"
877D EQUB &00
877E EQUS "free/"
8783 EQUB &00				;terminator byte
8784 AD 06 0F  LDA &0F06		;get sectors on volume high
8787 29 07     AND #&07			;mask all but low 3 bits
8789 8D 61 10  STA &1061		;store in accumulator high
878C AD 07 0F  LDA &0F07		;get sectors on volume low
878F 8D 60 10  STA &1060		;store accumulator low
8792 20 09 A4  JSR R409			;print decimal wor
8795 20 03 90  JSR Q003			;print space
8798 20 09 96  JSR Q609			;get boot option, X=offset
879B A9 20     LDA #&20			;start with a space
.P79D					;get char of boot opt string
879D 20 00 90  JSR Q000			;Print character in A
87A0 BD 0C 96  LDA Q60C,X
87A3 E8        INX			;increment X "OFF LOAD RUN EXEC "
87A4 C9 20     CMP #&20			;was the character space?
87A6 D0 F5     BNE P79D			;if not then loop
87A8 20 6B 89  JSR P96B			;else print newline
87AB AD 07 10  LDA &1007		;get default directory
87AE 85 C7     STA &C7			;store immediate directory
87B0 A9 00     LDA #&00			;set A=0 Immediate dir'y, A -> &00C7
87B2 20 18 89  JSR P918			;list files in immed dir
87B5 A9 80     LDA #&80			;set A=&80
87B7 20 18 89  JSR P918			;list files in all (other) dirs
87BA 38        SEC			;breakout ROM call and exit
87BB 60        RTS

.P7BC					;*DELETE
87BC 20 12 93  JSR Q312			;get fsp, cat &
87BF 20 83 89  JSR P983			;check if exists
87C2 20 21 A5  JSR R521			;check file not locked
87C5 20 00 A6  JSR R600			;delete catalogue entry
87C8 20 03 9B  JSR QB03			;write catalogue
87CB 38        SEC			;breakout ROM call
87CC 60        RTS			;and exit.

.P7CD					;*DESTROY
87CD 20 15 93  JSR Q315			;get afsp
87D0 20 00 9B  JSR QB00			;load catalogue
87D3 20 12 A5  JSR R512			;find unlocked file in cat
87D6 B0 34     BCS P80C			;if not found exit silently
87D8 20 6E 89  JSR P96E			;else reset column count
.P7DB
87DB 20 03 A6  JSR R603			;unpack fields from catalogue
87DE 20 03 A4  JSR R403			;print directory and filename
87E1 20 00 A6  JSR R600			;delete catalogue entry
87E4 20 18 A5  JSR R518			;find next unlocked match
87E7 B0 06     BCS P7EF			;if found, then tab to next 20-column
87E9 20 73 89  JSR P973			;and loop
87EC 4C DB 87  JMP P7DB			;else ask

.P7EF
87EF 20 18 90  JSR Q018			;"Destroy these files?" (*ENABLE won't bypass it)
87F2 EQUB &11
87F3 EQUS "Destroy these files"
8806 EQUB &00				;terminator byte
8807 D0 03     BNE P80C			;if user answers yes
8809 20 03 9B  JSR QB03			;then write catalogue.
.P80C
880C 38        SEC
880D 60        RTS			;breakout ROM call and exit.

.P80E					;*DIR
880E 20 09 93  JSR Q309			;get path spec
8811 20 06 92  JSR Q206			;Copy memory absolute
8814 EQUW &C7,&00			;from immediate path
8816 EQUW &07,&10			;to default path
8818 EQUB &03				;(dir, volume and drive)
8819 38        SEC
881A 60        RTS			;breakout ROM call and exit.

.P81B					;*VOL, *DRIVE
881B 20 03 93  JSR Q303			;get volume spec (no colon)
881E 20 06 92  JSR Q206			;Copy memory absolute
8821 EQUW &C8,&00			;from  vol+drive
8823 EQUW &08,&10			;to default path
8825 EQUB &02				;vol+drive
8826 38        SEC
8827 60        RTS			;breakout ROM call and exit.

.P828					;*DRIVE
8828 20 00 93  JSR Q300			;get drive number
882B 20 06 92  JSR Q206			;Copy memory absolute
882E EQUW &C9,&00			;from immediate drive
8830 EQUW &09,&10			;to default path
8832 EQUB &01 				;drive
8833 38        SEC
8834 60        RTS			;breakout ROM call and exit.

.P835					;*LIB
8835 20 09 93  JSR Q309			;get path spec
8838 20 06 92  JSR Q206			;Copy memory absolute
883B EQUW &C7,&00			;from immediate path, &00C7
883D EQUW &0A,&10			;to library path, &100A
883F EQUB &03
8840 38        SEC
8841 60        RTS			;breakout ROM call and exit.

.P842					;*INFO
8842 20 80 89  JSR P980			;get afsp, check it exists,
.P845
8845 20 03 A6  JSR R603			;unpack cat
8848 20 06 A4  JSR R406			;print *INFO line
884B 20 09 90  JSR Q009			;print newline
884E 20 0F A5  JSR R50F			;find next match of afsp
8851 90 F2     BCC P845			;loop,
8853 60        RTS			;else, reakout ROM call and exit.

.P854					;*RENAME
8854 98        TYA			;save command line pointer
8855 48        PHA
8856 20 12 93  JSR Q312			;Get file spec?
8859 20 0F 93  JSR Q30F			;get entry name
885C 68        PLA			;(to check syntax)
885D A8        TAY			;restore command line pointer
885E 20 12 93  JSR Q312			;Get file spec?
8861 20 83 89  JSR P983			;check file exists
8864 20 21 A5  JSR R521			;check file not locked
8867 A5 CC     LDA &CC			;get pointer to cat entry
8869 48        PHA			;save it
886A 20 0F 93  JSR Q30F			;get new entry name
886D 20 09 A5  JSR R509			;try to find it in cat
8870 B0 11     BCS P883			;if present
8872 20 18 90  JSR Q018			;then "File exists" error
8875 EQUB &0A
8876 EQUB &C4
8877 EQUS "File exists"
8882 EQUB &00				;terminator byte
.P883
8883 68        PLA			;else restore cat pointer
8884 AA        TAX
8885 20 09 92  JSR Q209			;copy immediate filename
8888 EQUW &C0,&00			;into catalogue at index X+8
888A EQUW &08,&0E
888C EQUW &08,&02
888E 4C B4 88  JMP P8B4			;jump to write cat and exit.

.P891					;*TITLE
8891 20 06 92  JSR Q206			;Copy default path to immed
8894 EQUW &00,&10			;FROM address &1000
8896 EQUW &C0,&00			;TO address &00C0
8898 EQUB &0A				;count
8899 20 00 9B  JSR QB00			;load catalogue
889C A2 00     LDX #&00			;clear index register
.P89E
889E 20 1E 93  JSR Q31E			;get character of string
88A1 9D 00 0E  STA &0E00,X		;store in first part of title
88A4 E8        INX			;increment index register
88A5 E0 08     CPX #&08			;is it now 8 or more?
88A7 D0 F5     BNE P89E			;if not loop
.P8A9
88A9 20 1E 93  JSR Q31E			;else get character of string
88AC 9D F8 0E  STA &0EF8,X		;store in last part of title
88AF E8        INX			;increment index register
88B0 E0 0C     CPX #&0C			;is it 12 or more?
88B2 D0 F5     BNE P8A9			;if not loop
.P8B4
88B4 20 03 9B  JSR QB03			;else write catalogue;
88B7 38        SEC			;breakout ROM call
88B8 60        RTS			;and exit.

.P8B9					;*WIPE
88B9 20 80 89  JSR P980			;get afsp, check it exists
.P8BC
88BC 20 03 A6  JSR R603			;unpack cat
88BF 20 03 A4  JSR R403			;print directory and filename
88C2 AD 47 10  LDA &1047		;get attribute bit
88C5 10 06     BPL P8CD			;if locked
88C7 20 09 90  JSR Q009			;then print newline
88CA 4C E3 88  JMP P8E3			;and loop to next file

.P8CD
88CD 20 18 90  JSR Q018			;ask " : delete?"
88D0 EQUB &10
88D1 EQUS " : delete"
88DA EQUB &00				;terminator byte
88DB D0 06     BNE P8E3			;if user answers no then loop
88DD 20 00 A6  JSR R600			;else delete entry
88E0 20 03 9B  JSR QB03			;and write catalogue.
.P8E3
88E3 20 0F A5  JSR R50F			;find next match of afsp
88E6 90 D4     BCC P8BC			;and loop else
88E8 60        RTS			;breakout +exit.

.P8E9					;Print " :"+path
88E9 BD 09 10  LDA &1009,X		;get drive, X = 3 library path, X = 0 default path
88EC 20 18 90  JSR Q018			;print " :"+drive
88EF EQUB &C0
88F0 EQUS " :"
88F2 EQUB &00				;terminator byte
88F3 BD 08 10  LDA &1008,X		;get volume letter
88F6 20 00 90  JSR Q000			;Print character in A
88F9 A9 2E     LDA #&2E			;set A=dot
88FB 20 00 90  JSR Q000			;Print character in A
88FE BD 07 10  LDA &1007,X		;get directory character
8901 4C 00 90  JMP Q000			;Print character in A

.P904
8904 20 18 90  JSR Q018			;Print "n tracks"
8907 EQUB &80
8908 EQUS "  "
890A EQUB &00				;terminator byte
890B 20 18 90  JSR Q018			;Print "n tracks"
890E EQUB &00
890F EQUS " tracks"
8916 EQUB &00				;terminator byte
8917 60        RTS			;and exit.

.P918					;List files in dir
8918 85 A8     STA &A8			;A=0 immed dir, A=&80 all dirs
891A 20 89 89  JSR P989			;select first file in cat para
891D B0 60     BCS P97F			;if none exit else print newline
891F 20 6B 89  JSR P96B			;set X = catalogue pointer
.P922
8922 A6 CC     LDX &CC
8924 86 A9     STX &A9			;store in temp
8926 20 09 92  JSR Q209			;copy catalogue entry
8929 EQUW &08,&0E			;to immediate name and directory
892B EQUW &C0,&00
892D EQUW &08,&20
.P92F
892F 20 8F 89  JSR P98F			;select next file in cat para
8932 B0 07     BCS P93B			;if no more files then break out
8934 20 1B A5  JSR R51B			;else compare immed - cat entry
8937 90 F6     BCC P92F			;if cat entry > immed then loop
8939 B0 E7     BCS P922			;else loop to set new 'minimum'.
.P93B
893B 20 06 92  JSR Q206			;Copy memory absolute
893E EQUW &C0,&00			;FROM immediate filename and dir &00C0
8940 EQUW &40,&10			;TO catalogue workspace &1040
8942 EQUB &08				;count
8943 20 03 90  JSR Q003			;print space
8946 24 A8     BIT &A8			;test directory flag
8948 30 0C     BMI P956			;if current dir only
894A 20 03 90  JSR Q003			;then print two spaces
894D 20 03 90  JSR Q003			;to replace directory and dot
8950 20 00 A4  JSR R400			;print filename
8953 4C 59 89  JMP P959			;and jump forward

.P956
8956 20 03 A4  JSR R403			;else print dir and filename.
.P959
8959 A6 A9     LDX &A9			;get temp value
895B 86 CC     STX &CC			;restore to catalogue pointer
895D 20 00 A6  JSR R600			;delete catalogue entry
8960 20 89 89  JSR P989			;select first file in cat para
8963 B0 06     BCS P96B			;if no more print nl and exit
8965 20 73 89  JSR P973			;else tab to next 20-column
8968 4C 22 89  JMP P922			;&loopfor next file in cat para.

.P96B
896B 20 09 90  JSR Q009			;Print newline +reset:
.P96E
896E 48        PHA
896F A9 00     LDA #&00			;Reset column COUNT = 0
8971 F0 09     BEQ P97C
.P973					;Tab to next 20-column
8973 48        PHA
8974 A5 AA     LDA &AA
8976 18        CLC
8977 69 14     ADC #&14
8979 20 06 90  JSR Q006			;Tab to column in A
.P97C
897C 85 AA     STA &AA
897E 68        PLA
.P97F
897F 60        RTS

.P980
8980 20 15 93  JSR Q315			;Get ambiguous file spec?
.P983
8983 20 00 9B  JSR QB00			;load catalogue
8986 4C 0C A5  JMP R50C			;and check file exists.

.P989
8989 20 00 A5  JSR R500			;Select first file in cat para
898C 4C 92 89  JMP P992			;select 1st file and jump

.P98F
898F 20 06 A5  JSR R506			;Select next file in cat para
.P992
8992 B0 0A     BCS P99E			;if no more files then exit C=1
8994 24 A8     BIT &A8			;else test directory flag
8996 30 05     BMI P99D			;if b7=1 then exit C=0
8998 20 1E A5  JSR R51E			;else compare directory letters
899B D0 F2     BNE P98F			;if mismatch then loop
.P99D
899D 18        CLC			;else exit C=0
.P99E
899E 60        RTS


;'Medium' DFS commands
.PA00
8A00 4C 15 8A  JMP PA15			;*BACKUP

.PA03
8A03 4C D3 8A  JMP PAD3			;*COMPACT

.PA06
8A06 4C 64 8B  JMP PB64			;*COPY

.PA09
8A09 4C E7 8B  JMP PBE7			;*ENABLE

.PA0C
8A0C 4C FA 8C  JMP PCFA			;Ask user for confirmation

.PA0F
8A0F 4C 77 8B  JMP PB77			;*SCOPY

.PA12
8A12 4C A5 8B  JMP PBA5			;*FCOPY

.PA15					;*BACKUP
8A15 20 00 93  JSR Q300			;get drive spec
8A18 A5 C9     LDA &C9			;A = current drive
8A1A 8D 70 10  STA &1070		;store source drive in workspace
8A1D 20 00 93  JSR Q300			;get drive spec
8A20 A5 C9     LDA &C9			;A = current drive
8A22 8D 71 10  STA &1071		;store dest drive in workspace
8A25 A9 00     LDA #&00
8A27 8D 72 10  STA &1072		;clear source volume
8A2A 8D 73 10  STA &1073		;and target volume
8A2D AD 70 10  LDA &1070		;A = source drive
8A30 20 18 90  JSR Q018			;print "Copying from drive " +source drive
8A33 EQUB &C0
8A34 EQUS "Copying from drive "
8A47 EQUB &00				;terminator byte
8A48 AD 71 10  LDA &1071
8A4B 20 18 90  JSR Q018			;print " to drive "+target+nl
8A4E EQUB &C2
8A4F EQUS " to drive "
8A59 EQUB &00				;terminator byte
8A5A 20 77 8D  JSR PD77			;Compare drive geometries,initialise and load source disc
8A5D 20 FF 8B  JSR PBFF			;set up prompt flag
8A60 AE 70 10  LDX &1070		;get source drive for use later
8A63 BD F4 0F  LDA &0FF4,X		;get no. tracks on source drive
8A66 8D 81 10  STA &1081		;store temp
8A69 BD F0 0F  LDA &0FF0,X		;get density of source drive
8A6C 48        PHA			;push density
8A6D 20 B7 8D  JSR PDB7			;swap source and target discs
8A70 20 91 8D  JSR PD91			;ensure catalogue loaded
8A73 AE 71 10  LDX &1071		;get target drive for use later
8A76 68        PLA			;pop source density
8A77 DD F0 0F  CMP &0FF0,X		;compare with target density
8A7A D0 3F     BNE PABB			;if unequal "Incompatible discs"
8A7C AD 81 10  LDA &1081		;else get source tracks
8A7F DD F4 0F  CMP &0FF4,X		;compare with target tracks
8A82 D0 37     BNE PABB			;if unequal "Incompatible discs"
8A84 A9 00     LDA #&00			;else clear src sectors-to-go
8A86 8D 76 10  STA &1076
8A89 8D 78 10  STA &1078
8A8C 8D 79 10  STA &1079		;and high byte of target stg.
.PA8F
8A8F BD F0 0F  LDA &0FF0,X		;get target sectors per track
8A92 18        CLC
8A93 6D 76 10  ADC &1076		;increase stg counts by this
8A96 8D 76 10  STA &1076
8A99 8D 77 10  STA &1077
8A9C 90 06     BCC PAA4			;carry out to high bytes
8A9E EE 78 10  INC &1078
8AA1 EE 79 10  INC &1079
.PAA4
8AA4 CE 81 10  DEC &1081
8AA7 D0 E6     BNE PA8F			;loop until all tracks done.
8AA9 AD 71 10  LDA &1071		;get target drive
8AAC 09 80     ORA #&80			;set top bit
8AAE 20 0C 8A  JSR PA0C			;confirm wipe of disc and memory
8AB1 90 06     BCC PAB9			;if No then exitAsk user for confirmation
8AB3 20 58 8E  JSR PE58			;else copy the disc
8AB6 20 58 8E  JSR PE58			;and make sure it is all done.
.PAB9
8AB9 38        SEC			;break out of ROM call
8ABA 60        RTS			;and exit

.PABB
8ABB 20 18 90  JSR Q018			;Error "Incompatible discs"
8ABE EQUB &0A				;LF
8ABF EQUB &D3
8AC0 EQUS "Incompatible discs"
8AD2 EQUB &00				;terminator byte
.PAD3					;*COMPACT
8AD3 20 EE 8B  JSR PBEE			;get and store volume spec
8AD6 20 F3 8B  JSR PBF3			;store it as 'target' volume too
8AD9 20 77 8D  JSR PD77			;Compare drive geometries
8ADC A9 80     LDA #&80			;initialise & load source disc
8ADE 8D 80 10  STA &1080		;set flag for single disc oper'n
8AE1 A2 00     LDX #&00			;set &106B,C = &0001
8AE3 8E 6C 10  STX &106C		;to search for one free sector
8AE6 E8        INX
8AE7 8E 6B 10  STX &106B
8AEA 20 0C A6  JSR R60C			;find a free space in volume
8AED B0 5B     BCS PB4A			;(not at end!) if not found quit
8AEF 20 06 A5  JSR R506			;else select next (a) file
8AF2 B0 56     BCS PB4A			;if no file found finish
8AF4 AD 70 10  LDA &1070		;else get source drive
8AF7 20 18 90  JSR Q018			;print "Compacting vol "+n
8AFA EQUB &C0
8AFB EQUS "Compacting vol "
8B0A EQUB &00				;terminator byte
8B0B AD 72 10  LDA &1072		;get source volume letter
8B0E 20 00 90  JSR Q000			;Print it in A
8B11 20 09 90  JSR Q009			;print newline
8B14 A9 80     LDA #&80			;this routine wipes memory only
8B16 20 0C 8A  JSR PA0C			;Ask user for confirmation
8B19 90 2F     BCC PB4A			;if not given then finish
.PB1B
8B1B 20 03 A6  JSR R603			;else unpack fields from cat
8B1E 20 CE 8E  JSR PECE			;copy entry from cat 1 to 2
8B21 20 00 A6  JSR R600			;delete catalogue entry
.PB24
8B24 20 2A 8F  JSR PF2A			;set copy range = entry range
.PB27
8B27 20 5B 8E  JSR PE5B			;copy file
8B2A 98        TYA			;if a write is now due
8B2B D0 0D     BNE PB3A			;then flush buffer &test if done
8B2D A6 CC     LDX &CC			;else get catalogue pointer
8B2F 20 06 A5  JSR R506			;select next 'source' file
8B32 90 E7     BCC PB1B			;and loop if one is found
8B34 20 B7 8D  JSR PDB7			;else 'swap discs'
8B37 4C 27 8B  JMP PB27			;and loop back to tidy up.

.PB3A
8B3A E4 AB     CPX &AB			;if all files have been saved
8B3C F0 09     BEQ PB47			;then finish
8B3E 20 F0 8E  JSR PEF0			;else unpack cat 2 entry
8B41 20 45 8F  JSR PF45			;create catalogue entry +*INFO
8B44 4C 24 8B  JMP PB24			;& loop back to save this file.

.PB47					;Finish *COMPACT
8B47 20 03 9B  JSR QB03			;write catalogue
.PB4A
8B4A 20 1B A6  JSR R61B			;get free space on volume
8B4D 20 09 A4  JSR R409			;print decimal word
8B50 20 18 90  JSR Q018			;print " free sectors"+newline
8B53 EQUB &02
8B54 EQUS " free sectors"
8B61 EQUB &00				;terminator byte
8B62 38        SEC
8B63 60        RTS			;and exit C=1.

.PB64					;*COPY
8B64 20 DC 8C  JSR PCDC			;process args
8B67 90 3A     BCC PBA3			;if user aborts, then exit
.PB69
8B69 20 03 A6  JSR R603			;else unpack fields
8B6C 20 49 8C  JSR PC49			;copy cat 1 to 2 and copy file
8B6F 20 0F A5  JSR R50F			;find next match of afsp
8B72 90 F5     BCC PB69			;and loop if one is found
8B74 4C 5B 8C  JMP PC5B			;else flush copy buffer &exit.

.PB77					;*SCOPY
8B77 20 DC 8C  JSR PCDC			;process args, if user aborts
8B7A 90 27     BCC PBA3			;then exit
.PB7C
8B7C 20 03 A6  JSR R603			;else unpack fields
8B7F 20 03 A4  JSR R403			;print directory and filename*SCOPY
8B82 20 18 90  JSR Q018			;ask " : copy?"
8B85 EQUB &10
8B86 EQUS " : copy"
8B8D EQUB &00				;terminator byte
8B8E D0 0E     BNE PB9E			;if user answers yes, then:
8B90 20 49 8C  JSR PC49			;copy cat 1 to 2 and copy file
8B93 20 5B 8C  JSR PC5B			;flush copy buffer
8B96 20 B7 8D  JSR PDB7			;swap discs (to reselect source)
8B99 20 91 8D  JSR PD91			;ensure catalogue loaded
8B9C 86 CC     STX &CC			;save catalogue pointer
.PB9E
8B9E 20 0F A5  JSR R50F			;find next match of afsp
8BA1 90 D9     BCC PB7C			;and loop if one is found
.PBA3
8BA3 38        SEC
8BA4 60        RTS			;else exit C=1.

.PBA5					;*FCOPY
8BA5 20 12 93  JSR Q312			;Get file spec?
8BA8 A2 00     LDX #&00			;clear X
8BAA 20 F3 8B  JSR PBF3			;store source vol for copier
8BAD 20 06 92  JSR Q206			;Copy memory absolute
8BB0 EQUW &C0,&00			;FROM immediate filename+dir, &00C0
8BB2 EQUW &40,&10			;TO catalogue block 1, &1040
8BB4 EQUB &08				;count
8BB5 20 12 93  JSR Q312			;Get file spec?
8BB8 20 F3 8B  JSR PBF3			;store target vol for copier
8BBB 20 06 92  JSR Q206			;Copy memory absolute
8BBE EQUW &C0,&00			;FROM immediate filename+dir,  &00C0
8BC0 EQUW &58,&10			;TO catalogue block 2, &1058
8BC2 EQUB &08				;count
8BC3 20 06 92  JSR Q206			;Copy memory absolute
8BC6 EQUW &40,&10			;FROM catalogue block 1, &1040
8BC8 EQUW &C0,&00			;back TO immediate filename+dir, &00C0
8BCA EQUB &08				;count
8BCB 20 98 8C  JSR PC98			;init copy, find source file
8BCE 20 F8 8C  JSR PCF8			;ask to overwrite memory
8BD1 90 D0     BCC PBA3			;if refused exit C=1
8BD3 20 03 A6  JSR R603			;else unpack fields from cat
8BD6 A6 CC     LDX &CC			;get catalogue pointer in X
8BD8 20 09 92  JSR Q209			;copy target filename+dir
8BDB EQUW &58,&10			;to catalogue entry
8BDD EQUW &08,&0E			;temporarily renaming the file
8BDF EQUW &08,&02
8BE1 20 49 8C  JSR PC49			;copy cat to cat2 and copy file
8BE4 4C 5B 8C  JMP PC5B			;flush copy buffer &exit.

.PBE7					;*ENABLE
8BE7 A9 02     LDA #&02			;set enabled flag b1=1
8BE9 8D 0F 10  STA &100F		;break out of ROM call
8BEC 38        SEC			;set carry
8BED 60        RTS			;and exit

.PBEE
8BEE A2 00     LDX #&00			;Get and store source vol spec:
.PBF0
8BF0 20 03 93  JSR Q303			;Get and store dest vol spec
.PBF3
8BF3 A5 C8     LDA &C8			;get volume letter of spec, A = Immediate volume
8BF5 9D 72 10  STA &1072,X		;store it in source/dest info
8BF8 A5 C9     LDA &C9			;get drive letter of spec, A = current drive
8BFA 9D 70 10  STA &1070,X		;store it in source/dest info
8BFD E8        INX			;move pointer from src to dest.
8BFE 60        RTS			;and exit

.PBFF
8BFF AD 72 10  LDA &1072		;Set up prompt flag
8C02 CD 73 10  CMP &1073		;compare src and target volumes
8C05 D0 08     BNE PC0F 		;if equal, then:
8C07 AD 70 10  LDA &1070		;compare src and target drives
8C0A CD 71 10  CMP &1071		;if equal,discs must be distinct
8C0D F0 34     BEQ PC43			;so jump to set prompt bit
.PC0F
8C0F AD 70 10  LDA &1070		;else get source drive
8C12 4D 71 10  EOR &1071		;XOR target drive
8C15 29 01     AND #&01			;A=1 iff different units
8C17 D0 2F     BNE PC48			;if so then exit
8C19 20 18 90  JSR Q018			;else ask, "Are source and target the same disc?"
8C1C EQUB &10
8C1D EQUS "Are source and target the same disc"
8C40 EQUB &00				;terminator byte
8C41 F0 05     BEQ PC48			;if Yes then exit
.PC43
8C43 A9 40     LDA #&40			;else, A = &40
8C45 8D 80 10  STA &1080		;set prompt flag.
.PC48
8C48 60        RTS			;exit

.PC49
8C49 20 CE 8E  JSR PECE			;copy entry from cat 1 to 2:

; Copy file.  Fulfils the entry now in catalogue block 2.
; On entry if Y=0 then the file's contents are read from the source
; disc into the data buffer.
; If Y=1 then the file's contents are written from the data buffer
; on to the target disc, and the rest of the copy buffer is flushed.

.PC4C					;Copy file
8C4C 20 2A 8F  JSR PF2A			;set copy range = entry range
8C4F 20 5B 8E  JSR PE5B			;read/write range to buffer
8C52 98        TYA
8C53 D0 09     BNE PC5E			;if write now due, flush else:
8C55 20 91 8D  JSR PD91			;ensure catalogue loaded
8C58 86 CC     STX &CC			;save catalogue ptr
8C5A 60        RTS			;and exit.

.PC5B
8C5B 20 58 8E  JSR PE58			;write(?) range, then:
.PC5E
8C5E E4 AB     CPX &AB			;Flush copy buffer. if empty
8C60 F0 31     BEQ PC93			;then flush cat 1 and exit C=1
8C62 20 F0 8E  JSR PEF0			;else unpack cat 2 entry
8C65 20 91 8D  JSR PD91			;ensure catalogue loaded
8C68 20 06 92  JSR Q206			;Copy memory absolute
8C6B EQUW &C0,&00			;FROM immediate filename+dir &00C0
8C6D EQUW &40,&10			;TO catalogue block 1, &1040 (save filename being read)
8C6F EQUB &08				;count
8C70 20 06 92  JSR Q206			;Copy memory absolute
8C73 EQUW &58,&10			;FROM catalogue block 2, &1058
8C75 EQUW &C0,&00			;TO immediate filename+dir, &00C0 (target file name)
8C77 EQUB &08				;count
8C78 20 09 A5  JSR R509			;find file in catalogue
8C7B B0 06     BCS PC83			;if not found skip, else:
8C7D 20 21 A5  JSR R521			;check file not locked
8C80 20 00 A6  JSR R600			;delete catalogue entry
.PC83
8C83 20 06 92  JSR Q206			;Copy memory absolute
8C86 EQUW &40,&10			;FROM catalogue block 1, &1040
8C88 EQUW &C0,&00			;TO immediate filename+dir, &00C0 (restore filename being read)
8C8A EQUB &08				;count
8C8B 20 45 8F  JSR PF45			;create cat entry +*INFO
8C8E E6 A8     INC &A8			;mark catalogue page as dirty
8C90 4C 4C 8C  JMP PC4C			;and go back to Copy file!

.PC93
8C93 20 A7 8D  JSR PDA7			;Flush catalogue,
8C96 38        SEC
8C97 60        RTS			;exit C=1

.PC98					;Initialise copy
8C98 20 77 8D  JSR PD77			;Compare drive geometries
8C9B 20 0C A5  JSR R50C			;init+cat, check file exists
8C9E AD 06 0F  LDA &0F06		;get top 3 bits of disc size
8CA1 8D 81 10  STA &1081		;(+boot option), store 1081
8CA4 AD 70 10  LDA &1070		;get source drive
8CA7 20 18 90  JSR Q018			;print "Copying from vol "+n
8CAA EQUB &C0
8CAB EQUS "Copying from vol "
8CBC EQUB &00				;terminator byte
8CBD AD 72 10  LDA &1072		;get source vol letter
8CC0 20 00 90  JSR Q000			;print it (Print character in A)
8CC3 AD 71 10  LDA &1071		;get target drive
8CC6 20 18 90  JSR Q018			;print " to vol "+n
8CC9 EQUB &C0
8CCA EQUS " to vol "
8CD2 EQUB &00				;terminator byte
8CD3 AD 73 10  LDA &1073		;get target volume
8CD6 20 00 90  JSR Q000			;Print it (print character in A)
8CD9 4C 09 90  JMP Q009			;print newline and exit.

.PCDC
8CDC 20 EE 8B  JSR PBEE			;Process *COPY, *SCOPY arguments
8CDF 20 F0 8B  JSR PBF0			;get &store src & dest vol specs
8CE2 20 15 93  JSR Q315			;Get ambiguous file spec?
8CE5 20 98 8C  JSR PC98			;initialise copy
8CE8 20 FF 8B  JSR PBFF			;set up prompt flag
8CEB 2C 80 10  BIT &1080
8CEE 50 08     BVC PCF8
8CF0 A9 01     LDA #&01
8CF2 0D 80 10  ORA &1080
8CF5 8D 80 10  STA &1080		;copy prompt bit of flag to b0
.PCF8					;Ask to overwrite memory only:
8CF8 A9 80     LDA #&80
.PCFA					;Ask user for confirmation
8CFA 0A        ASL A
8CFB 90 1A     BCC PD17			;if b0=1 caller will wipe memory
8CFD 2C 7A 02  BIT &027A		;so test Tube presence
8D00 30 15     BMI PD17			;if present caller won't wipe I/O
8D02 20 53 8D  JSR PD53			;else ensure *ENABLEd or warn
8D05 B0 4A     BCS PD51			;if *ENABLED exit C=1
8D07 20 18 90  JSR Q018			;complete warning of memory loss
8D0A EQUB &02
8D0B EQUS "user memory"
8D16 EQUB &00				;terminator byte
.PD17
8D17 4A        LSR A			;if b1=1 caller will wipe disc
8D18 F0 18     BEQ PD32			;drive number in b2..3, now b0..1
8D1A 20 53 8D  JSR PD53			;ensure *ENABLED or warn
8D1D B0 32     BCS PD51			;if *ENABLED exit C=1
8D1F 20 18 90  JSR Q018			;complete warning of disc erasure
8D22 EQUB &C2
8D23 EQUS "disc in drive "
8D31 EQUB &00				;terminator byte
.PD32
8D32 20 18 90  JSR Q018			;Ask if user wants to proceed
8D35 EQUB &15
8D36 EQUS "Do you want to proceed"
8D4C EQUB &00				;terminator byte
8D4D F0 02     BEQ PD51			;Z=yes, if so exit C=1
8D4F 18        CLC			;else
8D50 60        RTS			;exit C=0.

.PD51
8D51 38        SEC
8D52 60        RTS			;exit C=1

.PD53
8D53 4E 0F 10  LSR &100F		;Print warning
8D56 B0 1E     BCS PD76			;return C=*ENABLEd
8D58 20 18 90  JSR Q018			;if not *ENABLEd
8D5B EQUB &01				;begin warning message.
8D5C EQUS "WARNING: will overwrite "
8D74 EQUB &00				;terminator byte
8D75 18        CLC
.PD76
8D76 60        RTS

.PD77					;Compare drive geometries
8D77 A9 00     LDA #&00			;Initialise and load source disc
8D79 A8        TAY			;clear A,Y
8D7A 85 AB     STA &AB			;and &AB
8D7C A2 0B     LDX #&0B
.PD7E
8D7E 9D 76 10  STA &1076,X		;and &1076..81
8D81 CA        DEX
8D82 10 FA     BPL PD7E
8D84 A9 13     LDA #&13			;A = 8271 read cmd for source drive
8D86 8D 74 10  STA &1074
8D89 A9 0B     LDA #&0B			;A = 8271 write command for target
8D8B 8D 75 10  STA &1075
8D8E 20 C7 8D  JSR PDC7			;ask for disc, then:
.PD91
8D91 48        PHA			;Ensure catalogue loaded
8D92 A5 A8     LDA &A8			;get catalogue flag
8D94 D0 0F     BNE PDA5			;if catalogue empty
8D96 A5 C8     LDA &C8			;then get immediate volume
8D98 F0 06     BEQ PDA0			;if <>NUL, then
8D9A 20 00 9B  JSR QB00			;softmount and catalogue drive
8D9D 4C A3 8D  JMP PDA3

.PDA0
8DA0 20 0C 9B  JSR QB0C			;else softmount disc.
.PDA3
8DA3 E6 A8     INC &A8			;flag = 1, catalogue clean
.PDA5
8DA5 68        PLA
8DA6 60        RTS			;restore A and exit.

.PDA7
8DA7 48        PHA
8DA8 A5 A8     LDA &A8			;Flush catalogue
8DAA C9 02     CMP #&02			;save A, get page flag
8DAC 90 07     BCC PDB5			;if page is empty or clean,then exit
8DAE 20 03 9B  JSR QB03			;else write catalogue
8DB1 A9 01     LDA #&01
8DB3 85 A8     STA &A8			;and mark page as clean.
.PDB5
8DB5 68        PLA
8DB6 60        RTS			;restore A and exit.

.PDB7
8DB7 20 A7 8D  JSR PDA7			;Swap source and target discs
8DBA 48        PHA			;flush catalogue, save A
8DBB 8A        TXA
8DBC 99 7E 10  STA &107E,Y		;store current drive in temp
8DBF 98        TYA
8DC0 49 01     EOR #&01			;toggle source/target drive
8DC2 A8        TAY
8DC3 BE 7E 10  LDX &107E,Y		;load other drive no. into X
8DC6 68        PLA			;restore A, then:
.PDC7					;Ask for disc
8DC7 20 00 92  JSR Q200			;Save AXY
8DCA 2C 80 10  BIT &1080		;test flag,
8DCD 50 3C     BVC PE0B			;if prompt bit clear then skip
.PDCF
8DCF C0 00     CPY #&00			;else test Y, if Y<>0 then ask for target
8DD1 D0 11     BNE PDE4			;else ask for source
8DD3 20 18 90  JSR Q018			;print "Is source"
8DD6 EQUB &00
8DD7 EQUS "Is source"
8DE0 EQUB &00				;terminator byte
8DE1 4C F2 8D  JMP PDF2			;and jump.

.PDE4
8DE4 20 18 90  JSR Q018			;print "Is target"
8DE7 EQUB &00
8DE8 EQUS "Is target"
8DF1 EQUB &00				;terminator byte
.PDF2
8DF2 B9 70 10  LDA &1070,Y		;get source or target drv no.
8DF5 20 18 90  JSR Q018			;ask " disc in drive "+n+"?"
8DF8 EQUB &D0
8DF9 EQUS " disc in drive "
8E08 EQUB &00				;terminator byte
8E09 D0 C4     BNE PDCF			;if No then loop and ask again!
.PE0B
8E0B 2C 80 10  BIT &1080		;else test flag
8E0E 30 04     BMI PE14			;if b7 clear
8E10 A2 00     LDX #&00			;then mark catalogue empty.
8E12 86 A8     STX &A8
.PE14
8E14 B9 72 10  LDA &1072,Y		;get source/target volume
8E17 85 C8     STA &C8			;A -> &00C8 = Immediate volume
8E19 B9 70 10  LDA &1070,Y		;get source/target drive
8E1C 85 C9     STA &C9			;A = current drive/store immediate drive
8E1E A9 83     LDA #&83			;call OSBYTE
8E20 20 F4 FF  JSR osbyte		;to get OSHWM (High Water Mark)
8E23 86 A9     STX &A9			;store in &A9,&AA
8E25 84 AA     STY &AA			;pointer to catalogue
8E27 C8        INY
8E28 C8        INY			;increase by two pages
8E29 84 AC     STY &AC			;store in &AC, &AB(=00)
8E2B A9 84     LDA #&84			;pointer to buffer.
8E2D 20 F4 FF  JSR osbyte		;call OSBYTE to get HIMEM
8E30 98        TYA
8E31 38        SEC
8E32 E5 AC     SBC &AC			;subtract start of buffer
8E34 90 0E     BCC PE44			;if HIMEM <= buffer
8E36 F0 0C     BEQ PE44			;then error "No free memory"
8E38 85 AD     STA &AD			;else store buffer size
8E3A AD 80 10  LDA &1080		;test flag
8E3D 4A        LSR A			;if bit 1 set
8E3E 90 03     BCC PE43
8E40 20 91 8D  JSR PD91			;then ensure catalogue loaded
.PE43
8E43 60        RTS			;and exit.

.PE44
8E44 20 18 90  JSR Q018			;error "No free memory"
8E47 EQUB &0A				;LF
8E48 EQUB &D4
8E49 EQUS "No free memory"
8E57 EQUB &00				;terminator byte
.PE58					;Copy data between discs
8E58 20 B7 8D  JSR PDB7			;swap discs &flsh cat:
.PE5B
8E5B B9 76 10  LDA &1076,Y		;test src stg count
8E5E 19 78 10  ORA &1078,Y		;OR low & high bytes
8E61 D0 01     BNE PE64			;if =0
8E63 60        RTS			;then exit
					;else set O7F address
.PE64					;to address of data buffer
8E64 A5 AC     LDA &AC
8E66 8D 12 10  STA &1012
8E69 A9 00     LDA #&00
8E6B 8D 11 10  STA &1011
8E6E A9 FF     LDA #&FF
8E70 8D 13 10  STA &1013
8E73 8D 14 10  STA &1014
8E76 B9 74 10  LDA &1074		;set command = Read for src disc
8E79 8D 16 10  STA &1016		;or Write for target disc
8E7C A5 AD     LDA &AD			;if buffer size = 0
8E7E F0 D8     BEQ PE58			;then swap discs and start again
8E80 20 86 8E  JSR PE86			;else do disc transfer <= bufsiz
8E83 4C 5B 8E  JMP PE5B			;and start again.
					;Do disc transfer.A=sector count
.PE86					;if source stg <256 then
8E86 20 00 92  JSR Q200			;Save AXY
8E89 BE 78 10  LDX &1078,Y
8E8C D0 08     BNE PE96
8E8E D9 76 10  CMP &1076,Y
8E91 90 03     BCC PE96
8E93 B9 76 10  LDA &1076,Y		;A = max(A, source stg).
.PE96
8E96 85 AE     STA &AE			;save sector count
8E98 84 AF     STY &AF			;save source/target in temp
8E9A BE 7A 10  LDX &107A,Y		;get low byte of start sector
8E9D B9 7C 10  LDA &107C,Y		;get high byte
8EA0 A8        TAY			;set XY = start sector
8EA1 A5 AE     LDA &AE			;get sector count in A
8EA3 20 06 9B  JSR QB06			;do LBA transfer
8EA6 98        TYA			;XY = last+1 sector
8EA7 A4 AF     LDY &AF			;restore Y=source or target
8EA9 99 7C 10  STA &107C,Y		;store high byte
8EAC 8A        TXA			;store low byte
8EAD 99 7A 10  STA &107A,Y
8EB0 B9 76 10  LDA &1076,Y		;subtract sector count from
8EB3 38        SEC			;source sectors-to-go
8EB4 E5 AE     SBC &AE			;first low byte
8EB6 99 76 10  STA &1076,Y
8EB9 B9 78 10  LDA &1078,Y		;then borrow from high byte
8EBC E9 00     SBC #&00
8EBE 99 78 10  STA &1078,Y
8EC1 AD 12 10  LDA &1012		;number of last+1 page
8EC4 85 AC     STA &AC			;store start of data buffer
8EC6 A5 AD     LDA &AD
8EC8 38        SEC
8EC9 E5 AE     SBC &AE			;subtract sector count
8ECB 85 AD     STA &AD			;from buffer size
8ECD 60        RTS			;exit.

.PECE
8ECE A6 CC     LDX &CC			;Copy entry from cat 1 to 2
8ED0 20 00 92  JSR Q200			;cat ptr to X then save AXY
8ED3 A4 AB     LDY &AB			;?&AB = offset in cat 2
8ED5 98        TYA			;put into A and Y
8ED6 18        CLC
8ED7 69 08     ADC #&08			;add 8 to A
8ED9 85 AB     STA &AB			;store as loop limit
8EDB BD 08 0E  LDA &0E08,X		;copy name part of cat entry
8EDE 91 A9     STA (&A9),Y		;to catalogue buffer
8EE0 E6 AA     INC &AA			;point to next page up
8EE2 BD 08 0F  LDA &0F08,X		;copy attributes of cat entry
8EE5 91 A9     STA (&A9),Y		;to catalogue buffer
8EE7 C6 AA     DEC &AA			;point to original page
8EE9 E8        INX			;increment offsets
8EEA C8        INY
8EEB C4 AB     CPY &AB			;compare with loop limit
8EED D0 EC     BNE &8EDB		;if equal exit else loop.
8EEF 60        RTS

.PEF0					;Unpack catalogue 2 entry
8EF0 20 00 92  JSR Q200			;Save AXY
8EF3 8A        TXA			;X = offset in catalogue 2
8EF4 A8        TAY			;copy it to Y
8EF5 A2 00     LDX #&00			;then set X = 0
.PEF7
8EF7 B1 A9     LDA (&A9),Y		;copy cat entry in buffer 2
8EF9 9D 40 10  STA &1040,X		;to packed area in cat block 1
8EFC E6 AA     INC &AA
8EFE B1 A9     LDA (&A9),Y
8F00 9D 48 10  STA &1048,X
8F03 C6 AA     DEC &AA
8F05 E8        INX
8F06 C8        INY
8F07 E0 08     CPX #&08
8F09 D0 EC     BNE PEF7
8F0B AD 06 0F  LDA &0F06		;get cat 1 volume size high bits
8F0E 48        PHA			;save
8F0F AD 81 10  LDA &1081		;put cat 2's size in its place
8F12 8D 06 0F  STA &0F06		;(to select 18/19 bit fields):
8F15 20 12 A6  JSR R612			;unpack cat fields from wkspace
8F18 68        PLA			;and restore cat 1's size.
8F19 8D 06 0F  STA &0F06
8F1C 20 06 92  JSR Q206			;Copy memory absolute
8F1F EQUW &40,&10			;FROM cat block 1, &1040
8F21 EQUW &58,&10			;TO block 2, &1058
8F23 EQUB &18				;count
8F24 BA        TSX			;return new offset in X
8F25 98        TYA			;Y -> A =
8F26 9D 04 01  STA &0104,X
8F29 60        RTS			;and exit.

.PF2A
8F2A 48        PHA
8F2B AD 53 10  LDA &1053		;Set copy range = entry range
8F2E 99 76 10  STA &1076,Y		;get sector count low byte
8F31 AD 54 10  LDA &1054		;store sectors-to-go low byte
8F34 99 78 10  STA &1078,Y		;same with high byte
8F37 AD 51 10  LDA &1051		;Y=0 selects source Y=1 target
8F3A 99 7A 10  STA &107A,Y		;absolute start sector low
8F3D AD 52 10  LDA &1052		;(LBA)
8F40 99 7C 10  STA &107C,Y		;absolute start sector high
8F43 68        PLA
8F44 60        RTS			;restore A and exit.

.PF45
8F45 20 09 A6  JSR R609			;Create catalogue entry
8F48 20 06 A4  JSR R406			;print *INFO line
8F4B 4C 09 90  JMP Q009			;print newline and exit


;Console output subsystem

.Q000
9000 4C 1B 90  JMP Q01B			;Print character in A

.Q003
9003 4C 54 90  JMP Q054			;Print space

.Q006
9006 4C 5C 90  JMP Q05C			;Tab to column in A

.Q909
9009 4C 7E 90  JMP Q07E			;Display error message/newline

.Q00C
900C 4C D7 90  JMP Q0D7			;Print hex nibble

.Q00F
900F 4C CC 90  JMP Q0CC			;Print hex byte

.Q012
9012 4C F0 90  JMP Q0F0			;Print decimal byte

.Q015
9015 4C B1 90  JMP Q0B1			;Print hex word absolute

.Q018
9018 4C 19 91  JMP Q119			;Print string immediate

.Q01B					;Print character in A
901B 20 00 92  JSR Q200			;Save AXY
901E A4 F4     LDY rmslrg		;Get ROM type byte from ROM Select Register
9020 B9 A1 02  LDA &02A1,Y		;if b3=1 then error message
9023 29 08     AND #&08			;so add the character to it
9025 D0 1E     BNE Q045			;else get *FX3 setting
9027 AD 7C 02  LDA &027C		;is *SPOOL output disabled?
902A 29 10     AND #&10			;if so print the character
902C D0 10     BNE Q03E			;else disable *SPOOL output
902E AD 7C 02  LDA &027C
9031 09 10     ORA #&10
9033 8D 7C 02  STA &027C
9036 B9 A1 02  LDA &02A1,Y		;and set b2=1 in ROM type byte
9039 09 04     ORA #&04			;indicating it had been enabled.
903B 99 A1 02  STA &02A1,Y
.Q03E
903E BA        TSX
903F BD 05 01  LDA &0105,X		;get value in A on entry
9042 4C EE FF  JMP oswrch		;print it with OSWRCH and exit.

.Q045
9045 BA        TSX
9046 BD 05 01  LDA &0105,X		;add character to error message:
9049 AC 00 01  LDY &0100		;get value of A on entry
904C 99 00 01  STA &0100,Y		;get offset to end of error
904F C8        INY			;store character at end
9050 8C 00 01  STY &0100		;increment offset
9053 60        RTS			;store it and exit.

.Q054					;Print space
9054 48        PHA
9055 A9 20     LDA #&20
9057 20 1B 90  JSR Q01B			;Print character in A
905A 68        PLA
905B 60        RTS

.Q05C					;Tab to column in A
905C 20 00 92  JSR Q200			;Save AXY
905F A4 F4     LDY rmslrg		;get ROM type byte
9061 B9 A1 02  LDA &02A1,Y
9064 29 08     AND #&08			;test bit 3
9066 30 EC     BMI Q054			;if set print one space and exit
.Q068
9068 20 54 90  JSR Q054			;else print a space
906B A9 86     LDA #&86
906D 20 F4 FF  JSR osbyte		;get cursor position
9070 8A        TXA			;if cursor in column 0
9071 F0 06     BEQ &9079		;then return A=0
9073 BA        TSX			;else compare column number
9074 DD 05 01  CMP &0105,X		;with value of A on entry
9077 90 EF     BCC Q068			;if less print more spaces
9079 BA        TSX			;else return A=X coordinate
907A 9D 05 01  STA &0105,X		;of cursor
907D 60        RTS

.Q07E					;Display error message/newline
907E 20 00 92  JSR Q200			;Save AXY
9081 A4 F4     LDY rmslrg		;get ROM type byte
9083 B9 A1 02  LDA &02A1,Y		;clear b2..3
9086 48        PHA
9087 29 F3     AND #&F3			;mask bits 2-3
9089 99 A1 02  STA &02A1,Y
908C 68        PLA			;if b3 was 1
908D 48        PHA
908E 29 08     AND #&08			;mask bits 2-3 and 4-7
9090 D0 11     BNE Q0A3			;do a BRK error message in stack
9092 20 E7 FF  JSR osnewl		;else print a newline
9095 68        PLA
9096 29 04     AND #&04			;if b2 was 1 disable *SPOOL
9098 F0 08     BEQ Q0A2
909A AD 7C 02  LDA &027C
909D 29 EF     AND #&EF			;mask bit 4
909F 8D 7C 02  STA &027C
.Q0A2
90A2 60        RTS			;and exit.

.Q0A3
90A3 AC 00 01  LDY &0100		;error message. get length of err
90A6 A9 00     LDA #&00			;set NUL error message terminator
90A8 99 00 01  STA &0100,Y
90AB 8D 00 01  STA &0100		;and BRK instruction over length
90AE 4C 00 01  JMP &0100		;call BRK.

.Q0B1					;Print hex word absolute
90B1 20 00 92  JSR Q200			;Save AXY
90B4 20 03 92  JSR Q203			;address follows caller's JSR
90B7 85 B2     STA &B2			;store address in pointer
90B9 20 03 92  JSR Q203			;Get byte immediate
90BC 85 B3     STA &B3
90BE BA        TSX			;get status register on entry
90BF BD 06 01  LDA &0106,X
90C2 48        PHA			;C=print leading zeroes
90C3 28        PLP
90C4 A0 01     LDY #&01			;offset to top byte of word
90C6 20 CA 90  JSR Q0CA			;fetch high byte and print
90C9 88        DEY			;point to bottom byte
.Q0CA
90CA B1 B2     LDA (&B2),Y		;fetch it and fall through:
.Q0CC					;Print hex byte
90CC 48        PHA
90CD 08        PHP			;upper nibble first
90CE 4A        LSR A
90CF 4A        LSR A
90D0 4A        LSR A
90D1 4A        LSR A
90D2 28        PLP
90D3 20 D7 90  JSR Q0D7			;Print hex nibble
90D6 68        PLA			;then lower. Fall through:
.Q0D7					;Print hex nibble
90D7 48        PHA
90D8 29 0F     AND #&0F			;on entry C=print leading zeroes
90DA F0 01     BEQ Q0DD			;on exit C=a nonzero was printed
90DC 38        SEC
.Q0DD
90DD 08        PHP
90DE 09 20     ORA #&20
90E0 90 08     BCC Q0EA
90E2 09 30     ORA #&30
90E4 C9 3A     CMP #&3A
90E6 90 02     BCC &90EA
90E8 69 06     ADC #&06
.Q0EA
90EA 20 1B 90  JSR Q01B			;Print character in A
90ED 28        PLP
90EE 68        PLA
90EF 60        RTS

.Q0F0					;Print decimal byte
90F0 20 00 92  JSR Q200			;Save AXY
90F3 18        CLC			;C=0, suppress leading zeroes
90F4 A0 02     LDY #&02			;start with the hundreds
.Q0F6
90F6 08        PHP			;digit loop, save C
90F7 A2 00     LDX #&00			;set dividend = 0
.Q0F9
90F9 D9 16 91  CMP Q117-1,Y		;subtract loop
90FC 90 07     BCC Q105			;if A>=placevalue
90FE E8        INX			;then increment dividend
90FF 38        SEC			;and subtract placevalue
9100 F9 16 91  SBC Q117-1,Y		;from A
9103 D0 F4     BNE Q0F9			;if A>0 subtract again
.Q105
9105 28        PLP			;else restore C
9106 48        PHA			;save remnant
9107 8A        TXA
9108 D0 02     BNE Q10C			;if dividend>0 then print it
910A 90 03     BCC Q10F			;if a leading zero skip it
.Q10C
910C 20 D7 90  JSR Q0D7			;else print it
.Q10F
910F 68        PLA			;restore remnant
9110 88        DEY			;point to lower placevalue
9111 D0 E3     BNE Q0F6			;if not units then loop
9113 38        SEC			;else units. set carry
9114 4C D7 90  JMP Q0D7			;to print unit even if 0. exit.

.Q117
9117 EQUB &0A				;placevalue 10
9118 EQUB &64				;placevalue 100

.Q119					;Print string immediate
9119 20 00 92  JSR Q200			;Save AXY (a very powerful routine!)
911C 20 03 92  JSR Q203			;Get byte immediate
911F 48        PHA			;save it
9120 29 08     AND #&08			;00001000 = mask bits 0-2 and 4-7
9122 F0 0F     BEQ Q133			;if b3=1
9124 A9 01     LDA #&01			;then bottom of stack page =1
9126 8D 00 01  STA &0100
9129 A4 F4     LDY rmslrg4		;get our ROM socket number
912B B9 A1 02  LDA &02A1,Y		;get ROM type byte +flags
912E 09 08     ORA #&08			;set b3=1
9130 99 A1 02  STA &02A1,Y		;store it back.
.Q133
9133 68        PLA			;restore microcode byte
9134 A8        TAY			;copy to Y
9135 4A        LSR A			;shift b0 into carry
9136 90 0A     BCC Q142			;if b0=1
9138 A9 0A     LDA #&0A			;A = <LF>
913A 20 1B 90  JSR Q01B			;Print character in A
913D A9 0D     LDA #&0D			;A = <CR>
913F 20 1B 90  JSR Q01B			;Print character in A
.Q142
9142 20 03 92  JSR Q203			;Get byte immediate
9145 F0 06     BEQ Q14D			;if =NUL break out of loop
9147 20 1B 90  JSR Q01B			;else print the character in A and loop.
914A 4C 42 91  JMP Q142			;get A on entry

.Q14D
914D BA        TSX
914E BD 05 01  LDA &0105,X
9151 C0 80     CPY #&80			;10000000
9153 90 10     BCC Q165			;if microcode b7=1
9155 C0 C0     CPY #&C0			;11000000
9157 90 06     BCC Q15F			;then if b6=1
9159 20 1B 90  JSR Q01B			;then 11.. Print character in A
915C 4C 6C 91  JMP Q16C

.Q15F
915F 20 F0 90  JSR Q0F0			;else 10.. Print decimal byte
9162 4C 6C 91  JMP Q16C

.Q165
9165 C0 40     CPY #&40			;01000000
9167 90 03     BCC Q16C			;else if b6=1
9169 20 CC 90  JSR Q0CC			;Print hex byte
.Q16C
916C 98        TYA			;then 01.. print hex in A.
916D 29 02     AND #&02			;mask bits 2-7 = restore microcode byte
916F F0 03     BEQ Q174			;if b1=1
9171 20 7E 90  JSR Q07E			;Display error message/newline
.Q174
9174 98        TYA			;restore microcode byte
9175 29 04     AND #&04			;mask bits 0-1 and 3-4
9177 F0 05     BEQ Q17E			;if b2=1
9179 A9 07     LDA #&07			;then A = 7
917B 20 1B 90  JSR Q01B			;Print character in A = send BEL to make a beep.
.Q17E
917E 98        TYA			;restore microcode byte
917F 29 10     AND #&10			;mask bits 0-3 and 5-7
9181 F0 45     BEQ Q1C8			;if b4=1, then re-enter!
9183 20 18 90  JSR Q018			;else, print "? "
9186 EQUB &00
9187 EQUS "? "
9189 EQUB &00				;terminator byte
918A A2 01     LDX #&01
918C A9 0F     LDA #&0F			;call *FX 15,1
918E 20 F4 FF  JSR osbyte		;to clear input buffer
.Q191
9191 20 E0 FF  JSR osrdch		;call OSRDCH to GET character
9194 90 0C     BCC Q1A2			;if ESCAPE pressed, then re-enter
9196 20 18 90  JSR Q018			;to print "Escape" error
9199 EQUB &0A				;LF
919A EQUB &11
919B EQUS "Escape"
91A1 EQUB &00				;terminator byte
.Q1A2
91A2 C9 59     CMP #&59			;is it "Y"?
91A4 F0 16     BEQ Q1BC			;then register Yes
91A6 C9 79     CMP #&79			;is it "y"?
91A8 F0 12     BEQ Q1BC			;then register Yes
91AA C9 4E     CMP #&4E			;is it "N"?
91AC F0 04     BEQ Q1B2			;then register No
91AE C9 6E     CMP #&6E			;is it "n"?
91B0 D0 DF     BNE Q191			;if not get another keypress.
.Q1B2
91B2 20 18 90  JSR Q018			;else print "no"
91B5 EQUB &02
91B6 EQUS "no"
91B8 EQUB &00				;terminator byte
91B9 C9 FF     CMP #&FF			;return Z=0, C=0.
91BB 60        RTS

.Q1BC
91BC 20 18 90  JSR Q018			;print "yes"
91BF EQUB &02
91C0 EQUS "yes"
91C3 EQUB &00				;terminator byte
91C4 A9 00     LDA #&00
91C6 C9 00     CMP #&00
.Q1C8
91C8 60        RTS			;return Z=1, C=1.


;Macroassembly and miscellaneous

.Q200
9200 4C 12 92  JMP Q212			;Save AXY

.Q203
9203 4C 47 92  JMP Q247			;Get byte immediate

.Q206
9206 4C 68 92  JMP Q268			;Copy memory absolute

.Q209
9209 4C 6F 92  JMP Q26F			;Copy memory absolute indexed

.Q20C
920C 6C 1E 02  JMP (osfcv)		;Issue Filing System Call

.Q20F
920F 4C 0F 92  JMP Q20F			;Halt


; Save AXY, to be restored when the calling routine exits.
; At that point the status register will be passed back to the
; superroutine as in a normal RTS.
; On return to the caller the stack will contain (right to left):
; &2E, &92, Y, X, A, P, return address(-1) low, return address(-1) high,
; superroutine address(-1) low, superroutine address(-1) high
; i.e. &0101,S = &2E; &0105,S = A.

.Q212					;Save AXY, etc
9212 08        PHP			;to be restored
9213 48        PHA			;when the calling routine
9214 8A        TXA			;exits.  At that point P
9215 48        PHA			;will be passed back to
9216 98        TYA			;the superroutine as in a
9217 48        PHA			;normal RTS.
9218 A9 92     LDA #&92			;Within the call the stack
921A 48        PHA			;contains (right to left):
921B A9 2E     LDA #&2E			;&2E,&92,Y,X,A,P,rl,rh
921D 48        PHA			;i.e. &0101,S = &2E
921E A0 06     LDY #&06			;counter
.Q220
9220 BA        TSX			;get current stack pointer
9221 BD 08 01  LDA &0108,X		;peek at the 8th value down
9224 48        PHA			;push it on top, and loop x6.
9225 88        DEY			;(duplicates return address
9226 D0 F8     BNE Q220			;and PAXY)
9228 68        PLA
9229 A8        TAY
922A 68        PLA
922B AA        TAX
922C 68        PLA			;pop Y, X, A
922D 28        PLP			;pop P
922E 60        RTS			;and return to caller.


\Restore AXY.  Invoked by the caller of "Save AXY" when it reaches
\an RTS.
\After the PHP the stack contains (right to left):
\new P, old Y, X, A, P, return address(-1) low, return address(-1) high,
\superroutine address(-1) low, superroutine address(-1) high
\i.e. &0101,S = new P.

					;Restore AXY Invoked by caller on RTS.
922F 08        PHP			;push status register on entry
9230 BA        TSX
9231 BD 01 01  LDA &0101,X		;peek its value into A
9234 9D 05 01  STA &0105,X		;overwrite old status
9237 9D 06 01  STA &0106,X		;and "Save AXY" return address
923A 9D 07 01  STA &0107,X
923D 68        PLA			;discard status on entry
923E 68        PLA			;pop A
923F A8        TAY
9240 68        PLA			;pop Y
9241 AA        TAX
9242 68        PLA			;pop X
9243 28        PLP
9244 28        PLP
9245 28        PLP			;pop three copies of status
9246 60        RTS			;and return to superroutine


; Get byte immediate.  The caller has already called "Save AXY",
; and before that the superroutine called the caller with JSR.
; After this JSR instruction is a number of bytes for the subroutine
; to process.  This routine fetches the next byte for the subroutine
; and advances the return address back to the superroutine.
; During the TSX at &924A the stack contains (right to left):
; &2E, &92, caller Y, X, A, P,
; &49, &92, caller return address(-1) low, high,
; &2E, &92, superroutine Y, X, A, P,
; caller "save AXY" return address(-1) low, high,
; superroutine return address(-1) low, high
; therefore &0113..4,S = address of the immediate operand, less one.

.Q247					;Get byte immediate
9247 20 00 92  JSR Q200			;save caller's AXY
924A BA        TSX			;get stack pointer
924B 18        CLC
924C BD 13 01  LDA &0113,X
924F 69 01     ADC #&01			;add 1 to superroutine return address
9251 9D 13 01  STA &0113,X		;save result back on stack
9254 85 B0     STA &B0			;and as a pointer
9256 BD 14 01  LDA &0114,X
9259 69 00     ADC #&00			;complete the addition on the high byte
925B 9D 14 01  STA &0114,X		;save back on stack
925E 85 B1     STA &B1			;store high byte of pointer
9260 A0 00     LDY #&00			;clear Y
9262 B1 B0     LDA (&B0),Y		;clear index register
9264 9D 05 01  STA &0105,X		;get byte at new pointer
9267 60        RTS			;return in A on exit.


; Copy memory absolute
; The JSR instruction calling this routine is followed by:
; 2 bytes From address, 2 bytes To address, 1 byte length.
; Copying proceeds upwards in memory.

.Q268					;Copy memory absolute
9268 20 00 92  JSR Q200			;Save AXY
926B A0 05     LDY #&05			;5 argument bytes
926D D0 05     BNE Q274			;and jump always

; Copy memory absolute indexed
; Arguments as for "Copy memory absolute", except there is a sixth byte:
; bits 4 to 7 of this byte control indexing of the From address,
; bits 0 and 1 control indexing of the To address.
; When the field is all zeroes the relevant address is used as is;
; otherwise one of the following values is added to the given address
; to form an effective address where the transfer will start.
; Bits        Value to be added
; 0000 or 00  Zero
; 0001 or 01  Y on entry
; 0010 or 10  X on entry
; 0011 or 11  A on entry
; 0100        &71
; 0101        &92
; 0110        caller return address(-1) low byte
; 0111        caller return address(-1) high byte
; 1xxx        undefined

.Q26F					;Copy memory absolute indexed
926F 20 00 92  JSR Q200			;Save AXY
9272 A0 06     LDY #&06			;6 argument bytes
.Q274
9274 A2 00     LDX #&00			;clear offset
9276 86 B7     STX &B7			;default to no indexing
.Q278
9278 20 03 92  JSR Q203			;fetch operand byte
927B 95 B2     STA &B2,X		;store in workspace
927D E8        INX			;increment offset
927E 88        DEY			;decrement counter
927F D0 F7     BNE Q278			;loop while more argument bytes
9281 A5 B7     LDA &B7			;get indexing argument
9283 4A        LSR A
9284 4A        LSR A
9285 4A        LSR A
9286 4A        LSR A			;move bits 7..4 to 3..0
9287 20 AD 92  JSR Q2AD			;fetch relevant index value/Interpret index bits
928A 65 B2     ADC &B2			;add to From address
928C 85 B2     STA &B2			;store back in workspace
928E 90 02     BCC Q292			;if carry out occurs
9290 E6 B3     INC &B3			;then increment high byte.
.Q292
9292 A5 B7     LDA &B7			;get indexing argument
9294 29 03     AND #&03			;mask off From bits
9296 20 AD 92  JSR Q2AD			;mask bits 0-2 and 4-7/interpret To bits
9299 65 B4     ADC &B4			;add relevant index to To address/interpret index bits
929B 85 B4     STA &B4			;store back in workspace
929D 90 02     BCC Q2A1			;if carry out occurs
929F E6 B5     INC &B5			;then increment high byte.
.Q2A1
92A1 A0 00     LDY #&00			;clear offset
.Q2A3
92A3 B1 B2     LDA (&B2),Y		;fetch byte from From area
92A5 91 B4     STA (&B4),Y		;store in To area
92A7 C8        INY			;increment offset
92A8 C4 B6     CPY &B6			;have we copied all bytes?
92AA 90 F7     BCC Q2A3			;if not then loop
92AC 60        RTS			;else exit.

.Q2AD
92AD A8        TAY			;Interpret index bits.
92AE F0 08     BEQ Q2B8			;if none set then return zero
92B0 BA        TSX			;else put stack pointer in X
.Q2B1
92B1 E8        INX			;add Y to X without using memory
92B2 88        DEY
92B3 D0 FC     BNE Q2B1			;Interpret index bits
92B5 BD 04 01  LDA &0104,X		;peek one of the saved registers
.Q2B8
92B8 18        CLC
92B9 60        RTS			;clear carry for add and exit.


;Parsing and validation

.Q300
9300 4C 21 93  JMP Q321			;Get drive spec

.Q303
9303 4C 4A 93  JMP Q34A			;Get volume spec

.Q306
9306 4C 34 93  JMP Q334			;Get ambiguous volume spec

.Q309
9309 4C 5B 93  JMP Q35B			;Get path spec

.Q30C
930C 4C 53 93  JMP Q353			;Get ambiguous path spec

.Q30F
930F 4C 77 93  JMP Q377			;Get entry (dir+file) name

.Q312
9312 4C 96 93  JMP Q396			;Get file spec?

.Q315
9315 4C 8E 93  JMP Q38E			;Get ambiguous file spec?

.Q318
9318 4C 2B 94  JMP Q42B			;Get multiple drive spec

.Q31B
931B 4C 53 94  JMP Q453			;X=6, check volume letter

.Q31E
931E 4C 5E 94  JMP Q45E			;Get space padded string char

.Q321					;Get drive spec
9321 20 00 92  JSR Q200			;Save AXY
9324 20 06 92  JSR Q206			;Copy memory absolute
9327 EQUW &09,&10			;FROM default drive, &1009
9329 EQUW &C9,&00			;TO immediate drive, &00C9 (current drive)
932B EQUB &01				;count
932C A2 00     LDX #&00			;as it's a "drive" spec
932E 20 6F 94  JSR Q46F
9331 4C CF 93  JMP Q3CF			;get drive spec pt2 and finish.

.Q334					;Get ambiguous volume spec
9334 20 00 92  JSR Q200			;Save AXY
9337 20 98 94  JSR Q498			;Get volume spec 0, :2, :1A, 3H, 1* etc.
933A B0 0B     BCS Q347			;get volume spec pt2
933C C9 2A     CMP #&2A			;is it ASCII '*'?
933E D0 07     BNE Q347			;if this char <> "*" then finish
9340 A9 00     LDA #&00			;else immed vol = NUL ambiguous
9342 85 C8     STA &C8			;A -> &00C8 = Immediate volume
9344 20 C5 FF  JSR gsread		;call GSREAD and finish.
.Q347
9347 4C CF 93  JMP Q3CF			;get vol pt2 and finish

.Q34A					;Get ambiguous path spec
934A 20 00 92  JSR Q200			;Save AXY
934D 20 98 94  JSR Q498			;Get volume spec 0A,:2B etc.
9350 4C CF 93  JMP Q3CF			;get vol pt2 and finish

.Q353					;Get ambiguous path spec
9353 20 00 92  JSR Q200			;Save AXY
9356 A9 01     LDA #&01			;*, :0.*, :3A.*, etc. & as below
9358 4C 60 93  JMP Q360

.Q35B					;Get path spec
935B 20 00 92  JSR Q200			;Save AXY
935E A9 00     LDA #&00			;$, D, :0, :3.M, :2B.$, :1A etc.
.Q360
9360 85 CE     STA &CE			;A -> &00CE = ambiguous spec flag
9362 20 06 92  JSR Q206			;Copy memory absolute
9365 EQUW &07,&10			;FROM default path, &1007
9367 EQUW &C7,&00    			;TO immediate path, &00C7 = Immediate dir
9369 EQUB &03				;count
936A A2 0D     LDX #&0D			;this is a "directory" spec
936C 20 AB 94  JSR Q4AB			;get volume part of path spec
936F B0 03     BCS Q374			;if end-of-word then exit C=1.
9371 20 F0 94  JSR Q4F0			;get directory letter & finish.
.Q374
9374 4C CF 93  JMP Q3CF

.Q377					;Get entry (dir+file) name/PROG, $.!BOOT, M.DTX
9377 20 00 92  JSR Q200			;Save AXY
937A A9 00     LDA #&00			;clear A
937C 85 CE     STA &CE			;A -> &00CE = ambiguous spec flag
937E 20 06 92  JSR Q206			;Copy memory absolute
9381 EQUW &00,&10			;FROM default filename + directory, &1000
9383 EQUW &C0,&00			;TO immediate filename + directory, &00C0
9385 EQUB &08				;count
9386 A2 17     LDX #&17			;this is an "entry" spec
9388 20 47 95  JSR Q547			;set up and jump into file spec
938B 4C AA 93  JMP Q3AA

.Q38E					;Get ambiguous file spec
938E 20 00 92  JSR Q200			;Save AXY
9391 A9 01     LDA #&01			;INTRO, #####P, :2A.*.*,
9393 4C 9B 93  JMP Q39B			;(nothing)

.Q396					;Get file spec?
9396 20 00 92  JSR Q200			;Save AXY
9399 A9 00     LDA #&00			;KEYBD, B.DOTTY, :3.!BOOT, :2.$.LUNARLA, :A.DEBUG, :A.M.DEMO, :1G.DATA12, :0A.$.MENU, (nothing)
.Q39B
939B 85 CE     STA &CE			;A -> &00CE = ambiguous spec flag
939D 20 06 92  JSR Q206			;Copy memory absolute
93A0 EQUW &00,&10			;FROM default filename and full path, &1000
93A2 EQUW &C0,&00			;TO immediate filename and full path, &00C0
93A4 EQUB &0A				;count
93A5 A2 1D     LDX #&1D			;this is a "file" spec
93A7 20 AB 94  JSR Q4AB			;get volume part of path spec
.Q3AA
93AA B0 23     BCS Q3CF			;if end-of-word then exit C=1
93AC 20 1B 95  JSR Q51B			;else peek next char (AY presvd)
93AF D0 0C     BNE Q3BD			;if it was <>".", get filename
93B1 20 F0 94  JSR Q4F0			;else get directory letter
93B4 C9 2E     CMP #&2E			;compare current char with "."
93B6 D0 1F     BNE Q3D7			;if unequal then "Bad spec" err
93B8 20 C5 FF  JSR gsread		;else call GSREAD
93BB B0 12     BCS Q3CF			;if end-of-word then finish
.Q3BD
93BD 20 FA 94  JSR Q4FA			;else get filename proper
93C0 90 0D     BCC Q3CF			;if invalid then finish, else:
93C2 A5 CE     LDA &CE			;A = ambiguous spec flag
93C4 30 08     BMI Q3CE			;Accept filename if this spec is unambiguous
93C6 20 06 92  JSR Q206			;else, Copy memory absolute
93C9 EQUW &C0,&00			;FROM immediate filename, &00C0
93CB EQUW &00,&10			;TO default filename, &1000
93CD EQUB &07				;count
.Q3CE
93CE 38        SEC			;C=1 for success, fall through:
.Q3CF
93CF 90 06     BCC Q3D7			;Finish parsing.
.Q3D1
93D1 BA        TSX			;if carry flag is set
93D2 98        TYA			;then return Y to caller
93D3 9D 03 01  STA &0103,X		;A -> stack
93D6 60        RTS			;and exit

.Q3D7
93D7 20 18 90  JSR Q018			;Give bad spec error
93DA EQUB &08
93DB EQUB &CC
93DC EQUS "Bad "
93E0 EQUB &00				;terminator byte
93E1 A5 CE     LDA &CE			;A = ambiguous spec flag
93E3 F0 0F     BEQ Q3F4			;if unambiguous spec then skip
93E5 20 18 90  JSR Q018			;else, Print character in A = ambiguous
93E8 EQUB &00
93E9 EQUS "ambiguous "
93F3 EQUB &00				;terminator byte
.Q3F4
93F4 BD 09 94  LDA Q409,X		;append type of spec
93F7 F0 06     BEQ Q3FF			;to error. if NUL, finish
93F9 20 00 90  JSR Q000			;else 'print' character
93FC E8        INX			;increment offset and loop.
93FD D0 F5     BNE Q3F4
.Q3FF
93FF 20 18 90  JSR Q018			;finish error with " spec".
9402 EQUB &02
9403 EQUS " spec"
9408 EQUB &00				;terminator byte
.Q409
9409 EQUS "drive"
940E EQUB &00				;terminator byte
940F EQUS "volume"
9415 EQUB &00				;terminator byte
9416 EQUS "directory"
941F EQUB &00				;terminator byte
9420 EQUS "entry"
9425 EQUB &00				;terminator byte
9426 EQUS "file"
942A EQUB &00				;terminator byte
.Q42B					;Get multiple drive spec
942B 20 00 92  JSR Q200			;Save AXY
942E A2 00     LDX #&00			;(nothing), 0, :2, :1 2, 1 :3
.Q430
9430 20 47 95  JSR Q547			;call GSINIT C=0 then GSREAD
9433 B0 1B     BCS Q450			;if end-of-word then finish
9435 C9 3A     CMP #&3A			;else compare this char with ":"
9437 D0 06     BNE Q43F			;if unequal try it as drive no.
9439 20 7C 94  JSR Q47C			;else get drive character
943C 4C 47 94  JMP Q447			;and loop if EOW else bad spec.

.Q43F
943F 20 8A 94  JSR Q48A			;validate and store drive number
9442 90 08     BCC Q44C			;if invalid return in A
9444 20 C5 FF  JSR gsread		;else call GSREAD
.Q447					;if end-of-word then loop
9447 B0 E7     BCS Q430			;else give "Bad spec" error.
9449 4C D7 93  JMP Q3D7			;Return A to caller and finish parsing.

.Q44C
944C BA        TSX
944D 9D 05 01  STA &0105,X
.Q450
9450 4C D1 93  JMP Q3D1

.Q453					;X=6, check volume letter
9453 20 00 92  JSR Q200			;Save AXY
9456 A2 06     LDX #&06			;this is a "volume" spec
9458 20 D8 94  JSR Q4D8			;Validate volume letter
945B 4C CF 93  JMP Q3CF			;or error if invalid.

.Q45E					;Get space padded string char
945E 24 E4     BIT &E4			;test bit 6
9460 70 09     BVS Q46B			;if b6 of MOS workspace flag set (volatile?) then exit
9462 20 C5 FF  JSR gsread		;else GSRD
9465 90 07     BCC &946E		;if not EOS return character C=0
9467 66 E4     ROR &E4
9469 66 E4     ROR &E4			;else set b6 of workspace flag
.Q46B
946B A9 20     LDA #&20			;return a space
946D 38        SEC
946E 60        RTS			;and exit C=1 (end-of-string)

.Q46F					;Get drive spec pt2
946F A9 00     LDA #&00			;A = 0 = ambiguous spec not allowed
9471 85 CE     STA &CE			;0 -> &00CE = ambiguous spec flag
9473 20 47 95  JSR Q547			;call GSINIT C=0 then GSREAD
9476 B0 11     BCS Q489			;if end-of-word then exit C=1
9478 C9 3A     CMP #&3A			;else compare with ":"
947A D0 05     BNE Q481			;if unequal try as drive number
.Q47C
947C 20 C5 FF  JSR gsread		;else call GSREAD
947F B0 08     BCS Q489			;if end-of-word exit C=1, else:
.Q481
9481 20 8A 94  JSR Q48A			;Get drive character
9484 90 03     BCC Q489			;test&store, if invalid exit C= 0
9486 20 C5 FF  JSR gsread		;else call GSREAD
.Q489
9489 60        RTS			;and exit.

.Q48A					;Validate and store drive number
948A C9 30     CMP #&30			;if less than ASCII "0"
948C 90 08     BCC Q496
948E C9 34     CMP #&34			;or greater than "3"
9490 B0 04     BCS Q496			;then exit C=0
9492 85 C9     STA &C9			;else store immediate drive/A -> current drive
9494 38        SEC
9495 60        RTS			;and exit C = 1.

.Q496
9496 18        CLC
9497 60        RTS			;exit C = 0

.Q498
9498 20 06 92  JSR Q206			;Copy memory absolute
949B EQUW &08,&10			;FROM default volume letter and drive number, &1008
949D EQUW &C8,&00			;TO immediate volume letter and drive number, &00C8
949F EQUB &02				;count
94A0 A2 06     LDX #&06			;this is a "volume" spec
94A2 20 6F 94  JSR Q46F			;get drive spec pt2
94A5 B0 03     BCS Q4AA			;if end-of-word exit C=1
94A7 20 CF 94  JSR Q4CF			;else get volume letter & exit.
.Q4AA
94AA 60        RTS			;exit

.Q4AB					;Get volume part of path spec
94AB 20 47 95  JSR Q547			;call GSINIT C=0 then GSREAD
94AE B0 1E     BCS Q4CE			;if EOW exit C=1 else compare
94B0 C9 3A     CMP #&3A			;if this char <> ":" exit C=0/is it ASCII ':'?
94B2 D0 19     BNE Q4CD			;else call GSREAD
94B4 20 C5 FF  JSR gsread		;if end-of-word exit C=1
94B7 B0 15     BCS Q4CE			;else get drive character
94B9 20 81 94  JSR Q481			;if end-of-word exit C=1
94BC B0 10     BCS Q4CE			;else get volume letter
94BE 20 CF 94  JSR Q4CF			;if end-of-word exit C=1
94C1 B0 0B     BCS Q4CE			;else compare this char to "."
94C3 C9 2E     CMP #&2E			;if equal call GSREAD and exit
94C5 F0 03     BEQ Q4CA			;else give "Bad spec" error.
.Q4C7
94C7 4C D7 93  JMP Q3D7			;Give bad spec error

.Q4CA
94CA 4C C5 FF  JMP gsread		;call GSREAD and exit.

.Q4CD
94CD 18        CLC			;C=0
.Q4CE
94CE 60        RTS			;exit.

.Q4CF
94CF 20 D8 94  JSR Q4D8			;Get volume letter
94D2 90 03     BCC Q4D7			;test&store, if invalid exit C=0
94D4 20 C5 FF  JSR gsread		;else call GSREAD and exit.
.Q4D7
94D7 60        RTS			;exit.

.Q4D8					;Validate volume letter
94D8 C9 41     CMP #&41			;is it < ASCII 'A'?
94DA 90 12     BCC Q4EE			;if less than "A" exit C=0
94DC C9 49     CMP #&49			;is it >= ASCII 'I'?
94DE 90 0A     BCC Q4EA			;then store and exit C=1
94E0 C9 61     CMP #&61			;is it < ASCII 'a'?
94E2 90 0A     BCC Q4EE			;then exit C=0
94E4 C9 69     CMP #&69			;is it >= ASCII 'i'?
94E6 B0 06     BCS Q4EE			;then exit C=0
94E8 29 DF     AND #&DF			;convert to uppercase
.Q4EA
94EA 85 C8     STA &C8			;A -> &00C8 = Immediate volume
94EC 38        SEC
94ED 60        RTS			;and exit C=1

.Q4EE
94EE 18        CLC
94EF 60        RTS

.Q4F0
94F0 20 24 95  JSR Q524			;Get directory letter
94F3 90 D2     BCC Q4C7			;test spec char, error if bad
94F5 85 C7     STA &C7			;else store immediate directoryImmediate dir'y -> &00C7
94F7 4C C5 FF  JMP gsread		;call GSREAD and exit.

.Q4FA					;Get filename proper
94FA 20 00 92  JSR Q200			;Save AXY
94FD A2 00     LDX #&00			;X is now just an offset
.Q4FF
94FF 20 24 95  JSR Q524			;test spec character
9502 90 14     BCC Q518			;if invalid return Y, exit C=0
9504 95 C0     STA &C0,X		;else store immediate filename
9506 E8        INX			;increment offset
9507 E0 07     CPX #&07			;have we taken 7 characters?
9509 F0 0A     BEQ Q515			;if so get pad char and finish
950B C9 2A     CMP #&2A			;else compare this char with "*"
950D F0 03     BEQ Q512			;if unequal, then:
950F 20 1E 93  JSR Q31E			;get space padded character.
.Q512
9512 4C FF 94  JMP Q4FF			;now loop for more characters.

.Q515
9515 20 1E 93  JSR Q31E			;get space padded character
.Q518
9518 4C D1 93  JMP Q3D1			;return Y to caller and exit.

.Q51B
951B 20 00 92  JSR Q200			;Save AXY
951E 20 1E 93  JSR Q31E			;Peek next char and compare "."
9521 C9 2E     CMP #&2E			;get padded char
9523 60        RTS			;and return Z=1 if equals "."

.Q524
9524 C9 3A     CMP #&3A			;is it ASCII ':'?/Test spec character
9526 F0 19     BEQ Q541			;if so exit C=0
9528 C9 2E     CMP #&2E			;else, is it ASCII '.'?
952A F0 15     BEQ Q541			;if so exit C=0
952C C9 2A     CMP #&2A			;else, is it ASCII '*'?
952E F0 04     BEQ Q534			;if so go flag ambiguous
9530 C9 23     CMP #&23			;else, is it ASCII '#'?
9532 D0 0A     BNE Q53E			;if anything else exit C=1
.Q534
9534 48        PHA			;else save character
9535 A5 CE     LDA &CE			;A = ambiguous file spec flag
9537 F0 07     BEQ Q540			;if ambiguous file specs not allowed then exit C=0
9539 A9 FF     LDA #&FF			;else flag = &FF
953B 85 CE     STA &CE			;as this spec is ambiguous/A -> &00CE = ambiguous file spec flag
953D 68        PLA			;retrieve character
.Q53E
953E 38        SEC
953F 60        RTS			;and exit C=1.

.Q540
9540 68        PLA			;retrieve character
.Q541
9541 18        CLC
9542 60        RTS			;exit C=0

.Q543
9543 18        CLC
9544 4C C2 FF  JMP gsinit		;Call GSINIT with C=0.

.Q547					;Call GSINIT C=0 then GSREAD
9547 20 43 95  JSR Q543
954A 4C C5 FF  JMP gsread


; EDOS setup
.Q600
9600 4C 1E 96  JMP Q61E			;Print EDOS banner

.Q603
9603 4C 3C 96  JMP Q63C			;Initialise EDOS

.Q606
9606 4C 12 97  JMP Q712			;Save workspace to private page

.Q609
9609 4C 2A 97  JMP Q72A			;Get boot option

.Q60C
960C EQUS "OFF LOAD RUN EXEC "		;boot commands/descriptions 0..3

.Q61E					;Print EDOS banner
961E 20 00 92  JSR Q200			;Save AXY
9621 A2 00     LDX #&00			;set character offset=0 (to be 1)
9623 20 2F 96  JSR Q62F			;print "OPUS EDOS"
9626 49 00     EOR #&00			;00000000
9628 EA        NOP
9629 20 2F 96  JSR Q62F			;print version string
962C 4C 09 90  JMP Q009			;print newline and exit.

.Q62F					;Print title string. inc offset
962F E8        INX
9630 BD 08 80  LDA P008,X		;get character from ROM title
9633 F0 06     BEQ Q63B			;if zero then exit
9635 20 00 90  JSR Q000			;else print character in A
9638 4C 2F 96  JMP Q62F			;and repeat

.Q63B
963B 60        RTS

.Q63C					;Initialise EDOS
963C 20 00 92  JSR Q200			;Save AXY
963F A9 06     LDA #&06			;issue OSFSC 6 to notify current
9641 20 0C 92  JSR Q20C			;FS.
9644 A9 A8     LDA #&A8			;call OSBYTE &A8, X=0, Y=&FF
9646 20 EB 9A  JSR QAEB			;to get address of extended
9649 86 AA     STX &AA			;vector table
964B 84 AB     STY &AB			;store word in zero page
964D EA        NOP
964E A2 00     LDX #&00			;set X=0 offset in preset table
9650 A0 1B     LDY #&1B			;set Y=&1B offset in EVT
.Q652
9652 20 DA 96  JSR Q6DA
9655 20 DA 96  JSR Q6DA			;copy two bytes from ROM to EVT
9658 A5 F4     LDA rmslrg		;add our ROM number to the table
965A 91 AA     STA (&AA),Y
965C C8        INY
965D E0 0E     CPX #&0E			;have we copied 7 vectors?
965F D0 F1     BNE Q652			;if not loop
9661 A2 0F     LDX #&0F			;issue ROM service call &F,
9663 A9 8F     LDA #&8F			;vectors have been changed
9665 20 F4 FF  JSR osbyte
9668 A2 0A     LDX #&0A			;issue ROM service call &A,
966A A9 8F     LDA #&8F			;claiming absolute workspace
966C 20 F4 FF  JSR osbyte
966F 20 3A 97  JSR Q73A			;test flag in private page
9672 C9 EF     CMP #&EF			;=&EF workspace stowed?
9674 F0 13     BEQ Q689			;if so go and unstow
;9676 20 E5 9A  JSR QAE5		;else print EDOS banner
9676 20 CE 83  JSR P3CE			;else print EDOS banner and display error message
9679 A0 00     LDY #&00			;store meta-default path and lib
.Q67B
967B B9 04 97  LDA Q704,Y		;in private page, clear rest of
967E C0 0E     CPY #&0E			;page
9680 90 02     BCC Q684
9682 A9 00     LDA #&00
.Q684
9684 91 A8     STA (&A8),Y
9686 C8        INY
9687 D0 F2     BNE Q67B
.Q689
9689 A0 0D     LDY #&0D			;store &BE, workspace unstowed
968B A9 BE     LDA #&BE			;in flag in private page
968D 91 A8     STA (&A8),Y
968F A0 00     LDY #&00			;copy private page to absolute
.Q691
9691 B1 A8     LDA (&A8),Y		;workspace
9693 99 00 10  STA &1000,Y
9696 C8        INY
9697 D0 F8     BNE Q691
9699 20 06 92  JSR Q206			;copy default path to zero page
969C EQUW &00,&10			;FROM boot command, &1000
969E EQUW &C0,&00			;TO string workspace &00C0
96A0 EQUB &0A				;count
96A1 A9 36     LDA #&36			;&36 = EDOS pseudo-command
96A3 8D 16 10  STA &1016		;2791 Force Interrupt
96A6 20 12 9B  JSR QB12			;issue plain OSWORD &7F
96A9 BA        TSX			;get value of Y on entry
96AA BD 03 01  LDA &0103,X
96AD D0 20     BNE Q6CF			;if Y=0 exit with C=1, break out
96AF 20 00 9B  JSR QB00			;else softmount & load cat
96B2 20 09 96  JSR Q609			;get boot option
96B5 F0 18     BEQ Q6CF			;if boot is OFF, exit C=1
96B7 20 09 92  JSR Q209			;else copy boot command
96BA EQUW &0C,&96			;from &960C
96BC EQUW &58,&10			;to string workspace at &1058
96BE EQUW &04,&20			;4 bytes, X indexed source
96C0 20 06 92  JSR Q206			;copy
96C3 EQUW &D1,&96			;FROM filename " $.!boot"+cr, Q6D1
96C5 EQUW &5C,&10			;TO address &105C
96C7 EQUB &09				;count 9 bytes
96C8 A2 58     LDX #&58			;call OSCLI on command string
96CA A0 10     LDY #&10
96CC 20 F7 FF  JSR oscli
.Q6CF
96CF 38        SEC			;set C=1 to break out of ROM call
96D0 60        RTS			;and exit

.Q6D1
96D1 EQUS " $.!boot"			;"$.!boot" name of boot file
96D9 EQUB &0D				;CR
.Q6DA
96DA BD E8 96  LDA Q6E8,X		;get preset vector
96DD 9D 12 02  STA &0212,X		;store in vector tbl
96E0 BD F6 96  LDA Q6F6,X		;get extended vector preset
96E3 91 AA     STA (&AA),Y		;store in extended vector table
96E5 E8        INX			;increment pair offset
96E6 C8        INY			;increment triplet offset
96E7 60        RTS			;exit

.Q6E8					;Vectors to extended vector handlers, 7 pairs [0..13]
96E8 EQUW &1B,&FF			;&FF1B
96EA EQUW &1E,&FF			;&FF1E
96EC EQUW &21,&FF			;&FF21
96EE EQUW &24,&FF			;&FF24
96F0 EQUW &27,&FF			;&FF27
96F2 EQUW &2A,&FF			;&FF2A
96F4 EQUW &2D,&FF			;&FF2D

.Q6F6
96F6 EQUW &00,&B0			;S000, FILEV for OSFILE
96F8 EQUW &03,&B0			;S003, ARGSV for OSARGS
96FA EQUW &00,&B4			;S400, BGETV for OSBGET
96FC EQUW &03,&B4			;S403, BPUTV for OSBPUT
96FE EQUW &06,&B4			;S406, GBPBV for OSGBPB
9700 EQUW &06,&B0			;S006, FINDV for OSFIND
9702 EQUW &09,&B0			;S009, FSCV  for OSFILE

.Q704					;Meta-default filename and path
9704 EQUS "       "			;leaf name, seven spaces
970B EQUS "$A0"				;directory, volume and drive
970E EQUS "$A0"				;Default library
9711 EQUB &BE				;flag BE = we own absolute wksp

.Q712					;Save workspace to private page
9712 20 00 92  JSR Q200			;Save AXY
;9715 20 D0 9A  JSR QAD0		;if flag in private page+&D <> &BE
9715 20 D6 9A  JSR QAD6			;if flag in private page+&D <> &BE
9718 D0 0F     BNE Q729			;then exit
971A A9 EF     LDA #&EF			;else set absolute page flag = &EF
971C 8D 0D 10  STA &100D		;meaning workspace stowed
971F A0 00     LDY #&00			;and copy workspace to private pg.
.Q721
9721 B9 00 10  LDA &1000,Y		;load one byte from abs page
9724 91 A8     STA (&A8),Y		;store in private page
9726 C8        INY			;increment offset
9727 D0 F8     BNE Q721			;loop until whole page done
.Q729
9729 60        RTS			;exit

.Q72A					;Get boot option
972A AD 06 0F  LDA &0F06
972D 29 30     AND #&30			;extract boot option
972F 4A        LSR A			;shift right twice
9730 4A        LSR A			;A=0,4,8 or 12
9731 AA        TAX			;copy to X
9732 E0 08     CPX #&08			;if X>=8, increment X
9734 90 01     BCC Q737
9736 E8        INX			;now X=0,4,9 or 13
.Q737
9737 4A        LSR A			;shift A right twice more
9738 4A        LSR A			;return A=0 to 3, X=string ptr
9739 60        RTS

.Q73A					;Test if private page available
973A A4 F4     LDY rmslrg
973C B9 F0 0D  LDA &0DF0,Y		;get private page no. for our rom
973F 85 A9     STA &A9			;set high byte of pointer
9741 A9 00     LDA #&00			;clear low byte of pointer
9743 85 A8     STA &A8
9745 A0 0D     LDY #&0D			;load byte &D of private page
9747 B1 A8     LDA (&A8),Y		;through the pointer
9749 C9 BE     CMP #&BE			;compare with value &BE
974B 60        RTS			;return Z=page available


;Channel operations
.Q800
9800 4C 24 98  JMP Q824			;Initialise for open file

.Q803
9803 4C 4E 98  JMP Q84E			;Init & check file open

.Q806
9806 4C AC 98  JMP Q8AC			;Check file not open (mutex)

.Q809
9809 4C 73 98  JMP Q873			;Get unused file handle

.Q80C
980C 4C 9E 98  JMP Q89E			;Check file open & return pointer

.Q80F
980F 4C 0C 99  JMP Q90C			;Flush open file

.Q812
9812 4C 20 99  JMP Q920			;Transfer file buffer to LBA

.Q815
9815 4C 49 99  JMP Q949			;Close open file

.Q818
9818 4C 6B 99  JMP Q96B			;Close all files

.Q81B
981B 4C 84 99  JMP Q984			;Check volume not changed

.Q81E
981E 4C C7 99  JMP Q9C7			;Open a file

.Q821
9821 4C 2E 9A  JMP QA2E			;Print disc/volume error message

.Q824					;Initialise for open file
9824 86 CB     STX &CB			;set pointer to buffer
9826 A0 00     LDY #&00			;clear Y
.Q828
9828 84 CA     STY &CA			;clear &00CA
982A E0 11     CPX #&11			;validate file handle
982C 90 10     BCC Q83E			;if less than &11, branch
982E E0 16     CPX #&16			;else is X > 22?
9830 B0 0C     BCS Q83E			;if greater than &22, branch
9832 BC 28 98  LDY Q828,X		;else, point Y to file workspace
9835 B9 88 10  LDA &1088,Y		;put file flag byte in A
.Q838
9838 60        RTS

.Q828+11				;indexed by X above
9839 EQUW &00,&18			;table to start of workspace
983B EQUW &30,&48			;for channels &11..15
983D 60        RTS

.Q83E
983E 20 64 98  JSR Q864			;print "Channel n"
9841 20 18 90  JSR Q018			;print " invalid"
9844 EQUB &02
9845 EQUS " invalid"
984D EQUB &00				;terminator byte
.Q84E					;Init & check file open
984E 20 00 98  JSR Q800			;Initialise for open file
9851 D0 E5     BNE Q838			;if file closed
9853 20 64 98  JSR Q864			;print "Channel n"
9856 20 18 90  JSR Q018			;print " not open"
9859 EQUB &02
985A EQUS " not open"
9863 EQUB &00				;terminator byte
9864 8A        TXA
9865 20 18 90  JSR Q018
9868 EQUB &88
9869 EQUB &DE
986A EQUS "Channel "
9872 EQUB &00				;terminator byte
.Q873					;Get unused file handle
9873 48        PHA
9874 A2 11     LDX #&11			;start with lowest handle &11
.Q876
9876 20 00 98  JSR Q800			;initialise for this handle
9879 F0 21     BEQ Q89C			;if handle unused exit
987B E8        INX			;else increment handle number
987C E0 16     CPX #&16			;have we run out of handles?
987E D0 F6     BNE Q876			;if not try next handle
9880 20 18 90  JSR Q018			;else give error
9883 EQUB &0A				;LF
9884 EQUB &C0
9885 EQUS "Too many open channels"
989B EQUB &00				;terminator byte
.Q89C
989C 68        PLA			;return unused handle in X
989D 60        RTS

.Q89E					;Check file open & return pointer
989E 20 00 92  JSR Q200			;Save AXY
98A1 98        TYA			;copy handle to X
98A2 AA        TAX
98A3 20 03 98  JSR Q803			;initialise & check file open
98A6 BA        TSX			;return workspace pointer in Y
98A7 98        TYA
98A8 9D 03 01  STA &0103,X		;save on stack
98AB 60        RTS

.Q8AC					;Check file not open (mutex)
98AC 20 00 92  JSR Q200			;Save AXY
98AF A2 11     LDX #&11			;start with lowest handle &11
.Q8B1
98B1 20 00 98  JSR Q800			;initialise for this handle
98B4 F0 41     BEQ Q8F7			;no match if handle is unused
98B6 BA        TSX			;get A on entry. b7=we want to
98B7 1D 05 01  ORA &0105,X		;open for writing. if request and
98BA 10 3B     BPL Q8F7			;handle both read only, no match.
98BC A2 08     LDX #&08			;else 8 characters to compare
98BE 86 B9     STX &B9			;store a counter
98C0 A6 CC     LDX &CC			;point X to filename in catalogue
.Q8C2
98C2 BD 08 0E  LDA &0E08,X		;get character of file/dir name
98C5 20 FF 98  JSR Q8FF			;convert to upper case
98C8 85 B8     STA &B8			;store in temp location
98CA B9 8A 10  LDA &108A,Y		;get filename char fr this handle
98CD 20 FF 98  JSR Q8FF			;convert to upper case
98D0 C5 B8     CMP &B8			;compare with catalogue char
98D2 D0 23     BNE Q8F7			;no match if unequal
98D4 E8        INX			;else increment catalogue ptr
98D5 C8        INY			;and handle pointer
98D6 C6 B9     DEC &B9			;one less char to compare
98D8 D0 E8     BNE Q8C2			;loop if more characters
98DA A5 C8     LDA &C8			;else get volume of subject file, A = Immediate volume
98DC D9 8A 10  CMP &108A,Y		;compare with volume of handle
98DF D0 16     BNE Q8F7			;no match if unequal
98E1 A5 C9     LDA &C9			;else get drive of subject file, A = current drive
98E3 D9 8B 10  CMP &108B,Y		;compare with drive of handle
98E6 D0 0F     BNE Q8F7			;no match if unequal
98E8 20 18 90  JSR Q018			;else a match, "File open" error.
98EB EQUB &0A				;LF
98EC EQUB &C2
98ED EQUS "File open"
98F6 EQUB &00				;terminator byte
.Q8F7					;put handle number back in X
98F7 A6 CB     LDX &CB			;set pointer to buffer
98F9 E8        INX			;increment handle number
98FA E0 16     CPX #&16			;have we run out of handles?
98FC D0 B3     BNE Q8B1			;if not try next handle
98FE 60        RTS			;if so then file not open, exit

.Q8FF					;Convert to uppercase
98FF 29 7F     AND #&7F			;mask b7
9901 C9 61     CMP #&61			;less than "a"?
9903 90 06     BCC Q90B			;if so return
9905 C9 7B     CMP #&7B			;more than "z"?
9907 B0 02     BCS Q90B			;if so return
9909 29 DF     AND #&DF			;else return ASCII value A-Z
.Q90B
990B 60        RTS

.Q90C					;Flush file buffer
990C 20 00 92  JSR Q200			;Save AXY
990F B9 89 10  LDA &1089,Y		;test if page is dirty
9912 C9 02     CMP #&02
9914 A9 00     LDA #&00
9916 99 89 10  STA &1089,Y		;mark it empty
9919 90 F0     BCC Q90B
991B A9 4B     LDA #&4B			;if it was dirty, write it out.
991D 4C 23 99  JMP Q923

.Q920					;Transfer file buffer to LBA
9920 20 00 92  JSR Q200			;Save AXY
.Q923
9923 8D 16 10  STA &1016		;A=command, store it
9926 B9 93 10  LDA &1093,Y		;get drive the file is on
9929 85 C9     STA &C9			;current drive -> &00C9
992B A5 CA     LDA &CA			;give address of buffer
992D 8D 11 10  STA &1011
9930 A5 CB     LDA &CB
9932 8D 12 10  STA &1012
9935 A9 FF     LDA #&FF			;in I/O processor
9937 8D 13 10  STA &1013
993A 8D 14 10  STA &1014
993D BE 96 10  LDX &1096,Y		;and desired absolute sector
9940 B9 97 10  LDA &1097,Y
9943 A8        TAY
9944 A9 01     LDA #&01			;one sector to transfer
9946 4C 06 9B  JMP QB06			;do it

.Q949					;Close open file
9949 20 0F 98  JSR Q80F			;flush buffer
994C 24 CD     BIT &CD			;if &CD b7=1
994E 30 33     BMI Q983			;then exit
9950 48        PHA			;else clear channel flags
9951 A9 00     LDA #&00
9953 99 88 10  STA &1088,Y
9956 68        PLA			;if bit 7 of A clear then exit
9957 10 2A     BPL Q983
9959 20 1B 98  JSR Q81B			;else check volume not changed
995C 20 09 92  JSR Q209			;copy EXT to file length in cat
995F EQUW &9A,&10
9961 EQUW &4E,&10
9963 EQUW &03,&10
9965 20 06 A6  JSR R606			;pack catalogue fields
9968 4C 03 9B  JMP QB03			;write catalogue and exit.

.Q96B					;Close all files
996B A5 CD     LDA &CD
996D 30 05     BMI Q974			;if &CD b7=0
996F A9 77     LDA #&77			;then close *SPOOL/*EXEC files.
9971 20 F4 FF  JSR osbyte
.Q974
9974 A2 11     LDX #&11			;set file handle=&11
.Q976
9976 20 00 98  JSR Q800			;initialise for handle
9979 F0 03     BEQ Q97E			;if handle in use
997B 20 15 98  JSR Q815			;close open file
.Q97E
997E E8        INX			;increment handle
997F E0 16     CPX #&16			;repeat for all handles and exit
9981 D0 F3     BNE Q976
.Q983
9983 60        RTS

.Q984					;Check volume not changed
9984 20 09 92  JSR Q209			;Copy memory absolute indexed
9987 EQUW &8A,&10			;from path of open file	at &108A
9989 EQUW &C0,&00			;to immediate path at &100A
998B EQUW &0A,&10
998D 20 00 9B  JSR QB00			;softmount and catalogue drive
9990 20 09 A5  JSR R509			;find file in catalogue
9993 B0 26     BCS Q9BB			;if not found "Volume changed"
9995 20 03 A6  JSR R603			;unpack fields from catalogue
9998 AD 51 10  LDA &1051		;compare start sector
999B D9 94 10  CMP &1094,Y		;with one in file workspace
999E D0 1B     BNE Q9BB			;"Volume changed" if different
99A0 AD 52 10  LDA &1052
99A3 D9 95 10  CMP &1095,Y
99A6 D0 13     BNE Q9BB
99A8 AD 53 10  LDA &1053		;compare allocated length
99AB D9 98 10  CMP &1098,Y		;with one in file workspace
99AE D0 0B     BNE Q9BB			;"Volume changed" if different
99B0 AD 54 10  LDA &1054
99B3 D9 99 10  CMP &1099,Y
99B6 D0 03     BNE Q9BB
99B8 4C 21 A5  JMP R521			;else check file unlocked & exit

.Q9BB
99BB 20 21 98  JSR Q821			;print disc error +"changed"
99BE EQUB &C8
99BF EQUS "changed"
99C6 EQUB &00				;terminator byte
.Q9C7					;Open a file
99C7 20 09 98  JSR Q809			;check free handle available
99CA 20 06 92  JSR Q206			;if so copy
99CD EQUW &1E,&9A			;FROM addresses and desired length, &9A1E
99CF EQUW &60,&10			;TO file workspace, &1060
99D1 EQUB &10
99D2 A2 00     LDX #&00
99D4 20 18 A6  JSR R618			;check perms/create file
99D7 B0 44     BCS QA1D			;if failed exit C=1
99D9 20 09 98  JSR Q809			;else, get unused file handle
99DC 99 88 10  STA &1088,Y		;store read/write flags from A
99DF A9 00     LDA #&00
99E1 99 89 10  STA &1089,Y		;mark file buffer empty
99E4 99 9A 10  STA &109A,Y		;clear low byte of EXT
99E7 20 09 92  JSR Q209			;copy zero to clear EXT & PTR
99EA EQUW &9A,&10
99EC EQUW &9B,&10
99EE EQUW &05,&11
99F0 20 09 92  JSR Q209			;copy immediate name and path
99F3 EQUW &C0,&00			;to name and path of open file
99F5 EQUW &8A,&10
99F7 EQUW &0A,&01
99F9 20 09 92  JSR Q209			;copy absolute start sector
99FC EQUW &51,&10			;to file workspace
99FE EQUW &94,&10
9A00 EQUW &02,&01
9A02 20 09 92  JSR Q209			;copy number of sectors used
9A05 EQUW &53,&10			;(<=&40) to allocated length
9A07 EQUW &98,&10
9A09 EQUW &02,&01
9A0B B9 88 10  LDA &1088,Y		;get channel flag
9A0E 2A        ROL A
9A0F 10 09     BPL QA1A			;if open for writing/update
9A11 20 09 92  JSR Q209			;then copy file length to EXT
9A14 EQUW &4E,&10
9A16 EQUW &9A,&10
9A18 EQUW &03,&01
.QA1A
9A1A B9 88 10  LDA &1088,Y		; get channel flag
.QA1D
9A1D 60        RTS			; exit

;9A1E EQUB &00,&00,&00,&00		;table [0..15] of parameters for new open files
;9A22 EQUB &00,&00,&00,&40		;desired sector allocation &40
9A1E EQUB &FF,&FF,&03,&FF		;table [0..15] of parameters for new open files
9A22 EQUB &FF,&03,&00,&40		;desired sector allocation &40
9A26 EQUB &00,&00,&00,&40		;to open 5 files on a 100K disc
9A2A EQUB &00,&00,&00,&00

.QA2E					;Print disc/volume error message
9A2E 20 00 92  JSR Q200			;Save AXY
9A31 20 18 90  JSR Q018			;print newline /set up message?
9A34 EQUB &08
9A35 EQUB &00				;terminator byte
9A36 20 03 92  JSR Q203			;get error number\Get byte immediate
9A39 20 00 90  JSR Q000			;"print" it - Print character in A
9A3C A5 C9     LDA &C9			;A = current drive
9A3E AA        TAX			;X = offset by drive No.
9A3F BC FC 0F  LDY &0FFC,X		;does drive have multiple volums?
9A42 D0 0D     BNE QA51			;if not
9A44 20 18 90  JSR Q018			;print "Disc "+number
9A47 EQUB &C0
9A48 EQUS "Disc "
9A4D EQUB &00				;terminator byte
9A4E 4C 62 9A  JMP &9A62		;print space and string

.QA51
9A51 20 18 90  JSR Q018			;else print "Volume "+number
9A54 EQUB &C0
9A55 EQUS "Volume "
9A5C EQUB &00				;terminator byte
9A5D A5 C8     LDA &C8			;A = Immediate volume letter
9A5F 20 00 90  JSR Q000			;print it - Print character in A
9A62 20 03 90  JSR Q003			;print space
.QA65
9A65 20 03 92  JSR Q203			;print error string immediate:
9A68 F0 06     BEQ QA70			;get immediate byte, if not 0
9A6A 20 00 90  JSR Q000			;then print it - Print character in A
9A6D 4C 65 9A  JMP QA65			;and loop

.QA70
9A70 4C 09 90  JMP Q009			;else display error/newline

;EDOSPAT extensions, block 2

;.QAD0
;9AD0 20 3A 97  JSR Q73A		;test flag in private page
;9AD3 D0 0F     BNE QAE4		;if abs wksp not ours, exit Z=0
;.QAD5
;9AD5 A2 11     LDX #&11		;else start at channel &11:
;.QAD7
;9AD7 20 00 98  JSR Q800		;initialise for channel
;9ADA F0 03     BEQ QADF		;if not in use try next channel
;9ADC 20 0F 98  JSR Q80F		;else flush the channel.
;.QADF
;9ADF E8        INX			;increment handle (?&CD=random)
;9AE0 E0 16     CPX #&16		;have we done all handles?
;9AE2 D0 F3     BNE QAD7		;if not then loop else exit Z=1
;.QAE4
;9AE4 60        RTS

;.QAE5					;Print EDOS banner w/2 newlines
;9AE5 20 00 96  JSR Q600		;Print EDOS banner
;9AE8 4C 09 90  JMP Q009

9AD0 EQUD &00,&00,&00,&00
9AD4 EQUW &00,&00

.QACA
9ACA 20 88 9B  JSR QB88			;softmount disc
9ACD 08        PHP			;save status register
9ACE 4E 17 10  LSR &1017		;track no. =2 to test stepping
9AD1 4E 17 10  LSR &1017		;set it to 0 for *VERIFY
9AD4 28        PLP			;restore status and exit
9AD5 60        RTS

.QAD6
9AD6 20 3A 97  JSR Q73A			;test flag in private page
9AD9 D0 0F     BNE QAEA			;if abs wksp not ours, exit Z=0
.QADB
9ADB A2 11     LDX #&11			;else start at channel &11:
.QADD
9ADD 20 00 98  JSR Q800			;initialise for channel
9AE0 F0 03     BEQ QAE5			;if not in use try next channel
9AE2 20 0F 98  JSR Q80F			;else flush the channel
.QAE5
9AE5 E8        INX			;increment handle (?&CD=random)
9AE6 E0 16     CPX #&16			;have we done all handles?
9AE8 D0 F3     BNE QADD			;if not then loop else exit Z=1
.QAEA
9AEA 60        RTS

.QAEB
9AEB A2 00     LDX #&00			;Call high OSBYTE
9AED A0 FF     LDY #&FF			;set X&Y so not to change value
9AEF 4C F4 FF  JMP osbyte

.QAF2
9AF2 8D 12 10  STA &1012		;store updated address 2nd byte
9AF5 90 08     BCC QAFF			;if no carry out then exit
9AF7 EE 13 10  INC &1013		;else carry out to top word
9AFA D0 03     BNE QAFF			;of OSWORD &7F address
9AFC EE 14 10  INC &1014
.QAFF
9AFF 60        RTS


;Disc operations

.QB00
9B00 4C 4A 9B  JMP QB4A			;Softmount & load current cat

.QB03
9B03 4C E1 9B  JMP QBE1			;Write current catalogue

.QB06
9B06 4C 1B 9B  JMP QB1B			;Do LBA transfer

.QB09
9B09 4C 50 9B  JMP QB50			;Load volume catalogue

.QB0C
9B0C 4C CA 9A  JMP QACA			;Softmount disc

.QB0F
9B0F 4C 02 9C  JMP QC02			;Call OSWORD &7F, report errors

.QB12
9B12 4C FD 9C  JMP QCFD			;Call OSWORD &7F

.QB15
9B15 4C FF 9B  JMP QBFF			;Call OSWORD &7F r/w w/errors

.QB18
9B18 4C FA 9C  JMP QCFA			;Call OSWORD &7F read/write

.QB1B					;Do LBA transfer
9B1B 48        PHA			;convert LBA to cylinder/sector
9B1C 20 BD 9D  JSR QDBD			;compare request - dist to EOT
9B1F CD 19 10  CMP &1019		;if >0 then transfer to EOT
9B22 B0 03     BCS QB27			;else set O7F length = request
9B24 8D 19 10  STA &1019		;call OSWORD &7F r/w w/errors
.QB27
9B27 20 15 9B  JSR QB15			;get OSWORD &7F transfer length
9B2A AD 19 10  LDA &1019		;mask off sector size field
9B2D 29 DF     AND #&DF			;put back in OSWORD &7F block
9B2F 8D 19 10  STA &1019		;and add to O7F address (*256)
9B32 18        CLC
9B33 6D 12 10  ADC &1012
9B36 20 F2 9A  JSR QAF2			;carry out to high bytes
9B39 8A        TXA			;put LBA low byte in A
9B3A 18        CLC			;add OSWORD &7F transfer length
9B3B 6D 19 10  ADC &1019
9B3E AA        TAX			;put result back in X
9B3F 90 01     BCC QB42			;and carry out to Y
9B41 C8        INY
.QB42
9B42 68        PLA			;restore LBA request length
9B43 38        SEC
9B44 ED 19 10  SBC &1019		;subtract O7F transfer length
9B47 D0 D2     BNE QB1B			;and loop if result <>0
9B49 60        RTS			;else, exit

.QB4A
9B4A 20 0C 9B  JSR QB0C			; Softmount disc
9B4D D0 BA     BNE QB09			; if multi-volume load vol cat
9B4F 60        RTS

.QB50					;Load volume catalogue
9B50 20 00 92  JSR Q200			;Save AXY
9B53 20 AA 9D  JSR QDAA			;calculate sector offset
9B56 8A        TXA			;divide by 2 again
9B57 4A        LSR A
9B58 A8        TAY
9B59 B9 30 10  LDA &1030,Y		;does the volume exist?
9B5C F0 19     BEQ QB77			;if not give error
9B5E A9 00     LDA #&00			;page E contains disc cat
9B60 AC 03 0E  LDY &0E03		;get sectors per track
.QB63
9B63 18        CLC
9B64 7D 08 0E  ADC &0E08,X		;accum cur vol start track
9B67 90 03     BCC QB6C			;we're multiplying to get
9B69 EE 39 10  INC &1039		;absolute sector offset
.QB6C
9B6C 88        DEY			;to start of volume
9B6D D0 F4     BNE QB63			;store in 1038..9
9B6F 8D 38 10  STA &1038		;rollout read cat block,
9B72 A9 93     LDA #&93			;prepare O7F r/w, calculate
9B74 4C F1 9B  JMP QBF1			;vol offset, read vol cat

.QB77
9B77 20 21 98  JSR Q821			;Print disc/volume error message
9B7A EQUB &D1
9B7B EQUS "non-existent"
9B87 EQUB &00				;terminator byte
.QB88					;Softmount disc
9B88 20 00 92  JSR Q200			;Save AXY
9B8B A9 00     LDA #&00
9B8D 8D 38 10  STA &1038		;clear volume offset
9B90 8D 39 10  STA &1039
9B93 A6 C9     LDX &C9			;X = current drive
9B95 9D F4 0F  STA &0FF4,X		;clear number of tracks
9B98 9D F8 0F  STA &0FF8,X		;clear track stepping flag
9B9B 20 06 92  JSR Q206			;Copy memory absolute
9B9E EQUW &E6,&9C			;FROM read catalogue command, QCE6
9BA0 EQUW &11,&10			;TO OSWORD 7F block, &1011
9BA2 EQUB &09				;count
9BA3 AD 84 10  LDA &1084		;Get *OPT 6 density
9BA6 D0 14     BNE QBBC			;Not 0? you asked for it
9BA8 BD F0 0F  LDA &0FF0,X		;0=autodetect.
9BAB C9 0A     CMP #&0A			;Validate current density
9BAD F0 06     BEQ QBB5			;is it SD?, is so branch to QBB5
9BAF C9 12     CMP #&12			;else, is it DD?
9BB1 F0 02     BEQ QBB5			;is so branch to QBB5
9BB3 A9 0A     LDA #&0A			;else, set it to SD
.QBB5
9BB5 20 17 9D  JSR QD17			;try to load catalogue
9BB8 F0 0A     BEQ QBC4			;Z=success
9BBA 49 18     EOR #&18			;if failed swap 0A<->12
.QBBC
9BBC 20 17 9D  JSR QD17			;and try again
9BBF F0 03     BEQ QBC4			;if another failure
9BC1 4C 08 9C  JMP QC08			;interpret disc error

.QBC4
9BC4 AD 86 10  LDA &1086		;else get *OPT 8 tracks
9BC7 F0 14     BEQ QBDD			;0 means 1:1 stepping
9BC9 10 0F     BPL QBDA			;1..127 means skip track(s)
9BCB A9 1F     LDA #&1F			;>127 means autodetect.
9BCD 8D 16 10  STA &1016		;Prepare OSWORD &7F command
9BD0 A9 02     LDA #&02			;to verify track 2
9BD2 8D 17 10  STA &1017		;2 -> track number
9BD5 20 18 9B  JSR QB18			;call OSWORD &7F (with 1:1)
9BD8 F0 03     BEQ QBDD			;if failed
.QBDA
9BDA 9D F8 0F  STA &0FF8,X		;set stepping for current drive
.QBDD
9BDD BD FC 0F  LDA &0FFC,X		;return Z=single volume disc
9BE0 60        RTS

.QBE1					; Write catalogue
9BE1 20 00 92  JSR Q200			;Save AXY
9BE4 F8        SED			;Increment catalogue cycle no.
9BE5 18        CLC
9BE6 AD 04 0F  LDA &0F04
9BE9 69 01     ADC #&01
9BEB 8D 04 0F  STA &0F04
9BEE D8        CLD
9BEF A9 0B     LDA #&0B			;A = 8271 command = &0B = write. Fall through:
.QBF1
9BF1 20 06 92  JSR Q206			;Read/write volume catalogue.
9BF4 EQUW &E6,&9C			;FROM address = OSWORD &7F block = QCE6
9BF6 EQUW &11,&10			;store it in the TO address = &1011
9BF8 EQUB &09				;count
9BF9 8D 16 10  STA &1016		;set 8271 command
9BFC 20 AA 9D  JSR QDAA			;calculate volume offset
.QBFF					;Call OSWORD &7F r/w w/errors
9BFF 20 9A 9D  JSR QD9A			;Prepare O7F block
.QC02					;Call OSWORD &7F, report errors
9C02 20 12 9B  JSR QB12
9C05 D0 01     BNE QC08			;if failed print error
9C07 60        RTS

.QC08					;Decode errors
9C08 AE 15 10  LDX &1015		;X =
9C0B BD 17 10  LDA &1017,X
9C0E C9 12     CMP #&12
9C10 D0 16     BNE QC28
9C12 20 18 90  JSR Q018			;Print "Write protect"
9C15 EQUB &08
9C16 EQUB &C7
9C17 EQUS "Write protect"
9C24 EQUB &00				;terminator byte
9C25 4C B8 9C  JMP QCB8

.QC28
9C28 C9 20     CMP #&20
9C2A D0 1A     BNE QC46
9C2C 20 18 90  JSR Q018			;Print "Deleted data read"
9C2F EQUB &08
9C30 EQUB &C7
9C31 EQUS "Deleted data read"
9C42 EQUB &00				;terminator byte
9C43 4C B8 9C  JMP QCB8

.QC46
9C46 C9 0C     CMP #&0C
9C48 D0 15     BNE QC5F
9C4A 20 18 90  JSR Q018
9C4D EQUB &08
9C4E EQUB &C7
9C4F EQUS "ID CRC error"
9C5B EQUB &00				;terminator byte
9C5C 4C B8 9C  JMP QCB8

.QC5F
9C5F C9 18     CMP #&18
9C61 D0 13     BNE QC76
9C63 20 18 90  JSR Q018
9C66 08
9C67 C7
9C68 EQUS "Seek error"
9C72 EQUB &00				;terminator byte
9C73 4C B8 9C  JMP QCB8

.QC76
9C76 C9 0E     CMP #&0E
9C78 D0 17     BNE QC91
9C7A 20 18 90  JSR Q018
9C7D EQUB &08
9C7E EQUB &C7
9C7F EQUS "Data CRC error"
9C8D EQUB &00				;terminator byte
9C8E 4C B8 9C  JMP QCB8

.QC91
9C91 C9 0A     CMP #&0A
9C93 D0 12     BNE QCA7
9C95 20 18 90  JSR Q018
9C98 EQUB &08
9C99 EQUB &C7
9C9A EQUS "Lost data"
9CA3 EQUB &00				;terminator byte
9CA4 4C B8 9C  JMP QCB8

.QCA7
9CA7 20 18 90  JSR Q018
9CAA EQUB &48
9CAB EQUB &C7
9CAC EQUS "Disc Fault "
9CB7 EQUB &00				;terminator byte
.QCB8
9CB8 A5 C9     LDA &C9			;A = current drive
9CBA 20 18 90  JSR Q018			;Print " on drive "
9CBC EQUB &90
9CBD EQUB &C0
9CBE EQUS " on drive "
9CC8 EQUB &00				;terminator byte
9CC9 AD 17 10  LDA &1017		;A = track number
9CCC 20 18 90  JSR Q018
9CCF EQUB &80
9CD0 EQUS "."
9CD1 EQUB &00				;terminator byte
9CD2 20 06 92  JSR Q206			;Copy memory absolute
9CD5 EQUW &EF,&9C			;FROM command to read special register 05 (sector number) at QCEF
9CD7 EQUW &15,&10			;TO OSWORD &7F block at &1015
9CD9 EQUB &03				;count
9CDA 20 12 9B  JSR QB12			;call plain OSWORD &7F
9CDD AD 18 10  LDA &1018		;load sector number
9CE0 20 18 90  JSR Q018			;error msg "."+sector no
9CE3 EQUB &82
9CE4 EQUS "."
9CE5 EQUB &00				;terminator byte
.QCE6					;OSWORD &7F block
9CE6 EQUD &00,&0E,&FF,&FF		;load catalogue
9CEA EQUB &03				;No. of parameters
9CEB EQUB &93				;command = read sector
9CEC EQUB &00,&00,&22			;parameters

.QCEF					;3-bytes copied to &1015
9CEF EQUW &01,&3D			;special register 05 (sector number)
9CF1 EQUB &05

.QCF2					;Read DFS/disc catalogue
9CF2 9D FC 0F  STA &0FFC,X		;Store volume count for current drive
9CF5 0A        ASL A
9CF6 8D 18 10  STA &1018		;Store sector offset
9CF9 98        TYA			;what's in Y?
.QCFA					;Call OSWORD &7F read/write
9CFA 20 9A 9D  JSR QD9A			;prepare O7F block
.QCFD					;Call OSWORD &7F
9CFD 20 00 92  JSR Q200			;Save AXY
9D00 A5 C9     LDA &C9			;A = current drive
9D02 29 03     AND #&03			;mask bits 2-7, bits 0-1 = drive
9D04 8D 10 10  STA &1010		;store in OSWORD &7F block
9D07 A9 7F     LDA #&7F			;osword command
9D09 A2 10     LDX #&10			;LSB of parameter block
9D0B A0 10     LDY #&10			;MSB of parameter block
9D0D 20 F1 FF  JSR osword		;call OSWORD &7F
9D10 AE 15 10  LDX &1015
9D13 BD 17 10  LDA &1017,X		;return Z=success
9D16 60        RTS

.QD17					;Softmount part 2
9D17 20 00 92  JSR Q200			;Save AXY
9D1A 9D F0 0F  STA &0FF0,X		;set density of current drive
9D1D A8        TAY
9D1E AD 85 10  LDA &1085		;get *OPT 7 volumes
9D21 30 08     BMI QD2B			;If cheeseburger treat as SD
9D23 D0 24     BNE QD49			;Not 0? Load disc cat, YAFI
9D25 A9 08     LDA #&08			;0=autodetect: deflt 8 vols.
9D27 C0 12     CPY #&12			;if disc is double density
9D29 F0 1E     BEQ QD49			;load disc catalogue
.QD2B
9D2B A9 00     LDA #&00			;SD, disc has no volumes
9D2D 20 F2 9C  JSR QCF2			;Read DFS catalogue
9D30 D0 4A     BNE QD7C			;if read failed then exit
9D32 AD 06 0F  LDA &0F06		;Get sector count in AY
9D35 29 07     AND #&07
9D37 A8        TAY
9D38 AD 07 0F  LDA &0F07
.QD3B
9D3B 38        SEC			;Subtract one track's worth
9D3C FD F0 0F  SBC &0FF0,X
9D3F B0 03     BCS QD44
9D41 88        DEY
9D42 30 36     BMI QD7A			;If sectors run out exit
.QD44
9D44 FE F4 0F  INC &0FF4,X		;Calculate track count
9D47 D0 F2     BNE QD3B			;lucky it was zeroed first!
.QD49
9D49 20 F2 9C  JSR QCF2			;read disc catalogue
9D4C D0 2E     BNE QD7C			;if read failed then exit
9D4E CC 03 0E  CPY &0E03		;have we got density right?
9D51 D0 2A     BNE QD7D			;if not complain bad layout
9D53 AD 04 0E  LDA &0E04		;get track count from disc
9D56 9D F4 0F  STA &0FF4,X		;store it for current drive
9D59 A2 08     LDX #&08			;calculate number of tracks
9D5B A0 10     LDY #&10			;in each volume and store
.QD5D
9D5D 88        DEY			;in &1030,X
9D5E 88        DEY
9D5F CA        DEX
9D60 30 18     BMI QD7A			;when done exit
9D62 48        PHA			;save ceiling track number
9D63 B9 08 0E  LDA &0E08,Y		;get start track no.
9D66 9D 30 10  STA &1030,X		;store in &1030,X in case it's 0
9D69 C9 01     CMP #&01			;set C=1 if start track >0
9D6B 68        PLA			;restore ceiling track number
9D6C 90 EF     BCC QD5D			;if volume absent then loop
9D6E F9 08 0E  SBC &0E08,Y		;else ceiling - start track
9D71 9D 30 10  STA &1030,X		;=volume size. store in 1030,X
9D74 B9 08 0E  LDA &0E08,Y		;get new ceiling
9D77 4C 5D 9D  JMP QD5D			;and loop.

.QD7A
9D7A A9 00     LDA #&00			;0=success
.QD7C
9D7C 60        RTS

.QD7D
9D7D 20 18 90  JSR Q018			;Give error "Bad multi-volume layout"
9D80 EQUB &0A				;LF
9D81 EQUB &D0
9D82 EQUS "Bad multi-volume layout"
9D99 EQUB &00				;terminator byte
.QD9A					;Prepare OSWORD &7F block
9D9A 48        PHA
9D9B A9 03     LDA #&03			;for a read or write
9D9D 8D 15 10  STA &1015		;Three parameters
9DA0 AD 19 10  LDA &1019		;256 byte sectors
9DA3 09 20     ORA #&20
9DA5 8D 19 10  STA &1019
9DA8 68        PLA
9DA9 60        RTS

.QDAA					;calculate sector offset
9DAA A6 C9     LDX &C9			;A = current drive
9DAC BD FC 0F  LDA &0FFC,X		;for volume catalogue
9DAF F0 07     BEQ QDB8			;if disc has volumes
9DB1 A6 C8     LDX &C8			;A = Immediate volume
9DB3 CA        DEX			;convert to binary
9DB4 8A        TXA
9DB5 29 0F     AND #&0F			;mask bits 4-7
9DB7 0A        ASL A			;and multiply by 2
.QDB8
9DB8 AA        TAX			;store it in Osword block
9DB9 8E 18 10  STX &1018		;return in A and X
9DBC 60        RTS


; Convert logical block address (LBA) to cylinder/sector address.
; On entry XY contains an absolute logical block address and ?&C9
; contains the drive number.  On exit ?&1017 contains the corresponding
; cylinder (track) number, ?&1018 contains the sector number (zero based)
; and ?&1019 contains the number of sectors until the end of the track
; (i.e. ?&1018 + ?&1019 = sectors per track).  All taking into account
; the geometry of the drive identified by ?&C9.

.QDBD					;Convert LBA to CS
9DBD 20 00 92  JSR Q200			;Save AXY
9DC0 A9 FF     LDA #&FF			;preset track number = -1
9DC2 8D 17 10  STA &1017
9DC5 8A        TXA			;LBA low byte to A
9DC6 A6 C9     LDX &C9			;X = drive number
.QDC8
9DC8 EE 17 10  INC &1017		;increment track number
9DCB 8D 18 10  STA &1018		;save LBA low byte as abs sector
9DCE 38        SEC
9DCF FD F0 0F  SBC &0FF0,X		;subtract spt of drive from it
9DD2 B0 F4     BCS QDC8			;if no borrow-in then loop
9DD4 88        DEY			;else borrow from LBA high byte
9DD5 10 F1     BPL QDC8			;if LBA - spt >=0 then loop
9DD7 49 FF     EOR #&FF			;else invert result
9DD9 AA        TAX			;add 1 to make 2's complementinvert
9DDA E8        INX			;(positive difference) in X
9DDB 8E 19 10  STX &1019		;=distance to end of track.
9DDE 60        RTS			;exit


; Tube hosting

; For disassemblies of the BRK handler and Tube host code,
; please read J.G.Harston's extellent article:
; http://mdfs.net/Software/Tube/BBC/Host.lst

.R000
A000 4C 12 A0  JMP R012			;Initialise Tube

.R003
A003 4C 53 A0  JMP R053			;Tube post init

.R006
A006 4C 6D A0  JMP R06D			;*GO / open Tube channel 3?

.R009
A009 4C 87 A0  JMP R087			;Transfer byte to/from Tube

.R00C
A00C 4C 9B A0  JMP R09B			;Close Tube channel 3

.R00F
A00F 4C A8 A0  JMP R0A8			;Call code in Tube processor

.R012					;Initialise Tube
A012 20 00 92  JSR Q200			;Save AXY
A015 A9 8E     LDA #&8E			;set Tube status (NAUG p.329)
A017 8D E0 FE  STA tubeR1stat		;enable NMI on R3, IRQ on R1,R4
A01A 20 06 92  JSR Q206			;Copy BRK handler/Install BRK handler on BRKV &41 bytes
A01D EQUW &F1,&A0			;FROM address, R0F1
A01F EQUW &16,&00			;TO address, &0016
A021 EQUB &41
A022 A9 16     LDA #&16
A024 8D 02 02  STA brkv
A027 A9 00     LDA #&00
A029 8D 03 02  STA brkv+1		;brk vector = &0016
A02C 20 06 92  JSR Q206			;Copy Tube host code to &0400
A02F EQUW &32,&A1			;FROM address R132
A031 EQUW &00,&04			;TO address &0400
A033 EQUB &FF				;count
A034 20 06 92  JSR Q206			;Copy Tube host code to &04FF
A037 EQUW &31,&A2			;FROM address R231
A039 EQUW &FF,&04			;TO address&04FF
A03B EQUB &FF				;count
A03C 20 06 92  JSR Q206			;Copy memory absolute
A03F EQUW &30,&A3			;FROM address = R330
A041 EQUW &FE,&05			;TO address &05FE
A043 EQUB &D0				;count
A044 A9 AD     LDA #&AD
A046 8D 20 02  STA eventvec
A049 A9 06     LDA #&06
A04B 8D 21 02  STA eventvec+1		;event vector = &06AD
A04E 20 21 04  JSR &0421
.R051
A051 38        SEC
A052 60        RTS

.R053					;Tube post init
A053 20 00 92  JSR Q200			;Save AXY
A056 A2 06     LDX #&06
A058 A9 14     LDA #&14			;OSBYTE &14
A05A 20 F4 FF  JSR osbyte		;FONT EXPLOSION/DEFINITION
.R05D
A05D AD E0 FE  LDA tubeR1stat
A060 10 FB     BPL R05D
A062 AD E1 FE  LDA tubeR1data
A065 F0 EA     BEQ R051
A067 20 EE FF  JSR oswrch
A06A 4C 5D A0  JMP R05D

.R06D					;*GO / open Tube channel 3?
A06D 20 00 92  JSR Q200			;Save AXY
A070 20 76 A0  JSR R076
A073 4C 06 04  JMP tube_entry		;call tube

.R076
A076 20 00 92  JSR Q200			;Save AXY
A079 38        SEC
A07A 6A        ROR A
A07B 6A        ROR A
A07C 8D 3A 10  STA &103A
A07F A9 C1     LDA #&C1
A081 20 06 04  JSR tube_entry		;call tube
A084 90 F9     BCC R07F
A086 60        RTS

.R087					;Transfer byte to/from Tube
A087 20 00 92  JSR Q200			;Save AXY
A08A 2C 3A 10  BIT &103A		;103A: b6=Tube, b7=write to Tube
A08D 30 08     BMI R097
A08F AD E5 FE  LDA tubeR3data
A092 BA        TSX
A093 9D 05 01  STA &0105,X
A096 60        RTS

.R097
A097 8D E5 FE  STA tubeR3data
A09A 60        RTS

.R09B					;Close Tube channel 3
A09B 20 00 92  JSR Q200			;Save AXY
A09E A9 00     LDA #&00
A0A0 8D 3A 10  STA &103A
A0A3 A9 81     LDA #&81
A0A5 4C 06 04  JMP tube_entry		;call tube

.R0A8
A0A8 A9 04     LDA #&04
A0AA 4C 06 04  JMP tube_entry		;call tube

.R0F1					;Tube BRK handler
A0F1 A9 FF     LDA #&FF			;copied to &0016
A0F3 20 9E 06  JSR &069E
A0F6 AD E3 FE  LDA tubeR2data
A0F9 A9 00     LDA #&00
A0FB 20 95 06  JSR &0695
A0FE A8        TAY
A0FF B1 FD     LDA (&FD),Y
A101 20 95 06  JSR &0695
A104 C8        INY
A105 B1 FD     LDA (&FD),Y
A107 20 95 06  JSR &0695
A10A AA        TAX
A10B D0 F7     BNE &A104
A10D A2 FF     LDX #&FF
A10F 9A        TXA
A110 58        CLI
A111 2C E0 FE  BIT tubeR1stat
A114 10 06     BPL &A11C
A116 AD E1 FE  LDA &FEE1
A119 20 EE FF  JSR oswrch
A11C 2C E2 FE  BIT tubeR2stat
A11F 10 F0     BPL &A111
A121 2C E0 FE  BIT tubeR1stat
A124 30 F0     BMI &A116
A126 AE E3 FE  LDX tubeR2data
A129 86 51     STX &51
A12B 6C 00 05  JMP (&0500)

A12E EQUD &00,&80,&00,&00

.R132					;Tube host code to &0400, &FF bytes
A132 4C 84 04  JMP &0484

A135 4C A7 06  JMP &06A7

A138 C9 80     CMP #&80
A13A 90 2B     BCC R167
A13C C9 C0     CMP #&C0
A13E B0 1A     BCS R15A
A140 09 40     ORA #&40
A142 C5 15     CMP &15
A144 D0 20     BNE R166
A146 08        PHP
A147 78        SEI
A148 A9 05     LDA #&05
A14A 20 9E 06  JSR &069E
A14D A5 15     LDA &15
A14F 20 9E 06  JSR &069E
A152 28        PLP
A153 A9 80     LDA #&80
A155 85 15     STA &15
A157 85 14     STA &14
A159 60        RTS

.R15A
A15A 06 14     ASL &14
A15C B0 06     BCS R164
A15E C5 15     CMP &15
A160 F0 04     BEQ R166
A162 18        CLC
A163 60        RTS

.R164
A164 85 15     STA &15
.R166
A166 60        RTS

.R167
A167 08        PHP
A168 78        SEI
A169 84 13     STY &13
A16B 86 12     STX &12
A16D 20 9E 06  JSR &069E
A170 AA        TAX
A171 A0 03     LDY #&03
A173 A5 15     LDA &15
A175 20 9E 06  JSR &069E
.R178
A178 B1 12     LDA (&12),Y
A17A 20 9E 06  JSR &069E
A17D 88        DEY
A17E 10 F8     BPL R178
A180 A0 18     LDY #&18
A182 8C E0 FE  STY tubeR1stat
A185 BD 18 05  LDA &0518,X
A188 8D E0 FE  STA tubeR1stat
A18B 4A        LSR A
A18C 4A        LSR A
A18D 90 06     BCC &A195
A18F 2C E5 FE  BIT tubeR3data
A192 2C E5 FE  BIT tubeR3data
A195 20 9E 06  JSR &069E
.R198
A198 2C E6 FE  BIT tubsR4stat
A19B 50 FB     BVC R198
A19D B0 0D     BCS R1AC
A19F E0 04     CPX #&04
A1A1 D0 11     BNE R1B4
A1A3 20 14 04  JSR &0414
A1A6 20 95 06  JSR &0695
A1A9 4C 32 00  JMP &0032

.R1AC
A1AC 4A        LSR A
A1AD 90 05     BCC R1B4
A1AF A0 88     LDY #&88
A1B1 8C E0 FE  STY tubeR1stat
.R1B4
A1B4 28        PLP
A1B5 60        RTS

A1B6 58        CLI
A1B7 B0 11     BCS &A1CA
A1B9 D0 03     BNE &A1BE
A1BB 4C 9C 05  JMP &059C

A1BE A2 00     LDX #&00
A1C0 A0 FF     LDY #&FF
A1C2 A9 FD     LDA #&FD
A1C4 20 F4 FF  JSR osbyte
A1C7 8A        TXA
A1C8 F0 D9     BEQ &A1A3
A1CA A9 FF     LDA #&FF
A1CC 20 06 04  JSR tube_entry
A1CF 90 F9     BCC &A1CA
A1D1 20 D2 04  JSR &04D2
A1D4 A9 07     LDA #&07
A1D6 20 CB 04  JSR &04CB
A1D9 A0 00     LDY #&00
A1DB 84 00     STY &00
A1DD B1 00     LDA (&00),Y
A1DF 8D E5 FE  STA tubeR3data
A1E2 EA        NOP
A1E3 EA        NOP
A1E4 EA        NOP
A1E5 C8        INY
A1E6 D0 F5     BNE &A1DD
A1E8 E6 54     INC &54
A1EA D0 06     BNE &A1F2
A1EC E6 55     INC &55
A1EE D0 02     BNE &A1F2
A1F0 E6 56     INC &56
A1F2 E6 01     INC &01
A1F4 24 01     BIT &01
A1F6 50 DC     BVC &A1D4
A1F8 20 D2 04  JSR &04D2
A1FB A9 04     LDA #&04
A1FD A0 00     LDY #&00
A1FF A2 53     LDX #&53
A201 4C 06 04  JMP tube_entry

A204 A9 80     LDA #&80
A206 85 54     STA &54
A208 85 01     STA &01
A20A A9 20     LDA #&20
A20C 2D 06 80  AND &8006
A20F A8        TAY
A210 84 53     STY &53
A212 F0 19     BEQ &A22D
A214 AE 07 80  LDX &8007
A217 E8        INX
A218 BD 00 80  LDA &8000,X
A21B D0 FA     BNE &A217
A21D BD 01 80  LDA &8001,X
A220 85 53     STA &53
A222 BD 02 80  LDA &8002,X
A225 85 54     STA &54
A227 BC 03 80  LDY &8003,X
A22A BD 04 80  LDA &8004,X
A22D 85 56     STA &56
A22F 84 55     STY &55
.R231					;Copy Tube host code to &04FF, &FF bytes
A231 60        RTS

A232 EQUW &37,&05			;R2 was 0  - jump osrdch_call
A234 EQUW &96,&05			;R2 was 2  - jump oscli_call
A236 EQUW &F2,&05			;R2 was 4  - jump short_osbyte
A238 EQUW &07,&06			;R2 was 6  - jump long_osbyte
A23A EQUW &27,&06			;R2 was 8  - jump osword_call
A23C EQUW &68,&06			;R2 was A  - jump osword0_call
A23E EQUW &5E,&05			;R2 was C  - jump osargs_call
A240 EQUW &2D,&05			;R2 was E  - jump osbget_call
A242 EQUW &20,&05			;R2 was 10 - jump osbput_call
A244 EQUW &42,&05			;R2 was 12 - jump osfind_call_1
A246 EQUW &A9,&05			;R2 was 14 - jump osfild call
A248 EQUW &D1,&05			;R2 was 16 - jump osgbpb_call
A24A EQUW &86,&88
A24C EQUW &96,&98
A24E 18        CLC
A24F 18        CLC
A250 82        ???
A251 18        CLC
A252 20 C5 06  JSR &06C5
A255 A8        TAY
A256 20 C5 06  JSR &06C5
A259 20 D4 FF  JSR osbput
A25C 4C 9C 05  JMP &059C

A25F 20 C5 06  JSR &06C5
A262 A8        TAY
A263 20 D7 FF  JSR osbget
A266 4C 3A 05  JMP &053A

A269 20 E0 FF  JSR osrdch
A26C 6A        ROR A
A26D 20 95 06  JSR &0695
A270 2A        ROL A
A271 4C 9E 05  JMP &059E

A274 20 C5 06  JSR &06C5
A277 F0 0B     BEQ &A284
A279 48        PHA
A27A 20 82 05  JSR &0582
A27D 68        PLA
A27E 20 CE FF  JSR osfind
A281 4C 9E 05  JMP &059E

A284 20 C5 06  JSR &06C5
A287 A8        TAY
A288 A9 00     LDA #&00
A28A 20 CE FF  JSR osfind
A28D 4C 9C 05  JMP &059C

A290 20 C5 06  JSR &06C5
A293 A8        TAY
A294 A2 04     LDX #&04
A296 20 C5 06  JSR &06C5
A299 95 FF     STA &FF,X
A29B CA        DEX
A29C D0 F8     BNE &A296
A29E 20 C5 06  JSR &06C5
A2A1 20 DA FF  JSR osargs
A2A4 20 95 06  JSR &0695
A2A7 A2 03     LDX #&03
A2A9 B5 00     LDA &00,X
A2AB 20 95 06  JSR &0695
A2AE CA        DEX
A2AF 10 F8     BPL &A2A9
A2B1 4C 36 00  JMP &0036

A2B4 A2 00     LDX #&00
A2B6 A0 00     LDY #&00
A2B8 20 C5 06  JSR &06C5
A2BB 99 00 07  STA &0700,Y
A2BE C8        INY
A2BF F0 04     BEQ &A2C5
A2C1 C9 0D     CMP #&0D
A2C3 D0 F3     BNE &A2B8
A2C5 A0 07     LDY #&07
A2C7 60        RTS

A2C8 20 82 05  JSR &0582
A2CB 20 F7 FF  JSR oscli
A2CE A9 7F     LDA #&7F
A2D0 2C E2 FE  BIT tubeR2stat
A2D3 50 FB     BVC &A2D0
A2D5 8D E3 FE  STA tubeR2data
A2D8 4C 36 00  JMP &0036

A2DB A2 10     LDX #&10
A2DD 20 C5 06  JSR &06C5
A2E0 95 01     STA &01,X
A2E2 CA        DEX
A2E3 D0 F8     BNE &A2DD
A2E5 20 82 05  JSR &0582
A2E8 86 00     STX &00
A2EA 84 01     STY &01
A2EC A0 00     LDY #&00
A2EE 20 C5 06  JSR &06C5
A2F1 20 DD FF  JSR &FFDD
A2F4 20 95 06  JSR &0695
A2F7 A2 10     LDX #&10
A2F9 B5 01     LDA &01,X
A2FB 20 95 06  JSR &0695
A2FE CA        DEX
A2FF D0 F8     BNE &A2F9
A301 F0 D5     BEQ &A2D8
A303 A2 0D     LDX #&0D
A305 20 C5 06  JSR &06C5
A308 95 FF     STA &FF,X
A30A CA        DEX
A30B D0 F8     BNE &A305
A30D 20 C5 06  JSR &06C5
A310 A0 00     LDY #&00
A312 20 D1 FF  JSR &FFD1
A315 48        PHA
A316 A2 0C     LDX #&0C
A318 B5 00     LDA &00,X
A31A 20 95 06  JSR &0695
A31D CA        DEX
A31E 10 F8     BPL &A318
A320 68        PLA
A321 4C 3A 05  JMP &053A

A324 20 C5 06  JSR &06C5
A327 AA        TAX
A328 20 C5 06  JSR &06C5
A32B 20 F4 FF  JSR osbyte
A32E 2C E2 FE  BIT tubeR2stat
;.R330 FE				;copied to address &05FE
A331 50 FB     BVC &A32E
A333 8E E3 FE  STX tubeR2data
A336 4C 36 00  JMP &0036

A339 20 C5 06  JSR &06C5
A33C AA        TAX
A33D 20 C5 06  JSR &06C5
A340 A8        TAY
A341 20 C5 06  JSR &06C5
A344 20 F4 FF  JSR osbyte
A347 49 9D     EOR #&9D
A349 F0 EB     BEQ &A336
A34B 6A        ROR A
A34C 20 95 06  JSR &0695
A34F 2C E2 FE  BIT tubeR2stat
A352 50 FB     BVC &A34F
A354 8C E3 FE  STY tubeR2data
A357 70 D5     BVS &A32E
A359 20 C5 06  JSR &06C5
A35C A8        TAY
A35D 2C E2 FE  BIT tubeR2stat
A360 10 FB     BPL &A35D
A362 AE E3 FE  LDX tubeR2data
A365 CA        DEX
A366 30 0F     BMI &A377
A368 2C E2 FE  BIT tubeR2stat
A36B 10 FB     BPL &A368
A36D AD E3 FE  LDA tubeR2data
A370 9D 28 01  STA &0128,X
A373 CA        DEX
A374 10 F2     BPL &A368
A376 98        TYA
A377 A2 28     LDX #&28
A379 A0 01     LDY #&01
A37B 20 F1 FF  JSR osword
A37E 2C E2 FE  BIT tubeR2stat
A381 10 FB     BPL &A37E
A383 AE E3 FE  LDX tubeR2data
A386 CA        DEX
A387 30 0E     BMI &A397
A389 BC 28 01  LDY &0128,X
A38C 2C E2 FE  BIT tubeR2stat
A38F 50 FB     BVC &A38C
A391 8C E3 FE  STY tubeR2data
A394 CA        DEX
A395 10 F2     BPL &A389
A397 4C 36 00  JMP &0036

A39A A2 04     LDX #&04
A39C 20 C5 06  JSR &06C5
A39F 95 00     STA &00,X
A3A1 CA        DEX
A3A2 10 F8     BPL &A39C
A3A4 E8        INX
A3A5 A0 00     LDY #&00
A3A7 8A        TXA
A3A8 20 F1 FF  JSR osword
A3AB 90 05     BCC &A3B2
A3AD A9 FF     LDA #&FF
A3AF 4C 9E 05  JMP &059E

A3B2 A2 00     LDX #&00
A3B4 A9 7F     LDA #&7F
A3B6 20 95 06  JSR &0695
A3B9 BD 00 07  LDA &0700,X
A3BC 20 95 06  JSR &0695
A3BF E8        INX
A3C0 C9 0D     CMP #&0D
A3C2 D0 F5     BNE &A3B9
A3C4 4C 36 00  JMP &0036

A3C7 2C E2 FE  BIT tubeR2stat
A3CA 50 FB     BVC &A3C7
A3CC 8D E3 FE  STA tubeR2data
A3CF 60        RTS

A3D0 2C E6 FE  BIT tubsR4stat
A3D3 50 FB     BVC &A3D0
A3D5 8D E7 FE  STA tubeR4data
A3D8 60        RTS

A3D9 A5 FF     LDA &FF
A3DB 38        SEC
A3DC 6A        ROR A
A3DD 30 0F     BMI &A3EE
A3DF 48        PHA
A3E0 A9 00     LDA #&00
A3E2 20 BC 06  JSR &06BC
A3E5 98        TYA
A3E6 20 BC 06  JSR &06BC
A3E9 8A        TXA
A3EA 20 BC 06  JSR &06BC
A3ED 68        PLA
A3EE 2C E0 FE  BIT tubeR1stat
A3F1 50 FB     BVC &A3EE
A3F3 8D E1 FE  STA tubeR1data
A3F6 60        RTS

A3F7 2C E2 FE  BIT tubeR2stat
A3FA 10 FB     BPL &A3F7
A3FC AD E3 FE  LDA tubeR2data
A3FF 60        RTS


;EDOS console output
.R400
A400 4C 1F A4  JMP R41F			;Print filename

.R403
A403 4C 0C A4  JMP R40C			;Print directory and filename

.R406
A406 4C 3D A4  JMP R43D			;Print *INFO line

.R409
A409 4C 6D A4  JMP R46D			;Print decimal word

.R40C					;Print directory and filename
A40C 20 00 92  JSR Q200			;Save AXY
.R40F					;print directory and filename
A40F AD 47 10  LDA &1047
A412 29 7F     AND #&7F			;remove Locked bit
A414 20 00 90  JSR Q00	0		;print directory letter in A
A417 A9 2E     LDA #&2E			;print "."
A419 20 00 90  JSR Q000			;Print character in A, fall through:
A41C 4C 22 A4  JMP R422

.R41F
A41F 20 00 92  JSR Q200			;Save AXY;Print filename
.R422
A422 A0 00     LDY #&00			;set offset = 0
.R424
A424 B9 40 10  LDA &1040,Y		;get character from cat wksp
A427 20 00 90  JSR Q000			;print the character in A
A42A C8        INY			;increment offset
A42B C0 07     CPY #&07			;reached end of name proper?
A42D D0 F5     BNE R424			;if not then loop.
A42F AD 47 10  LDA &1047		;get directory and attribute
A432 10 08     BPL R43C			;if Locked
A434 20 18 90  JSR Q018			;then print "  L".
A437 EQUB &00
A438 EQUS "  L"
A43B EQUB &00
.R43C
A43C 60        RTS			;exit

.R43D					;Print *INFO line
A43D 20 00 92  JSR Q200			;Save AXY
A440 20 0F A4  JSR R40F			;print directory and filename
A443 A9 0E     LDA #&0E			;tab to column 14
A445 20 06 90  JSR Q006			;Tab to column in A
A448 A2 00     LDX #&00			;catalogue field offset = 0
A44A 20 64 A4  JSR R464			;print load address
A44D 20 64 A4  JSR R464			;print execution address
A450 20 64 A4  JSR R464			;print file length
A453 CA        DEX			;pretend startsec is 3byte field:
.R454
A454 18        CLC			;Print top word w/o leading 0s
A455 BD 4A 10  LDA &104A,X		;load top byte
A458 20 5E A4  JSR R45E			;print hex byte, allow zeroes
A45B BD 48 10  LDA &1048,X		;load middle byte
.R45E
A45E 20 0F 90  JSR Q00F			;print hex byte
A461 38        SEC			;allow zeroes
A462 E8        INX			;increment offset
A463 60        RTS			;exit.

.R464
A464 20 54 A4  JSR R454			;Print 3byte field from cat
A467 BD 46 10  LDA &1046,X		;print top word w/o leading 0s
A46A 4C 5E A4  JMP R45E			;0s allowed, print bottom byte.

.R46D					;Print decimal word
A46D 20 00 92  JSR Q200			;Save AXY
A470 18        CLC 			;similar algorithm to
A471 A0 04     LDY #&04			;print-decimal-byte (Q012)
.R473
A473 08        PHP
A474 A2 00     LDX #&00
.R476
A476 AD 61 10  LDA &1061
A479 D9 B2 A4  CMP R4B3-1,Y
A47C D0 06     BNE R484
A47E AD 60 10  LDA &1060
A481 D9 AE A4  CMP R4AF-1,Y
.R484
A484 90 16     BCC R49C
A486 E8        INX
A487 AD 60 10  LDA &1060
A48A F9 AE A4  SBC R4AF-1,Y
A48D 8D 60 10  STA &1060
A490 AD 61 10  LDA &1061
A493 F9 B2 A4  SBC R4B3-1,Y
A496 8D 61 10  STA &1061
A499 4C 76 A4  JMP R476

.R49C
A49C 28        PLP
A49D 8A        TXA
A49E D0 02     BNE R4A2
A4A0 90 03     BCC R4A5
.R4A2
A4A2 20 0C 90  JSR Q00C			;Print hex nibble
.R4A5
A4A5 88        DEY
A4A6 D0 CB     BNE R473
A4A8 AD 60 10  LDA &1060
A4AB 38        SEC
A4AC 4C 0C 90  JMP Q00C			;Print hex nibble

.R4AF					;powers of ten
A4AF EQUD &0A,&64,&E8,&10		;low bytes [0..3]

.R4B3					;(placevalues)
A4B3 EQUD &00,&00,&03,&27		;high bytes [0..3]


;File selection
.R500
A500 4C 2A A5  JMP R52A			;Select first file in catalogue

					;it's not called from here?
A503 4C 24 A5  JMP R524			;Select and ensure first file

.R506
A506 4C 31 A5  JMP R531			;Select next file in catalogue

.R509
A509 4C 47 A5  JMP R547			;Find file in catalogue

.R50C
A50C 4C 41 A5  JMP R541			;Check file exists

.R50F
A50F 4C 51 A5  JMP R551			;Find next match of afsp

.R512
A512 4C 70 A5  JMP R570			;Find unlocked file in cat

					;it's not called from here?
A515 4C 57 A5  JMP R557			;Check unlocked file exists

.R518
A518 4C 7A A5  JMP R57A			;Find next unlocked match

.R51B
A51B 4C 80 A5  JMP R580			;Compare filenames

.R51E
A51E 4C 99 A5  JMP R599			;Compare directory letters

.R521
A521 4C CE A5  JMP R5CE			;Check file not locked

.R524					;Select and ensure first file
A524 20 00 A5  JSR R500			;Select first file in catalogue
A527 4C 5A A5  JMP R55A			;give error if catalogue empty.

.R52A					;Select first file in catalogue
A52A 48        PHA
A52B AD 05 0F  LDA &0F05		;get file count from catalogue
A52E 4C 34 A5  JMP R534			;set ptr = count - 8 and exit.

.R531					;Select next file in catalogue
A531 48        PHA
A532 A5 CC     LDA &CC			;get catalogue pointer
.R534
A534 38        SEC
A535 E9 08     SBC #&08			;Subtract 8 to pt to next entry
A537 90 05     BCC R53E			;if borrow then exit C=1
A539 85 CC     STA &CC			;else store catalogue pointer
A53B 68        PLA			;restore A and
.R53C
A53C 18        CLC
A53D 60        RTS			;exit C=0

.R53E
A53E 68        PLA			;restore A
.R53F
A53F 38        SEC
A540 60        RTS			;exit C=1

.R541					;Check file exists
A541 20 09 A5  JSR R509			;find file, else "Not found"
A544 4C 5A A5  JMP R55A			;Find file in catalogue

.R547					;Find file in catalogue
A547 20 00 A5  JSR R500			;Select first file in catalogue
A54A B0 F3     BCS R53F
.R54C
A54C 20 1B A5  JSR R51B			;Compare filenames
A54F F0 EB     BEQ R53C
.R551					;Find next match of afsp
A551 20 06 A5  JSR R506			;Select next file in catalogue
A554 90 F6     BCC R54C
A556 60        RTS

.R557					;Check unlocked file exists
A557 20 12 A5  JSR R512			;Find unlocked file in cat
.R55A
A55A 90 E0     BCC R53C
A55C 20 18 90  JSR Q018
A55F EQUB &0A
A560 EQUB &D6
A561 EQUS "File not found"
A56F EQUB &00
.R570					;Find unlocked file in cat
A570 20 09 A5  JSR R509			;Find file in catalogue
A573 B0 CA     BCS R53F			;find file, else exit C=1
.R575
A575 20 E4 A5  JSR R5E4			;Read catalogue entry and get attribute bit of file
A578 10 C2     BPL R53C			;if unlocked exit with C=0
.R57A					;Find next unlocked match
A57A 20 0F A5  JSR R50F			;Find next match of afsp
A57D 90 F6     BCC R575			;if found loop
A57F 60        RTS			;else exit C=1

.R580					;Compare filenames
A580 20 00 92  JSR Q200			;Save AXY
A583 20 9C A5  JSR R59C			;compare directory letters
A586 D0 10     BNE R598			;if mismatch then exit Z=0
A588 A0 00     LDY #&00			;else clear Y index register
.R58A
A58A BD 08 0E  LDA &0E08,X		;get character of entry name
A58D 20 AD A5  JSR R5AD			;compare to immediate filename
A590 D0 06     BNE R598			;if mismatch then exit Z=0
A592 E8        INX			;else increment copy of cat ptr
A593 C8        INY			;and immediate filename offset
A594 C0 07     CPY #&07			;have we compared 7 characters?
A596 D0 F2     BNE R58A			;if so then exit else loop.
.R598
A598 60        RTS			;exit

.R599					;Compare directory letters
A599 20 00 92  JSR Q200			;Save AXY
.R59C
A59C 20 E7 A5  JSR R5E7			;Reads catalogue entry
A59F 29 7F     AND #&7F			;mask bit 7 (attribute bit)
A5A1 20 C3 A5  JSR R5C3			;convert lower case to upper case
A5A4 85 B8     STA &B8			;store in temp
A5A6 A5 C7     LDA &C7			;A = Immediate dir'y
A5A8 29 7F     AND #&7F			;mask bit 7 (attribute bit)
A5AA 4C B5 A5  JMP R5B5			;and jump forward

.R5AD
A5AD 20 C3 A5  JSR R5C3			;convert lower case to upper case
A5B0 85 B8     STA &B8			;store in temp
A5B2 B9 C0 00  LDA &00C0,Y		;get char of immediate filename
.R5B5
A5B5 C9 2A     CMP #&2A			;is search character ASCII '*'?
A5B7 F0 09     BEQ R5C2			;if it is, exit
A5B9 C9 23     CMP #&23			;else, is it ASCII '#'?
A5BB F0 05     BEQ R5C2			;if it is, exit
A5BD 20 C3 A5  JSR R5C3			;else, convert lower case to upper case
A5C0 C5 B8     CMP &B8			;and compare w/temp (Z=match)
.R5C2
A5C2 60        RTS			;exit

.R5C3					; convert lower case to upper case
A5C3 C9 61     CMP #&61			;is it < ASCII 'a'?
A5C5 90 06     BCC R5CD			;if so, not lower case, exit
A5C7 C9 7B     CMP #&7B			;else, is it >=
A5C9 B0 02     BCS R5CD			;if so, not alpha, exit
A5CB 29 DF     AND #&DF			;else, convert to upper case
.R5CD
A5CD 60        RTS			;exit

.R5CE					;Check file not locked
A5CE 20 E4 A5  JSR R5E4			;Reads catalogue entry
A5D1 10 FA     BPL R5CD			;pointed to by &CC
A5D3 20 18 90  JSR Q018			;Print "File locked"
A5D6 EQUB &0A
A5D7 EQUB &C3
A5D8 EQUS "File locked"
A5E3 EQUB &00
.R5E4					;Reads catalogue entry
A5E4 20 00 92  JSR Q200			;Save AXY
.R5E7
A5E7 A6 CC     LDX &CC			;at catalogue pointer
A5E9 BD 0F 0E  LDA &0E0F,X
A5EC 60        RTS

A5ED EQUB &00				;garbage from page &9C
A5EE EQUW &00,&00			;shifted down one byte
A5F0 EQUD &00,&00,&00,&00
A5F4 EQUD &00,&00,&00,&00
A5F8 EQUD &00,&00,&00,&00
A5FC EQUD &00,&00,&00,&00


;Catalogue operations

.R600
A600 4C 21 A6  JMP R621			;Delete catalogue entry

.R603
A603 4C 44 A6  JMP R644			;Unpack fields from catalogue

.R606
A606 4C 93 A7  JMP R793			;Pack fields into catalogue

.R609
A609 4C 22 A7  JMP R722			;Create catalogue entry

.R60C
A60C 4C 07 A8  JMP R807			;Find a free space in volume

.R60F
A60F 4C 4C A8  JMP R84C			;Calculate absolute end of file

.R612
A612 4C 5E A6  JMP R65E			;Unpack cat fields from wkspace

.R615
A615 4C 62 A8  JMP R862			;Determine if room to extend

.R618
A618 4C E9 A6  JMP R6E9			;Check parms/create file

.R61B
A61B 4C 25 A8  JMP R825			;Get free space on volume

.R61E
A61E 4C 7B A8  JMP R87B			;Get ceiling over cat entry

.R621					;Delete catalogue entry
A621 20 00 92  JSR Q200			;Save AXY
A624 AD 05 0F  LDA &0F05		;pointed to by &CC
A627 38        SEC			;by moving valid entries
A628 E9 08     SBC #&08			;over it
A62A 8D 05 0F  STA &0F05
A62D A6 CC     LDX &CC			;X = Pointer to file entry in catalogue
.R62F
A62F EC 05 0F  CPX &0F05
A632 B0 0F     BCS R643
A634 BD 10 0E  LDA &0E10,X
A637 9D 08 0E  STA &0E08,X
A63A BD 10 0F  LDA &0F10,X
A63D 9D 08 0F  STA &0F08,X
A640 E8        INX
A641 D0 EC     BNE R62F
.R643
A643 60        RTS

.R644					;Unpack fields from catalogue
A644 20 00 92  JSR Q200			;Save AXY
A647 A6 CC     LDX &CC			;X = Pointer to file entry in catalogue
A649 20 09 92  JSR Q209			;Copy memory absolute indexed
A64C EQUW &08,&0E			;from catalogue entry
A64E EQUW &40,&10			;to wksp
A650 EQUW &08,&20
A652 20 09 92  JSR Q209			;Copy memory absolute indexed
A655 EQUW &08,&0F
A657 EQUW &48,&10
A659 EQUW &08,&20
A65B 4C 61 A6  JMP R661			;fall through:

.R65E					;Unpack cat fields from wkspace
A65E 20 00 92  JSR Q200			;Save AXY
.R661
A661 A2 07     LDX #&07
A663 A0 0A     LDY #&0A
A665 AD 06 0F  LDA &0F06		;Is volume >= 256 KB?
A668 29 04     AND #&04			;00000100;mask bits 0-1 and 3-7
A66A D0 1F     BNE R68B
A66C AD 4E 10  LDA &104E		;If not
A66F 48        PHA
A670 20 D6 A6  JSR R6D6			;copy start sector to &1051..52
A673 C8        INY
A674 68        PLA
A675 4A        LSR A			;push 00eelldd
A676 4A        LSR A
A677 48        PHA
A678 4A        LSR A			;push 0000eell
A679 4A        LSR A
A67A 48        PHA
A67B 20 D6 A6  JSR R6D6			;copy length to &104E..50
A67E 68        PLA
A67F 4A        LSR A
A680 4A        LSR A
A681 20 D6 A6  JSR R6D6			;copy exec to 104B..4D
A684 68        PLA
A685 20 D6 A6  JSR R6D6			;copy load to 1048..4A
A688 4C A7 A6  JMP R6A7			;chip up and exit

.R68B
A68B AD 4E 10  LDA &104E		;else same as above
A68E 48        PHA			;for volumes >=256 KB
A68F 20 D8 A6  JSR R6D8
A692 C8        INY
A693 68        PLA
A694 4A        LSR A
A695 4A        LSR A
A696 48        PHA
A697 4A        LSR A
A698 4A        LSR A
A699 48        PHA
A69A 20 D8 A6  JSR R6D8
A69D 68        PLA
A69E 4A        LSR A
A69F 4A        LSR A
A6A0 20 D0 A6  JSR R6D0
A6A3 68        PLA
A6A4 20 D0 A6  JSR R6D0
.R6A7					;Chip up catalogue fields
A6A7 18        CLC
A6A8 AD 51 10  LDA &1051		;add volume offset
A6AB 6D 38 10  ADC &1038		;to start sector to make
A6AE 8D 51 10  STA &1051		;absolute offset
A6B1 AD 52 10  LDA &1052		;store in &1051..52
A6B4 6D 39 10  ADC &1039
A6B7 8D 52 10  STA &1052
A6BA AD 4E 10  LDA &104E		;store number of sectors used
A6BD C9 01     CMP #&01			;in &1053..54
A6BF AD 4F 10  LDA &104F
A6C2 69 00     ADC #&00
A6C4 8D 53 10  STA &1053
A6C7 AD 50 10  LDA &1050
A6CA 69 00     ADC #&00
A6CC 8D 54 10  STA &1054
A6CF 60        RTS

.R6D0
A6D0 29 02     AND #&02			;Extend 17 bit to 18 bit - mask bits 0 and 2-7
A6D2 F0 02     BEQ R6D6			;catalogue field
A6D4 09 03     ORA #&03			;00000011
.R6D6
A6D6 29 03     AND #&03			;00000011 ;Unpack 18 bit field
.R6D8
A6D8 29 07     AND #&07			;00000111 ;Unpack 19 bit field
A6DA 20 E4 A6  JSR R6E4
A6DD 20 E0 A6  JSR R6E0
.R6E0
A6E0 BD 48 10  LDA &1048,X
A6E3 CA        DEX
.R6E4
A6E4 99 48 10  STA &1048,Y
A6E7 88        DEY
A6E8 60        RTS

.R6E9					;Check parms/create file
A6E9 20 00 9B  JSR QB00			;softmount and catalogue driv
A6EC 20 09 A5  JSR R509			;A=desired mode (OSFIND)
A6EF 90 0A     BCC R6FB			;read catalogue, find file
A6F1 C9 80     CMP #&80			;if not found, then:
A6F3 F0 1A     BEQ R70F			;if OPENOUT
A6F5 C9 A0     CMP #&A0			;or if called from OSFILE
A6F7 F0 16     BEQ R70F			;then create catalogue entry
A6F9 38        SEC			;else OPENIN/UP not found,
A6FA 60        RTS			;exit C=1.

.R6FB
A6FB C9 40     CMP #&40			;else file found. if OPENIN
A6FD F0 03     BEQ R702			;then don't check lock
A6FF 20 21 A5  JSR R521			;else check file not locked
.R702
A702 20 06 98  JSR Q806			;check file not open (mutex)
A705 20 03 A6  JSR R603			;unpack fields from catalogue
A708 C9 A0     CMP #&A0			;if not called from OSFILE
A70A D0 11     BNE R71D			;then monitor and exit C=0.
A70C 20 00 A6  JSR R600			;else delete catalogue entry
.R70F
A70F 20 06 92  JSR Q206			;Copy memory absolute
A712 EQUW &C0,&00			;from immediate dir+filename at &00C0
A714 EQUW &58,&10			;to catalogue block 2 at &1058
A716 EQUB &08				;8-bytes
A717 20 09 A6  JSR R609			;create catalogue entry
A71A 20 03 9B  JSR QB03			;write catalogue
.R71D
A71D 20 1B B7  JSR &B71B		;call file access monitor
A720 18        CLC			;and
A721 60        RTS			;exit C=0.

.R722					;Create catalogue entry
A722 20 00 92  JSR Q200			;Save AXY
A725 AD 05 0F  LDA &0F05		;get number of files
A728 C9 F8     CMP #&F8			;11111000, if =31
A72A 90 13     BCC R73F			;then give volume error
A72C 20 21 98  JSR Q821			;Print disc/volume error message
A72F EQUB &BE
A730 EQUS "catalogue full"
A73E EQUB &00
.R73F
A73F 20 0A A8  JSR R80A			;else find a free space in vol
A742 90 31     BCC R775			;if C=0 then success, do insert
A744 20 1B A6  JSR R61B			;else get amount of free space on volume
A747 AD 60 10  LDA &1060		;16 bit compare:
A74A CD 6B 10  CMP &106B		;free space - desired allocation
A74D D0 06     BNE R755
A74F AD 61 10  LDA &1061
A752 CD 6C 10  CMP &106C
.R755
A755 90 15     BCC R76C			;if <0 then print disc/volume error message
A757 20 21 98  JSR Q821			;else, print "need compacting" error message
A75A EQUB &C6
A75B EQUS "needs compacting"
A76B EQUB &00
.R76C
A76C 20 21 98  JSR Q821			;Print disc/volume error message
A76F EQUB &C6
A770 EQUS "full"
A774 EQUB &00
.R775					;Do insert at slot &CC points to
A775 AD 05 0F  LDA &0F05		;LDA &0F05 get file pointer
A778 AA        TAX			;copy to X (assert X<=&F0)
A779 18        CLC			;add 8 to pointer
A77A 69 08     ADC #&08 		;(assert 0<=?&CC<=&F0)
A77C 8D 05 0F  STA &0F05		;and store back in catalogue.
.R77F
A77F E4 CC     CPX &CC			;if catalogue slot at ?&CC free
A781 F0 13     BEQ R796			;then pack it (assert X>=?&CC)
A783 CA        DEX			;else bubble entries
A784 BD 08 0E  LDA &0E08		;into the next slot up
A787 9D 10 0E  STA &0E10		;going from end to start
A78A BD 08 0F  LDA &0F08		;and
A78D 9D 10 0F  STA &0F10
A790 4C 7F A7  JMP R77F			;loop back to the test.

.R793					;Pack fields into catalogue
A793 20 00 92  JSR Q200			;Save AXY
.R796
A796 A6 CC     LDX &CC			;as pointed to by &CC
A798 20 09 92  JSR Q209			;copy name and directory
A79B EQUW &40,&10
A79D EQUW &08,&0E
A79F EQUW &08,&02
A7A1 A0 00     LDY #&00
A7A3 20 D2 A7  JSR R7D2			;copy low bytes load address
A7A6 20 D2 A7  JSR R7D2			;copy low bytes exec address
A7A9 0A        ASL A			;A = %00ee0000 or %00e00000
A7AA 0A        ASL A
A7AB 0A        ASL A
A7AC 0A        ASL A
A7AD 05 B8     ORA &B8			;A = %00ee00dd or %00e000d0
A7AF 0A        ASL A			;A = %ee00dd00 or %e000d000
A7B0 0A        ASL A
A7B1 20 EC A7  JSR R7EC			;copy low bytes length
A7B4 0A        ASL A			;A = %00ll0000 or %0lll0000
A7B5 0A        ASL A
A7B6 0A        ASL A
A7B7 0A        ASL A
A7B8 05 B8     ORA &B8			;A = %eelldd00 or %ellld000
A7BA 85 B8     STA &B8			;save A
A7BC 38        SEC
A7BD AD 51 10  LDA &1051		;subtract absolute start sector
A7C0 ED 38 10  SBC &1038		;from start of volume
A7C3 9D 09 0F  STA &0F09,X		;store relative start sector
A7C6 AD 52 10  LDA &1052		;calculate high bits
A7C9 ED 39 10  SBC &1039		;A = %000000ss or %00000sss
A7CC 05 B8     ORA &B8			;A = %eellddss or %ellldsss
A7CE 9D 08 0F  STA &0F08,X		;store packed byte
A7D1 60        RTS

.R7D2
A7D2 20 EC A7  JSR R7EC			;Save A in temp, copy 2 bytes
A7D5 29 03     AND #&03			;00000011	;of address,
A7D7 48        PHA			;return high 2 bits of source
A7D8 AD 06 0F  LDA &0F06		;(if both set and disc >=256K,
A7DB 29 04     AND #&04			;00000100	;returns binary 2
A7DD D0 02     BNE R7E1			;to accommodate 19 bit addrs)
A7DF 68        PLA
A7E0 60        RTS

.R7E1
A7E1 68        PLA
A7E2 C9 03     CMP #&03
A7E4 D0 03     BNE R7E9
A7E6 A9 02     LDA #&02
A7E8 60        RTS

.R7E9
A7E9 A9 00     LDA #&00
A7EB 60        RTS

.R7EC
A7EC 85 B8     STA &B8			;Save A in temp, copy 2 bytes,
A7EE 20 FA A7  JSR R7FA			;load third from fields,
A7F1 20 FA A7  JSR R7FA			;return low 3 bits
A7F4 20 02 A8  JSR R802
A7F7 29 07     AND #&07			;00000111
A7F9 60        RTS

.R7FA
A7FA 20 02 A8  JSR R802			;Copy byte from fields to high
A7FD 9D 08 0F  STA &0F08,X		;catalogue, increment X and Y
A800 E8        INX
A801 60        RTS

.R802					;Get byte from fields
A802 B9 48 10  LDA &1048,Y
A805 C8        INY			;increment Y
A806 60        RTS

.R807					;Find a free space in volume
A807 20 00 92  JSR Q200			;Save AXY
.R80A
A80A 20 95 A8  JSR R895			;initialise for zeroth file
.R80D
A80D 20 06 92  JSR Q206			;Copy memory absolute
A810 EQUW &58,&10			;from catalogue block 2 at &1058
A812 EQUW &40,&10			;to catalogue block 1 at &1040
A814 EQUB &18				;(block 2 contains prospective file)
A815 20 0F A6  JSR R60F			;Calculate absolute end of file
A818 20 68 A8  JSR R868			;determine if room to extend
A81B B0 06     BCS R823			;if so exit C=0
A81D 20 B3 A8  JSR R8B3			;else unpack next file in cat
A820 90 EB     BCC R80D			;if more files then loop
A822 60        RTS			;else exit C=1.

.R823
A823 18        CLC
A824 60        RTS

.R825					;Get free space on volume
A825 20 00 92  JSR Q200			;Save AXY
A828 A9 00     LDA #&00			;set accumulator = 0
A82A 8D 60 10  STA &1060
A82D 8D 61 10  STA &1061
A830 20 95 A8  JSR R895			;initialise for zeroth file
.R833
A833 20 68 A8  JSR R868			;get free space *before* file
A836 90 13     BCC R84B			;if overlap then exit
A838 18        CLC
A839 6D 60 10  ADC &1060		;else add AX to accumulator
A83C 8D 60 10  STA &1060
A83F 8A        TXA
A840 6D 61 10  ADC &1061
A843 8D 61 10  STA &1061
A846 20 B3 A8  JSR R8B3			;select next file in catalogue
A849 90 E8     BCC R833			;inc.imaginary end of volume file
.R84B
A84B 60        RTS			;and loop until no more files.

.R84C					;Calculate absolute end of file
A84C 48        PHA			;(last used sector +1)
A84D 18        CLC
A84E AD 53 10  LDA &1053
A851 6D 51 10  ADC &1051
A854 8D 69 10  STA &1069
A857 AD 54 10  LDA &1054
A85A 6D 52 10  ADC &1052
A85D 8D 6A 10  STA &106A
A860 68        PLA
A861 60        RTS

.R862					;Determine if room to extend
A862 20 00 92  JSR Q200			;Save AXY
A865 20 0F A6  JSR R60F			;calculate absolute last sec+1
.R868
A868 20 1E A6  JSR R61E			;get ceiling over file
A86B 38        SEC			;subtract absolute end of file
A86C ED 69 10  SBC &1069
A86F 48        PHA
A870 8A        TXA
A871 ED 6A 10  SBC &106A
A874 AA        TAX
A875 68        PLA
A876 D0 02     BNE R87A
A878 E8        INX			;return in AX
A879 CA        DEX			;Z=no free sectors
.R87A
A87A 60        RTS

.R87B					;Get ceiling over catalogue entry
A87B A6 CC     LDX &CC
A87D 18        CLC			;end of free space above
A87E BD 07 0F  LDA &0F07,X		;catalogue entry &CC->
A881 6D 38 10  ADC &1038		;(ie absolute start sector of
A884 48        PHA			;next file, or if &CC=0,
A885 AD 06 0F  LDA &0F06		;absolute start sector of
A888 29 04     AND #&04			;00000100;next volume /end of disc)
A88A 09 03     ORA #&03			;00000011;Return in A (low byte) and X
A88C 3D 06 0F  AND &0F06,X		;(high byte)
A88F 6D 39 10  ADC &1039
A892 AA        TAX
A893 68        PLA
A894 60        RTS

.R895
A895 48        PHA			;Initialise for zeroth file
A896 AD 38 10  LDA &1038		;copy offset to start of volume
A899 8D 69 10  STA &1069		;to absolute end of file
A89C AD 39 10  LDA &1039		;representing end of imaginary
A89F 8D 6A 10  STA &106A		;zero the file
A8A2 0D 38 10  ORA &1038		;if offset = 0
A8A5 D0 05     BNE R8AC
A8A7 A9 02     LDA #&02			;then set offset = 2
A8A9 8D 69 10  STA &1069
.R8AC
A8AC AD 05 0F  LDA &0F05		;set catalogue pointer
A8AF 85 CC     STA &CC			;to number of entries in cat.
A8B1 68        PLA
A8B2 60        RTS

.R8B3
A8B3 20 06 A5  JSR R506			;select next file in catalogue
A8B6 B0 06     BCS R8BE			;if no more files exit
A8B8 20 03 A6  JSR R603			;else unpack fields from cat
A8BB 20 0F A6  JSR R60F			;calculate absolute end of file
.R8BE
A8BE 60        RTS			;exit


;'Heavy' DFS commands
.R000
A900 4C 09 A9  JMP R909			;*FORMAT

.R903
A903 4C C9 AB  JMP RBC9			;*CATGEN

.R906
A906 4C 8E AB  JMP RB8E			;*VERIFY

.R909					;*FORMAT
A909 A9 FF     LDA #&FF
A90B 8D 70 10  STA &1070		;set &1070..75 = &FF
A90E 20 06 92  JSR Q206			;Copy memory absolute
A911 EQUW &70,&10			;FROM address &1070
A913 EQUW &71,&10			;TO address &1071
A915 EQUB &05				;5-bytes
A916 20 04 AE  JSR RE04			;set default drive
.R919
A919 20 18 93  JSR Q318			;get optional drive spec
A91C 90 03     BCC R921			;if no more arguments
A91E 4C 9C A9  JMP R99C			;then proceed with format, else test first nonspace char

.R921
A921 C9 34     CMP #&34			;Is it "4"?
A923 D0 21     BNE R946			;if not try others
A925 A9 28     LDA #&28			;else set no. tracks = 40
A927 8D 71 10  STA &1071
A92A 20 88 A9  JSR R988			;do GSREAD, syntax error if EOW
A92D C9 30     CMP #&30			;is next character "0"?
A92F D0 54     BNE R985			;syntax error if not
A931 20 C5 FF  JSR gsread		;call GSREAD
A934 B0 E3     BCS R919			;if end of arg, scan for another
A936 8D 72 10  STA &1072		;else store char
A939 C9 2D     CMP #&2D			;is it "-"?
A93B D0 48     BNE R985			;syntax error if not
A93D 20 88 A9  JSR R988			;else GSREAD, syntax err if EOW
A940 C9 38     CMP #&38			;is character "8"?
A942 D0 41     BNE R985			;syntax error if not
A944 F0 09     BEQ R94F			;else ensure "0" follows.
.R946
A946 C9 38     CMP #&38			;does argument begin "8"?
A948 D0 0F     BNE R959			;if not try other characters
A94A A9 50     LDA #&50			;else set no. tracks = 80
A94C 8D 71 10  STA &1071
.R94F
A94F 20 88 A9  JSR R988			;do GSREAD, syntax error if EOW
A952 C9 30     CMP #&30			;is character "0"?
A954 D0 2F     BNE R985			;syntax error if not
A956 4C 7D A9  JMP R97D			;else skip " ", scan next arg.

.R959
A959 29 5F     AND #&5F			;convert lowercase to uppercase
A95B C9 53     CMP #&53			;is it ASCII 'S'?
A95D D0 08     BNE R967			;if not try "D" or "O"
A95F A9 0A     LDA #&0A			;else
A961 8D 70 10  STA &1070		;set density = single
A964 4C 7D A9  JMP R97D			;skip space, scan next arg.

.R967
A967 C9 44     CMP #&44			;is it ASCII 'D'?
A969 D0 08     BNE R973			;if not try "O"
A96B A9 12     LDA #&12			;else
A96D 8D 70 10  STA &1070		;set density = double
A970 4C 7D A9  JMP R97D			;skip space, scan next arg.

.R973
A973 C9 4F     CMP #&4F			;is it ASCII 'O'?
A975 D0 0E     BNE R985			;syntax error if not
A977 20 8E A9  JSR R98E			;else get outstep value
A97A 8D 74 10  STA &1074		;and save it
.R97D
A97D 20 C5 FF  JSR gsread		;call GSREAD to skip space
A980 90 03     BCC R985			;syntax error if another char
A982 4C 19 A9  JMP R919			;else scan next argument.

.R985
A985 4C 09 81  JMP P109			;print syntax and quit

.R988
A988 20 C5 FF  JSR gsread		;call GSREAD
A98B B0 F8     BCS R985			;syntax error if end of word
A98D 60        RTS			;else return.
.R98E
A98E 20 88 A9  JSR R988			;do GSREAD, syntax error if EOW
A991 C9 30     CMP #&30			;is character less than "0"?
A993 90 F0     BCC R985			;syntax error if so
A995 C9 39     CMP #&39			;is character "9" or greater?
A997 B0 EC     BCS R985			;syntax error if so
A999 29 0F     AND #&0F			;else mask bits 0-3
A99B 60        RTS			;return value 0..9.

.R99C
A99C 20 09 90  JSR Q009			;print newline
A99F 20 70 AE  JSR RE70			;print "Formatting "
A9A2 20 93 AE  JSR RE93			;print "drive n"
A9A5 AD 70 10  LDA &1070		;if density given on cmd line
A9A8 10 0C     BPL R9B6			;then use that density
A9AA AD 84 10  LDA &1084		;else get *OPT 6 density
A9AD D0 07     BNE R9B6			;if manual, use that setting
A9AF BD F0 0F  LDA &0FF0,X		;else use density of curr drive
A9B2 D0 02     BNE R9B6			;if no disc has been used in it
A9B4 A9 12     LDA #&12			;then default density = double!
.R9B6
A9B6 8D 70 10  STA &1070		;set density
A9B9 0A        ASL A
A9BA 0A        ASL A			;multiply by 4
A9BB 8D 76 10  STA &1076		;= number of CHRN bytes
A9BE 2C 76 10  BIT &1076		;if fewer than 16 sectors
A9C1 70 0D     BVS R9D0
A9C3 20 18 90  JSR Q018			;then print " Sing"
A9C6 EQUB &00
A9C7 EQUS " Sing"
A9CC EQUB &00
A9CD 4C DA A9  JMP R9DA

.R9D0
A9D0 20 18 90  JSR Q018			;else print " Doub"
A9D3 EQUB &00
A9D4 EQUS " Doub"
A9D9 EQUB &00
.R9DA
A9DA 20 18 90  JSR Q018			;print "le Density"+newline
A9DD EQUB &02
A9DE EQUS "le Density"
A9E8 EQUB &00
A9E9 AD 71 10  LDA &1071		;if no. tracks given
A9EC 10 07     BPL R9F5			;then validate that number
A9EE BD F4 0F  LDA &0FF4,X		;else get tracks on curr drive
A9F1 D0 02     BNE R9F5			;if no disc has been used in it
A9F3 A9 50     LDA #&50			;then default tracks = 80!
.R9F5
A9F5 C9 50     CMP #&50			;allow 80 tracks maximum
A9F7 90 02     BCC R9FB			;(can save 2 bytes here)
A9F9 A9 50     LDA #&50			;set number of tracks
.R9FB
A9FB 8D 71 10  STA &1071
A9FE 20 18 90  JSR Q018			;print " Tracks = "+n
AA01 EQUB &80
AA02 EQUS " Tracks = "
AA0C EQUB &00
AA0D AD 72 10  LDA &1072		;if 40-80 mode specified
AA10 10 0C     BPL RA1E			;then set 2:1 stepping
AA12 A9 00     LDA #&00			;else default to 1:1
AA14 AC 71 10  LDY &1071		;check number of tracks = 40
AA17 C0 28     CPY #&28
AA19 D0 03     BNE RA1E			;if not then keep 1:1 stepping
AA1B AD 86 10  LDA &1086		;else use *OPT 8 tracks setting
.RA1E
AA1E 8D 72 10  STA &1072		;save stepping parameter
AA21 A8        TAY
AA22 F0 08     BEQ RA2C			;if not 1:1 stepping
AA24 20 18 90  JSR Q018			;then print "-80".
AA27 EQUB &00
AA28 EQUS "-80"
AA2B EQUB &00
.RA2C
AA2C 20 09 90  JSR Q009			;print newline
AA2F AD 85 10  LDA &1085		;get *OPT 7 volumes
AA32 30 09     BMI RA3D			;if cheeseburger, volumes = 0
AA34 D0 09     BNE RA3F			;if manual, use that setting
AA36 A9 08     LDA #&08			;else volumes = 8 in double den
AA38 2C 76 10  BIT &1076		;test bit 6
AA3B 70 02     BVS RA3F			;if double density, branch
.RA3D
AA3D A9 00     LDA #&00			;else, volumes = 0.
.RA3F
AA3F 8D 73 10  STA &1073		;set number of volumes
AA42 2C 76 10  BIT &1076		;if it is not the default
AA45 70 06     BVS RA4D			;for that density, branch
AA47 C9 00     CMP #&00			;else,
AA49 F0 16     BEQ RA61			;if zero, branch
AA4B D0 04     BNE RA51			;else if <> zero, print " Volumes = "+n+nl
.RA4D
AA4D C9 08     CMP #&08			;is volumes = 8 in double den?
AA4F F0 10     BEQ RA61			;if it is,
.RA51
AA51 20 18 90  JSR Q018			;then print " Volumes = "+n+nl
AA54 EQUB &82
AA55 EQUS " Volumes = "
AA60 EQUB &00
.RA61
AA61 AD 74 10  LDA &1074		;if outstep specified
AA64 10 0F     BPL RA75			;then print its value
AA66 A9 05     LDA #&05			;else outstep = 5 in dbl dens
AA68 2C 76 10  BIT &1076		;if single density
AA6B 70 02     BVS RA6F
AA6D A9 03     LDA #&03			;then outstep = 3.
.RA6F
AA6F 8D 74 10  STA &1074		;set default outstep
AA72 4C 85 AA  JMP RA85			;and skip printing it.

.RA75
AA75 20 18 90  JSR Q018			;print " Outstep = "+n+nl
AA78 EQUB &82
AA79 EQUS " Outstep = "
AA84 EQUB &00
.RA85
AA85 AD 70 10  LDA &1070		;calculate density - outstep
AA88 38        SEC			;to obtain logical outstep.
AA89 ED 74 10  SBC &1074		;sector nos on the next track
AA8C 8D 74 10  STA &1074		;are higher by this amount.
AA8F 8A        TXA			;put drive number in A
AA90 20 0C 8A  JSR PA0C			;and confirm overwrite
AA93 B0 02     BCS RA97			;if refused
AA95 38        SEC
AA96 60        RTS			;exit C=1, else:

.RA97					;Do *FORMAT
AA97 AD 70 10  LDA &1070
AA9A 9D F0 0F  STA &0FF0,X		;Configure target drive
AA9D AD 71 10  LDA &1071
AAA0 9D F4 0F  STA &0FF4,X
AAA3 AD 72 10  LDA &1072
AAA6 9D F8 0F  STA &0FF8,X
AAA9 AD 73 10  LDA &1073
AAAC 9D FC 0F  STA &0FFC,X
AAAF A9 00     LDA #&00			;Point O7F block to CHRN table
AAB1 38        SEC			;at end of page &0E
AAB2 ED 76 10  SBC &1076		;and set a pointer to fill it
AAB5 85 A8     STA &A8
AAB7 8D 11 10  STA &1011
AABA A9 0F     LDA #&0F
AABC E9 00     SBC #&00
AABE 85 A9     STA &A9
AAC0 8D 12 10  STA &1012
AAC3 A9 FF     LDA #&FF
AAC5 8D 13 10  STA &1013
AAC8 8D 14 10  STA &1014
AACB A9 00     LDA #&00
AACD 8D 17 10  STA &1017		;Track no. = 0
AAD0 8D 77 10  STA &1077		;Sector no. = 0
AAD3 8D 1A 10  STA &101A		;Gap 5 size = 0 (mini floppy)
AAD6 A9 05     LDA #&05			;5 parameters
AAD8 8D 15 10  STA &1015
AADB A9 23     LDA #&23			;&23 = 8271 Format command
AADD 8D 16 10  STA &1016
AAE0 AD 70 10  LDA &1070		;No. sectors to format = spt
AAE3 09 20     ORA #&20			;00100000, 256 byte sectors
AAE5 8D 19 10  STA &1019
AAE8 A9 12     LDA #&12			;set gap1 and gap3 sizes
AAEA 8D 18 10  STA &1018		;according to density
AAED 8D 1B 10  STA &101B
AAF0 2C 76 10  BIT &1076		;test bit
AAF3 50 0A     BVC RAFF
AAF5 A9 1B     LDA #&1B			;Read ID
AAF7 8D 18 10  STA &1018
AAFA A9 24     LDA #&24			;Write track
AAFC 8D 1B 10  STA &101B
.RAFF
AAFF 20 09 90  JSR Q009
.RB02
AB02 20 70 AE  JSR RE70			;print "Formatting "
AB05 20 A2 AE  JSR REA2			;print "track n"
AB08 AE 70 10  LDX &1070		;fill out CHRN block:
AB0B A0 00     LDY #&00
.RB0D
AB0D AD 17 10  LDA &1017		;set cylinder (track)
AB10 91 A8     STA (&A8),Y
AB12 C8        INY
AB13 AD 10 10  LDA &1010		;A = OSWORD &7F block, bit 1 = SS
AB16 29 02     AND #&02			;00000010 = mask bits 0 and 2-7, bit 1 = head
AB18 4A        LSR A
AB19 91 A8     STA (&A8),Y
AB1B C8        INY
AB1C AD 77 10  LDA &1077		;set record (sector)
AB1F 91 A8     STA (&A8),Y
AB21 C8        INY
AB22 A9 01     LDA #&01			;set record length = 256 bytes
AB24 91 A8     STA (&A8),Y
AB26 C8        INY
AB27 20 F6 AD  JSR RDF6			;add 1 to sector iter, mod spt.
AB2A CA        DEX			;loop until all sectors done
AB2B D0 E0     BNE RB0D
AB2D 20 0F 9B  JSR QB0F			;call OSWORD &7F, report errors
AB30 AD 74 10  LDA &1074		;get track skew
AB33 20 F6 AD  JSR RDF6			;add to sector iterator
AB36 EE 17 10  INC &1017		;increment track number
AB39 AD 17 10  LDA &1017		;have we formatted all tracks?
AB3C CD 71 10  CMP &1071
AB3F D0 C1     BNE RB02			;loop until all tracks done
AB41 20 70 AE  JSR RE70			;print "Formatting "
AB44 20 18 90  JSR Q018			;print "catalog "
AB47 EQUB &02
AB48 EQUS "catalog "
AB50 EQUB &00
AB51 AD 73 10  LDA &1073		;get no. volumes
AB54 D0 0C     BNE RB62			;if =0
AB56 AD 71 10  LDA &1071		;then get tracks on disc
AB59 8D 78 10  STA &1078		;set as tracks in volume
AB5C 20 18 AE  JSR RE18			;create volume catalogues
AB5F 4C 85 AB  JMP RB85			;then go to verify

.RB62
AB62 20 F0 AE  JSR REF0			;set size of volume A
AB65 90 05     BCC RB6C			;if more than one volume
AB67 A9 21     LDA #&21			;then set volume B = 33 tracks
AB69 8D 79 10  STA &1079
.RB6C
AB6C AD 71 10  LDA &1071
AB6F C9 50     CMP #&50			;is it an 80 track disc?
AB71 F0 06     BEQ RB79			;if not
AB73 4E 78 10  LSR &1078		;then
AB76 4E 79 10  LSR &1079		;halve those two values.
.RB79
AB79 20 91 AC  JSR RC91			;validate volume allocation
AB7C 20 03 AD  JSR RD03			;adjust volumes to fill disc
AB7F 20 4E AC  JSR RC4E			;create volume and disc cats
AB82 20 09 90  JSR Q009			;print newline
.RB85
AB85 20 70 AE  JSR RE70			;print "Formatting "
AB88 20 B1 AE  JSR REB1			;print "complete"
AB8B 4C 99 AB  JMP RB99			;verify disc and exit

.RB8E					;*VERIFY.
AB8E 20 04 AE  JSR RE04			;set default drive
AB91 20 18 93  JSR Q318			;parse arguments
AB94 B0 03     BCS RB99			;if incorrectly formed
AB96 4C 09 81  JMP P109			;print syntax and quit.

.RB99
AB99 20 09 90  JSR Q009			;else print newline
AB9C 20 82 AE  JSR RE82			;print "Verifying "
AB9F 20 93 AE  JSR RE93			;Print "drive n"
ABA2 20 0C 9B  JSR QB0C			;Softmount disc
.RBA5
ABA5 20 53 AE  JSR RE53			;verify track
ABA8 24 FF     BIT &FF			;test Escape flag
ABAA 10 0C     BPL RBB8			;if clear then continue
ABAC 20 18 90  JSR Q018			;else "Escape" error
ABAF EQUB &0A				;<LF>
ABB0 EQUB &11
ABB1 EQUS "Escape"
ABB7 EQUB &00
.RBB8
ABB8 EE 17 10  INC &1017		;increment track number
ABBB AD 17 10  LDA &1017		;fetch it
ABBE DD F4 0F  CMP &0FF4,X		;compare with tracks on disc
ABC1 D0 E2     BNE RBA5			;loop until all tracks done.
ABC3 20 82 AE  JSR RE82			;Print "Verifying "
ABC6 4C B1 AE  JMP REB1			;Print "complete"

.RBC9					;*CATGEN
ABC9 8E 72 10  STX &1072		;do some initialisation
ABCC 20 04 AE  JSR RE04			;get multiple drive spec/set default drive
.RBCF
ABCF 20 18 93  JSR Q318			;if absent proceed with catgen
ABD2 B0 27     BCS RBFB			;else get volume letter
ABD4 20 1B 93  JSR Q31B			;X=6, check volume letter, put it in A
ABD7 A5 C8     LDA &C8			;volume letter -> Immediate volume
ABD9 29 0F     AND #&0F			;00001111, convert to binary 1..8
ABDB AA        TAX
ABDC CA        DEX			;subtract 1
ABDD A9 00     LDA #&00			;clear this vol's track count
ABDF 9D 78 10  STA &1078,X		;store
.RBE2
ABE2 20 C5 FF  JSR gsread		;call GSREAD
ABE5 B0 E8     BCS RBCF			;if EOW scan next argument
ABE7 C9 30     CMP #&30			;else is character "0"?
ABE9 90 0A     BCC RBF5			;syntax error if less
ABEB C9 3A     CMP #&3A			;is it more than "9"?
ABED B0 06     BCS RBF5			;syntax error if more.
ABEF 20 EF AC  JSR RCEF			;add digit to track count
ABF2 4C E2 AB  JMP RBE2			;loop to process more digits

.RBF5
ABF5 AE 72 10  LDX &1072		;restore command table pointer
ABF8 4C 09 81  JMP P109			;print syntax and quit

.RBFB
ABFB 20 0C 9B  JSR QB0C			;Softmount disc
ABFE A6 C9     LDX &C9			;X = current drive
AC00 8A        TXA			;X -> A = current drive
AC01 20 18 90  JSR Q018			;print "Drive "+n
AC04 EQUB &C0
AC05 EQUS "Drive "
AC0B EQUB &00
AC0C BD FC 0F  LDA &0FFC,X		;get no. volumes on drive
AC0F 8D 73 10  STA &1073		;store in temp
AC12 D0 1B     BNE RC2F			;if =0
AC14 20 18 90  JSR Q018			;then print ": single volume disc"+nl
AC17 EQUB &02
AC18 EQUS ": single volume disc"
AC2C EQUB &00
AC2D 38        SEC
AC2E 60        RTS			;and exit C=1

.RC2F
AC2F 20 91 AC  JSR RC91			;else validate vol allocation
AC32 AD 81 10  LDA &1081		;get total number of tracks
AC35 D0 0D     BNE RC44			;if =0, then user wants a volume cat
AC37 20 06 92  JSR Q206			;Copy memory absolute
AC3A EQUB &30,&10			;FROM actual vol allocations at &1030
AC3C EQUB &78,&10			;TO command line workspace at &1078
AC3E EQUB &08				;count
AC3F 20 4A AD  JSR RD4A			;Print *CATGEN heading
AC42 38        SEC
AC43 60        RTS			;and exit C=1

.RC44
AC44 20 03 AD  JSR RD03			;else adjust volumes to fill
AC47 A5 C9     LDA &C9			;A = current drive
AC49 20 0C 8A  JSR PA0C			;Ask user for confirmation
AC4C 90 41     BCC RC8F			;if refused exit C=1, else:
.RC4E
AC4E 20 18 AE  JSR RE18			;Create volume and disc catalogues
AC51 A9 00     LDA #&00			;create volume catalogues
AC53 AC 70 10  LDY &1070		;get density (=sec/trk)
AC56 8C 03 0E  STY &0E03		;store in disc catalogue
.RC59
AC59 18        CLC
AC5A 6D 71 10  ADC &1071		;add number of tracks
AC5D 90 03     BCC RC62			;carry out to disc cat
AC5F EE 01 0E  INC &0E01
.RC62
AC62 88        DEY			;decrement sectors
AC63 D0 F4     BNE RC59			;and loop while more to go.
AC65 20 E7 AE  JSR REE7			;store no. of sectors on disc
AC68 AD 71 10  LDA &1071		;get number of tracks
AC6B 8D 04 0E  STA &0E04		;store in disc catalogue
AC6E A9 01     LDA #&01			;start volumes on track 1
AC70 A2 00     LDX #&00			;clear X and Y offsets
AC72 A0 00     LDY #&00			;to start at first volume:
.RC74
AC74 99 08 0E  STA &0E08,Y		;store start track number
AC77 18        CLC
AC78 7D 78 10  ADC &1078,X		;add no. tracks in volume
AC7B 48        PHA
AC7C BD 78 10  LDA &1078,X
AC7F D0 03     BNE RC84			;if volume is absent
AC81 99 08 0E  STA &0E08,Y		;then delete start track no.
.RC84
AC84 68        PLA
AC85 C8        INY
AC86 C8        INY			;increase disc cat offset by 2
AC87 E8        INX			;increment volume cat offset
AC88 E0 08     CPX #&08
AC8A D0 E8     BNE RC74			;and loop for all 8 volumes.
AC8C 20 03 9B  JSR QB03			;write disc catalogue
.RC8F
AC8F 38        SEC
AC90 60        RTS			;and exit C=1.

.RC91
AC91 20 00 92  JSR Q200			;Save AXY
AC94 A6 C9     LDX &C9			;X = current drive
AC96 BD F4 0F  LDA &0FF4,X		;get no. tracks on this drive
AC99 8D 71 10  STA &1071		;store in cmd line parameter
AC9C 8D 80 10  STA &1080		;and in temp
AC9F BC F0 0F  LDY &0FF0,X		;get density of this drive
ACA2 8C 70 10  STY &1070		;store in cmd line parameter
ACA5 A2 00     LDX #&00			;clear total number of tracks
ACA7 8E 81 10  STX &1081		;X = volume offset = 0 (A)
.RCAA
ACAA BD 78 10  LDA &1078,X		;get no. tracks in this volume
ACAD F0 17     BEQ RCC6			;if nonexistent vol then skip
ACAF EC 73 10  CPX &1073		;else if >= no.volumes
ACB2 B0 18     BCS RCCC			;error "vol nn unavailable"
ACB4 CD 80 10  CMP &1080		;else if >= tracks on disc
ACB7 B0 23     BCS RCDC			;error "vol nn spec too large"
ACB9 6D 81 10  ADC &1081		;else add to total tracks
ACBC B0 72     BCS RD30			;if >255
ACBE CD 71 10  CMP &1071		;or if >= tracks on disc
ACC1 B0 6D     BCS RD30			;error "total tracks too many"
ACC3 8D 81 10  STA &1081		 else store new total.
.RCC6
ACC6 E8        INX			;increment volume pointer
ACC7 E0 08     CPX #&08			;and loop for all 8 volumes
ACC9 D0 DF     BNE RCAA
ACCB 60        RTS			;then exit

.RCCC
ACCC 20 21 98  JSR Q821			;Print disc/volume error message
ACCF EQUB &D2
ACD0 EQUS "unavailable"
ACDB EQUB &00
.RCDC
ACDC 20 21 98  JSR Q821			;Print disc/volume error message
ACDF EQUB &D2
ACE0 EQUS "spec too large"
ACEE EQUB &00
.RCEF					;Add digit to track count
ACEF 20 00 92  JSR Q200			;Save AXY
ACF2 29 0F     AND #&0F			;convert ASCII num to binary
ACF4 A0 0A     LDY #&0A			;set counter = 10
ACF6 18        CLC			;add former units digit
.RCF7
ACF7 7D 78 10  ADC &1078,X		;give error if carry out
ACFA B0 E0     BCS RCDC			;else loop to multiply x10.
ACFC 88        DEY
ACFD D0 F8     BNE RCF7
ACFF 9D 78 10  STA &1078,X		;store tens plus new unit.
AD02 60        RTS

.RD03					;Adjust volumes to fill disc
AD03 20 00 92  JSR Q200			;Save AXY
AD06 AD 71 10  LDA &1071		;get no. tracks on disc
AD09 18        CLC			;clear carry
AD0A ED 81 10  SBC &1081		;sub (tracks in volumes + 1)
AD0D F0 3E     BEQ RD4D			;if zero result go and print
AD0F AE 73 10  LDX &1073		;else get no. volumes
.RD12
AD12 18        CLC			;clear carry
AD13 7D 77 10  ADC &1077,X		;add track slack to last vol
AD16 9D 77 10  STA &1077,X		;and store
AD19 CD 80 10  CMP &1080		;compare new size - disc size
AD1C 90 2F     BCC RD4D			;if <0 go and print
AD1E 48        PHA			;else volume overflows.
AD1F AD 80 10  LDA &1080		;get total tracks
AD22 38        SEC			;set carry
AD23 E9 01     SBC #&01			;reduce by 1
AD25 9D 77 10  STA &1077,X		;store as volume size
AD28 68        PLA			;restore calculated size
AD29 38        SEC			;subtract (total - 1)
AD2A FD 77 10  SBC &1077,X		;= slack remaining
AD2D CA        DEX			;try again with next volume
AD2E D0 E2     BNE RD12			;if no more volumes then:
.RD30
AD30 20 21 98  JSR Q821			;Print disc/volume error message
AD33 EQUB &D2
AD34 EQUS "total tracks too many"
AD49 EQUB &00
.RD4D					;Print *CATGEN heading
AD4A 20 00 92  JSR Q200			;Save AXY;
AD4D 20 18 90  JSR Q018			;print heading on its own line ....
AD50 EQUB &03
AD51 EQUS "Volume  Tracks  Sectors  K bytes"
AD71 EQUB &00
AD72 A9 01     LDA #&01			;A=1, cats take one track
AD74 20 18 90  JSR Q018			;print nl+" Cat"
AD77 EQUB &01
AD78 EQUS " Cat"
AD7C EQUB &00
AD7D 20 9B AD  JSR RD9B			;print volume listing line
AD80 A0 41     LDY #&41			;Y="A"
.RD82
AD82 B9 37 10  LDA &1037,Y		;get size from 1078..F
AD85 F0 0E     BEQ RD95			;if =0 then skip volume
AD87 48        PHA			;else save no. tracks
AD88 98        TYA			;A=volume letter
AD89 20 18 90  JSR Q018			;print 3 spaces + letter
AD8C EQUB &C0
AD8D EQUS "   "
AD90 EQUB &00
AD91 68        PLA			;restore no. tracks
AD92 20 9B AD  JSR RD9B			;print volume listing line
.RD95
AD95 C8        INY			;increment volume letter
AD96 C0 49     CPY #&49			;have we gone past "H"?
AD98 D0 E8     BNE RD82			;if not loop
AD9A 60        RTS			;else exit C=1

.RD9B
AD9B 48        PHA			;Print volume listing line
AD9C A9 0A     LDA #&0A			;save no. tracks in A
AD9E 20 06 90  JSR Q006			;Tab to column in A
ADA1 68        PLA			;peek no. tracks
ADA2 48        PHA
ADA3 20 12 90  JSR Q012			;Print decimal byte
ADA6 8D 74 10  STA &1074		;store in temp
ADA9 A9 12     LDA #&12			;A=18
ADAB 20 06 90  JSR Q006			;Tab to column in A
ADAE 20 DB AD  JSR RDDB			;multiply to get sectors
ADB1 20 09 A4  JSR R409			;print decimal word
ADB4 A9 1B     LDA #&1B			;A=27
ADB6 20 06 90  JSR Q006			;Tab to column in A
ADB9 20 DB AD  JSR RDDB			;regenerate no. sectors
ADBC 4E 61 10  LSR &1061		;shift right twice
ADBF 6E 60 10  ROR &1060		;to divide by 4
ADC2 4E 61 10  LSR &1061		;and get kilobytes.
ADC5 6E 60 10  ROR &1060		;C=1 if we get half a K
ADC8 08        PHP			;save carry flag
ADC9 20 09 A4  JSR R409			;print decimal word
ADCC 28        PLP			;restore carry flag
ADCD 90 07     BCC RDD6			;if set
ADCF 20 18 90  JSR Q018			;then print ".5"
ADD2 EQUB &00
ADD3 EQUS ".5"
ADD5 EQUB &00
.RDD6
ADD6 20 09 90  JSR Q009			;print newline
ADD9 68        PLA			;restore no. tracks
ADDA 60        RTS			;and exit

.RDDB					;Multiply tracks by spt
ADDB 20 00 92  JSR Q200			;Save AXY
ADDE A9 00     LDA #&00			;and result word high byte.
ADE0 8D 61 10  STA &1061		;get density (=sectors/track)
ADE3 AE 70 10  LDX &1070		;into X.
.RDE6
ADE6 18        CLC			;clear carry
ADE7 6D 74 10  ADC &1074		;add track count to total
ADEA 90 03     BCC RDEF			;if carry out occurs
ADEC EE 61 10  INC &1061		;increment result high byte
.RDEF
ADEF CA        DEX			;decrement sectors remaining
ADF0 D0 F4     BNE RDE6			;loop if more to go
ADF2 8D 60 10  STA &1060		;else store low byte and exit
ADF5 60        RTS

.RDF6
ADF6 18        CLC			;clear carry
ADF7 6D 77 10  ADC &1077		;Add A to sector iterator and modulo sectors-per-track.
ADFA 38        SEC			;set carry
.RDFB
ADFB 8D 77 10  STA &1077
ADFE ED 70 10  SBC &1070
AE01 B0 F8     BCS RDFB
AE03 60        RTS

.RE04					;Set immediate drive = default
AE04 20 00 92  JSR Q200			;Save AXY,
AE07 AD 09 10  LDA &1009		;zero *command argument space
AE0A 85 C9     STA &C9			;A = current drive
AE0C A2 00     LDX #&00
AE0E 8A        TXA
.RE0F
AE0F 9D 78 10  STA &1078,X
AE12 E8        INX
AE13 E0 08     CPX #&08
AE15 D0 F8     BNE RE0F
AE17 60        RTS

.RE18					;Create volume catalogues
AE18 20 00 92  JSR Q200			;Save AXY
AE1B A9 41     LDA #&41			;Set immediate volume = A
AE1D 85 C8     STA &C8			;A -> &00C8 = Immediate volume
AE1F A9 00     LDA #&00			;Zero catalogue pages
AE21 AA        TAX
.RE22
AE22 9D 00 0E  STA &0E00,X
AE25 9D 00 0F  STA &0F00,X
AE28 E8        INX
AE29 D0 F7     BNE RE22
.RE2B
AE2B A9 99     LDA #&99			;Cat version no, will => &00
AE2D 8D 04 0F  STA &0F04
AE30 A9 00     LDA #&00
AE32 8D 06 0F  STA &0F06
AE35 AC 70 10  LDY &1070		;Multiply spt by tracks in vol
.RE38
AE38 18        CLC
AE39 7D 78 10  ADC &1078,X
AE3C 90 03     BCC RE41
AE3E EE 06 0F  INC &0F06
.RE41
AE41 88        DEY
AE42 D0 F4     BNE RE38
AE44 8D 07 0F  STA &0F07		;Store in size field of cat
AE47 20 03 9B  JSR QB03			;write current catalogue
AE4A E6 C8     INC &C8			;increment volume letter
AE4C E8        INX
AE4D EC 73 10  CPX &1073		;have we created all volumes?
AE50 90 D9     BCC RE2B			;loop until done
AE52 60        RTS			;then exit

.RE53
AE53 48        PHA
AE54 20 82 AE  JSR RE82
AE57 20 A2 AE  JSR REA2			;Print "track n"
AE5A A9 1F     LDA #&1F
AE5C 8D 16 10  STA &1016
AE5F A9 00     LDA #&00
AE61 8D 18 10  STA &1018
AE64 A6 C9     LDX &C9			;X = current drive
AE66 BD F0 0F  LDA &0FF0,X
AE69 8D 19 10  STA &1019
AE6C 68        PLA
AE6D 4C 15 9B  JMP QB15

.RE70
AE70 20 18 90  JSR Q018			;Print "Formatting "
AE73 EQUB &00
AE74 EQUB &0B
AE75 EQUS "Formatting "
AE80 EQUB &00
AE81 60	 RTS

.RE82
AE82 20 18 90  JSR Q018			;Print "Verifying "
AE85 EQUB &00
AE86 EQUB &0B
AE87 EQUS "Verifying "
AE91 EQUB &00
AE92 60	 RTS

.RE93					;Print "drive n"
AE93 A6 C9     LDX &C9			;X = current drive
AE95 8A        TXA			;X -> A = current drive
AE96 20 18 90  JSR Q018			;Print "drive n"
AE99 EQUB &C2
AE9A EQUS "drive "
AEA0 EQUB &00
AEA1 60        RTS

.REA2					;Print "track n"
AEA2 AD 17 10  LDA &1017		;A = track number
AEA5 20 18 90  JSR Q018
AEA8 EQUB &82
AEA9 EQUS "track "
AEAF EQUB &00
AEB0 60        RTS

.REB1
AEB1 20 18 90  JSR Q018			;Print "complete"
AEB4 EQUB &02
AEB5 EQUS "complete"
AEBD EQUB &00
;set CF = 1 and exit
AEBE 38        SEC
AEBF 60        RTS


; EDOSPAT extensions, block 3

.REE7
AEE7 8D 02 0E  STA &0E02		;store sector count low byte
AEEA A9 20     LDA #&20			;set catalogue version=&20
AEEC 8D 00 0E  STA &0E00		;to show count is big-endian.
AEEF 60        RTS

.REF0
AEF0 C9 02     CMP #&02			;C=1 if more than one volume
AEF2 A9 2E     LDA #&2E			;default of 46 tracks for volume A
AEF4 B0 06     BCS REFC			;use A=46 if multiple volumes
AEF6 AD 71 10  LDA &1071		;else get number of tracks
AEF9 E9 00     SBC #&00			;C=0, subtract 1 for catalogue track
AEFB 18        CLC 			;reset C to indicate single volume.
.REFC
AEFC 8D 78 10  STA &1078		;set number of tracks in volume A
AEFF 60        RTS 			;exit

.RF04					;OSGBPB read/write w/sector ops
AF04 B9 9D 10  LDA &109D,Y		;A = PTR file pointer
AF07 D0 60     BNE RF69			;if not on sector boundary
AF09 AD 78 10  LDA &1078		;do a bytewise transfer
.RF0C
AF0C 0D 77 10  ORA &1077		;else OR high bytes of L
AF0F F0 02     BEQ RF13			;if either >0
AF11 A9 FF     LDA #&FF			;then request=255
.RF13
AF13 0D 76 10  ORA &1076		;else request=2nd byte of L
AF16 F0 39     BEQ RF51			;if request=0 finish sector loop
AF18 85 BA     STA &BA			;else store it in temp
AF1A 98        TYA			;copy channel pointer to A
AF1B 2C 3A 10  BIT &103A		;test Tube channel flag
AF1E 10 02     BPL RF22			;if reading from disc
AF20 09 03     ORA #&03			;00000011;then point A to EXT mid/hi
.RF22
AF22 AA        TAX			;instead of allocated length.
AF23 BD 98 10  LDA &1098,X		;copy to X, get alloc length low
AF26 38        SEC			;subtract PTR middle byte
AF27 F9 9E 10  SBC &109E,Y		;=maximum transfer size low
AF2A 85 BB     STA &BB			;store in another temp
AF2C BD 99 10  LDA &1099,X		;get allocated length high
AF2F A6 BA     LDX &BA			;load request for later
AF31 F9 9F 10  SBC &109F,Y		;subtract PTR high = maximum high
AF34 90 1B     BCC RF51			;if maximum<0 finish sector loop
AF36 D0 08     BNE RF40			;if maximum>=256 transfer sectors
AF38 E4 BB     CPX &BB			;else 0<=maximum<256.
AF3A 90 04     BCC RF40			;if request<maximum do sectors
AF3C A6 BB     LDX &BB			;else request=maximum
AF3E F0 11     BEQ RF51			;if maximum=0 finish sector loop
.RF40
AF40 20 0F 98  JSR Q80F			;transfer sectors. flush channel
AF43 A9 13     LDA #&13			;A=&13, 8271 read command
AF45 2C 3A 10  BIT &103A		;test Tube channel flag
AF48 30 02     BMI RF4C			;if writing to disc
AF4A A9 4B     LDA #&4B			;then replace with &4B to write.
.RF4C
AF4C 20 85 AF  JSR RF85			;do the transfer
AF4F B0 BB     BCS RF0C			;if L>=0 (alw?) loop for more.
.RF51
AF51 2C 3A 10  BIT &103A		;test Tube channel flag
AF54 30 0E     BMI RF64			;if writing to disc
AF56 20 0C B4  JSR S40C			;test if we are at end-of-file
.RF59
AF59 90 09     BCC RF64			;if so
AF5B 20 09 92  JSR Q209			;set EXT=PTR, extending file.
AF5E EQUW &9D,&10			;FROM PTR, &109D,Y
AF60 EQUW &9A,&10			;TO EXT, &109A,Y
AF62 EQUW &03,&11			;3 bytes, Y indexed FROM and TO

.RF64
AF64 20 D6 B6  JSR S6D6			;test if L>0 bytes.
AF65 D6 B6     DEC &B6,X
AF67 F0 10     BEQ RF79			;if no more to transfer, exit.
.RF69
AF69 2C 3A 10  BIT &103A		;bytewise transfer. test flag
AF6C 30 0C     BMI RF7A			;if writing to disc
AF6E 20 E5 B6  JSR S6E5			;get byte from memory
AF71 20 4B B6  JSR S64B			;put byte to disc
.RF74
AF74 20 C8 B6  JSR S6C8			;decrement L
AF77 D0 8B     BNE RF04			;if more bytes then loop
.RF79
AF79 60        RTS			;else exit.

.RF7A
AF7A 20 21 B6  JSR S621			;else get byte from disc
AF7D B0 FA     BCS RF79			;if EOF then exit
AF7F 20 E5 B6  JSR S6E5			;else put byte to memory
AF82 4C 74 AF  JMP RF74			;decrement L and loop if >0.

.RF85
AF85 8D 16 10  STA &1016		;Multi-sector op on open file.
AF88 86 BB     STX &BB			;A=command,X=sector count
AF8A B9 94 10  LDA &1094,Y		;Y=channel pointer.get start LBA
AF8D 18        CLC			;add PTR middle byte
AF8E 79 9E 10  ADC &109E,Y		;=transfer start LBA low byte.
AF91 AA        TAX			;save in X
AF92 B9 95 10  LDA &1095,Y		;get start LBA high byte
AF95 79 9F 10  ADC &109F,Y		;add PTR high byte.
AF98 84 BA     STY &BA			;LBA now in XA. save pointer
AF9A 48        PHA			;save LBA high byte
AF9B B9 93 10  LDA &1093,Y		;copy drive of open file
AF9E 85 C9     STA &C9			;to immediate drive for OSWORD, A = current drive.
AFA0 68        PLA			;restore LBA high byte
AFA1 A8        TAY			;set up LBA in XY
AFA2 A5 BB     LDA &BB			;set A=sector count
AFA4 20 06 92  JSR Q206			;copy
AFA7 EQUW &BC,&00			;FROM data addr at &00BC
AFA9 EQUW &71,&10			;TO OSGBPB block at &1071
AFAB EQUB &02				;count
AFAC 20 06 92  JSR Q206			;copy
AFAF EQUW &71,&10			;FROM OSGBPB address at &1071
AFB1 EQUW &11,&10			;TO OSWORD at &1011
AFB3 EQUB &04				;count
AFB4 20 06 9B  JSR QB06			;do LBA transfer
AFB7 A4 BA     LDY &BA			;set Y=channel pointer for return
AFB9 A6 BA     LDX &BA			;and X too for incrementing PTR
AFBB A5 BB     LDA &BB			;set A=sector count
AFBD 18        CLC			;clear carry
AFBE 7D 9E 10  ADC &109E,X		;add to PTR middle byte
AFC1 9D 9E 10  STA &109E,X		;store back
AFC4 90 03     BCC RFC9			;carry out to PTR high byte
AFC6 FE 9F 10  INC &109F,X
.RFC9
AFC9 A5 BB     LDA &BB			;set A=sector count again
AFCB 18        CLC			;clear carry
AFCC 65 BD     ADC &BD			;add to data address 2nd byte
AFCE 85 BD     STA &BD			;store back
AFD0 90 03     BCC RFD5			;carry out to high bytes in OSGBPB
AFD2 20 F7 AF  JSR RFF7			;block
.RFD5
AFD5 A9 FE     LDA #&FE			;11111110/A=&FE
AFD7 AA        TAX			;copy to X as reverse counter
AFD8 39 88 10  AND &1088,Y		;clear EOF-warning-given flag
AFDB 99 88 10  STA &1088,Y		;store back
AFDE AD 76 10  LDA &1076		;get 2nd byte of L
AFE1 38        SEC			;set carry
AFE2 E5 BB     SBC &BB			;subtract sector count
AFE4 8D 76 10  STA &1076
.RFE7
AFE7 BD 79 0F  LDA &0F79,X		;borrow in from 3rd and top bytes
AFEA E9 00     SBC #&00			;of L
AFEC 9D 79 0F  STA &0F79,X
AFEF E8        INX			;return top byte of L
AFF0 D0 F5     BNE RFE7			;and C=1 if L>=256 bytes
AFF2 60        RTS

.RFF3
AFF3 E6 BD     INC &BD			;Increment top 3 bytes of data address
AFF5 D0 08     BNE RFFF
.RFF7
AFF7 EE 73 10  INC &1073		;Increment top word of data address
AFFA D0 03     BNE RFFF
AFFC EE 74 10  INC &1074
.RFFF
AFFF 60        RTS


;EDOS API, part 1
.S000
B000 4C 0C B0  JMP S00C			;OSFILE

.S003
;B003 4C 5F B9  JMP S95F		;OSARGS
B003 4C 58 B9  JMP S958			;OSARGS

.S006
B006 4C 7C B1  JMP S17C			;OSFIND

.S009
B009 4C A9 B1  JMP S1A9			;OSFSC

.S00C					;OSFILE
B00C 20 00 92  JSR Q200			;Save AXY
B00F 20 06 B7  JSR S706			;call monitor
B012 20 09 B4  JSR S409			;Copy user's OSFILE/GBPB block
B015 AA        TAX			;transfer reason code to X
B016 E8        INX			;add 1
B017 E0 08     CPX #&08			;does A equal 0..6 or &FF?
B019 90 01     BCC S01C			;if so continue
B01B 60        RTS			;else exit C=1.

.S01C
B01C BD 12 B1  LDA S112,X		;get microcode byte from B112..9
B01F 85 CD     STA &CD			;store in shift register
B021 BA        TSX			;have A=1 returned on exit
B022 A9 01     LDA #&01			;as no hierarchical directories
B024 9D 05 01  STA &0105,X		;and err given if file not found
B027 AE 70 10  LDX &1070		;put address of filename in XY
B02A AC 71 10  LDY &1071
B02D 20 33 B3  JSR S333			;set up GSINIT/OSFSC 2 & 4. *RUN, */
B030 20 12 93  JSR Q312			;and get file spec from the string
B033 46 CD     LSR &CD			;sample first bit of microcode
B035 90 43     BCC S07A
B037 A2 72     LDX #&72			;......1 Save file
B039 A0 60     LDY #&60			;OSFILE load addr to cat block 2
B03B 20 51 B3  JSR S351			;do 32 to 18 bit copy
B03E A2 76     LDX #&76			;OSFILE exec addr to cat block 2
B040 A0 63     LDY #&63
B042 20 51 B3  JSR S351			;do 32 to 18 bit copy
B045 38        SEC
B046 AD 7E 10  LDA &107E		;subtract OSFILE end address
B049 ED 7A 10  SBC &107A		;from start address
B04C 8D 66 10  STA &1066		;to get length
B04F AD 7F 10  LDA &107F		;(note 16 bit so file 64K max)
B052 ED 7B 10  SBC &107B
B055 8D 67 10  STA &1067
B058 AE 66 10  LDX &1066		;is low byte of length zero?
B05B E0 01     CPX #&01			;if not set carry flag
B05D 69 00     ADC #&00			;and increment high byte
B05F 8D 6B 10  STA &106B		;to make the sector count
B062 A9 00     LDA #&00			;clear high byte
B064 8D 6C 10  STA &106C		;of sector count
B067 8A        TXA			;low byte to A and discard
B068 A9 A0     LDA #&A0			;&A0 = OSFILE reason code
B06A 20 18 A6  JSR R618			;check perms/create file
B06D 20 06 92  JSR Q206			;Copy memory absolute
B070 EQUW &7A,&10			;FROM start address at &107A
B072 EQUW &11,&10			;TO OSWORD &7F block at &1011
B074 EQUB &04				;count
B075 A9 0B     LDA #&0B			;A = 8271 write command
B077 4C 42 B3  JMP &B342		;save data to disc and exit

.S07A
B07A 20 00 9B  JSR QB00			; softmount and catalogue driv
B07D 20 0C A5  JSR R50C			;......0 Not a file save
B080 20 03 A6  JSR R603			;load cat, check file exists
B083 46 CD     LSR &CD			;unpack fields from catalogue
B085 90 13     BCC S09A
B087 20 06 92  JSR Q206			;Copy memory absolute
B08A EQUW &72,&10			;FROM OSFILE load address at &1072
B08C EQUW &11,&10			;TO OSWORD &7F block at &1011
B08E EQUB &04				;count
B08F AD 76 10  LDA &1076		;test low byte of exec address
B092 F0 03     BEQ S097			;if =0 then skip, else:
B094 20 70 B3  JSR S370			;copy load addr from cat to O7F
.S097
B097 20 40 B3  JSR S340			;load data from disc and exit
.S09A
B09A 46 CD     LSR &CD			;....1x0 Get file info
B09C 90 38     BCC S0D6			;load addr from cat to OSFILE
B09E A2 48     LDX #&48			;do 18 to 32 bit copy
B0A0 A0 72     LDY #&72			;exec addr from cat to OSFILE
B0A2 20 74 B3  JSR S374
B0A5 A2 4B     LDX #&4B
B0A7 A0 76     LDY #&76
B0A9 20 74 B3  JSR S374			;do 18 to 32 bit copy
B0AC 20 06 92  JSR Q206			;Copy memory absolute
B0AF EQUW &4E,&10			;FROM length from cat at &104E
B0B1 EQUW &7A,&10			;TO OSFILE at &107A
B0B3 EQUB &03				;count
B0B4 A9 00     LDA #&00			;clear top byte of length
B0B6 AA        TAX			;and attribute word
.S0B7
B0B7 9D 7D 10  STA &107D,X
B0BA E8        INX
B0BB E0 05     CPX #&05
B0BD D0 F8     BNE S0B7
B0BF 2C 47 10  BIT &1047		;test lock bit of cat entry
B0C2 10 05     BPL S0C9			;if clear then skip, else:
;B0C4 A9 0A     LDA #&0A		;set low attribute byte = &0A
B0C4 A9 08     LDA #&08			;set low attribute byte = &08
B0C6 8D 7E 10  STA &107E		;as user can't write or delete
.S0C9
B0C9 A0 00     LDY #&00			;copy OSFILE block back
.S0CB
B0CB B9 70 10  LDA &1070,Y		;to user's area
B0CE 91 BE     STA (&BE),Y
B0D0 C8        INY
B0D1 C0 12     CPY #&12
B0D3 D0 F6     BNE S0CB
B0D5 60        RTS			;and exit

;.S0D6
;B0D6 20 21 A5  JSR R521		;Check file not locked
;B0D9 46 CD     LSR &CD			;Microcode shift register in OSGBPB etc
;B0DB 90 06     BCC S0E3

.S0D6
B0D6 46 CD     LSR &CD			;Microcode shift register in OSGBPB etc
B0D8 90 09     BCC S0E3
B0DA 20 21 A5  JSR R521			;Check file not locked
B0DD 20 00 A6  JSR R600			;..10x0 Delete file
B0E0 4C 03 9B  JMP QB03			;write catalogue

.S0E3
B0E3 46 CD     LSR &CD			;Microcode shift register in OSGBPB etc
B0E5 90 07     BCC S0EE
B0E7 A2 72     LDX #&72			;..100x0 Set load address
B0E9 A0 48     LDY #&48			;load address to cat block 1
B0EB 20 51 B3  JSR S351			;do 32 to 18 bit copy.
.S0EE
B0EE 46 CD     LSR &CD			;Microcode shift register in OSGBPB etc
B0F0 90 07     BCC S0F9
B0F2 A2 76     LDX #&76			;.1x00x0 Set exec address
B0F4 A0 4B     LDY #&4B			;exec address to cat block 1
B0F6 20 51 B3  JSR S351			;to 32 to 18 bit copy
.S0F9
B0F9 46 CD     LSR &CD			;Microcode shift register in OSGBPB etc
B0FB 90 0F     BCC S10C
B0FD AD 7E 10  LDA &107E		;1xx00x0 Set attributes
;B100 29 0A     AND #&0A		;test bits 1 and 3 of attributes
;B102 F0 02     BEQ S106		;is either one set?
;B104 A9 80     LDA #&80		;if so set Locked bit
;.S106
;B106 0D 47 10  ORA &1047		;of entry in catalogue block 1
;B109 8D 47 10  STA &1047
B100 29 0A     AND #&0A			;mask bits 0,2,4-7 of attributes
B102 49 00     EOR #&00			;quicker than two NOPs
B104 0E 47 10  ASL &1047		;discard top bit
B107 C9 01     CMP #&01			;C=1 if A>0 (attribs b1 or b3 set)
B109 6E 47 10  ROR &1047		;set L bit of catalogue entry
.S10C
B10C 20 06 A6  JSR R606			;xxx00x0 Not save delete or info pack fields
B10F 4C 03 9B  JMP QB03			;write catalogue and exit

.S112					;table
B112 EQUD &06,&01,&70,&10		;8 microcode bytes for OSFILE
B116 EQUD &20,&40,&04,&08		;&FF and 0 to 6

.S11A
B11A 20 09 B7  JSR S709			;OSARGS Monitor
B11D 85 CD     STA &CD			;when A=&FF flush routine flushes
B11F C0 00     CPY #&00
B121 D0 25     BNE S148
B123 C9 00     CMP #&00
B125 D0 03     BNE S12A			;a=0, y=0: return FS number
B127 60        RTS			;exit; the wrapper does that.

B128 EQUW &00,&00

.S12A
B12A 20 00 92  JSR Q200			;Save AXY
B12D C9 01     CMP #&01			;a=1, y=0: return cmd line tail
B12F D0 10     BNE S141
B131 20 09 92  JSR Q209			;Copy memory absolute indexed
B134 EQUW &82,&10			;from workspace
B136 EQUW &00,&00			;to bottom of user's block
B138 EQUW &02,&02			;2 bytes, X indexed destination
B13A A9 FF     LDA #&FF			;set top word to &FFFF
B13C 95 02     STA &02,X		;indicating I/O memory
B13E 95 03     STA &03,X
.S140
B140 60        RTS			;and exit.

.S141
B141 C9 FF     CMP #&FF			;a=&FF, y=0: flush all files
B143 D0 FB     BNE S140
;B145 4C D5 9A  JMP QAD5		;jump to our routine.
B145 4C DB 9A  JMP QADB			;jump to our routine.

.S148
B148 20 00 92  JSR Q200			;Save AXY
B14B 20 0C 98  JSR Q80C			;Check file open & return pointer
B14E C9 00     CMP #&00			;y>0: file handle given
B150 D0 11     BNE S163			;ensure file is open
B152 C8        INY			;a=0, y>0: return PTR
B153 C8        INY			;increment channel pointer
B154 C8        INY			;to point to PTR not EXT:
.S155					;a=2, y>0: return EXT
B155 20 09 92  JSR Q209			;Copy memory absolute indexed
B158 EQUW &9A,&10			;from workspace
B15A EQUW &00,&00			;to bottom of user's block
B15C EQUW &03,&12			;3 bytes
B15E A9 00     LDA #&00			;Y index source, Y index dest
B160 95 03     STA &03,X		;clear top byte of PTR
B162 60        RTS			;and exit.

.S163
B163 C9 01     CMP #&01			;a=1, y>0: write PTR
B165 D0 0A     BNE S171
B167 20 09 92  JSR Q209			;Copy memory absolute indexed
B16A EQUW &00,&00			;from user's block
B16C EQUW &9D,&10			;to workspace
B16E EQUW &03,&21			;nothing happens to file until next write!
.S170
B170 60	RTS				;exit

.S171
B171 C9 02     CMP #&02
B173 F0 E0     BEQ S155
B175 C9 FF     CMP #&FF
B177 D0 F7     BNE S170			;a=&FF, y>0: flush file
B179 4C 0F 98  JMP Q80F

.S17C					;OSFIND
B17C 20 00 92  JSR Q200			;Save AXY
B17F 20 15 B7  JSR S715			;Call OSFIND Monitor
B182 C9 00     CMP #&00			;is it a CLOSE# ?
B184 F0 03     BEQ S189			;if so,
B186 4C 98 B1  JMP S198			;then:

.S189
B189 85 CD     STA &CD			;flag=0 so flush routine closes
B18B 98        TYA
B18C AA        TAX			;channel number to X
B18D D0 03     BNE S192			;if channel number =0
B18F 4C 18 98  JMP Q818			;then close all channels &exit

.S192
B192 20 03 98  JSR Q803			;else set up for channel X
B195 4C 15 98  JMP Q815			;close channel and exit.

.S198
B198 48        PHA			;save file open mode
B199 20 33 B3  JSR S333			;GSINIT string in XY
B19C 20 12 93  JSR Q312			;Get file spec?
B19F 68        PLA			 restore mode
B1A0 20 1E 98  JSR Q81E			;Open a file
B1A3 8A        TXA			;return channel in A
B1A4 BA        TSX			;SP -> X
B1A5 9D 05 01  STA &0105,X		;save on stack
B1A8 60        RTS			;and exit.

.S1A9					;OSFSC
B1A9 20 18 B7  JSR S718			;Filing system call monitor
B1AC C9 00     CMP #&00			;if A=0 then *OPT
B1AE F0 03     BEQ S1B3
B1B0 4C 90 B2  JMP S290

.S1B3					;*OPT
B1B3 E0 01     CPX #&01
B1B5 F0 0E     BEQ S1C5
B1B7 B0 10     BCS S1C9
B1B9 A9 00     LDA #&00			;*OPT 0
B1BB A2 06     LDX #&06			;Clear options 6..9
.S1BD
B1BD 9D 7E 10  STA &107E,X
B1C0 E8        INX
B1C1 E0 0A     CPX #&0A
B1C3 D0 F8     BNE S1BD			;then fall through:
.S1C5
B1C5 8C 0E 10  STY &100E		;*OPT 1 monitor
B1C8 60        RTS

.S1C9
B1C9 E0 04     CPX #&04			;bad options 2 or 3
B1CB 90 25     BCC S1F2
B1CD D0 33     BNE S202
B1CF 20 06 92  JSR Q206			;Copy memory absolute *OPT 4
B1D2 EQUW &07,&10			;set boot option
B1D4 EQUW &C7,&00			;copy default dir/vol/drive
B1D6 EQUB &03				;to immediate path
B1D7 20 00 9B  JSR QB00			;softmount and read catalogue
B1DA AD 06 0F  LDA &0F06		;clear boot option bits
B1DD 29 CF     AND #&CF			;11001111
B1DF 8D 06 0F  STA &0F06
B1E2 98        TYA			;replace them with bits from Y
B1E3 29 03     AND #&03			;00000011
B1E5 0A        ASL A
B1E6 0A        ASL A
B1E7 0A        ASL A
B1E8 0A        ASL A
B1E9 0D 06 0F  ORA &0F06
B1EC 8D 06 0F  STA &0F06
B1EF 4C 03 9B  JMP QB03			;write catalogue and exit

.S1F2
B1F2 20 18 90  JSR Q018			;Print "Bad option"
B1F5 EQUB &0A
B1F6 EQUB &CB
B1F7 EQUS "Bad option"
B201 EQUB &00
.S202
B202 E0 05     CPX #&05			;*OPT 5 display options
B204 D0 7E     BNE S284			;LDA &100E get option 1
B206 AD 0E 10  LDA &100E		;JSR &9018
B209 20 18 90  JSR Q018			;print "*opt 1 monitor = "+n
B20C EQUB &82
B20D EQUS "*opt 1 monitor = "
B21E EQUB &00
B21F AD 84 10  LDA &1084		;get option 6
B222 20 18 90  JSR Q018			;print "*opt 6 density = "+n
B225 EQUB &82
B226 EQUS "*opt 6 density = "
B237 EQUB &00
B238 AD 85 10  LDA &1085		;get option 7
B23B 20 18 90  JSR Q018			;print "*opt 7 volumes = "+n
B23E EQUB &82
B23F EQUS "*opt 7 volumes = "
B250 EQUB &00
B251 AD 86 10  LDA &1086		;get option 8
B254 20 18 90  JSR Q018			;print "*opt 8 tracks = "+n
B257 EQUB &82
B258 EQUS "*opt 8 tracks  = "
B269 EQUB &00
B26A AD 87 10  LDA &1087		;get option 9
B26D 20 18 90  JSR Q018			;print "*opt 9 saverom = "+n
B270 EQUB &82
B271 EQUS "*opt 9 saverom = "
B282 EQUB &00
B283 60        RTS

.S284
B284 E0 0A     CPX #&0A			;reject options >=10
B286 90 03     BCC S28B
B288 4C F2 B1  JMP S1F2

.S28B
B28B 98        TYA			;*OPT 6..9
B28C 9D 7E 10  STA &107E,X		;set EDOS options
B28F 60        RTS

.S290
B290 C9 02     CMP #&02
B292 F0 1E     BEQ S2B2
B294 B0 0D     BCS S2A3
B296 20 03 98  JSR Q803			;OSFSC 1
B299 20 0C B4  JSR S40C			;Test EOF (don't warn)
B29C A2 00     LDX #&00
B29E 90 02     BCC S2A2
B2A0 A2 FF     LDX #&FF			;C=1, X=&FF if EOF
.S2A2
B2A2 60        RTS

.S2A3
B2A3 C9 04     CMP #&04
B2A5 F0 0B     BEQ S2B2
B2A7 B0 6A     BCS S313
B2A9 20 33 B3  JSR S333			;String init\OSFSC 3.
B2AC 20 00 81  JSR P100			;Unknown OSCLI offered to current FS.
B2AF 90 04     BCC S2B5			;If not built in to EDOS try to *RUN it.
B2B1 60        RTS

.S2B2					;OSFSC 2 & 4. *RUN, */
B2B2 20 33 B3  JSR S333			;String init
.S2B5
B2B5 20 12 93  JSR Q312			;expand path at XY, Get file spec?
B2B8 20 00 9B  JSR QB00			;softmount & load catalogue
B2BB 20 09 A5  JSR R509			;find file
B2BE 90 21     BCC S2E1			;if not found
B2C0 20 06 92  JSR Q206			;replace path with library's
B2C3 EQUW &0A,&10			;FROM address &101A
B2C5 EQUW &C7,&00			;TO address &00C7 = Immediate dir'y
B2C7 EQUB &03				;count
B2C8 20 00 9B  JSR QB00			;load library catalogue
B2CB 20 09 A5  JSR R509			;find file
B2CE 90 11     BCC S2E1			;if not found:
B2D0 20 18 90  JSR Q018			;Print "Bad Command" error
B2D3 EQUB &0A
B2D4 EQUB &FE
B2D5 EQUS "Bad command"
B2E0 EQUB &00
.S2E1
B2E1 98        TYA			;else store pointer
B2E2 18        CLC			;to arguments
B2E3 65 F2     ADC &F2
B2E5 8D 82 10  STA &1082
B2E8 A5 F3     LDA &F3
B2EA 69 00     ADC #&00
B2EC 8D 83 10  STA &1083
B2EF 20 03 A6  JSR R603			;unpack fields from catalogue
B2F2 20 3D B3  JSR S33D			;load file
B2F5 AD 4D 10  LDA &104D		;if execution address
B2F8 49 03     EOR #&03			;00000011;has high bits clear
B2FA 2D 7A 02  AND &027A		;and Tube is present
B2FD D0 0B     BNE S30A			;then call address over Tube
B2FF 20 06 92  JSR Q206			;else copy exec to zero page
B302 EQUW &4B,&10			;FROM address &104B
B304 EQUW &BE,&00			;TO address &00BE
B306 EQUB &02				;count
B307 6C BE 00  JMP (&00BE)		;and call it (can save 8 bytes here)

.S30A
B30A A2 4B     LDX #&4B			;Do a *GO to the exec address
B30C A0 10     LDY #&10
B30E A9 04     LDA #&04
B310 4C 06 A0  JMP R006

.S313
B313 C9 06     CMP #&06
B315 F0 08     BEQ S31F
B317 B0 0B     BCS S324
B319 20 33 B3  JSR S333			;OSFSC 5 *CAT. string init.
B31C 4C 03 86  JMP P603			;*CAT

.S31F
B31F A9 77     LDA #&77			;OSFSC 6 FS about to change.
B321 4C F4 FF  JMP osbyte		;close *SPOOL and *EXEC files

.S324
B324 C9 08     CMP #&08
B326 F0 07     BEQ S32F
B328 B0 08     BCS S332
B32A A2 11     LDX #&11			;OSFSC 7 Return semi-incl.
B32C A0 15     LDY #&15			;range of file handles
B32E 60        RTS

.S32F
B32F 4E 0F 10  LSR &100F		;OSFSC 8 *command issued
.S332
B332 60        RTS			;Clear *ENABLE status

.S333					;String init
B333 86 F2     STX &F2
B335 84 F3     STY &F3			;store XY in GS pointer
B337 A0 00     LDY #&00
B339 18        CLC
B33A 4C C2 FF  JMP gsinit		;jump to GSINIT

.S33D					;Load file.
B33D 20 70 B3  JSR S370			;copy addr to O7F
.S340
B340 A9 13     LDA #&13			;store read command in block
B342 8D 16 10  STA &1016
B345 AE 51 10  LDX &1051		;absolute start sector in XY
B348 AC 52 10  LDY &1052
B34B AD 53 10  LDA &1053		;sector length (mod 256) in A
B34E 4C 06 9B  JMP QB06			;do LBA transfer and exit

.S351					;Copy 32 bit to 18 bit addr
B351 48        PHA
B352 20 09 92  JSR Q209			;Copy memory
B355 EQUW &00,&10			;from 1000,X
B357 EQUW &00,&10			;to 1000,Y
B359 EQUW &02,&21
B35B BD 02 10  LDA &1002,X		;AND high bytes of source
B35E 3D 03 10  AND &1003,X		;together
B361 C9 FF     CMP &FF			;Are they &FFFF?
B363 F0 04     BEQ S369
B365 A9 00     LDA #&00			;If not clear high bits
B367 F0 02     BEQ S36B
.S369
B369 A9 03     LDA #&03			;else set high bits
.S36B
B36B 99 02 10  STA &1002,Y		;and store with address
B36E 68        PLA
B36F 60        RTS

.S370
B370 A2 48     LDX #&48			;Copy load address
B372 A0 11     LDY #&11			;to OSWORD &7F block:
.S374
B374 48        PHA			;Copy 18 bit to 32 bit addr
B375 20 09 92  JSR Q209			;from 1000,X to 1000,Y
B378 EQUW &00,&10
B37A EQUW &00,&10
B37C EQUW &02,&21
B37E BD 02 10  LDA &1002,X		;Are both high bits set?
B381 29 03     AND #&03
B383 C9 03     CMP #&03
B385 F0 04     BEQ S38B
B387 A9 00     LDA #&00			;If not high bytes = 0000
B389 F0 02     BEQ S38D
.S38B
B38B A9 FF     LDA #&FF			;else high bytes = FFFF
.S38D
B38D 99 02 10  STA &1002,Y
B390 99 03 10  STA &1003,Y
B393 68        PLA
B394 60        RTS

;B395 EQUB &00
;B396 EQUW &00,&00
;B398 EQUD &00,&00,&00,&00


;;EDOSPAT extensions, block 4

;.S39C					;Return binary 2 plus default
;B39C A9 02     LDA #&02
;B39E 20 E5 B6  JSR S6E5		;or library drive number
;B3A1 B9 09 10  LDA &1009,Y		;to OSGBPB data address
;B3A4 4C E5 B6  JMP S6E5		;(so volume letter can be added)

;.S3A7
;B3A7 2C 8F 02  BIT &028F
;B3AA 10 03     BPL S3AF
;.S3AC
;B3AC 4C 20 0D  JMP &0D20		;Jump to disc operation busywait

;.S3AF
;B3AF 4C AC B3  JMP S3AC		;Jump to disc operation busywait

;B3B2 EQUB &00
;B3B3 EQUW &00,&00
;B3B5 EQUD &00,&00,&00,&00

;; Convert DDOS latch to BBC Model B+
;; A = contents of DDOS control reg
;.S3B9
;B3B9 29 43     AND #&43		; mask bits 2-5 and 7 (bits 0 and 1 = drive, bit 6 = DEN)
;B3BB 48        PHA			; save latch on stack
;B3BC 4A        LSR A			; bit 0 -> 7 and CF, ie CF = DS
;B3BD 68        PLA			; retrieve latch from stack
;B3BE 2A        ROL A			; CF (DS) -> bit 0 (DS0), bit 7 -> CF, bit 6 -> bit 7, bit 1 (SS) -> bit 2 (SEL), bit 0 (DS) -> bit 1 (DS1)
;B3BF 10 02     BPL S3C3		; if bit 7 (old bit 6) unset (ie DDOS SDEN), EOR #&09
;B3C1 49 88     EOR #&88      		; 10001000, else, toggle bit 7 to 0 (old bit 6) and bit 3 to 1
;.S3C3
;;B3C3 49 09     EOR #&09      		; 00001001, toggle bit 3 (DEN) and bit 0 (DS0)
;B3C3 49 29     EOR #&29      		; 00101001, toggle bit 5 (RES), bit 3 (DEN) and bit 0 (DS0)
;B3C5 60        RTS			; exit

;EDOSPAT extensions, block 4

.S395
B395 A9 02     LDA #&02			;Return binary 2 plus default
B397 20 E5 B6  JSR S6E5			;or library drive number
B39A B9 09 10  LDA &1009,Y		;to OSGBPB data address (so volume letter can be added)

B39D 4C E5 B6  JMP S6E5			;Jump to disc operation busywait

.S3A0
B3A0 2C 8F 02  BIT &028F
B3A3 10 03     BPL S3A8
.S3A5
B3A5 4C 20 0D  JMP &0D20

.S3A8
B3A8 4C A5 B3  JMP S3A5

B3AB EQUB &00
B3AC EQUW &00,&00
B3AE EQUD &00,&00,&00,&00

; Convert DDOS latch to BBC Master
; A = contents of DDOS control reg
.S3B2
B3B2 29 43     AND #&43			;mask bits 2-5 and 7 (bits 0 and 1 = drive, bit 6 = DEN)
B3B4 C9 40     CMP #&40			;if bit 6 = 1 (DDEN), CF = 1 else bit 6 = 0 (SDEN), CF = 0
B3B6 2A        ROL A			;CF (DEN) -> bit 0, bit 0 (DS) -> bit 1, bit 1 (SS) -> bit 2
B3B7 29 07     AND #&07			;mask bits 3-7
B3B9 AA        TAX			;A -> X = SS + DS + DEN
B3BA BD BE B3  LDA S3BE,X		;A = appropriate bits from table
B3BD 60        RTS			;exit

.S3BE
;B3BE EQUD &29,&21,&2A,&22		for B+
;B3C2 EQUD &2D,&25,&2E,&26		for B+
B3BE EQUD &25,&05,&26,&06
B3C2 EQUD &35,&15,&36,&16

;+---+---+---+---+---+---+---+---+--------+---+---+---+
;|b 7|b 6|b 5|b 4|b 3|b 2|b 1|b 0|        |b 2|b 1|b 0|
;+---+---+---+---+---+---+---+---+--------+---+---+---+
;| - | - |RES|INT|DEN|SEL|DS1|DS0|   B+   |SEL|DS |DEN|
;| - | - |DEN|SEL|DS2|RES|DS1|DS0| Master | ----X---- |
;+---+---+---+---+---+---+---+---+--------+---+---+---+
;| 0 | 0 | 1 | 0 | 0 | 1 | 0 | 1 | X = 00 | 0 | 0 | 0 |
;+---+---+---+---+---+---+---+---+--------+-----------+
;| 0 | 0 | 0 | 0 | 0 | 1 | 0 | 1 | X = 01 | 0 | 0 | 1 |
;+---+---+---+---+---+---+---+---+--------+-----------+
;| 0 | 0 | 1 | 0 | 0 | 1 | 1 | 0 | X = 02 | 0 | 1 | 0 |
;+---+---+---+---+---+---+---+---+--------+-----------+
;| 0 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | X = 03 | 0 | 1 | 1 |
;+---+---+---+---+---+---+---+---+--------+-----------+
;| 0 | 0 | 1 | 0 | 0 | 1 | 0 | 1 | X = 04 | 1 | 0 | 0 |
;+---+---+---+---+---+---+---+---+--------+-----------+
;| 0 | 0 | 0 | 0 | 0 | 1 | 0 | 1 | X = 05 | 1 | 0 | 1 |
;+---+---+---+---+---+---+---+---+--------+-----------+
;| 0 | 0 | 1 | 0 | 0 | 1 | 1 | 0 | X = 06 | 1 | 1 | 0 |
;+---+---+---+---+---+---+---+---+--------+-----------+
;| 0 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | X = 07 | 1 | 1 | 1 |
;+---+---+---+---+---+---+---+---+--------+-----------+



.S3C6
B3C6 A4 F0     LDY &F0			;OSWORD &7D, &7E
B3C8 84 BE     STY &BE			;copy OSWORD block pointer
B3CA A4 F1     LDY &F1			;to scratch space
B3CC 84 BF     STY &BF			;as OSWORD &7F will overwrite
B3CE 20 06 92  JSR Q206			;Copy memory absolute
B3D1 EQUW &07,&10			;FROM default dir vol and drive at &1007
B3D3 EQUW &C7,&00			;TO immediate dir'y at &00C7
B3D5 EQUB &03				;count
B3D6 20 00 9B  JSR QB00			;softmount and catalogue driv
B3D9 A0 00     LDY #&00			;clear Y=0 for later
B3DB C9 7E     CMP #&7E			;if command is OSWORD &7D
B3DD B0 09     BCS S3E8
B3DF AD 04 0F  LDA &0F04
B3E2 91 BE     STA (&BE),Y		;then copy catalogue cycle
B3E4 98        TYA			;number to user's block
B3E5 38        SEC
B3E6 B0 17     BCS S3FF			;break out of ROM call and exit
.S3E8
B3E8 98        TYA			;else OSWORD &7E.
B3E9 91 BE     STA (&BE),Y		;low byte of volume size =0
B3EB C8        INY			;increment pointer
B3EC AD 07 0F  LDA &0F07		;next byte = low byte of sector
B3EF 91 BE     STA (&BE),Y		;count
B3F1 C8        INY			;increment pointer
B3F2 AD 06 0F  LDA &0F06		;mask all but low 3 bits of
B3F5 29 07     AND #&07			;high byte of sector count
B3F7 91 BE     STA (&BE),Y		;(volumes <512 KB) and store
B3F9 C8        INY			;increment pointer
B3FA A9 00     LDA #&00			;top byte of volume size =0
B3FC 91 BE     STA (&BE),Y
B3FE A8        TAY
.S3FF
B3FF 60        RTS			;exit C=1 to break ROM call.


;EDOS API, part 2: random access I/O
.S400
B400 4C 0F B4  JMP S40F			;OSBGET

.S403
B403 4C 1D B4  JMP S41D			;OSBPUT

.S406
B406 4C 2B B4  JMP S42B			;OSGBPB

.S409
B409 4C 71 B5  JMP S571			;Copy user's OSFILE/GBPB block

.S40C
B40C 4C 82 B5  JMP S582			;Test EOF (warned flag not set)

.S40F					;OSBGET
B40F 20 00 92  JSR Q200			;Save AXY
B412 20 0C B7  JSR S70C			;call monitor
B415 98        TYA
B416 AA        TAX
B417 20 03 98  JSR Q803			;init for file handle
B41A 4C 24 B6  JMP S624			;get byte and exit

.S41D					;OSBPUT
B41D 20 00 92  JSR Q200			;Save AXY
B420 20 0F B7  JSR S70F			;call monitor
B423 98        TYA
B424 AA        TAX
B425 20 AF B6  JSR S6AF			;check file is writeable
B428 4C 4E B6  JMP S64E			;put byte and exit

.S42B					;OSGBPB
B42B 20 00 92  JSR Q200			;Save AXY
B42E 20 12 B7  JSR S712			;call OSGBPB monitor
B431 20 09 B4  JSR S409			;Copy user's OSFILE/GBPB block
B434 AA        TAX			;Validate call number
B435 CA        DEX
B436 E0 08     CPX #&08
B438 90 01     BCC S43B			;If invalid exit with C=1
B43A 60        RTS			;how convenient

.S43B
B43B BD 69 B5  LDA S569,X		;OSGBPB microcode table 1..8
B43E 85 CD     STA &CD
B440 20 06 92  JSR Q206			;Copy memory absolute
B443 EQUW &71,&10			;FROM address &1071
B445 EQUW &BC,&00			;TO address &00BC
B447 EQUB &02				;count
B448 29 80     AND #&80			;10000000,take high bit of microcode
B44A 8D 3A 10  STA &103A		;1=read, store in Tube flag
B44D A9 00     LDA #&00			;have A=0 returned on exit
B44F BA        TSX			;to indicate the command is
B450 9D 05 01  STA &0105,X		;implemented
B453 AD 73 10  LDA &1073		;test high word of address
B456 2D 74 10  AND &1074
B459 49 FF     EOR #&FF			;A=0 if in I/O space, invert
B45B 2D 7A 02  AND &027A		;A=0 if Tube absent too
B45E F0 0D     BEQ S46D			;in which case skip forward
B460 AD 3A 10  LDA &103A		;else a Tube transfer.
B463 18        CLC			;set A=0 if writing to disc,
B464 2A        ROL A			;A=1 if reading from disc
B465 2A        ROL A
B466 A2 71     LDX #&71			;point XY to the full address
B468 A0 10     LDY #&10
B46A 20 06 A0  JSR R006			;open Tube channel 3.
.S46D					;now sample microcode
B46D 46 CD     LSR &CD			;to select actions:
B46F 90 72     BCC S4E3			;.....1 Get title / get cat
B471 20 06 92  JSR Q206			;copy default to immediate path.....1 Get title / get cat
B474 EQUW &07,&10			;FROM address &1007
B476 EQUW &C7,&00			;TO address &00C7 = Immediate dir'y
B477 EQUB &00				;count
B478 EQUB &03
B479 20 00 9B  JSR QB00			;softmount and load catalogue.
B47C 46 CD     LSR &CD
B47E 90 27     BCC S4A7
B480 A0 00     LDY #&00			;....11 Get title
B482 A9 0C     LDA #&0C			;clear offset; length byte = 12
.S484
B484 20 E5 B6  JSR S6E5			;send byte in A to user
B487 C8        INY			;send first 8 bytes of sector 0
B488 B9 FF 0D  LDA &0DFF,Y		;(with Y = 1 to 8)
B48B C0 09     CPY #&09
B48D D0 F5     BNE S484
.S48F
B48F B9 F7 0E  LDA &0EF7,Y		;send first 4 bytes of sector 1
B492 20 E5 B6  JSR S6E5			;(with Y = 9 to 12)
B495 C8        INY
B496 C0 0D     CPY #&0D
B498 D0 F5     BNE S48F
B49A 20 09 96  JSR Q609			;get boot option
B49D 20 E5 B6  JSR S6E5			;send it
B4A0 A5 C9     LDA &C9			;get immed (A = current = default) drive
B4A2 29 03     AND #&03			;make binary, send and exit.
B4A4 10 58     BPL S4FE
B4A6 EQUB &00
.S4A7
B4A7 AD 04 0F  LDA &0F04		;....01 Get catalogue
B4AA 8D 70 10  STA &1070		;get catalogue cycle number
B4AD AD 05 0F  LDA &0F05		;store in file handle byte of
B4B0 38        SEC			;OSGBPB block.
B4B1 ED 79 10  SBC &1079		;files * 8 - OSGBPB pointer
B4B4 85 CC     STA &CC			;=starting catalogue pointer
.S4B6
B4B6 20 06 A5  JSR R506			;select next file in catalogue
B4B9 B0 1C     BCS S4D7			;if no more files then finish
B4BB 20 1E A5  JSR R51E			;else compare directory letters
B4BE D0 F6     BNE S4B6			;if unequal skip to next file
B4C0 20 03 A6  JSR R603			;else unpack fields from cat
B4C3 A0 00     LDY #&00			;clear offset
B4C5 A9 07     LDA #&07			;set length byte = 7
.S4C7
B4C7 20 E5 B6  JSR S6E5			;send byte in A to user
B4CA B9 40 10  LDA &1040,Y		;send 7 bytes of filename proper
B4CD C8        INY			;(with Y = 1 to 7)
B4CE C0 08     CPY #&08
B4D0 D0 F5     BNE S4C7
B4D2 20 C8 B6  JSR S6C8			;decrement number of entries
B4D5 D0 DF     BNE S4B6			;remaining to be transferred
.S4D7					;if more then loop
B4D7 AD 05 0F  LDA &0F05		;else files * 8 - final cat ptr
B4DA 38        SEC			;=new OSGBPB pointer
B4DB E5 CC     SBC &CC			;store in OSGBPB block & finish.
B4DD 8D 79 10  STA &1079
B4E0 4C 4C B5  JMP S54C

.S4E3
B4E3 46 CD     LSR &CD			;.....0
B4E5 90 1D     BCC S504
B4E7 A0 00     LDY #&00			;....10 Get default/get library
B4E9 46 CD     LSR &CD			;Y=0 to point to default path
B4EB 90 02     BCC S4EF
B4ED A0 03     LDY #&03			;...110 Get library.  Y=3
.S4EF					;...x10 Get default/get library
B4EF 20 95 B3  JSR S395			;send binary 2 + drive number
B4F2 B9 08 10  LDA &1008,Y		;send volume letter
B4F5 20 E5 B6  JSR S6E5
B4F8 20 E3 B6  JSR S6E3			;send binary 1
B4FB B9 07 10  LDA &1007,Y		;get directory letter
.S4FE
B4FE 20 E5 B6  JSR S6E5			;send it
B501 4C 60 B5  JMP S560			;set C correctly and exit

.S504
B504 AE 70 10  LDX &1070		;....00 Read/write.  get handle
B507 46 CD     LSR &CD
B509 90 03     BCC S50E
B50B 20 AF B6  JSR S6AF			;...100 Write.  check writeable
.S50E
B50E 46 CD     LSR &CD			;...x00 Read/write
B510 90 03     BCC S515
B512 20 03 98  JSR Q803			;..1x00 Read. check file is open
.S515
B515 46 CD     LSR &CD			;..xx00 Read/write
B517 90 09     BCC S522
B519 20 09 92  JSR Q209			;.1xx00 Set PTR
B51C EQUW &79,&10			;copy FROM OSGBPB block, &1079
B51E EQUW &9D,&10			;TO PTR, &109D,Y
B520 EQUW &03,&01			;3 bytes, Y indexed TO
.S522
B522 20 D6 B6  JSR S6D6			;.xxx00 Read/write.  compare L=0
B525 F0 1C     BEQ S543			;if no bytes to transfer, finish
B527 20 04 AF  JSR RF04			;OSGBPB read/write w/sector ops
B52A 4C 43 B5  JMP S543			;and finish

.S52F
B52F 46 CD     LSR &CD			;take next bit of microcode
B531 90 05     BCC S538			;if clear C=0 on exit
B533 20 D6 B6  JSR S6D6			;else test L
B536 C9 01     CMP #&01			;C=1 if L>0
.S538
B538 08        PHP			;save status
B539 2C 3A 10  BIT &103A		;test transfer flag
B53C 50 03     BVC S541			;if a Tube transfer
B53E 20 0C A0  JSR R00C			;then close the Tube channel.
.S541
B541 28        PLP			;restore status
B542 60        RTS			;and return C

.S543					;Read/write finished
B543 20 09 92  JSR Q209			;copy PTR to OSGBPB block
B546 EQUW &9D,&10			;FROM PTR, &109D,Y
B548 EQUW &79,&10			;TO OSGBPB block, &1079
B54A EQUW &03,&10			;3 bytes, y indexed FROM
.S54C
B54C 20 06 92  JSR Q206			;copy address to OSGBPB block
B54F EQUW &BC,&00			;FROM address &00BC
B551 EQUW &71,&10			;TO address &1071
B553 EQUB &02				;count
B554 A0 00     LDY #&00
.S556
B556 B9 70 10  LDA &1070,Y		;copy OSGBPB block to user's block
B559 91 BE     STA (&BE),Y		;from &1070 to (&BE), 13 bytes
B55B C8        INY
B55C C0 0D     CPY #&0D
B55E D0 F6     BNE S556
.S560
B560 4C 2F B5  JMP S52F			;go to set C correctly and exit.

.S569
B569 EQUD &34,&24,&B8,&A8		;OSGBPB microcode table 1..8
B56D EQUD &83,&82,&86,&85

.S571					;Copy user's OSFILE/GBPB block
B571 48        PHA			;to workspace at &1070..81
B572 86 BE     STX &BE
B574 84 BF     STY &BF
B576 A0 11     LDY #&11
.S578
B578 B1 BE     LDA (&BE),Y
B57A 99 70 10  STA &1070,Y
B57D 88        DEY
B57E 10 F8     BPL S578
B580 68        PLA
B581 60        RTS

.S582					;Test EOF (warned flag not set)
B582 B9 9D 10  LDA &109D,Y
.S585
B585 38        SEC			;compare PTR - EXT, channel in Y
B586 F9 9A 10  SBC &109A,Y		;return C=1 if EOF
B589 B9 9E 10  LDA &109E,Y
B58C F9 9B 10  SBC &109B,Y
B58F B9 9F 10  LDA &109F,Y
B592 F9 9C 10  SBC &109C,Y
B595 60        RTS

.S596
B596 B9 88 10  LDA &1088,Y		;Increment PTR.
B599 29 FE     AND #&FE			;11111110;invoked by BGET/BPUT/GBPB.
B59B 99 88 10  STA &1088,Y		;note AXY not saved!
B59E 18        CLC			;clear warning-given flag
B59F B9 94 10  LDA &1094,Y		;get start sector of file
B5A2 79 9E 10  ADC &109E,Y		;add middle & high bytes PTR
B5A5 85 BA     STA &BA			;store &BA,&BB: target page
B5A7 B9 95 10  LDA &1095,Y
B5AA 79 9F 10  ADC &109F,Y
B5AD 85 BB     STA &BB
B5AF B9 89 10  LDA &1089,Y		;is page empty?
B5B2 F0 11     BEQ S5C5			;if so go to set target
B5B4 A5 BA     LDA &BA			;else get target page
B5B6 D9 96 10  CMP &1096,Y		;compare with current page
B5B9 D0 07     BNE S5C2
B5BB A5 BB     LDA &BB
B5BD D9 97 10  CMP &1097,Y
B5C0 F0 24     BEQ S5E6			;if same don't touch page/flag
.S5C2
B5C2 20 0F 98  JSR Q80F			;if different flush page
.S5C5
B5C5 A5 BA     LDA &BA			;set target as current page
B5C7 99 96 10  STA &1096,Y
B5CA A5 BB     LDA &BB
B5CC 99 97 10  STA &1097,Y
B5CF 38        SEC
B5D0 A9 00     LDA #&00			;supposing LSB of PTR = 0,
B5D2 20 85 B5  JSR S585			;would we be at end-of-file?
B5D5 B0 0C     BCS S5E3
B5D7 A9 13     LDA #&13			;if not read current page
B5D9 20 12 98  JSR Q812			;Transfer file buffer to LBA
B5DC A9 01     LDA #&01			;mark as clean
B5DE 99 89 10  STA &1089,Y
B5E1 D0 03     BNE S5E6
.S5E3
B5E3 20 15 B6  JSR S615			;else definite EOF, clear page
.S5E6
B5E6 B9 9D 10  LDA &109D,Y		;get PTR low byte
B5E9 48        PHA			;push it
B5EA 20 0C B4  JSR S40C			;are we really at EOF?
B5ED 08        PHP			;remember for later
B5EE 18        CLC
B5EF B9 9D 10  LDA &109D,Y		;increment PTR nevertheless
B5F2 69 01     ADC #&01
B5F4 99 9D 10  STA &109D,Y
B5F7 B9 9E 10  LDA &109E,Y
B5FA 69 00     ADC #&00
B5FC 99 9E 10  STA &109E,Y
B5FF B9 9F 10  LDA &109F,Y
B602 69 00     ADC #&00
B604 99 9F 10  STA &109F,Y
B607 28        PLP
B608 90 09     BCC S613			;if we weren't at EOF then exit
B60A 20 09 92  JSR Q209			;else extend file
B60D EQUW &9D,&10			;by copying PTR to EXT
B60F EQUW &9A,&10			;(we're still at EOF)
B611 EQUW &03,&11			;return A=offset of byte in buf
.S613
B613 68        PLA
B614 60        RTS

.S615					;Clear page &CA,CB points to
B615 20 00 92  JSR Q200			;Save AXY
B618 A9 00     LDA #&00
B61A A8        TAY
.S61B
B61B 91 CA     STA (&CA),Y
B61D C8        INY
B61E D0 FB     BNE S61B
B620 60        RTS

.S621					;Get byte
B621 20 00 92  JSR Q200			;Save AXY
.S624
B624 20 0C B4  JSR S40C			;test for end-of-file
B627 B0 0C     BCS S635			;if so set warned and exit C=1
B629 20 96 B5  JSR S596			;else increment PTR
B62C A8        TAY
B62D BA        TSX
B62E B1 CA     LDA (&CA),Y		;get byte that PTR had PTd to
B630 9D 05 01  STA &0105,X		;return it in A
B633 18        CLC			;exit C=0
B634 60        RTS

.S635
B635 B9 88 10  LDA &1088,Y		;We've read past end-of-file.
B638 6A        ROR A			;test warning-given flag
B639 B0 07     BCS S642			;if set give EOF error
B63B 38        SEC			;else set warning-given
B63C 2A        ROL A			;flag and return C=1
B63D 99 88 10  STA &1088,Y
B640 38        SEC
B641 60        RTS

.S642
B642 20 18 90  JSR Q018			;raise "EOF" error
B645 EQUB &0A				;error message, LF before
B646 EQUB &DF				;error number &DF
B647 EQUS "EOF"				;message string "EOF"
B64A EQUB &00				;terminator byte
.S64B					;Put byte to file
B64B 20 00 92  JSR Q200			;Save AXY
.S64E
B64E 38        SEC
B64F B9 9E 10  LDA &109E,Y		;compare PTR high bytes
B652 F9 98 10  SBC &1098,Y		; - allocated length
B655 B9 9F 10  LDA &109F,Y
B658 F9 99 10  SBC &1099,Y
B65B 90 40     BCC S69D			;if PTR<len then write byte
B65D 20 1B 98  JSR Q81B			;else check volume is same
B660 20 15 A6  JSR R615			;determine if room to extend
B663 90 27     BCC S68C			;if <=0 then "Cant extend"
B665 F0 25     BEQ S68C
B667 A9 00     LDA #&00			;LSB file length = 0
B669 8D 4E 10  STA &104E
B66C 20 1E A6  JSR R61E			;get ceiling over file into AX
B66F 38        SEC
B670 ED 51 10  SBC &1051		;subtract absolute start sector
B673 8D 4F 10  STA &104F		;store in middle byte of length
B676 99 98 10  STA &1098,Y		;and allocated length of f.h.
B679 8A        TXA			;thereby fully extending file.
B67A ED 52 10  SBC &1052
B67D 8D 50 10  STA &1050
B680 99 99 10  STA &1099,Y
B683 20 06 A6  JSR R606			;pack fields into catalogue
B686 20 03 9B  JSR QB03			;write catalogue
B689 4C 4E B6  JMP S64E			;and try to put the byte again

.S68C
B68C 20 18 90  JSR Q018
B68F EQUB &0A
B690 EQUB &BF
B691 EQUS "Cant extend"
B69C EQUB &00				;terminator byte
.S69D
B69D 20 96 B5  JSR S596			;Write byte. increment PTR
B6A0 48        PHA			;save buffer offset
B6A1 A9 02     LDA #&02
B6A3 99 89 10  STA &1089,Y		;mark buffer dirty
B6A6 68        PLA
B6A7 A8        TAY
B6A8 BA        TSX
B6A9 BD 05 01  LDA &0105,X		;write byte into buffer
B6AC 91 CA     STA (&CA),Y
.S6AE
B6AE 60        RTS

.S6AF					;Check file is writeable
B6AF 20 03 98  JSR Q803
B6B2 30 FA     BMI S6AE
B6B4 20 18 90  JSR Q018
B6B7 EQUB &0A
B6B8 EQUB &C1
B6B9 EQUS "File read only"
B6C7 EQUB &00				; terminator byte
.S6C8
B6C8 A2 FF     LDX #&FF			;Decrement count of bytes
.S6CA
B6CA E8        INX			;remaining to be transferred
B6CB BD 75 10  LDA &1075,X
B6CE F0 FA     BEQ S6CA
.S6D0
B6D0 DE 75 10  DEC &1075,X
B6D3 CA        DEX
B6D4 10 FA     BPL S6D0
.S6D6
B6D6 AD 75 10  LDA &1075		;Compare L=0, return Z
B6D9 0D 76 10  ORA &1076
B6DC 0D 77 10  ORA &1077
B6DF 0D 78 10  ORA &1078
.S6E2
B6E2 60        RTS

B6E3 A9 01     LDA #&01			;Send binary 1
.S6E5
B6E5 A2 00     LDX #&00			;Transfer byte between GBPB
B6E7 2C 3A 10  BIT &103A		;buffer and memory
B6EA 70 0A     BVS S6F6			;103A: b6=Tube, b7=write to mem
B6EC 30 04     BMI S6F2
B6EE A1 BC     LDA (&BC,X)
B6F0 50 07     BVC S6F9
.S6F2
B6F2 81 BC     STA (&BC,X)
B6F4 50 03     BVC S6F9
.S6F6
B6F6 20 09 A0  JSR R009
.S6F9
B6F9 E6 BC     INC &BC
B6FB D0 E5     BNE S6E2
B6FD 4C F3 AF  JMP RFF3			;Increment top 3 bytes of data address


;Monitor
.S700
B700 4C 1E B7  JMP S71E			;OSWORD Monitor

.S703
B703 4C 5C B7  JMP S75C			;ROM Service call monitor

.S706
B706 4C 86 B7  JMP S786			;OSFILE Monitor

.S709
B709 4C B6 B7  JMP S7B6			;OSARGS Monitor

.S70C
B70C 4C D6 B7  JMP S7D6			;OSBGET Monitor

.S70F
B70F 4C EC B7  JMP S7EC			;OSBPUT Monitor

.S712
B712 4C 03 B8  JMP S803			;OSGBPB Monitor

.S715
B715 4C 2E B8  JMP S82E			;OSFIND Monitor

.S718
B718 4C 4A B8  JMP S84A			;Filing system call monitor

B71B 4C 9E B8  JMP S89E			;File access monitor

.S71E					;OSWORD Monitor
B71E 20 00 92  JSR Q200			;Save AXY
B721 AD 0E 10  LDA &100E		;quit if b3 clear
B724 29 08     AND #&08
B726 F0 5D     BEQ S785
B728 A5 EF     LDA &EF
B72A A6 F0     LDX &F0
B72C A4 F1     LDY &F1
B72E 20 C6 B8  JSR S8C6			;start monitor message
B731 20 18 90  JSR Q018			;print immediate "O"
B734 EQUB &40				;plus hex byte in A
B735 EQUB &4F				;(OSWORD call type)
B736 EQUB &00
B737 A9 64     LDA #&64			;d=drive number
B739 20 E5 B8  JSR S8E5
B73C A9 61     LDA #&61			;a=address
B73E 20 F5 B8  JSR S8F5
B741 20 1F B9  JSR S91F
B744 AA        TAX
B745 A9 63     LDA #&63			;c=command
B747 20 E5 B8  JSR S8E5
B74A 8A        TXA 			;if no parameters skip
B74B F0 0C     BEQ S759
.S74D
B74D 20 1F B9  JSR S91F			;else get parameter
B750 20 03 90  JSR Q003			;print space
B753 20 10 B9  JSR S910			;print parameter
B756 CA        DEX			;repeat until all printed
B757 D0 F4     BNE S74D			;then exit monitor
.S759
B759 4C AB B8  JMP S8AB

.S75C					;ROM Service call monitor
B75C 20 00 92  JSR Q200			;Save AXY
B75F AA        TAX
B760 AD 0E 10  LDA &100E
B763 29 02     AND #&02			;Quit if b1 clear
B765 F0 1E     BEQ S785
B767 20 C6 B8  JSR S8C6			;Else start monitor message
B76A 8A        TXA
B76B 20 18 90  JSR Q018			;print "Rom Call "+hex byte
B76E EQUB &40				;(call type)
B76F EQUS "Rom Call "
B778 EQUB &00
B779 98        TYA
B77A 20 18 90  JSR Q018			;print parameter using
B77D EQUB &40				;immediate call as value
B77E EQUS " p="				;is in register not memory
B781 EQUB &00
B782 4C AB B8  JMP S8AB			;exit monitor

.S785
B785 60        RTS

.S786					;OSFILE Monitor
B786 20 00 92  JSR Q200			;Save AXY
B789 20 BC B8  JSR S8BC			;print header
B78C 90 F7     BCC S785			;or quit if monitor b2 clear
B78E 20 18 90  JSR Q018			;print "OSFILE "+call type
B791 EQUB &40
B792 EQUS "OSFILE "
B799 EQUB &00
B79A A9 66     LDA #&66			;f=filename pointer
B79C 20 EB B8  JSR S8EB
B79F A9 64     LDA #&64			;d=load address
B7A1 20 F5 B8  JSR S8F5
B7A4 A9 65     LDA #&65			;e=execution address
B7A6 20 F5 B8  JSR S8F5
B7A9 A9 6C     LDA #&6C			;l=length
B7AB 20 F5 B8  JSR S8F5
B7AE A9 61     LDA #&61			;a=attributes
B7B0 20 F5 B8  JSR S8F5			;exit monitor
B7B3 4C AB B8  JMP S8AB

.S7B6					;OSARGS Monitor
B7B6 20 00 92  JSR Q200			;Save AXY
B7B9 20 BC B8  JSR S8BC			;print header
B7BC 90 C7     BCC S785			;or quit if b2 clear
B7BE 20 18 90  JSR Q018			;print "OSARGS "+call type
B7C1 EQUB &40
B7C2 EQUS "OSARGS "
B7C9 EQUB &00
B7CA 8A        TXA			;transfer X to A
B7CB 20 18 90  JSR Q018			;z=zero page address
B7CE EQUB &40				;might not contain data yet
B7CF EQUS " z="				;so not printing!
B7D2 EQUB &00				;h=handle; exit monitor
B7D3 4C 46 B8  JMP S846

.S7D6					;OSBGET Monitor
B7D6 20 00 92  JSR Q200			;Save AXY
B7D9 20 BC B8  JSR S8BC			;print header
B7DC 90 A7     BCC S785
B7DE 20 18 90  JSR Q018			;print "OSBGET ", no call type
B7E1 EQUB &00
B7E2 EQUS "OSBGET"
B7E8 EQUB &00				;h=handle; exit monitor
B7E9 4C 46 B8  JMP S846

.S7EC					;OSBPUT Monitor
B7EC 20 00 92  JSR Q200			;Save AXY
B7EF 20 BC B8  JSR S8BC			;print header
B7F2 90 91     BCC S785
B7F4 20 18 90  JSR Q018			;print "OSBPUT ", no call type
B7F7 EQUB &40
B7F8 EQUS "OSBPUT "			;h=handle; exit monitor
B7FF EQUB &00
B800 4C 46 B8  JMP S846

.S803					;OSGBPB Monitor
B803 20 00 92  JSR Q200			;Save AXY
B806 20 BC B8  JSR S8BC			;print header
B809 90 79     BCC S884
B80B 20 18 90  JSR Q018			;print "OSGBPB "+call type
B80E EQUB &40
B80F EQUS "OSGBPB "
B816 EQUB &00
B817 A9 68     LDA #&68			;h=handle
B819 20 E5 B8  JSR S8E5
B81C A9 6D     LDA #&6D			;m=address
B81E 20 F5 B8  JSR S8F5
B821 A9 6C     LDA #&6C			;l=length
B823 20 F5 B8  JSR S8F5
B826 A9 70     LDA #&70			;p=pointer
B828 20 F5 B8  JSR S8F5			;exit monitor
B82B 4C AB B8  JMP S8AB

.S82E					;OSFIND monitor
B82E 20 00 92  JSR Q200			;Save AXY
B831 20 BC B8  JSR S8BC			;print header
B834 90 4E     BCC S884
B836 20 18 90  JSR Q018			;print "OSFIND "+call type
B839 EQUB &40
B83A EQUS "OSFIND "
B841 EQUB &00
B842 C9 00     CMP #&00			;if not CLOSE then print
B844 D0 43     BNE S889			;$=string and exit; else:
.S846
B846 98        TYA			;Print " h=" plus hex byte in Y
B847 4C 79 B8  JMP S879			;then exit monitor

.S84A					;Filing system call monitor
B84A 20 00 92  JSR Q200			;Save AXY
B84D 20 BC B8  JSR S8BC			;print header
B850 90 32     BCC S884
B852 20 18 90  JSR Q018			;print "OSFSC "+call type
B855 EQUB &40
B856 EQUS "OSFSC "
B85C EQUB &00
B85D C9 01     CMP #&01			;if type=1 print h=handle, exit
B85F F0 17     BEQ S878
B861 B0 22     BCS S885
B863 8A        TXA			;else print x=X, y=Y, exit
B864 20 18 90  JSR Q018
B867 EQUB &40
B868 EQUS " x="
B86B EQUB &00
B86C 98        TYA
B86D 20 18 90  JSR Q018
B870 EQUB &40
B871 EQUS " y="
B874 EQUB &00
B875 4C AB B8  JMP S8AB

.S878
B878 8A        TXA			;transfer X to A
.S879
B879 20 18 90  JSR Q018			;print " h=" plus hex byte in A
B87C EQUB &40				;then exit monitor
B87D EQUS " h="
B880 EQUB &00
B881 4C AB B8  JMP S8AB

.P884
B884 60        RTS

.S885
B885 C9 06     CMP #&06			;if type>=6 exit, else:
B887 B0 22     BCS S8AB
.S889
B889 20 18 90  JSR Q018			;Dump string value and exit mon
B88C EQUB &00
B88D EQUS " $="
B890 EQUB &00
.S891
B891 20 1F B9  JSR S91F
B894 C9 0D     CMP #&0D
B896 F0 13     BEQ S8AB
B898 20 00 90  JSR Q000			;Print character in A
B89B 4C 91 B8  JMP S891

.S89E					;File access monitor
B89E 20 00 92  JSR Q200			;Save AXY
B8A1 AD 0E 10  LDA &100E		;Print *INFO if b1 set.
B8A4 29 01     AND #&01			;00000001
B8A6 F0 DC     BEQ P884			;exit
B8A8 20 06 A4  JSR R406
.S8AB
B8AB AD 0E 10  LDA &100E		;Exit monitor.
B8AE 10 09     BPL P8B9			;get *OPT 1 monitor byte
.P8B0
B8B0 CA        DEX			;pause if b7=1
B8B1 D0 FD     BNE P8B0
B8B3 88        DEY
B8B4 D0 FA     BNE P8B0
B8B6 4A        LSR A
B8B7 D0 F7     BNE P8B0
.P8B9
B8B9 4C E7 FF  JMP osnewl		;print newline & exit

.S8BC					;print header
B8BC 48        PHA			;test *OPT 1 monitor bit 2
B8BD AD 0E 10  LDA &100E
B8C0 4A        LSR A
B8C1 4A        LSR A
B8C2 4A        LSR A
B8C3 68        PLA
B8C4 90 1E     BCC S8E4			;no message if clear
.S8C6
B8C6 20 18 90  JSR Q018			;Start monitor message
B8C9 EQUB &00
B8CA EQUS "EDOS: "
B8D0 EQUB &00				; terminator byte
B8D1 48        PHA			;set up LDA instruction
B8D2 A9 AD     LDA #&AD			;in stack page
B8D4 8D 20 01  STA &0120		;to load from address in XY
B8D7 8E 21 01  STX &0121
B8DA 8C 22 01  STY &0122
B8DD A9 60     LDA #&60			;follow with RTS
B8DF 8D 23 01  STA &0123
B8E2 68        PLA
B8E3 38        SEC			;return C=1 since mon bit set
.S8E4
B8E4 60        RTS

.S8E5
B8E5 20 14 B9  JSR S914			;Dump 8-bit value.
B8E8 4C 10 B9  JMP S910

.S8EB
B8EB 20 14 B9  JSR S914			;Dump 16-bit value.
B8EE 48        PHA			;print " n=", push low byte
B8EF 20 1F B9  JSR S91F			;get high byte
B8F2 4C 0C B9  JMP S90C			;print hex word

.S8F5
B8F5 20 14 B9  JSR S914			;Dump 32-bit value.
B8F8 48        PHA			;print " n=", push low byte
B8F9 20 1F B9  JSR S91F			;push low middle byte
B8FC 48        PHA
B8FD 20 1F B9  JSR S91F			;push high middle byte
B900 48        PHA
B901 20 1F B9  JSR S91F			;get high byte. Fall though:
B904 20 10 B9  JSR S910			;Print 32-bit hex word (JMP)
B907 68        PLA			;High byte in A, other bytes
B908 20 10 B9  JSR S910			;on stack, pushed in ascending
B90B 68        PLA			;order. Fall through:
.S90C
B90C 20 10 B9  JSR S910			;Print 16-bit hex word (JMP)
B90F 68        PLA			;high byte in A, low byte
.S910
B910 38        SEC			;on stack. print hex byte
B911 4C 0F 90  JMP Q00F

.S914
B914 20 03 90  JSR Q003			;Print " n=" & get byte value
B917 20 00 90  JSR Q000			;print character in A
B91A A9 3D     LDA #&3D			;print = sign
B91C 20 00 90  JSR Q000			;Print character in A, Fall through:
.S91F
B91F 20 20 01  JSR &0120		;call LDA in stack page
B922 EE 21 01  INC &0121		;increment LDA address
B925 D0 03     BNE S92A
B927 EE 22 01  INC &0122
.S92A
B92A 60        RTS

;EDOSPAT extensions, block 5
.S931
B931 C9 7D     CMP #&7D			;compare call number with &7D
B933 90 22     BCC S95E			;if not ours then exit C=0
B935 08        PHP			;else test MOS option byte
B936 78        SEI			;if b7 clear then exit C=1
B937 48        PHA			;to enable the call, else:
B938 A5 A8     LDA &A8			;save state, disable interrupts
B93A 48        PHA			;save call number
B93B A5 A9     LDA &A9			;localise pointer in zero page
B93D 48        PHA
B93E 20 3A 97  JSR Q73A			;test flag in private page
B941 49 41     EOR #&41			;01000001, invert bits 0 and 6
B943 AA        TAX			;hold result
B944 68        PLA
B945 85 A9     STA &A9
B947 68        PLA
B948 85 A8     STA &A8
B94A 68        PLA			;restore call number
B94B 28        PLP			;restore interrupt state
B94C E0 FF     CPX #&FF			;is absolute workspace ours?
B94E B0 07     BCS S956
B950 2C 8F 02  BIT &028F		;else test MOS option byte
B953 30 02     BMI S956
B955 C9 7F     CMP #&7F
.S957
B957 60        RTS

.S958					;OSARGS wrapper
B958 D8        CLD			;clear decimal
B959 20 1A B1  JSR S11A			;call EDOS routine
B95C 38        SEC
B95D 08        PHP
B95E 78        SEI
B95F 85 CD     STA &CD			;map calls FF..03 to 00..04
B961 E9 FF     SBC #&FF			;11111111
B963 C0 01     CPY #&01			;set C=1 if Y>0
B965 2A        ROL			;double call number and add C
B966 B0 0F     BCS S977			;if call was 7F..FE exit C=1
B968 C9 09     CMP #&09
B96A B0 0B     BCS S977			;if call was 04..7E exit C=1
B96C 86 CD     STX &CD			;else transfer to X as index
B96E AA        TAX			;look up return value in table
B96F BD 7B B9  LDA S97B,X		;have it returned in A on exit
B972 A6 CD     LDX &CD
B974 28        PLP
B975 18        CLC
B976 60        RTS

.S977
B977 A5 CD     LDA &CD
B979 28        PLP
.S97A
B97A 60        RTS

.S97B					;table
B97B EQUD &00,&00,&04,&00		;Return values for A=&FF to &03
B97F EQUD &DC,&FF,&01,&00		;in pairs Y=0, then Y>0
B983 EQUW &FF

.S984
B984 2C 8F 02  BIT &028F		;test bit 7 FDC register access emulators.
B987 10 06     BPL S98F			;if unset, branch
.S989
B989 AD 29 FE  LDA fdc_trck
B98C 49 00     EOR #&00			;null invert for 1770
B98E 60        RTS

.S98F
B98F 4C 89 B9  JMP S989

.S992
B992 2C 8F 02  BIT &028F		;test bit 7 FDC register access emulators.
B995 10 06     BPL S99D			;if unset, branch
.S997
B997 AD 2A FE  LDA fdc_sect
B99A 49 00     EOR #&00			;null invert for 1770
B99C 60        RTS

.S99D
B99D 4C 97 B9  JMP S997

.S9A0					;setup drive control register, Y = drive number, X = density
B9A0 2C 8F 02  BIT &028F		;test bit 7 FDC register access emulators.
B9A3 10 07     BPL S9AC			;if unset, branch
.S9A5
B9A5 20 B2 B3  JSR S3B2			;Convert DDOS latch to BBC Master
B9A8 8D 24 FE  STA fdc_cntrl
B9AB 60        RTS

.S9AC
B9AC 4C A5 B9  JMP S9A5

; A = &D0 (11010000)
.S9B2					;send Force Interrupt to command register
B9B2 2C 8F 02  BIT &028F		;test bit 7 FDC register access emulators.
B9B5 10 06     BPL S9BD			;if unset, branch
.S9B7
B9B7 49 00     EOR #&00			;A = &D0 (11010000), null invert for 1770
B9B9 8D 28 FE  STA fdc_comm		;send Force Interrupt
B9BC 60        RTS

.S9BD
B9BD 4C B7 B9  JMP S9B7

.S9C0					;test and write to track register
B9C0 2C 8F 02  BIT &028F		;test bit 7 FDC register access emulators.
B9C3 10 06     BPL S9CB			;if unset, branch
.S9C5
B9C5 49 00     EOR #&00			;null invert for 1770
B9C7 8D 29 FE  STA fdc_trck
B9CA 60        RTS

.S9CB
B9CB 4C C5 B9  JMP S9C5

.S9CE					;test and write to sector register
B9CE 2C 8F 02  BIT &028F		;test bit 7 FDC register access emulators.
B9D1 10 06     BPL S9D9			;if unset, branch
.S9D3
B9D3 49 00     EOR #&00			;null invert for 1770
B9D5 8D 2A FE  STA fdc_sect
B9D8 60        RTS

.S9D9
B9D9 4C D3 B9  JMP S9D3

.S9DC
B9DC 2C 8F 02  BIT &028F		;if unset, branch
B9DF 10 06     BPL S9E7			;test bit 7 FDC register access emulators.
.S9E1
B9E1 49 00     EOR #&00			;null invert for 1770
B9E3 8D 2B FE  STA fdc_data
B9E6 60        RTS

.S9E7
B9E7 4C E1 B9  JMP S9E1

.S9EA
B9EA 2C 8F 02  BIT &028F		;if unset, branch
B9ED 10 04     BPL S9F3			;test bit 7 FDC register access emulators.
.S9EF
B9EF EE 2A FE  INC fdc_sect
B9F2 60        RTS

.S9F3
B9F3 4C EF B9  JMP S9EF			;would be JSR S997

					;increment virtual sector register
B9F6 08        PHP			;unused routine
B9F7 18        CLC			;would be needed for e.g. GoMMC
B9F8 69 01     ADC #&01
B9FA 28        PLP
B9FB 49 00     EOR #&00
B9FD 4C D3 B9  JMP S9D3


;EDOS API, part 3: OSWORD
.SA00					;OSWORD
BA00 20 00 92  JSR Q200			;Save AXY
BA03 18        CLC			;clear carry flag
BA04 A5 EF     LDA &EF			;if OSWORD call >=&80
BA06 30 05     BMI SA0D			;then return
BA08 20 31 B9  JSR S931			;if < &7D or no wksp then return
BA0B B0 01     BCS SA0E			;(C=0; passed to lower ROMs)
.SA0D
BA0D 60        RTS

.SA0E
BA0E 58        CLI
BA0F C9 7F     CMP #&7F			;if not &7F (ie &7D or &7E)
BA11 F0 03     BEQ SA16			;then process via hook
BA13 4C C6 B3  JMP S3C6

.SA16
BA16 A0 06     LDY #&06			;else &7F disc op.
BA18 B1 F0     LDA (&F0),Y		;get command byte
BA1A 29 3F     AND #&3F			;00111111 mask it
BA1C A2 00     LDX #&00			;search for it in table
.SA1E
BA1E DD FD BA  CMP SAFD,X		;OSWORD &7F 8271 command lookup table
BA21 F0 0E     BEQ SA31			;if found carry on
BA23 48        PHA			;else go to next row
BA24 8A        TXA			;8 bytes in each row
BA25 18        CLC
BA26 69 08     ADC #&08
BA28 AA        TAX
BA29 68        PLA
BA2A E0 70     CPX #&70			;have we reached end of table?
BA2C D0 F0     BNE SA1E			;if so unrecognised command
BA2E 4C FC BA  JMP SAFC			;so quit C=1 (hook)

.SA31
BA31 BD FE BA  LDA SAFE,X		;get microcode
BA34 29 10     AND #&10			;if b4 set
BA36 F0 13     BEQ SA4B
BA38 A0 07     LDY #&07			;then get first 8271 parameter
BA3A B1 F0     LDA (&F0),Y		;(special register number)
BA3C C9 05     CMP #&05			;if none of these values
BA3E F0 0B     BEQ SA4B
BA40 C9 12     CMP #&12
BA42 F0 07     BEQ SA4B
BA44 C9 1A     CMP #&1A
BA46 F0 03     BEQ SA4B			;then quit.
BA48 4C FC BA  JMP SAFC

.SA4B
BA4B 20 00 B7  JSR S700			;call OSWORD monitor
BA4E A0 00     LDY #&00			;get O7F drive number
BA50 B1 F0     LDA (&F0),Y		;A = OSWORD X register value
BA52 10 01     BPL SA55			;if top bit clear, branch
BA54 C8        INY			;else, copy it to workspace.
.SA55
BA55 B1 F0     LDA (&F0),Y		;copy rest of block to worksp.
BA57 99 10 10  STA &1010,Y		;OSWORD &7F block
BA5A C8        INY
BA5B C0 0C     CPY #&0C
BA5D D0 F6     BNE SA55
BA5F 20 06 92  JSR Q206			;copy
BA62 EQUW &F0,&00			;FROM user O7F block address &00F0
BA64 EQUW &1C,&10			;TO workspace at &101C
BA66 EQUB &02				;count
BA67 EA        NOP
BA68 EA        NOP
BA69 EA        NOP
BA6A BD FE BA  LDA SAFE,X		;get microcode
BA6D 29 60     AND #&60			;01100000 ;if b5 and b6 clear
BA6F F0 1A     BEQ SA8B			;then start O7F command
BA71 AD 17 10  LDA &1017		;else get track number
BA74 20 40 BE  JSR SE40			;test if drive double-stepped
BA77 90 01     BCC SA7A			;if so
BA79 0A        ASL A			;then double track number.
.SA7A
BA7A 20 CF BB  JSR SBCF			;seek that track
BA7D C9 FF     CMP #&FF			;if Escape pressed during seek
BA7F D0 03     BNE SA84
BA81 4C 9A BB  JMP SB9A			;save status and ack. error.

.SA84
BA84 29 99     AND #&99			;if { NotReady RecordNotFound
BA86 F0 03     BEQ SA8B			;CRCError Busy } any are set
BA88 4C 6D BB  JMP SB6D			;then finish O7F, else:

.SA8B
BA8B BD FE BA  LDA SAFE,X		;Start O7F command.
.SA8B
BA8E 29 20     AND #&20			;00100000 ;test b5 of microcode
BA90 F0 08     BEQ SA9A			;if set
BA92 20 43 BC  JSR SC43			;prepare for read/write
BA95 D0 03     BNE SA9A			;if no. sectors to transfer =0
BA97 4C 6D BB  JMP SB6D			;then finish O7F, else:

.SA9A
BA9A 20 06 92  JSR Q206			;Save original transfer address in z.p.
BA9D EQUW &11,&10			;FROM address &1011
BA9F EQUW &A2,&00			;TO address &00A2
BAA1 EQUB &02				;count
BAA2 A9 00     LDA #&00
BAA4 8D 65 0D  STA &0D65
BAA7 AD 13 10  LDA &1013		;part of OSWORD &7F block
BAAA 2D 14 10  AND &1014		;test high bits of address
BAAD 49 FF     EOR #&FF			;invert - if any are clear
BAAF 2D 7A 02  AND &027A		;and Tube is present, then:
BAB2 F0 1E     BEQ SAD2
BAB4 BD FE BA  LDA SAFE,X		;a Tube transfer. Get microcode
BAB7 29 03     AND #&03			;00000011 ;test two low bits
BAB9 F0 06     BEQ SAC1			;if either one is set
BABB 20 5B BC  JSR SC5B			;open channel 3 for data
BABE 8D 64 0D  STA &0D64		;set Tube flag >0
.SAC1
BAC1 BC 01 BB  LDY SB01,X		;get offset of NMI code
BAC4 F0 28     BEQ SAEE			;if zero there's no NMI handler
BAC6 20 09 92  JSR Q209			;Copy NMI handler
BAC9 EQUW &A4,&BE			;from &BEA4
BACB EQUW &00,&0D			;to &0D00
BACD EQUW &20,&10
BACF 4C EE BA  JMP SAEE

.SAD2
BAD2 BC FF BA  LDY SAFF,X		;an I/O transfer. Get NMI
BAD5 F0 17     BEQ SAEE			;offset, no handler if zero.
BAD7 20 09 92  JSR Q209			;Copy NMI handler
BADA EQUW &A4,&BE			;from &BEA4
BADC EQUW &00,&0D			;to &0D00
BADE EQUW &20,&10
BAE0 BC 00 BB  LDY SB00,X		;does NMI take an address?
BAE3 F0 09     BEQ SAEE			;0=no address / fixed address
BAE5 20 09 92  JSR Q209			;if so copy bytes
BAE8 EQUW &11,&10			;from O7F address low at &1011
BAEA EQUW &FF,&0C			;to NMI handler at &0CFF(the address of an LDA/STA.)
BAEC EQUW &02,&01
.SAEE
BAEE BD 02 BB  LDA SB02,X		;get 2793 command
BAF1 49 00     EOR #&00			;null invert for 1770
BAF3 A8        TAY
BAF4 BD 04 BB  LDA SB04,X		;get jump-table address
BAF7 48        PHA			;A -> (SP) = MSB
BAF8 BD 03 BB  LDA SB03,X		;for command routine (minus 1 of course)
BAFB 48        PHA			;A -> (SP) = LSB
.SAFC
BAFC 60        RTS			;and jump to the routine.

.SAFD					;OSWORD &7F 8271 command lookup table.
BAFD EQUB &36				;  &36 Force interrupt
.SAFE					;microcode table
BAFE EQUB &00				;  0 = no microcoded actions
.SAFF					;1 + address of I/O ISR
BAFF EQUB &00				;  0 = no ISR needed
.SB00					;1 + offset of address within I/O ISR
BB00 EQUB &00				;  0 = fixed or no address
.SB01					;1 + address of Tube ISR
BB01 EQUB &00				;  0 = no ISR needed
.SB02					;Equivalent 2791 command
BB02 EQUB &D0				;  &D0 = Force Interrupt
.SB03					;OSWORD &7F command jump table
BB03 EQUB &4E				;\
.SB04					; >&BE4E+1 = &BE4F = send Force Interrupt to command register
BB04 EQUB &BE				;/

BB05 EQUB &13				;&13 Read data
BB06 EQUD &E2,&31,&10,&4D,&80		;parameters
BB0B EQUB &69,&BC			;&BC69+1=&BC6A = Read data command

BB0D EQUB &0B				;&0B Write data
BB0E EQUD &E1,&01,&0B,&1D,&A0		;parameters
BB13 EQUW &65,&BC			;&BC65+1=&BC66 = Write data command

BB15 EQUB &29				;&29 Seek
BB16 EQUD &40,&00,&00,&00,&00		;parameters
BB1B EQUW &BE,&BC			;&BCBE+1=&BCBF = Seek command

BB1D EQUB &1F				;&1F Verify data
BB1E EQUD &E0,&99,&00,&99,&80		;parameters
BB23 EQUW &65,&BC,			;&BC65+1=&BC66 = Write data command

BB25 EQUB &17				;&17 Read data & deleted data
BB26 EQUD &E2,&31,&10,&4D,&80		;parameters
BB2B EQUW &65,&BC 			;&BC65+1=&BC66 = Write data command

BB2D EQUB &0F	 			;&0F Write deleted data
BB2E EQUD &E1,&01,&0B,&1D,&A1		;parameters
BB33 EQUW &65,&BC 			;&BC65+1=&BC66 = Write data command

BB35 EQUB &1B	 			;&1B Read ID
BB36 EQUD &62,&61,&14,&81,&C4		;parameters
BB3B EQUW &AD,&BC			;&BCAD+1=&BCAE = Read ID command

BB3D EQUB &23				;&23 Format track
BB3E EQUD &C1,&9D,&00,&9D,&F4		;parameters
BB43 EQUW &CF,&BC			;&BCCF+1=&BCD0 = Format command

BB45 EQUB &24				;&24 (Write track)
BB46 EQUD &41,&01,&0B,&1D,&F4		;parameters
BB4B EQUW &A5,&BD			;&BDA5+1=&BDA6 = Do disc op and finish O7F

BB4D EQUB &25				;&25 (Read track)
BB4E EQUD &42,&31,&10,&4D,&E4		;parameters
BB53 EQUW &A5,&BD			;&BDA5+1=&BDA6 = Do disc op and finish O7F

BB55 EQUB &2C				;&2C Read drive status
BB56 EQUD &00,&00,&00,&00,&00		;parameters
BB5B EQUW &AB,&BD			;&3BDAB+1=&BDAC =

BB5D EQUB &3A				;&3A Write special registers
BB5E EQUD &10,&00,&00,&00,&00		;parameters
BB63 EQUW &E9,&BD			;&BDE9+1=&BDEA = Write special registers

BB65 EQUB &3D				;&3D Read special registers
BB66 EQUD &10,&00,&00,&00,&00		;parameters
BB6B EQUW &11,&BE			;&BE11+1=&BE12 = Read special registers

.SB6D
BB6D C9 FF     CMP #&FF			;Finish OSWORD &7F.
BB6F F0 15     BEQ SB86			;Bogus status? else 2791 result
BB71 29 7C     AND #&7C			;01111100 ;mask off { NotReady Track
BB73 F0 11     BEQ SB86			;Index } if other bits then
BB75 A2 05     LDX #&05			;error. search in table
.SB77
BB77 DD C3 BB  CMP SBC3,X
BB7A F0 07     BEQ SB83			;found.
BB7C CA        DEX
BB7D 10 F8     BPL SB77
BB7F 09 01     ORA #&01			;00000001 ;not found.
BB81 D0 03     BNE SB86
.SB83
BB83 BD C9 BB  LDA SBC9,X		;if found get 8271 equivalent
.SB86
BB86 48        PHA
BB87 AD 64 0D  LDA &0D64		;was it a Tube transfer?
BB8A F0 03     BEQ SB8F			;if so
BB8C 20 0C A0  JSR R00C			;close Tube channel 3.
.SB8F
BB8F A2 0B     LDX #&0B			;issue Rom Call &0B,
BB91 AC 61 0D  LDY &0D61		;release NMI. give our ROM
BB94 A9 8F     LDA #&8F			;number as parameter
BB96 20 F4 FF  JSR osbyte
BB99 68        PLA
.SB9A
BB9A 20 06 92  JSR Q206			;copy user's O7F block address to zero page
BB9D EQUW &1C,&10			;FROM address &101C
BB9F EQUW &A0,&00			;TO address &00A0
BBA1 EQUB &02				;count
BBA2 48        PHA
BBA3 A0 05     LDY #&05			;get no. parameters to command
BBA5 B1 A0     LDA (&A0),Y
BBA7 18        CLC			;point to byte after parameters
BBA8 69 07     ADC #&07
BBAA A8        TAY
BBAB 68        PLA			;store O7F result there
BBAC 91 A0     STA (&A0),Y
BBAE EA        NOP
BBAF EA        NOP
BBB0 EA        NOP
BBB1 C9 FF     CMP #&FF			;if bogus status returned
BBB3 D0 0C     BNE SBC1
BBB5 20 18 90  JSR Q018			;give Escape error
BBB8 EQUB &0A				;linefeed
BBB9 EQUB &11
BBBA EQUS "Escape"
BBC0 EQUB &00
.SBC1
BBC1 38        SEC			;else end OSWORD & break ROM
BBC2 60        RTS			;call chain.

.SBC3					;2793 error table 0..5
BBC3 EQUD &04,&08,&10,&18
BBC7 EQUW &20,&40

.SBC9					;8271 equivalent errors
BBC9 EQUD &0A,&0E,&18,&0C
BBCD EQUW &20,&12

.SBCF					;seek that track
BBCF 20 00 92  JSR Q200			;Save AXY
BBD2 48        PHA
BBD3 A2 0C     LDX #&0C			;Y = parameter passed = issue Rom Call &0B,
BBD5 A0 FF     LDY #&FF			;X = reason code = claim NMI
BBD7 A9 8F     LDA #&8F			;A = call No.
BBD9 20 F4 FF  JSR osbyte		;call OSBYTE &8F = Paged ROM Service Request
BBDC 8C 61 0D  STY &0D61		;Y = previous owner
BBDF 20 06 92  JSR Q206			;copy memory absolute
BBE2 EQUW &66,&BE			;from disc op code at &BE66
BBE4 EQUW &20,&0D			;to &0D20
BBE6 EQUB &40				;No. of bytes
BBE7 A9 40     LDA #&40			;= RTI instruction
BBE9 8D 00 0D  STA &0D00		;store it at NMI entry point
BBEC A9 10     LDA #&10			;set retry counter = 16
BBEE 8D 62 0D  STA &0D62
BBF1 A9 00     LDA #&00			;set Tube flag = 0
BBF3 8D 64 0D  STA &0D64
BBF6 AD 10 10  LDA &1010		;A = OSWORD &7F block = drive
BBF9 29 03     AND #&03			;00000011 mask bits 2-7, bits 0-1 = drive number
BBFB A8        TAY			;A -> Y = drive number
BBFC BE 20 10  LDX &1020,Y		;get DEN for drive in X, 0FF0,X Density of drives 0..3  0A=SD 12=DD
BBFF E0 12     CPX #&12			;if =18 sectors/track
BC01 D0 02     BNE SC05			;set MFM latch bit
BC03 09 40     ORA #&40			;01000000, set bit 6 (DEN)
.SC05
BC05 20 A0 B9  JSR S9A0			;setup drive control register
BC08 20 36 BE  JSR SE36			;get track no. under head
BC0B 20 C0 B9  JSR S9C0			;test and write to track register
BC0E 49 00     EOR #&00			;null invert
BC10 A0 08     LDY #&08			;=Restore command
BC12 68        PLA			;recover logical track number
BC13 F0 07     BEQ SC1C			;if >0
BC15 20 DC B9  JSR S9DC
BC18 49 00     EOR #&00
BC1A A0 18     LDY #&18			;=Seek command
.SC1C
BC1C 8C 63 0D  STY &0D63		;Temp. 2791 command
BC1F AD 8F 02  LDA &028F		;get MOS option byte
BC22 4A        LSR A			;b4..b5 = stepping rate
BC23 4A        LSR A			;default = 11 = slowest
BC24 4A        LSR A
BC25 4A        LSR A
BC26 29 03     AND #&03			;00000011 mask bits 2-7, bits 0-1 =
BC28 0D 63 0D  ORA &0D63		;merge into 2791 command
BC2B 49 00     EOR #&00			;null invert
BC2D A8        TAY
BC2E 20 5B BE  JSR SE5B			;do disc operation
BC31 48        PHA			;save result status
BC32 20 36 BE  JSR SE36			;get track no. under head/set X to actuator number
BC35 20 84 B9  JSR S984
BC38 49 00     EOR #&00			;null invert
BC3A 9D 1E 10  STA &101E,X		;set new track no. under head
BC3D 68        PLA
BC3E BA        TSX
BC3F 9D 05 01  STA &0105,X		;return status in A
BC42 60        RTS

.SC43					;Prepare for read/write.
BC43 AD 17 10  LDA &1017		;A = track number
BC46 20 C0 B9  JSR S9C0			;test and write to track register
BC49 49 00     EOR #&00			;store track register
BC4B AD 18 10  LDA &1018		;get O7F sector no.
BC4E 20 CE B9  JSR S9CE			;test and write to sector register
BC51 49 00     EOR #&00			;null invert
.SC53
BC53 AD 19 10  LDA &1019		;Get no. sectors
BC56 29 1F     AND #&1F			;00011111 ;mask off sector size bits
BC58 85 A4     STA &A4			;store in counter for later
BC5A 60        RTS

.SC5B					;Open Tube channel to O7F addr
BC5B 20 00 92  JSR Q200			;Save AXY
BC5E 4A        LSR A
BC5F A2 11     LDX #&11
BC61 A0 10     LDY #&10
BC63 4C 06 A0  JMP R006

					;called from jump table at &BB13
BC66 A9 00     LDA #&00			;Write data command
BC68 F0 02     BEQ SC6C
					;called from jump table at &BB0B
BC6A A9 FF     LDA #&FF			;Read data command
.SC6C
BC6C 8D 66 0D  STA &0D66
.SC6F
BC6F 20 5B BE  JSR SE5B			;do disc op, return status
BC72 C9 20     CMP #&20			;if { Ready DeletedData }
BC74 F0 08     BEQ SC7E			;then scrub last sector
BC76 E6 A3     INC &A3
BC78 29 DF     AND #&DF			;11011111 ;else mask off { HeadLoaded }
BC7A D0 2F     BNE SCAB			;other bits? finish O7F
BC7C F0 23     BEQ SCA1			;no other bits? do next sector
.SC7E
BC7E 8D 65 0D  STA &0D65		;Scrub sector. save status
BC81 AD 66 0D  LDA &0D66		;if Write Data command
BC84 F0 1B     BEQ SCA1			;then we requested it, carry on
BC86 AD 64 0D  LDA &0D64		;else is Read. if I/O transfer
BC89 D0 06     BNE SC91
BC8B CE 0B 0D  DEC &0D0B
BC8E 4C A1 BC  JMP SCA1			;and do next sector

.SC91
BC91 20 0C A0  JSR R00C			;else close TUBE channel
BC94 20 06 92  JSR Q206			;and copy address to O7F block
BC97 EQUW &A2,&00			;FROM address &00A2 to &1011
BC99 EQUW &11,&10			;scrubbing all sectors in track.
BC9B EQUB &02				;i/o only scrubs the deleted one
BC9C A9 02     LDA #&02
BC9E 20 5B BC  JSR SC5B			;and open Tube channel
.SCA1
BCA1 20 EA B9  JSR S9EA
BCA4 C6 A4     DEC &A4			;decrement sector count
BCA6 D0 C7     BNE SC6F			;loop if more sectors
BCA8 AD 65 0D  LDA &0D65		;else retrieve status
.SCAB
BCAB 4C 6D BB  JMP SB6D			;post disc op

.SCAE					;called from jump table
BCAE A9 04     LDA #&04			;Read ID command. 4 bytes to get
BCB0 85 A1     STA &A1			;save in counter
BCB2 20 5B BE  JSR SE5B			;do disc op
BCB5 D0 0D     BNE SCC4			;if status = zero
BCB7 98        TYA			;then set b2 of command
BCB8 09 04     ORA #&04			;00000100 ;{ SettlingDelay }
BCBA A8        TAY
BCBB C6 A4     DEC &A4			;decrement sector counter
BCBD D0 EF     BNE SCAE			;repeat command if more.
					;called from jump table at &BB1B
BCBF A9 00     LDA #&00			;else finish with zero status.
.SCC1
BCC1 4C 6D BB  JMP SB6D

.SCC4
BCC4 C9 08     CMP #&08			;was there a { CRCError } ?
BCC6 D0 F9     BNE SCC1			;if not then finish.
BCC8 CE 62 0D  DEC &0D62		;decrement retry counter
BCCB F0 F4     BEQ SCC1			;exit if run out
BCCD 4C 8B BA  JMP SA8B			;else restart command.

;Format command				;called from jump table
BCD0 8C 63 0D  STY &0D63
BCD3 A0 00     LDY #&00			;zero RLE table index
BCD5 84 A1     STY &A1			;store index at &00A1
BCD7 20 53 BC  JSR SC53			;set &A4 = no. sectors
BCDA AD 19 10  LDA &1019		;get no. sectors
BCDD 0A        ASL A
BCDE 0A        ASL A
BCDF 0A        ASL A			;multiply by 8
BCE0 85 A0     STA &A0			;save in temp.
BCE2 AD 10 10  LDA &1010		;A = OSWORD &7F block = drive number 0..3
BCE5 29 03     AND #&03			;00000011 mask bits 2-7, bits 0-1 = drive number
BCE7 24 A0     BIT &A0			;if no. sectors >=16
BCE9 10 02     BPL SCED
BCEB 09 40     ORA #&40			;01000000, then set double density bit.
.SCED
BCED 20 A0 B9  JSR &S9A0		;setup drive control register
BCF0 AE 1B 10  LDX &101B		;get gap1 length
.SCF3
BCF3 A9 FE     LDA #&FE			;do gap (&FE emits IDAM)
BCF5 20 41 BD  JSR SD41
BCF8 24 A0     BIT &A0			;if SD
BCFA 30 09     BMI SD05
BCFC 20 66 BD  JSR SD66			;then fetch C byte
BCFF 20 66 BD  JSR SD66			;fetch H byte
BD02 4C 0F BD  JMP SD0F

.SD05
BD05 A2 02     LDX #&02			;else fetch C byte,
BD07 20 68 BD  JSR SD68			;to be sent twice (C and H)
BD0A 20 66 BD  JSR SD66			;fetch H byte
BD0D C6 A1     DEC &A1			;and discard.
.SD0F
BD0F 20 66 BD  JSR SD66			;fetch R byte
BD12 20 66 BD  JSR SD66			;fetch N byte
BD15 20 79 BD  JSR SD79			;place CRC here
BD18 A2 0B     LDX #&0B			;gap2 = 11 if SD,
BD1A 24 A0     BIT &A0
BD1C 10 02     BPL SD20
BD1E A2 16     LDX #&16			;or 22 if DD.
.SD20
BD20 A9 FB     LDA #&FB			;append gap (&FB emits DAM)
BD22 20 41 BD  JSR SD41
BD25 A9 E5     LDA #&E5			;append sector
BD27 A2 00     LDX #&00			;256 x &E5
BD29 20 88 BD  JSR SD88
BD2C 20 79 BD  JSR SD79			;append CRC
BD2F AE 18 10  LDX &1018		;get gap3 length specified in
BD32 C6 A4     DEC &A4			;O7F param 2. Dec sector count
BD34 D0 BD     BNE SCF3			;loop if more sectors
BD36 A2 00     LDX #&00			;else append gap4
BD38 20 80 BD  JSR SD80
BD3B AC 63 0D  LDY &0D63		;get command
BD3E 4C A6 BD  JMP SDA6			;do it and finish.

.SD41
BD41 20 00 92  JSR Q200			;Save AXY;Append gap to byte stream.
BD44 20 80 BD  JSR SD80			;Write initial part (X=length)
BD47 A9 00     LDA #&00			;if SD
BD49 A2 06     LDX #&06			;then append 6 x &00
BD4B 24 A0     BIT &A0
BD4D 10 0B     BPL SD5A
BD4F A9 00     LDA #&00			;else append 12 x &00
BD51 A2 0C     LDX #&0C
BD53 20 88 BD  JSR SD88
BD56 A9 F5     LDA #&F5			;then 3 x &F5 sync tokens
BD58 A2 03     LDX #&03
.SD5A
BD5A 20 88 BD  JSR SD88
BD5D BA        TSX			;retrieve A on entry
BD5E BD 05 01  LDA &0105,X
BD61 A2 01     LDX #&01			;add address mark and exit
BD63 4C 88 BD  JMP SD88

.SD66
BD66 A2 01     LDX #&01			;Fetch 1xbyte from I/O/Tube:
.SD68
BD68 AD 64 0D  LDA &0D64		;Fetch byte from I/O/Tube
BD6B F0 06     BEQ SD73			;to be repeated X times.
BD6D AD E5 FE  LDA tubeR3data		;If Tube, read FIFO 3
BD70 4C 76 BD  JMP SD76

.SD73
BD73 B1 A2     LDA (&A2),Y		;else read from (XY+1)
BD75 C8        INY			;and increment pointer
.SD76
BD76 4C 88 BD  JMP SD88			;add to RLE table and exit

.SD79
BD79 A9 F7     LDA #&F7			;Add CRC token to table.
BD7B A2 01     LDX #&01
BD7D 4C 88 BD  JMP SD88

.SD80
BD80 A9 FF     LDA #&FF			;Add first part of gap.
BD82 24 A0     BIT &A0			;if SD then value = &FF
BD84 10 02     BPL SD88
BD86 A9 4E     LDA #&4E			;else value = &4E.
.SD88
BD88 20 00 92  JSR Q200			;Save AXY;Add (byte,runlen) to table
BD8B A4 A1     LDY &A1			;get RLE table pointer
BD8D 99 00 0E  STA &0E00,Y		;store byte value
BD90 8A        TXA
BD91 99 00 0F  STA &0F00,Y		;store run length
BD94 E6 A1     INC &A1			;increment table pointer
BD96 F0 01     BEQ SD99			;"Bad spt" error if overrun
BD98 60        RTS			;else exit.

.SD99
BD99 20 18 90  JSR Q018
BD9C EQUB &0A
BD9D EQUB &D0
BD9E EQUS "Bad spt"
BDA5 EQUB &00
.SDA6					;called from jump table
BDA6 20 5B BE  JSR SE5B			;Do disc op and finish O7F.
BDA9 4C 6D BB  JMP SB6D

					;called from jump table
BDAC 20 36 BE  JSR SE36			;get track no. under head
BDAF 20 CF BB  JSR SBCF			;seek that track
BDB2 48        PHA			;Read drive status.
BDB3 A0 81     LDY #&81			;Preset b7 = unused,
BDB5 68        PLA			;b0 = "CNT/OP1"
BDB6 48        PHA			;if { Ready }
BDB7 30 10     BMI SDC9
BDB9 AD 10 10  LDA &1010		;A = OSWORD &7F block,
BDBC 4A        LSR A			;then set relevant RDYn bit according to O7F drive;
BDBD 90 06     BCC SDC5
BDBF 98        TYA
BDC0 09 40     ORA #&40			;01000000 = set b6 = RDY1
BDC2 A8        TAY
BDC3 D0 04     BNE SDC9
.SDC5
BDC5 98        TYA
BDC6 09 04     ORA #&04			;00000100 = set b2 = RDY0
BDC8 A8        TAY
.SDC9
BDC9 68        PLA
BDCA 48        PHA
BDCB 29 40     AND #&40			;01000000 ;if { WriteProtect }
BDCD F0 04     BEQ SDD3
BDCF 98        TYA
BDD0 09 08     ORA #&08			;00001000 then set b3 = WRPROT
BDD2 A8        TAY
.SDD3
BDD3 68        PLA
BDD4 48        PHA
BDD5 29 04     AND #&04			;00000100 ;if { Track00 }
BDD7 F0 04     BEQ SDDD
BDD9 98        TYA
BDDA 09 02     ORA #&02			;00000010 ;then set b1 = TRACK0
BDDC A8        TAY
.SDDD
BDDD 68        PLA
BDDE 29 02     AND #&02			;00000010 ;if { Index }
BDE0 F0 04     BEQ SDE6
BDE2 98        TYA
BDE3 09 10     ORA #&10			;00010000 ;then set b4 = INDEX
BDE5 A8        TAY
.SDE6
BDE6 98        TYA
BDE7 4C 9A BB  JMP SB9A			;store result and exit

; Write special registers, called from jump table
BDEA AD 17 10  LDA &1017		;A = track number
BDED C9 05     CMP #&05
BDEF F0 14     BEQ SE05			;if not register 5
BDF1 20 2D BE  JSR SE2D			;then set X b0 = parm b3
BDF4 AD 18 10  LDA &1018		;get track no. to write
BDF7 20 40 BE  JSR SE40			;if drive is double-stepped
BDFA 90 01     BCC SDFD
BDFC 0A        ASL A			;double the track number.
.SDFD
BDFD 9D 1E 10  STA &101E,X		;store in workspace
BE00 A9 00     LDA #&00			;return zero status.
BE02 4C 9A BB  JMP SB9A

.SE05
BE05 AD 18 10  LDA &1018		;&05 (Current sector)
BE08 20 CE B9  JSR S9CE			;test and write to sector register
BE0B 49 00     EOR #&00			;null invert for 1770
BE0D A9 00     LDA #&00			;return zero status
BE0F 4C 9A BB  JMP SB9A

; Read special registers,  called from jump table
BE12 AD 17 10  LDA &1017		;A = track number
BE15 C9 05     CMP #&05
BE17 F0 0C     BEQ SE25			;if not register 5
BE19 20 2D BE  JSR SE2D			;then set X b0 = parm b3
BE1C 20 40 BE  JSR SE40			;test if drive is double-stepped
BE1F 90 01     BCC SE22
BE21 4A        LSR A			;then halve the track number
.SE22
BE22 4C 9A BB  JMP SB9A			;return value as result

.SE25
BE25 20 92 B9  JSR S992			;read sector register
BE28 49 00     EOR #&00			;null invert
BE2A 4C 9A BB  JMP SB9A			;return value as result

.SE2D
BE2D AD 17 10  LDA &1017		;A = track number/&12, &1A (Current track)
BE30 4A        LSR A			;returns track under head of
BE31 4A        LSR A			;drives 0 and 1; 8271 returns
BE32 4A        LSR A			;track for surfaces 0 and 1
BE33 4C 39 BE  JMP SE39			;fall through:

.SE36
BE36 AD 10 10  LDA &1010		;A = OSWORD &7F block = track no. under head
.SE39
BE39 29 01     AND #&01			;00000001 = mask bit 1-7, bit 0 = drive number
BE3B AA        TAX			;A -> X = drive specified in the OSWORD &7F command
BE3C BD 1E 10  LDA &101E,X		;A = Track no. under heads on drives 0&2, 1&3
BE3F 60        RTS

.SE40					;Test if drive is double-stepped
BE40 20 00 92  JSR Q200			;Save AXY
BE43 AD 10 10  LDA &1010		;A = OSWORD &7F block = drive number
BE46 29 03     AND #&03			;00000011, mask bits 2-7, bis 0-1 = drive number
BE48 A8        TAY
BE49 B9 28 10  LDA &1028,Y		;get track stepping for drive
BE4C C9 01     CMP #&01			;return C=1 if enabled.
BE4E 60        RTS

					;from where is this called?
BE4F A9 D0     LDA #&D0			;A = Force interrupt, 11010000
BE51 20 B2 B9  JSR S9B2			;send Force Interrupt to command register
BE54 49 00     EOR #&00			;null invert for 1770
BE56 A9 00     LDA #&00			;return zero result
BE58 4C 9A BB  JMP SB9A

.SE5B					;Do disc op.
BE5B A5 F4     LDA rmslrg		;save EDOS socket
BE5D 8D 60 0D  STA &0D60		;number in NMI area
BE60 AD 87 10  LDA &1087		;get *OPT 9 saverom
;BE63 4C A7 B3  JMP S3A7
BE63 4C A0 B3  JMP S3A0

; disc op code/Disc ancillary loop	;called by routine at &BBDF to copy &3F btes to &0D20
BE66 85 F4       STA rmslrg		;set ROM bank to *OPT 9 saverom
BE68 8D 30 FE    STA romselr
.SE6B
;BE6B AD 84 FE    LDA fdc_stat		;FDC status -> A
BE6B AD 28 FE	LDA fdc_stat		;FDC status -> A
BE6E 49 20       EOR #&20		;00100000 - if { NotReady SpinUpComplete } toggle bit 5 = spinup
BE70 29 A0       AND #&A0		;10100000 - mask bits 0-5 and 7 (bit 6 = WRP)
BE72 F0 F7       BEQ SE6B
;BE74 8C 84 FE    STY fdc_comm		;Y -> FDC command register
BE74 8C 28 FE	STY fdc_comm		;Y -> FDC command register
BE77 A9 14       LDA #&14		;allow status register
BE79 E9 01       SBC #&01		;to settle (50 us)
BE7B D0 FC       BNE &BE79
.SE7D					;poll status register
;BE7D AD 84 FE    LDA fdc_stat		;FDC status -> A
BE7D AD 28 FE	LDA fdc_stat		;FDC status -> A
BE80 49 80       EOR #&80		;if Ready then test Busy flag toggle bit 7 = Motor On
BE82 10 12       BPL SE96		;or Escape flag clear
BE84 AD 16 10    LDA &1016		;then poll again
BE87 25 FF       AND &FF		;else issue Restore command
BE89 10 F2       BPL SE7D
BE8B A9 00       LDA #&00
BE8D 49 00       EOR #&00		;nullifies invert for 1770
;BE8F 8D 84 FE    STA fdc_comm		;zero FDC command register
BE8F 8D 28 FE	STA fdc_comm		;zero FDC command register = restore
BE92 A9 FF       LDA #&FF		;&FF -> A
BE94 D0 04       BNE SE9A		;and exit with bogus status
.SE96					;if busy flag set
BE96 6A          ROR A			;poll again
BE97 B0 E4       BCS SE7D
BE99 2A          ROL A
.SE9A					;else restore ROM bank (EDOS)
BE9A 48          PHA
BE9B AD 60 0D    LDA &0D60
BE9E 85 F4       STA rmslrg		;and return status register
BEA0 8D 30 FE    STA romselr
BEA3 68          PLA
BEA4 60          RTS

;					;Copy NMI handler to &0D00
BEA5 85 A0       STA &A0		;NMI write I/O
BEA7 A9 02       LDA #&02		;All NMIs copied to &0D00
;BEA9 2C 84 FE    BIT fdc_stat		;If not Data Request
BEA9 2C 28 FE    BIT fdc_stat
BEAC F0 10       BEQ SEBE		;else read memory then ignore interrupt
BEAE AD 00 0D    LDA &0D00
BEB1 49 00       EOR #&00		;nullifies invert for 1770
;BEB3 8D 87 FE    STA fdc_data		;store in Data Register
BEB3 8D 2B FE    STA fdc_data
BEB6 EE 0A 0D    INC &0D0A		;modify read instruction
BEB9 D0 03       BNE SEBE		 incrementing the address
BEBB EE 0B 0D    INC &0D0B		;restore accumulator and exit
.SEBE
BEBE A5 A0       LDA &A0
BEC0 40          RTI
BEC1 85 A0       STA &A0		;NMI write Tube
BEC3 A9 02       LDA #&02
;BEC5 2C 84 FE    BIT fdc_stat
BEC5 2C 28 FE    BIT fdc_stat
BEC8 F0 08       BEQ SED2
BECA AD E5 FE    LDA tubeR3data		;Fetch from Tube FIFO 3
BECD 49 00       EOR #&00		;nullifies invert for 1770
;BECF 8D 87 FE    STA fdc_data		;Store in data register
BECF 8D 2B FE    STA fdc_data
.SED2
BED2 A5 A0       LDA &A0
BED4 40          RTI
BED5 85 A0       STA &A0		;NMI read I/O
BED7 A9 02       LDA #&02
;BED9 2C 84 FE    BIT fdc_stat
BED9 2C 28 FE    BIT fdc_stat
BEDC F0 10       BEQ SEEE
;BEDE AD 87 FE    LDA fdc_data		;read from data register
BEDE AD 2B FE    LDA fdc_data
BEE1 49 00       EOR #&00		;nullifies invert for 1770
BEE3 8D 00 0D    STA &0D00		;store
BEE6 EE 0F 0D    INC &0D0F		;modify store instruction
BEE9 D0 03       BNE SEEE
BEEB EE 10 0D    INC &0D10		;incrementing the address
.SEEE
BEEE A5 A0       LDA &A0
BEF0 40          RTI
BEF1 85 A0       STA &A0		;NMI read Tube
BEF3 A9 02       LDA #&02
;BEF5 2C 84 FE    BIT fdc_stat
BEF5 2C 28 FE    BIT fdc_stat
BEF8 F0 08       BEQ SF02
;BEFA AD 87 FE    LDA fdc_data		;fetch from data register
BEFA AD 2B FE    LDA fdc_data		;fetch from data register
BEFD 49 00       EOR #&00		;nullifies invert for 1770
BEFF 8D E5 FE    STA tubeR3data         ;store in Tube FIFO 3
.SF02
BF02 A5 A0       LDA &A0
BF04 40          RTI
BF05 85 A0       STA &A0		;NMI read ID I/O
BF07 A9 02       LDA #&02		;ignore if not Data Request
;BF09 2C 84 FE    BIT fdc_stat
BF09 2C 28 FE    BIT fdc_stat
BF0C F0 14       BEQ SF22
;BF0E AD 87 FE    LDA fdc_data		;read data register
BF0E AD 2B FE    LDA fdc_data		;read data register
BF11 49 00       EOR #&00		;null invert for 1770
BF13 C6 A1       DEC &A1		;decrement counter
BF15 30 0B       BMI SF22		;discard data if enough read
BF17 8D 00 0D    STA &0D00		;store in memory
BF1A EE 13 0D    INC &0D13		;increment store address
BF1D D0 03       BNE SF22
BF1F EE 14 0D    INC &0D14
.SF22
BF22 A5 A0       LDA &A0		;NMI read ID Tube
BF24 40          RTI
BF25 85 A0       STA &A0
BF27 A9 02       LDA #&02
;BF29 2C 84 FE    BIT fdc_stat
BF29 2C 28 FE    BIT fdc_stat
BF2C F0 0C       BEQ SF3A
;BF2E AD 87 FE    LDA fdc_data		;fetch from data register
BF2E AD 2B FE    LDA fdc_data		;fetch from data register
BF31 49 00       EOR #&00		;nullifies invert rfor 1770
BF33 C6 A1       DEC &A1		;decrement counter
BF35 30 03       BMI SF3A		;discard data if enough read
BF37 8D E5 FE    STA tubeR3data		;store in Tube FIFO 3
.SF3A
BF3A A5 A0       LDA &A0
BF3C 40          RTI
;BF3D 2C 87 FE    BIT fdc_data		;NMI verify
BF3D 2C 2B FE    BIT fdc_data		;NMI verify
BF40 40          RTI			;fetch data and discard
BF41 85 A0       STA &A0		;NMI format
BF43 A9 02       LDA #&02
;BF45 2C 84 FE    BIT fdc_stat
BF45 2C 28 FE    BIT fdc_stat
BF48 F0 13       BEQ SF5D
BF4A AD 00 0E    LDA &0E00		;get byte from table
BF4D 49 00       EOR #&00		;nullifies invert for 1770
;BF4F 8D 87 FE    STA fdc_data		;store in data register
BF4F 8D 2B FE    STA fdc_data		;store in data register
BF52 CE 00 0F    DEC &0F00		;decrement run length
BF55 D0 06       BNE SF5D		;(01..00, 1..256 bytes)
BF57 EE 0A 0D    INC &0D0A		;if run out
BF5A EE 12 0D    INC &0D12		;move to next entry in table
.SF5D
BF5D A5 A0       LDA &A0
BF5F 40          RTI


;Variables

;00A0..A1  Pointer to user's OSWORD &7F block
;00A0	   Temporary for A in NMI service routines
;00A1	   No. bytes to fetch in Read ID NMI service routine
;00A2..A3  CHRN block address from O7F 1..2 for Format command
;00A4	   No. sectors to read
;00A8..A9  Pointer to CHRN table in *FORMAT
;00A8..A9  Pointer to private page when stowing/restoring workspace
;00AA..AB  Pointer to extended vector table while setting up FS
;00B2..B3  Pointer to hex word in print-absolute
;00B8	   Temp for high bits when packing catalogue entry
;00B8	   Uppercased character to compare with names of open handles
;00B9	   Counter to compare filename with names of open handles
;00BA..BB  Target absolute sector when advancing PTR
;00BA..BB  Temporary during OSGBPB sector operations
;00BC..BD  Pointer to user memory in OSGBPB
;00BE..BF  Pointer to user's OSGBPB block
;00C0..C6  Immediate file name
;00C7..C9  Immediate dir, volume, drive (ASCII)
;00CA..CB  Pointer to buffer of open file (CB=file handle)
;00CC	   Pointer to file entry in catalogue
;00CD	   Microcode shift register in OSGBPB etc.
;00CE	   ambiguous file spec flag
;00CF	   used in Master in Convert DDOS latch routine

;0D60	   Socket no. of EDOS ROM during disc op
;0D61	   Socket no. of previous NMI owner during disc op
;0D62	   Retry counter in Read ID command
;0D63	   Temp. 2791 command (may not be the exact one issued)
;0D64	   >0 = Disc op is transferring to Tube
;0D65	   Temporary for status after disc operation
;0D66	   0 = Write to disc, &FF = Read from disc

;1000..06  Default file name
;1007..09  Default directory, volume, drive (ASCII)
;100A..0C  Library directory, volume, drive (ASCII)
;100D	   In absolute workspace: &BE=workspace in absolute page,
	   other=absolute page not initialised.
	   Private page+&D: &BE=workspace in absolute page,
	   &EF=workspace in private page, other=private page
	   not initialised.
;100E	   *OPT 1 monitor
;100F	   b1=1 if *ENABLEd
;1010..1B  OSWORD &7F block
;101C..1D  Address of user's OSWORD &7F block
;101E..1F  Track no. under heads on drives 0&2, 1&3
;1020..23  0FF0,X Density of drives 0..3  0A=SD 12=DD
;1024..27  0FF4,X No. tracks on drives 0..3
;1028..2B  0FF8,X Track stepping on drives 0..3 >0=step
;102C..2F  0FFC,X No. volumes on disc, offset of disc cat /2
;1030..37  No. tracks in volumes A..H
;1038..39  Offset to start of volume in sectors
;103A	   b6=Tube transfer, b7=write to Tube or I/O memory
	   (when transferring bytes to/from open files)
;1040..46  Filename (used by *INFO)
;1047	   Directory letter (used by *INFO)
;1048..4F  Load/exec/length/start sector in catalogue format
;1048..4A  Load address from catalogue (18 bit)
;104B..4D  Execution address from catalogue (18 bit)
;104E..50  File length from catalogue
;1051..52  Absolute start sector
;1053..54  Number of sectors used
;1058..64  OSCLI boot command string
;1060..6F  Table from &9A1E..2D
;1069..6A  Absolute end sector (last used +1)
;1070..81  OSFILE/OSGBPB block
;1070..    Workspace used by *FORMAT
;1070..73  Density,tracks,track stepping,volumes
;1074	   Outstep (track skew)
;1076	   4 * sector count (density)
;1077	   Sector iterator
;1078..7F  No. tracks in each volume of disc to format
;1082..83  Pointer to arguments of *RUN, */ command
;1084..87  *OPT 6..9 density, volumes, tracks, saverom
;1088,Y	   Channel flags b0=EOF warning given b6=open for reading
	   b7=open for writing
;1089,Y	   Current buffer 0=empty 1=clean 2=dirty
;108A..0,Y Name of open file
;1091,Y	   Directory of open file
;1092,Y	   Volume containing open file
;1093,Y	   Drive containing open file
;1094..5,Y Absolute start LBA of open file
;1096..7,Y Absolute LBA of sector currently in buffer
;1098..9,Y Allocated file length (!== EXT)
;109A..C,Y EXT file length
;109D..F,Y PTR file pointer

;This Perl script recreates the binary from this listing.
;Copy the text between the cut lines.
;Paste it into a new file, asm2bin.pl, and remove the column of
;Then call it with
;  perl asm2bin.pl -b 8000 -o m1770w m1770w.asm.txt
;-------->8---
;#!/usr/bin/perl
;
;#Usage: perl asm2bin.pl [-D] [-b BASE] -o OUTFILE [FILE...]
;
;use Getopt::Std;
;use IO::Seekable qw(SEEK_SET SEEK_CUR SEEK_END);
;
;getopts("Db:o:");
;die "No output file specified" if $opt_o eq '';
;$opt_b = hex($opt_b);
;
;open(BIN,"+>$opt_o") or die;
;binmode(BIN);
;while(<>) {
;  y/\n\r//d;
;  if(/^ {0,2}([0-9A-F]{4})/) {
;    print STDERR "seek $1\n" if $opt_D;
;    seek(BIN,hex($1)-$opt_b,SEEK_SET);
;  }
;  if(/^ {0,2}[^;\\]{4}((?: {0,2}[0-9A-F]{2}){1,3})/) {
;    ($a=$1)=~y/ //d;
;    print STDERR "         write $a\n" if $opt_D;
;    print BIN pack("H*",$a);
;  }
;  if(/^ {0,2}[^;\\]{4} {0,2}EQUS ((?:"[^"]*")*)/) {
;    ($a=substr($1,1,length($1)-2))=~s/""/"/g;
;    print STDERR "         write $a\n" if $opt_D;
;    print BIN $a;
;  }
;  if(/^ {0,2}[^;\\]{4} {0,2}EQU[^S] (&[0-9A-F]{2}(?:,&[0-9A-F]{2})*)/){
;    ($a=$1)=~y/,&//d;
;    print STDERR "         write $a\n" if $opt_D;
;    print BIN pack("H*",$a);
;  }
;}
;close(BIN);
;-------->8---

;End of m1770w.asm.txt
