; 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 "U" ; Version No. 8009 EQUS "OPUS EDOS " ; title 8013 EQUB &00 ; terminator byte 8014 EQUS "0.40 (25 Feb 2008)" ; 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.51 (U) 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 = 913A 20 1B 90 JSR Q01B ;Print character in A 913D A9 0D LDA #&0D ;A = 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 .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 88 9B JMP QB88 ;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 0