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