;Disassembly of Opus EDOS 0.4 patched by EDOSPAT 7.05 (5)/5.65 (4) ;Last updated 2 April 2021 ;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 ;EDOSPAT source: http://regregex.bbcmicro.net/#prog.edospat ;Pass this file through a C preprocessor or the attached asm2bin.pl ;to produce an assembly listing targeting one of the eleven supported ;floppy drive controllers. ;Define one of the following symbols during preprocessing to assemble ;for its associated controller:- ;_O27915 EDOSPAT 7.05 for the Opus WD 2791 controller (default) ;_O27935 EDOSPAT 7.05 for the Opus WD 2793 controller ;_O17705 EDOSPAT 7.05 for the Opus WD 1770 controller ;_CHALL5 EDOSPAT 7.05 for the Opus Challenger 3-in-1 unit ;_W17705 EDOSPAT 7.05 for the Watford WD 1770 controller ;_A17705 EDOSPAT 7.05 for the Acorn B/B+ WD 1770 controller ;_M17705 EDOSPAT 7.05 for the Acorn Master WD 1770 controller ;_PG4005 EDOSPAT 7.05 for the Slogger Pegasus 400 controller ;_O27914 EDOSPAT 5.65 for the Opus WD 2791 HD controller ;_A17724 EDOSPAT 5.65 for the B/B+ Ajax controller ;_M17724 EDOSPAT 5.65 for the Master Ajax controller ;EDOSPAT 7.05 code length: &3BE8 (=&3F6B-&0383) ;EDOSPAT 5.65 code length: &3C0E (=&3F74-&0366) ;Name Acorn CRC PKZIP CRC XFER CRC Cksum ;edos04 &5523 &1D8A3860 &EA30334D 1245836096 ;o27915 &8FF0 &4443F74E &2124FAC1 3791540560 ;o27935 &75C6 &CC94F61E &86DF0F3F 3460147232 ;o17705 &A563 &B98B0489 &A57262BC 2032496921 ;chall5 &BF0F &7CEC0857 &25D69E8C 557719049 ;w17705 &0C15 &E7786813 &A923144E 3456131798 ;a17705 &7933 &EEBCFDE2 &7BEE9121 2886981617 ;m17705 &49EC &44E93F94 &937B6B7F 3193298168 ;pg4005 &85FE &BDF7261A &88C54392 3414631481 ;o27914 &FBE6 &2D966706 &1114C4F1 2759984706 ;a17724 &7E73 &6AC7E5CB &4EE172D8 1926977983 ;m17724 &C758 &8F9F57AF &21B99097 996068370 ;Additional symbols: ;_NOMON Disable system call monitors ;_WHOLE Load and save whole sectors in OSFILE #undef _EP565 /* EDOSPAT 5.65 */ #undef _WD2791 /* WD 2791 levels & stat.reg. */ #undef _WD2793 /* WD 2793 levels & stat.reg. */ #undef _BPLUS /* B+ addresses (not control) */ #undef _MASTER /* Master addresses (not co.) */ #if defined _O27935 # define _WD2793 1 #elif defined _O17705 #elif defined _CHALL5 #elif defined _W17705 # define _BPLUS 1 #elif defined _A17705 # define _BPLUS 1 #elif defined _M17705 # define _MASTER 1 #elif defined _PG4005 #elif defined _O27914 # define _EP565 1 # define _WD2791 1 #elif defined _A17724 # define _EP565 1 # define _BPLUS 1 #elif defined _M17724 # define _EP565 1 # define _MASTER 1 #else /* _O27915 */ # define _WD2791 1 #endif /* _O27935 */ ;ZERO PAGE WORKSPACE ;******************* ; ;00EF OSWORD/OSBYTE accumulator value ;00F0 OSWORD/OSBYTE X register value ;00F1 OSWORD/OSBYTE Y register value ; gsflag = &E4 ;flags set up by GSINIT 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 romselr = &FE30 ;Paged ROM select register acccon = &FE34 ;Memory access control register #if defined _BPLUS fdc_base = &FE84 fdc_cntrl = &FE80 fdc_stat = &FE84 fdc_comm = &FE84 fdc_trck = &FE85 fdc_sect = &FE86 fdc_data = &FE87 #elif defined _MASTER fdc_base = &FE28 fdc_cntrl = &FE24 fdc_stat = &FE28 fdc_comm = &FE28 fdc_trck = &FE29 fdc_sect = &FE2A fdc_data = &FE2B #elif defined _CHALL5 fdc_base = &FCF8 fdc_cntrl = &FCFC fdc_stat = &FCF8 fdc_comm = &FCF8 fdc_trck = &FCF9 fdc_sect = &FCFA fdc_data = &FCFB #elif defined _PG4005 fdc_base = &FCC4 fdc_cntrl = &FCC0 fdc_stat = &FCC4 fdc_comm = &FCC4 fdc_trck = &FCC5 fdc_sect = &FCC6 fdc_data = &FCC7 #else /* _O27935, _O17705, _O27915 or _O27914 */ fdc_base = &FE80 fdc_cntrl = &FE84 fdc_stat = &FE80 fdc_comm = &FE80 fdc_trck = &FE81 fdc_sect = &FE82 fdc_data = &FE83 #endif /* _BPLUS */ ; ; ;STANDARD MOS CALLS & VECTORS USED BY THIS CODE ;********************************************** ; osfscv = &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 osasci = &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 ;Constants defined by macro functions module saved_x = &0103 ;saved X is 3rd byte down in the stack saved_a = &0104 ;saved A is 4th byte down in the stack saved_y = &0105 ;saved Y is 5th byte down in the stack ;Paged ROM header 8000 4C C7 80 JMP language ;Language entry (RTS) 8003 4C 3D 80 JMP service ;Service entry 8006 EQUB &82 ;rom type: service only 8007 EQUB &26 ;Copyright offset pointer .P008 #if defined _EP565 8008 EQUS "4" ;Version No. #else /* _EP705 */ 8008 EQUS "5" ;Version No. #endif /* _EP565 */ 8009 EQUS "OPUS EDOS " ;title 8013 EQUB &00 ;terminator byte 8014 EQUS "0.40 (02 Apr 2021)" ;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 48 PHA ;save call type 803E AD 0E 10 LDA &100E ;*OPT 1 monitor 8041 29 02 AND #&02 ;00000010 ;if bit 2 clear 8043 F0 05 BEQ P04A ;then skip 8045 68 PLA ;else restore call type 8046 48 PHA ;save it again 8047 20 03 B7 JSR S703 ;call monitor .P04A 804A 68 PLA ;restore call type 804B F0 2D BEQ P07A ;&00 = null call (exit) 804D C9 0E CMP #&0E 804F 90 17 BCC P068 8051 D0 03 BNE P056 8053 60 RTS ;&0E = ROMFS get byte .P056 8056 C9 12 CMP #&12 8058 F0 66 BEQ P0C0 ;&12 = initialise filing system 805A 90 07 BCC P063 805C C9 FE CMP #&FE 805E F0 6A BEQ P0CA ;&FE = tube post initialisation 8060 B0 72 BCS P0D4 ;&FF = tube main initialisation 8062 60 RTS ;if A=&13..&FD then exit .P063 8063 C9 0F CMP #&0F 8065 F0 56 BEQ P0BD ;&0F = vectors claimed 8067 60 RTS ;if A=&10..&11 then exit .P068 8068 C9 04 CMP #&04 806A F0 3F BEQ P0AB ;&04 = unrecognised OSCLI 806C 90 0D BCC P07B 806E C9 0A CMP #&0A 8070 F0 4B BEQ P0BD ;&0A = claim absolute workspace 8072 B0 06 BCS P07A ;if A=&0B..&0D then exit 8074 C9 08 CMP #&08 8076 F0 39 BEQ P0B1 ;&08 = unrecognised OSWORD 8078 B0 3D BCS help ;&09 = *HELP .P07A 807A 60 RTS ;if A=&05..&07 then exit .P07B 807B C9 02 CMP #&02 807D F0 09 BEQ P088 ;&02 = request private workspace 807F B0 24 BCS boot ;&03 = boot 8081 C0 16 CPY #&16 ;&01 = request absolute workspace 8083 B0 02 BCS P087 8085 A0 16 LDY #&16 ;we need 8 pages 0E..15 incl .P087 8087 60 RTS ;SVCE CALL 2 - CLAIM PRIVATE WORK SPACE ;A = SVCE CALL No., X = ROM No., Y = value of first free page. .P088 ;request private workspace 8088 48 PHA ;save on stack 8089 98 TYA ;save our page number in the 808A 9D F0 0D STA &0DF0,X ;OS ROM table 808D 85 A9 STA &A9 ;and in high byte of pointer 808F 18 CLC ;claim one page 8090 69 01 ADC #&01 8092 A8 TAY 8093 68 PLA ;restore ROM call number 8094 20 00 92 JSR Q200 ;save AXY 8097 AD 8D 02 LDA &028D ;get last reset type 809A F0 08 BEQ P0A4 ;if not 0 soft break 809C A9 00 LDA #&00 ;then low byte of pointer =0 809E 85 A8 STA &A8 ;clear workspace flag in 80A0 A0 0D LDY #&0D ;byte &D of private page 80A2 91 A8 STA (&A8),Y ;marking it uninitialised. .P0A4 80A4 60 RTS .boot 80A5 20 DA 80 JSR P0DA ;test boot key 80A8 B0 1A BCS P0C4 ;if okay boot the disc 80AA 60 RTS ;SVCE CALL 4 - UNRECOGNISED * COMMAND ;On entry &F2 and &F3 point to the start of the string .P0AB ;Unrecognised OSCLI 80AB 20 03 81 JSR P103 ;scan it 80AE B0 17 BCS P0C7 ;if we ran it break out 80B0 60 RTS .P0B1 ;unrecognised OSWORD 80B1 20 00 BA JSR SA00 ;compare OSWORD 80B4 B0 11 BCS P0C7 ;with our codes && break out 80B6 60 RTS .help ;*HELP 80B7 20 06 81 JSR P106 ;search our topics 80BA B0 0B BCS P0C7 ;if specific to us break out 80BC 60 RTS .P0BD ;claim absolute workspace 80BD 4C 06 96 JMP Q606 ;Wksp claim/vectors changed. .P0C0 ;Initialise FS 80C0 C0 04 CPY #&04 ;our FS ID = 4 80C2 D0 05 BNE language .P0C4 80C4 20 03 96 JSR Q603 .P0C7 ;Break out of ROM call chain 80C7 A9 00 LDA #&00 .language 80C9 60 RTS .P0CA ;Post-initialise Tube 80CA C0 00 CPY #&00 80CC F0 FB BEQ language ;edos ignores if Y=0 80CE 20 03 A0 JSR R003 ;otherwise it does post-init 80D1 A9 00 LDA #&00 ;and consumes the call. 80D3 60 RTS .P0D4 ;Tube main init 80D4 20 00 A0 JSR R000 80D7 A9 00 LDA #&00 ;edos consumes this call 80D9 60 RTS .P0DA ;Test boot key 80DA 20 00 92 JSR Q200 ;Save AXY 80DD A9 7A LDA #&7A 80DF 20 F4 FF JSR osbyte ;scan keyboard from code &10 80E2 8A TXA 80E3 30 09 BMI P0EE ;if no keypress C=1, allow boot 80E5 C9 32 CMP #&32 ;if key is not "D" disallow boot 80E7 D0 07 BNE P0F0 ;return C=0 disallow boot 80E9 A9 78 LDA #&78 ;else 80EB 20 F4 FF JSR osbyte ;register keypress for 2KR .P0EE 80EE 38 SEC ;return C=1 allow boot 80EF 60 RTS .P0F0 80F0 18 CLC ;return C=0 disallow boot 80F1 60 RTS ;Keyword recognition and help subsystem .P100 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 #dfs-keyword ;X=table offset=&2C 8111 D0 0C BNE P11F .P113 ;scans help keywords 8113 20 00 92 JSR Q200 ;Save AXY etc 8116 A2 EA LDX #helpkywd-keyword ;X=table offset=&EA 8118 D0 05 BNE P11F .P11A ;OSCLI. scans UTILS commands 811A 20 00 92 JSR Q200 ;Save AXY etc 811D A2 00 LDX #utils-keyword ;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 03 82 LDA keyword,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 03 82 LDA keyword,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 04 82 LDA keyword+1,X ;else accept command. 815B 85 A8 STA &A8 ;get action address 815D BD 05 82 LDA keyword+2,X ;store in temp pointer 8160 85 A9 STA &A9 8162 49 00 EOR #&00 ;no-op (deleted call to GSINIT) 8164 49 00 EOR #&00 ;no-op 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 CC 81 JSR P1CC ;print help entry 8180 20 09 90 JSR Q009 ;display error (never returns) .P183 8183 A9 02 LDA #&02 ;*HELP 8185 A2 ED LDX #helplist-keyword ;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 #dfs-keyword ;offset to point to DFS table 818E D0 02 BNE P192 .P190 ;*HELP UTILS 8190 A2 00 LDX #utils-keyword ;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 D1 83 JSR P3D1 ;print EDOS banner .P199 8199 20 CC 81 JSR P1CC ;print help entry 819C E8 INX ;skip syntax and action address 819D E8 INX .P19E 819E E8 INX 819F BD 00 82 LDA keyword-3,X ;search keyword just printed 81A2 10 FA BPL P19E ;until terminator found 81A4 BD 03 82 LDA keyword,X ;test first char of next keyword 81A7 F0 1E BEQ P1C7 ;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 29 LDA #&29 ;else 81B9 20 06 90 JSR Q006 ;Tab to column 41 81BC 4C 99 81 JMP P199 ;and loop. .P1BF ;*HELP E 81BF 20 D1 83 JSR P3D1 ;prints banner 81C2 A2 F9 LDX #&F9 ;X=(table offset=&79) EOR &80 81C4 20 E8 81 JSR P1E8 ;prints banner .P1C7 81C7 20 09 90 JSR Q009 ;print newline 81CA 18 CLC ;pass all *HELP to lower ROMs 81CB 60 RTS ;exit .P1CC 81CC 20 00 92 JSR Q200 ;Save AXY 81CF A9 02 LDA #&02 ;tab to column 2 or more 81D1 20 06 90 JSR Q006 ;returning current POS in A 81D4 48 PHA ;save POS on stack .P1D5 81D5 BD 03 82 LDA keyword,X ;get character from table of commands 81D8 30 06 BMI P1E0 ;if not the terminator 81DA 20 00 90 JSR Q000 ;print the character in A 81DD E8 INX ;advance offset 81DE D0 F5 BNE P1D5 ;and loop .P1E0 81E0 AA TAX ;else save offset of syntax 81E1 68 PLA ;get back POS 81E2 18 CLC 81E3 69 09 ADC #&09 ;add 9 81E5 20 06 90 JSR Q006 ;tab to 9 places after command .P1E8 81E8 A9 FF LDA #&FF ;a=&FF sentinel value 81EA 48 PHA ;push onto stack 81EB 8A TXA ;put offset of syntax in A .P1EC 81EC 49 80 EOR #&80 ;10000000 toggle top bit .P1EE 81EE 48 PHA ;push offset on stack 81EF AA TAX ;transfer to X to use as index 81F0 BD 03 83 LDA particle,X ;get character of syntax 81F3 F0 06 BEQ P1FB ;if NUL then end syntax string 81F5 30 F5 BMI P1EC ;if >=&80 print substring 81F7 20 00 90 JSR Q000 ;else print character 81FA 48 PHA ;push dummy to stay on level .P1FB 81FB 68 PLA ;pop dummy/current offset 81FC 68 PLA ;pop current/parent offset 81FD 18 CLC ;increment offset 81FE 69 01 ADC #&01 8200 D0 EC BNE P1EE ;if not the sentinel then loop 8202 60 RTS ;else exit .keyword .utils 8203 EQUS "BUILD" ;*BUILD fsp P400 8208 EQUB &F5 ;Syntax fsp (b7 set) 8209 EQUW &00,&84 ;Action address &8400 820B EQUS "DISC" ;*DISC I, P403 820F EQUB &88 ;Syntax I (b7 set) 8210 EQUW &03,&84 ;Action address &8403 8212 EQUS "DISK" ;*DISK I, P403 8216 EQUB &88 ;Syntax I (b7 set) 8217 EQUW &03,&84 ;Action address &8403 8219 EQUS "DUMP" ;*DUMP fsp, P406 821D EQUB &F5 ;Syntax fsp (b7 set) 821E EQUW &06,&84 ;Action address &8406 8220 EQUS "LIST" ;*LIST fsp, P409 8224 EQUB &F5 ;Syntax fsp (b7 set) 8225 EQUW &09,&84 ;Action address &8409 8227 EQUS "TYPE" ;*TYPE fsp, P40C 822B EQUB &F5 ;Syntax fsp (b7 set) 822C EQUW &0C,&84 ;Action address &840C 822E EQUB &00 ;terminator byte ;Table of DFS commands .dfs 822F EQUS "ACCESS" ;*ACCESS fsp L, P600 8235 EQUB &99 ;Syntax fsp L 8236 EQUW &00,&86 ;Action address &8600 8238 EQUS "ADDRESS" ;*ADDRESS fsp load exec, Q755 823F EQUB &9D ;Syntax afsp load exec 8240 EQUW &55,&97 ;Action address &9755 8242 EQUS "BACKUP" ;*BACKUP drv drv, PA00 8248 EQUB &E8 ;Syntax drv drv 8249 EQUW &00,&8A ;Action address &8A00 824B EQUS "CATGEN" ;*CATGEN vol ..., R903 8251 EQUB &CB ;Syntax vol ... 8252 EQUW &03,&A9 ;Action address &A903 8254 EQUS "COMPACT" ;*COMPACT vol, PA03 825B EQUB &95 ;Syntax vol 825C EQUW &03,&8A ;Action address &8A03 825E EQUS "COPY" ;*COPY vol vol afsp, PA06 8262 EQUB &EF ;Syntax vol vol afsp 8263 EQUW &06,&8A ;Action address &8A06 8265 EQUS "DELETE" ;*DELETE fsp, P606 826B EQUB &F5 ;Syntax fsp (b7 set) 826C EQUW &06,&86 ;Action address &8606 826E EQUS "DESTROY" ;*DESTROY afsp, P609 8275 EQUB &F4 ;Syntax afsp 8276 EQUW &09,&86 ;Action address &8609 8278 EQUS "DIR" ;*DIR dir, P60C 827B EQUB &84 ;Syntax dir 827C EQUW &0C,&86 ;Action address &860C 827E EQUS "DRIVE" ;*DRIVE vol, P627 8283 EQUB &95 ;Syntax vol 8284 EQUW &27,&86 ;Action address &8627 8286 EQUS "ENABLE" ;*ENABLE, PA09 828C EQUB &83 ;Syntax 828D EQUW &09,&8A ;Action address &8A09 828F EQUS "FCOPY" ;*FCOPY fsp name, PA12 8294 EQUB &D3 ;Syntax fsp name 8295 EQUW &12,&8A ;Action address &8A12 8297 EQUS "FORMAT" ;*FORMAT drv ..., R900 829D EQUB &B6 ;Syntax drv ... 829E EQUW &00,&A9 ;Action address &A900 82A0 EQUS "INFO" ;*INFO afsp, P612 82A4 EQUB &F4 ;Syntax afsp 82A5 EQUW &12,&86 ;Action address &8612 82A7 EQUS "LIB" ;*LIB dir, P615 82AA EQUB &84 ;Syntax dir 82AB EQUW &15,&86 ;Action address &8615 82AD EQUS "LOCK" ;*LOCK afsp, P621 82B1 EQUB &F4 ;Syntax afsp 82B2 EQUW &21,&86 ;Action address &8621 82B4 EQUS "RENAME" ;*RENAME fsp name, P618 82BA EQUB &D3 ;Syntax fsp name 82BB EQUW &18,&86 ;Action address &8618 82BD EQUS "SCOPY" ;*SCOPY vol vol afsp, PA0F 82C2 EQUB &EF ;Syntax vol vol afsp 82C3 EQUW &0F,&8A ;Action address &8A0F 82C5 EQUS "TITLE" ;*TITLE title, P61B 82CA EQUB &8F ;Syntax title 82CB EQUW &1B,&86 ;Action address &861B 82CD EQUS "UNLOCK" ;*UNLOCK afsp, P624 82D3 EQUB &F4 ;Syntax afsp 82D4 EQUW &24,&86 ;Action address &8624 82D6 EQUS "VERIFY" ;*VERIFY drv, R906 82DC EQUB &EB ;Syntax drv 82DD EQUW &06,&A9 ;Action address &A906 82DF EQUS "VOL" ;*VOL vol, P627 82E2 EQUB &95 ;Syntax vol 82E3 EQUW &27,&86 ;Action address &8627 82E5 EQUS "WIPE" ;*WIPE afsp, P61E 82E9 EQUB &F4 ;Syntax afsp 82EA EQUW &1E,&86 ;Action address &861E 82EC EQUB &00 ;terminator byte ;Help keywords .helpkywd 82ED EQUB &83 ;*HELP, P3E5 82EE EQUW &E5,&83 ;Action address &83E5 .helplist 82F0 EQUS "E" ;*HELP E, P1BF 82F1 EQUB &83 ;Syntax 82F2 EQUW &BF,&81 ;Action address &81BF 82F4 EQUS "DFS" ;*HELP DFS, P18C 82F7 EQUB &83 ;Syntax 82F8 EQUW &8C,&81 ;Action address &818C 82FA EQUS "UTILS" ;*HELP UTILS, P190 82FF EQUB &83 ;Syntax 8300 EQUW &90,&81 ;Action address &8190 8302 EQUB &00 ;terminator byte .particle ;Syntax particles 8303 EQUS " " 8304 EQUS " " 8306 EQUB &00 ;terminator byte 8307 EQUS "dir" 830A EQUB &00 ;terminator byte 830B EQUS "I" 830C EQUB &00 ;terminator byte 830D EQUS "src " 8311 EQUB &00 ;terminator byte 8312 EQUS "title" 8317 EQUB &00 ;terminator byte 8318 EQUS "vol" 831B EQUB &00 ;terminator byte 831C EQUB &F4 ;afsp 831D EQUB &81 ;" " 831E EQUS "L" 831F EQUB &00 ;terminator byte 8320 EQUB &F4 ;afsp 8321 EQUB &80 ;" " 8322 EQUS "load" 8326 EQUB &A9 ;" addr" 8327 EQUB &80 ;" " 8328 EQUS "exec" 832C EQUS " addr" 8331 EQUB &00 ;terminator byte 8332 EQUB &80 ;" " 8333 EQUS "dest " 8338 EQUB &00 ;terminator byte 8339 EQUB &EB ;drv 833A EQUB &81 ;" " 833B EQUS "S|D" 833E EQUB &81 ;" " 833F EQUS "40|80|40-80" 834A EQUB &81 ;" " 834B EQUS "Oo" 834D EQUB &00 ;terminator byte 834E EQUB &EB ;drv 834F EQUB &80 ;" " 8350 EQUS "vt..." 8355 EQUB &00 ;terminator byte 8356 EQUS "old " 835A EQUB &F5 ;fsp 835B EQUB &80 ;" " 835C EQUS "new entry name" 836A EQUB &00 ;terminator byte 836B EQUB &8A ;"src " 836C EQUB &EB ;drv 836D EQUB &AF ;" dest " 836E EQUS "drv" 8371 EQUB &00 ;terminator byte 8372 EQUB &8A ;"src " 8373 EQUB &95 ;vol 8374 EQUB &AF ;" dest " 8375 EQUB &95 ;vol 8376 EQUB &80 ;" " 8377 EQUS "a" 8378 EQUS "fsp" 837B EQUB &00 ;terminator byte #if defined _O27935 837C EQUS "EDOSPAT 7.05 (5) Opus 2793 :Greg Cook" 83A2 EQUB &00 ;terminator byte #elif defined _O17705 837C EQUS "EDOSPAT 7.05 (5) Opus 1770 :Greg Cook" 83A2 EQUB &00 ;terminator byte #elif defined _CHALL5 837C EQUS "EDOSPAT 7.05 (5) Challenger :Greg Cook" 83A2 EQUB &00 ;terminator byte #elif defined _W17705 837C EQUS "EDOSPAT 7.05 (5) Watford1770:Greg Cook" 83A2 EQUB &00 ;terminator byte #elif defined _A17705 837C EQUS "EDOSPAT 7.05 (5) Acorn 1770 :Greg Cook" 83A2 EQUB &00 ;terminator byte #elif defined _M17705 837C EQUS "EDOSPAT 7.05 (5) Master 1770:Greg Cook" 83A2 EQUB &00 ;terminator byte #elif defined _PG4005 837C EQUS "EDOSPAT 7.05 (5) Pegasus 400:Greg Cook" 83A2 EQUB &00 ;terminator byte #elif defined _O27914 837C EQUS "EDOSPAT 5.65 (4) Opus 2791HD:Greg Cook" 83A2 EQUB &00 ;terminator byte #elif defined _A17724 837C EQUS "EDOSPAT 5.65 (4) Acorn Ajax :Greg Cook" 83A2 EQUB &00 ;terminator byte #elif defined _M17724 837C EQUS "EDOSPAT 5.65 (4) Master Ajax:Greg Cook" 83A2 EQUB &00 ;terminator byte #else /* _O27915 */ 837C EQUS "EDOSPAT 7.05 (5) Opus 2791 :Greg Cook" 83A2 EQUB &00 ;terminator byte #endif /* _O27935 */ ;EDOSPAT extensions, block 1 #if defined _EP565 .P3C2 83C2 BD F0 0F LDA &0FF0,X ;get density of current drive 83C5 18 CLC ;increase it by 2 to display 83C6 69 02 ADC #&02 ;density 1, 2 or 4 in *CAT. 83C8 60 RTS #endif /* _EP565 */ .P3C9 83C9 A0 FF LDY #&FF ;&FF = don't show version no. 83CB 20 00 96 JSR Q600 ;print EDOS banner 83CE 4C 09 90 JMP Q009 ;print newline and exit .P3D1 83D1 20 09 90 JSR Q009 ;display error message/newline 83D4 A0 00 LDY #&00 ;&00 = show version number 83D6 4C 00 96 JMP Q600 ;print EDOS banner and exit .P3D9 83D9 20 43 95 JSR Q543 ;*TITLE. call GSINIT first 83DC 4C 91 88 JMP P891 .P3DF ;get character from *DUMP row 83DF B9 00 01 LDA &0100,Y ;get byte from stack page 83E2 C9 7F CMP #&7F ;if DEL or higher 83E4 60 RTS ;exit C=1 .P3E5 ;*HELP with empty keyword: 83E5 20 C5 FF JSR gsread ;call GSREAD, read first char 83E8 49 2E EOR #&2E ;if dot 83EA F0 09 BEQ P3F5 ;then show all help 83EC 90 10 BCC P3FE ;if another char, ignore call 83EE 24 E4 BIT gsflag ;else EOS. if GSINIT found " 83F0 30 0C BMI P3FE ;then ignore call 83F2 4C 83 81 JMP P183 ;else print *HELP keywords. .P3F5 ;*HELP . 83F5 20 BF 81 JSR P1BF ;do *HELP E 83F8 20 8C 81 JSR P18C ;do *HELP DFS 83FB 20 90 81 JSR P190 ;do *HELP UTILS .P3FE 83FE 18 CLC ;and pass *HELP . to lower ROMs. 83FF 60 RTS ;Utilities .P400 8400 4C 0F 84 JMP P40F ;*BUILD fsp .P403 8403 4C 71 84 JMP P471 ;*DISC, *DISK .P406 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 47 95 JSR Q547 8474 A0 01 LDY #&01 ;call GSINIT then GSREAD for ch 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 DF 83 JSR P3DF ;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 EQUB &10,&08,&04,&10 ;*DUMP bytes/row in MODEs [0..7] 84E8 EQUB &08,&04,&08,&08 .P4EC 84EC EQUB &37,&1F,&8E,&37 ;*DUMP ASCII tab in MODEs [0..7] 84F0 EQUB &1F,&8E,&1F,&1F .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 osasci ;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 osasci ;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. .P539 8539 A9 40 LDA #&40 ;Open file for reading .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 05 01 STA saved_y,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 .P571 8571 38 SEC ;break unrecognised OSCLI .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 EQUW &A8,&00 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 ;EDOSPAT extensions, block 2 .P59B 859B 20 09 92 JSR Q209 ;swap PTR with unused OSFILE blk 859E EQUW &7F,&10 ;FROM top of OSFILE block, &107F 85A0 EQUW &9D,&10 ;TO PTR, &109D,Y 85A2 EQUB &03,&B0 ;3 bytes, to Y with swap 85A4 4C 5B B5 JMP S55B ;clear EOF warning flag. .P5A7 ;set PTR from OSGBPB block 85A7 20 00 92 JSR Q200 ;save AXY 85AA 4A LSR A ;b7=0 indicates setting PTR: .P5AB ;OSARGS A=1/3, Y>0 set PTR/EXT 85AB 48 PHA ;b7=0 if setting PTR, =1 if EXT 85AC 20 9B 85 JSR P59B ;save PTR in unused OSFILE block .P5AF 85AF B9 9A 10 LDA &109A,Y ;set PTR=EXT 85B2 99 9D 10 STA &109D,Y ;while comparing EXT - request 85B5 D5 00 CMP &00,X 85B7 B9 9B 10 LDA &109B,Y 85BA 99 9E 10 STA &109E,Y 85BD F5 01 SBC &01,X 85BF B9 9C 10 LDA &109C,Y 85C2 99 9F 10 STA &109F,Y 85C5 F5 02 SBC &02,X 85C7 A9 00 LDA #&00 ;24-bit EXT, 32-bit request 85C9 F5 03 SBC &03,X ;if 3,X >0 then C=0 always: 85CB B0 15 BCS P5E2 ;if EXT >= request then finish 85CD B9 88 10 LDA &1088,Y ;else get channel flag 85D0 10 2B BPL P5FD ;if read-only then raise error 85D2 A9 00 LDA #&00 ;else return A=0 on exit 85D4 BA TSX ;indicating file extended 85D5 9D 05 01 STA saved_a+1,X ;A on exit + 1 byte 85D8 20 4B B6 JSR S64B ;add zero byte to end of file 85DB BD 04 01 LDA saved_x+1,X ;restore X on entry 85DE AA TAX 85DF 4C AF 85 JMP P5AF ;and loop until EXT=request. .P5E2 85E2 20 9B 85 JSR P59B ;restore PTR from OSFILE block 85E5 68 PLA ;restore accumulator 85E6 10 08 BPL P5F0 ;if b7=0, set PTR=request 85E8 20 F3 85 JSR P5F3 ;else set EXT=request 85EB 20 0C B4 JSR S40C ;is pointer now at/past EOF? 85EE 90 0C BCC P5FC ;if so, set PTR=request too: .P5F0 85F0 C8 INY ;point Y to PTR not EXT: 85F1 C8 INY 85F2 C8 INY .P5F3 85F3 20 09 92 JSR Q209 ;copy request to EXT 85F6 EQUW &00,&00 ;FROM OSARGS block, &0000,X 85F8 EQUW &9A,&10 ;TO EXT, &109A,Y 85FA EQUB &03,&31 ;3 bytes, from X to Y .P5FC 85FC 60 RTS .P5FD 85FD 4C B4 B6 JMP S6B4 ;'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 P80E ;*DIR ;.P60F 860F 4C 28 88 JMP P828 ;Was *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 D9 83 JMP P3D9 ;*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 47 95 JSR Q547 ;get afsp, call GSINIT/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 .P63B 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 #if defined _EP565 86D6 20 C2 83 JSR P3C2 ;get density flag #else /* _EP705 */ 86D6 BD F0 0F LDA &0FF0,X ;get density flag #endif /* _EP565 */ 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 P6FC ;if none volume not present 86F8 98 TYA ;else print volume letter 86F9 20 00 90 JSR Q000 ;Print character in A .P6FC 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 EQUB &40 874A EQUS " (" 874C EQUB &00 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 MSB sectors on volume 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 word 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 ;Was *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 EQUB &08,&10 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 EQUB &08,&01 .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 ;EDOSPAT extensions, block 3 .P9AD 89AD 20 B8 89 JSR P9B8 ;Set PTR from OSGBPB block: 89B0 A2 BC LDX #&BC ;swap block pointers with req. 89B2 20 A7 85 JSR P5A7 ;point X at request and set PTR 89B5 AE 70 10 LDX &1070 ;X=file handle and swap back: .P9B8 89B8 20 09 92 JSR Q209 ;copy 89BB EQUW &79,&10 ;from OSGBPB block PTR, &1079 89BD EQUW &BC,&00 ;to user block+data addrs,&00BC 89BF EQUB &04,&80 ;4 bytes, fixed addresses +swap 89C1 60 RTS .P9C2 ;OSARGS A=0/2, Y>0 get PTR/EXT 89C2 84 CD STY &CD ;Y=channel workspace offset or 0 89C4 18 CLC ;add to offset in A 89C5 65 CD ADC &CD 89C7 20 09 92 JSR Q209 ;copy 89CA EQUW &00,&10 ;FROM EDOS workspace, &1000 89CC EQUW &00,&00 ;TO OSARGS block, &0000,X 89CE EQUB &03,&12 ;3 bytes, from A to X 89D0 A0 00 LDY #&00 ;clear top byte of OSARGS block 89D2 F0 0E BEQ P9E2 .P9D4 ;OSARGS A=5, Y>0 return EOF 89D4 20 0C B4 JSR S40C ;compare PTR - EXT 89D7 A0 00 LDY #&00 ;OSARGS block = &00000000 89D9 90 01 BCC P9DC ;if PTR is at EOF 89DB 88 DEY ;then OSARGS block = &FFFFFFFF. .P9DC 89DC 94 00 STY &00,X ;set OSARGS block to 4 copies Y 89DE 94 01 STY &01,X .P9E0 89E0 94 02 STY &02,X ;set top two bytes of OSARGS blk .P9E2 89E2 94 03 STY &03,X 89E4 60 RTS .P9E5 ;OSARGS A=1, Y=0 command tail 89E5 20 C2 89 JSR P9C2 ;copy from EDOS workspace 89E8 88 DEY ;Y=&FF, tail always in I/O mem 89E9 D0 F5 BNE P9E0 ;set block=&FFFF0000 + address. .P9EB ;OSARGS A=4, Y=0 vol used space 89EB 20 EC 95 JSR Q5EC ;set OSARGS block to free space 89EE AD 07 0F LDA &0F07 ;get LSB volume size from cat 89F1 38 SEC ;subtract LSB free space 89F2 F5 01 SBC &01,X 89F4 95 01 STA &01,X ;save result in OSARGS block 89F6 AD 06 0F LDA &0F06 ;get MSB volume size 89F9 29 07 AND #&07 ;mask bottom 3 bits 89FB F5 02 SBC &02,X ;subtract MSB free space 89FD 95 02 STA &02,X ;save result in OSARGS block. 89FF 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 EQUB &08,&10 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 .PE64 8E64 A5 AC LDA &AC ;else set O7F address 8E66 8D 12 10 STA &1012 ;to address of data buffer 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,Y ;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. .PE86 8E86 20 00 92 JSR Q200 ;Do disc transfer.A=sector count 8E89 BE 78 10 LDX &1078,Y ;save AXY. if source stg <256 8E8C D0 08 BNE PE96 8E8E D9 76 10 CMP &1076,Y 8E91 90 03 BCC PE96 8E93 B9 76 10 LDA &1076,Y ;then 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 .PEDB 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 PEDB ;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 03 01 STA saved_x,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 ;EDOSPAT extensions, block 4 #if defined _EP565 .PF54 8F54 8D 80 10 STA &1080 ;Limit volume size in *CATGEN 8F57 BD F0 0F LDA &0FF0,X ;store no. tracks in limit var. 8F5A C9 24 CMP #&24 ;get density. 36 sectors? 8F5C F0 06 BEQ PF64 ;then A=&39: allow <=56 tracks 8F5E C9 1E CMP #&1E ;else are there 30 sectors/trk? 8F60 D0 09 BNE PF6B ;if not allow whole-disc volumes 8F62 A9 58 LDA #&58 ;else A=&45: allow <=68 tracks .PF64 8F64 49 1D EOR #&1D ;change &24->&39, &58->&45: 8F66 CD 80 10 CMP &1080 ;compare A with current limit 8F69 90 E9 BCC PF54 ;if A < limit then set new limit .PF6B 8F6B 60 RTS ;else exit .PF6C 8F6C AD 19 10 LDA &1019 ;get sector count from O7F block 8F6F C9 C0 CMP #&C0 ;is it in extended format? 8F71 B0 02 BCS PF75 ;then preserve b5, 0..63 sectors 8F73 29 1F AND #&1F ;else mask b5, 0..31 sectors .PF75 8F75 60 RTS ;caller will mask b6, b7. .PF76 8F76 AC A6 00 LDY &00A6 ;Backspace over CRC 8F79 D0 0F BNE PF8A ;if reading IDs to Tube, exit 8F7B AC 21 0D LDY &0D21 ;else get stored copy of X 8F7E 88 DEY ;subtract 2 from pointer 8F7F 88 DEY 8F80 8C 21 0D STY &0D21 ;store to be loaded in busy loop 8F83 C0 FE CPY #&FE ;if borrow 8F85 90 03 BCC PF8A 8F87 CE 07 0D DEC &0D07 ;then decrement high byte. exit. .PF8A 8F8A 60 RTS .PF8B 8F8B C9 0A CMP #&0A ;Cycle density.Is it now single? 8F8D F0 06 BEQ PF95 ;then set to &0A EOR &18=&12, DD 8F8F C9 12 CMP #&12 ;else was it double density? 8F91 F0 04 BEQ PF97 ;then set to &12 EOR &36=&24, QD 8F93 A9 12 LDA #&12 ;else set to &12 EOR &18=&0A, SD .PF95 8F95 49 2E EOR #&2E .PF97 8F97 49 36 EOR #&36 8F99 4C 17 9D JMP QD17 ;and try to load the catalogue. .PF9C 8F9C AD 84 10 LDA &1084 ;compare density with catalogue 8F9F D0 10 BNE PFB1 ;use *OPT 6 density if set ;.PFA1 8FA1 98 TYA ;else auto. A=density to test 8FA2 C9 24 CMP #&24 ;is it quad density? 8FA4 F0 04 BEQ PFAA ;then try both QD sector counts 8FA6 C9 1E CMP #&1E ;did last disc have 30 sectors? 8FA8 D0 07 BNE PFB1 ;if not, only make one guess .PFAA 8FAA CD 03 0E CMP &0E03 ;else QD. compare with disc cat 8FAD F0 05 BEQ PFB4 ;if sector count correct, exit 8FAF 49 3A EOR #&3A ;else swap 30<->36 sectors: .PFB1 8FB1 CD 03 0E CMP &0E03 ;compare sector count to cat .PFB4 8FB4 9D F0 0F STA &0FF0,X ;save our guess, Z=1 if correct 8FB7 60 RTS #else /* _EP705 */ .PF72 8F72 A9 08 LDA #&08 ;default 8 volumes 8F74 C0 10 CPY #&10 ;unless density of this attempt 8F76 D0 02 BNE PF7A ;is 16 sectors .PF78 8F78 A9 07 LDA #&07 ;in which case default to 7. .PF7A 8F7A 60 RTS .PF7B 8F7B A9 00 LDA #&00 ;Load DFS volume catalogue 8F7D 4C F2 9C JMP QCF2 ;from sectors 0..1. .PF80 ;Validate disc catalogue 8F80 38 SEC ;on entry Z=1 if read succeeded 8F81 D0 05 BNE PF88 ;if failed try 7 volumes 8F83 20 9C 8F JSR PF9C ;else compare density 8F86 F0 30 BEQ PFB8 ;if catalogue good exit Z=1, C=0 .PF88 8F88 AD 85 10 LDA &1085 ;else if *OPT 7 volumes manual 8F8B D0 2B BNE PFB8 ;exit Z=0; C=1 no read/0 bad cat 8F8D BD FC 0F LDA &0FFC,X ;else have we just tried 7 vols? 8F90 49 07 EOR #&07 8F92 F0 E4 BEQ PF78 ;if so exit Z=0, C as above 8F94 A9 0E LDA #&0E ;else try reading from sector 14 8F96 20 F2 9C JSR QCF2 8F99 38 SEC 8F9A D0 1C BNE PFB8 ;if read failed exit Z=0, C=1 .PF9C 8F9C AD 84 10 LDA &1084 ;compare density with catalogue 8F9F D0 10 BNE PFB1 ;use *OPT 6 density if set ;.PFA1 8FA1 98 TYA ;else auto. A=density to test 8FA2 C9 12 CMP #&12 ;is it double density? 8FA4 F0 04 BEQ PFAA ;then try both DD sector counts 8FA6 C9 10 CMP #&10 ;did last disc have 16 sectors? 8FA8 D0 07 BNE PFB1 ;if not, only make one guess .PFAA 8FAA CD 03 0E CMP &0E03 ;else DD. compare with disc cat 8FAD F0 05 BEQ PFB4 ;if sector count correct, exit 8FAF 49 02 EOR #&02 ;else swap 16<->18 sectors: .PFB1 8FB1 CD 03 0E CMP &0E03 ;compare sector count to cat .PFB4 8FB4 9D F0 0F STA &0FF0,X ;save our guess, Z=1 if correct 8FB7 18 CLC ;exit C=0 as read succeeded .PFB8 8FB8 60 RTS #endif /* _EP565 */ .PFB9 8FB9 20 80 BD JSR SD80 ;write first part of gap 8FBC A4 A1 LDY &A1 ;fetch RLE table pointer 8FBE C0 FF CPY #&FF ;have we reached the last cell? 8FC0 D0 F7 BNE PFB9 ;if not then loop 8FC2 8E FF 0F STX &0FFF ;else set last cell=256 bytes: #if defined _EP565 .PFC5 # if defined _WD2791 8FC5 49 FF EOR #&FF ;Pre-invert format byte table. # else /* _WD1772 */ 8FC5 49 00 EOR #&00 ;null invert for 1770 # endif /* _WD2791 */ 8FC7 99 00 0E STA &0E00,Y 8FCA 60 RTS #else /* _EP705 */ 8FC5 8D FF 0E STA &0EFF ;set gap byte SD=&FF, DD=&4E. 8FC8 60 RTS #endif /* _EP565 */ .PFCB 8FCB A9 86 LDA #&86 ;call OSBYTE &86 8FCD 20 F4 FF JSR osbyte 8FD0 8A TXA ;put horiz. cursor position in A .PFD1 8FD1 18 CLC ;Validate cursor position in A 8FD2 6D 08 03 ADC &0308 ;add text window left column 8FD5 CD 0A 03 CMP &030A ;compare with right column. 8FD8 60 RTS .PFD9 ;Print one or more spaces 8FD9 E8 INX ;put POS+1 in A 8FDA 8A TXA 8FDB 20 54 90 JSR Q054 ;print a space 8FDE 48 PHA ;if cursor moved, A = POS now 8FDF 20 CB 8F JSR PFCB ;get actual cursor position 8FE2 8A TXA 8FE3 BA TSX 8FE4 DD 01 01 CMP &0101,X ;compare with reckoned POS 8FE7 68 PLA ;put reckoned POS back in A 8FE8 B0 07 BCS PFF1 ;if cursor moved cmp POS-TAB 8FEA 90 0A BCC PFF6 ;if cursor is stuck then exit .PFEC 8FEC 69 01 ADC #&01 ;increment POS 8FEE 20 54 90 JSR Q054 ;print a space .PFF1 8FF1 DD 05 01 CMP saved_a+1,X ;else are we at/past the TAB? 8FF4 90 F6 BCC PFEC ;if not then loop .PFF6 8FF6 4C 76 90 JMP Q076 ;else return POS in A and exit .PFF9 ;Advance cursor 8FF9 20 CB 8F JSR PFCB ;would a space wrap around? 8FFC 90 DB BCC PFD9 ;if not then print spaces 8FFE B0 71 BCS Q071 ;else print a newline instead ;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 .Q009 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 ;00010000 902C D0 10 BNE Q03E ;if so print the character 902E AD 7C 02 LDA &027C ;else disable *SPOOL output 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 04 01 LDA saved_a,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 04 01 LDA saved_a,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 .Q055 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 48 PHA ;save A again 9060 A4 F4 LDY rmslrg ;get ROM type byte 9062 B9 A1 02 LDA &02A1,Y 9065 29 08 AND #&08 ;test bit 3 9067 D0 EC BNE Q055 ;if set print one space and exit 9069 68 PLA ;else restore entry value of A 906A 20 D1 8F JSR PFD1 ;is this TAB within text window? 906D 90 8A BCC PFF9 ;if so then print whitespace 906F F0 88 BEQ PFF9 .Q071 9071 20 81 90 JSR Q081 ;else print a newline 9074 A9 00 LDA #&00 ;POS is now 0 so clear A: .Q076 9076 BA TSX ;return A=X coordinate 9077 9D 04 01 STA saved_a,X ;of cursor 907A 60 RTS .Q07E ;Display error message/newline 907E 20 00 92 JSR Q200 ;Save AXY .Q081 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 0-2 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 enable *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 6A ROR A ;save carry flag in Y b7 90B5 A8 TAY 90B6 20 03 92 JSR Q203 ;address follows caller's JSR 90B9 AA TAX 90BA 20 03 92 JSR Q203 ;get byte immediate 90BD 86 B2 STX &B2 ;store address in pointer 90BF 85 B3 STA &B3 90C1 C0 80 CPY #&80 ;get carry flag on entry 90C3 EA NOP ;c=print leading zeroes 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 Q0EA 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 ;Print string immediate ;The JSR instruction calling this routine is followed by: ;1 byte microcode (see below), 1 byte error number (if applicable), ;string terminated by NUL. ;The microcode byte is made up as follows: ;&01 .......1 Print newline before string ;&02 ......1. Print newline after string ;&04 .....1.. Beep at end of string ;&08 ...01... Error message, issue it if b1=1 or on JSR &9009 ;&10 ...10... Ask question, get yes/no answer, return Z=1, C=1 if yes ;&40 01...... Print hex value in A after string ;&80 10...... Print decimal value in A after string ;&C0 11...... Print character in A after string .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 rmslrg ;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 04 01 LDA saved_a,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 ;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 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. ;EDOSPAT extensions, block 5 .Q1CB 91CB A0 05 LDY #&05 ;Get OSFILE microcode 91CD BD E6 91 LDA Q1E6,X ;fetch code from table 91D0 85 CD STA &CD ;store it for main routine 91D2 0A ASL A ;set C=b7, N=b6 91D3 B0 10 BCS Q1E5 ;if C=1 return to main routine 91D5 10 09 BPL Q1E0 ;if C=0, N=0 jump into loop 91D7 4C 5C A5 JMP R55C ;else raise File not found error .Q1DA 91DA A9 00 LDA #&00 ;OSFILE A=24 natural block size 91DC 2A ROL A ;set A=0 or 1 according to C 91DD 91 BE STA (&BE),Y ;save in user's OSFILE block 91DF 88 DEY ;offsets 5..2 = &00000100 .Q1E0 91E0 06 CD ASL &CD ;C=next bit (shifting left) 91E2 D0 F6 BNE Q1DA ;loop if more to do 91E4 18 CLC ;else C=0 to exit from OSFILE .Q1E5 91E5 60 RTS ;OSFILE microcode table .Q1E6 91E6 EQUB &86 ;1 ...0110 &FF Load file 91E7 EQUB &83 ;1 .....11 &00 Save file 91E8 EQUB &B8 ;1 .111000 &01 Write catalogue information 91E9 EQUB &88 ;1 .001000 &02 Write load address 91EA EQUB &90 ;1 .010000 &03 Write exec address 91EB EQUB &A0 ;1 .100000 &04 Write attributes 91EC EQUB &84 ;1 ...0100 &05 Read catalogue information 91ED EQUB &8C ;1 ...1100 &06 Delete file 91EE EQUB &81 ;1 .....01 &07 Create file 91EF EQUB &00 ;0 0...... &08 (Create directory) 91F0 EQUB &80 ;1 .000000 &09 Write timestamp 91F1 EQUB &83 ;1 .....11 &0A Save file and write timestamp 91F2 EQUB &81 ;1 .....01 &0B Create file and write timestamp 91F3 EQUB &86 ;1 ...0110 &0C Load file (using path string) 91F4 EQUB &84 ;1 ...0100 &0D Read catalogue information (using path str) 91F5 EQUB &86 ;1 ...0110 &0E Load file (using path variable) 91F6 EQUB &84 ;1 ...0100 &0F Read catalogue information (using path var) 91F7 EQUB &86 ;1 ...0110 &10 Load file (using no path) 91F8 EQUB &84 ;1 ...0100 &11 Read catalogue information (using no path) 91F9 EQUB &80 ;1 .000000 &12 Set type 91FA EQUB &40 ;0 1...... &13 Generate error message 91FB EQUB &84 ;1 ...0100 &14 Read catalogue information 91FC EQUB &84 ;1 ...0100 &15 Read catalogue information (using path str) 91FD EQUB &84 ;1 ...0100 &16 Read catalogue information (using path var) 91FE EQUB &84 ;1 ...0100 &17 Read catalogue information (using no path) 91FF EQUB &28 ;0 0101... &18 Read natural block size ;The other available actions are:- ; EQUB &8E ;1 ...1110 Load and delete file ; EQUB &BA ;1 .111010 Load file and write catalogue information ; EQUB &8A ;1 .001010 Load file and write load address ; EQUB &92 ;1 .010010 Load file and write exec address ; EQUB &A2 ;1 .100010 Load file and write attributes ; EQUB &82 ;1 .000010 Load file and increment catalogue cycle no. ;Macro functions and miscellaneous .Q200 9200 4C 12 92 JMP Q212 ;Save AXY .Q203 9203 4C C7 92 JMP Q2C7 ;Get byte immediate .Q206 9206 4C 42 92 JMP Q242 ;Copy memory absolute .Q209 9209 4C 45 92 JMP Q245 ;Copy memory absolute indexed .Q20C 920C 6C 1E 02 JMP (osfscv) ;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): ;&B8, &92, X, A, Y, superroutine address(-1) low, high ;i.e. &0101,S = &B8; &0104,S = A. ;Save AXY (incl. caller's JSR) execution time = 49 us ;Save AXY (incl. caller's JSR) + Restore AXY execution time = 68 us .Q212 ;Save AXY 9212 08 PHP ;save status (placeholder) 9213 08 PHP ;save status 9214 48 PHA ;save A 9215 8A TXA 9216 BA TSX 9217 9D 03 01 STA saved_x,X ;save X over placeholder 921A BD 05 01 LDA &0105,X ;push caller address high 921D 48 PHA 921E BD 04 01 LDA &0104,X ;push caller address low 9221 48 PHA 9222 BD 02 01 LDA &0102,X ;push status on entry 9225 48 PHA 9226 98 TYA ;save Y over caller addr high 9227 9D 05 01 STA saved_y,X 922A BD 01 01 LDA &0101,X ;push A on entry 922D 48 PHA 922E 9D 04 01 STA saved_a,X ;and overwrite caller addr low 9231 A9 92 LDA #&92 ;save return address high 9233 9D 02 01 STA &0102,X ;over status 9236 A9 B8 LDA #&B8 ;save return address low 9238 9D 01 01 STA &0101,X ;over A 923B BD 03 01 LDA saved_x,X ;get X on entry 923E AA TAX ;restore to X register 923F 68 PLA ;restore A 9240 28 PLP ;restore status 9241 60 RTS ;return to caller. ;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. .Q242 ;Copy memory absolute 9242 18 CLC ;continue with C=0 9243 90 01 BCC Q246 ;Copy memory absolute indexed ;Arguments as for "Copy memory absolute", plus a sixth byte: ;bits 1 and 0 of this byte control indexing of the From address, ;bits 5 and 4 control indexing of the To address. ;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 ;00 Zero ;01 X on entry ;10 A on entry ;11 Y on entry ;Bits 6, 3 and 2 are reserved and must be zero. ;Bit 7, if set, causes the contents of the two memory areas to be swapped. .Q245 ;Copy memory absolute indexed 9245 38 SEC ;continue with C=1 .Q246 9246 08 PHP ;save status (placeholder) 9247 48 PHA ;save A 9248 8A TXA ;save X 9249 48 PHA 924A BA TSX ;save Y over placeholder 924B 98 TYA 924C 9D 03 01 STA saved_y-2,X 924F BD 04 01 LDA &0104,X ;get LSB of superroutine return 9252 85 B2 STA &B2 ;address, save operand pointer 9254 BD 05 01 LDA &0105,X ;hold MSB operand pointer in A 9257 A0 06 LDY #&06 ;6 operand bytes to copy 9259 90 14 BCC Q26F ;but only copy 5 if not indexed .Q25B 925B BA TSX 925C FE 04 01 INC &0104,X ;increment return address 925F D0 03 BNE Q264 9261 FE 05 01 INC &0105,X .Q264 9264 A6 B3 LDX &B3 ;save MSB of copy from address 9266 48 PHA 9267 85 B3 STA &B3 ;reform operand pointer 9269 B1 B2 LDA (&B2),Y ;fetch operand byte from pointer 926B 99 B1 00 STA &00B1,Y ;save at &B7..&B2, offsets 6..1 926E 68 PLA ;pop MSB operand pointer .Q26F 926F 88 DEY ;next byte 9270 D0 E9 BNE Q25B ;loop until offset=0 9272 86 B3 STX &B3 ;reform copy from address 9274 90 3A BCC Q2B0 ;if C=0 then start copying 9276 98 TYA ;else push 0 on stack 9277 48 PHA ;stack now contains 0,X,A,Y .Q278 9278 BA TSX ;start with X pointing at 0 9279 46 B7 LSR &B7 ;shift indexing argument 927B 90 01 BCC Q27E ;if b0=1 or b4=1 927D E8 INX ;then add 1 to X, point at X .Q27E 927E 46 B7 LSR &B7 ;shift indexing argument 9280 90 02 BCC Q284 ;if b1=1 or b5=1 9282 E8 INX ;then add 2 to X, point at A/Y 9283 E8 INX .Q284 9284 46 B7 LSR &B7 ;discard b2 and b6 (into carry) 9286 BD 01 01 LDA &0101,X ;put requested adjustment in A 9289 79 B2 00 ADC &00B2,Y ;add to byte of to/from address 928C 99 B2 00 STA &00B2,Y ;store result in address 928F 90 04 BCC Q295 ;carry out to high byte 9291 98 TYA 9292 AA TAX 9293 F6 B3 INC &B3,X .Q295 9295 A0 02 LDY #&02 ;point Y to To address 9297 46 B7 LSR &B7 ;discard b3 of index arg 9299 D0 DD BNE Q278 ;adjust To address if required 929B 68 PLA ;discard 0 on stack 929C A8 TAY ;set Y=0. C=index argument b7 929D 90 11 BCC Q2B0 ;if C=0 then copy one way .Q29F 929F B1 B2 LDA (&B2),Y ;Swap. fetch byte from From area 92A1 AA TAX ;hold it in X 92A2 B1 B4 LDA (&B4),Y ;fetch byte from To area 92A4 91 B2 STA (&B2),Y ;store in From area 92A6 8A TXA ;put From byte back in A 92A7 91 B4 STA (&B4),Y ;store in To area 92A9 C8 INY ;increment offset 92AA C4 B6 CPY &B6 ;have we copied all bytes? 92AC D0 F1 BNE Q29F ;if not then loop 92AE F0 09 BEQ Q2B9 ;else restore AXY and exit .Q2B0 92B0 B1 B2 LDA (&B2),Y ;fetch byte from From area 92B2 91 B4 STA (&B4),Y ;store in To area 92B4 C8 INY ;increment offset 92B5 C4 B6 CPY &B6 ;have we copied all bytes? 92B7 D0 F7 BNE Q2B0 ;if not then loop, else: ;Restore AXY. Invoked by the caller of "Save AXY" when it reaches ;an RTS. ;During the TSX at &92BB the stack contains (right to left): ;X, A, Y, superroutine address(-1) low, high ;i.e. &0101,S = X. ;Restore AXY execution time = 19 us (22 us incl. caller's RTS) .Q2B9 ;Restore AXY Invoked by caller on RTS. 92B9 08 PHP ;push status register on entry 92BA 68 PLA ;peek its value into A 92BB BA TSX ;get stack pointer 92BC BC 03 01 LDY saved_y-2,X ;restore Y 92BF 9D 03 01 STA saved_y-2,X ;replace on stack with status 92C2 68 PLA ;pop X 92C3 AA TAX 92C4 68 PLA ;pop A 92C5 28 PLP ;pop status 92C6 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 &92CA the stack contains (right to left): ;&B8, &92, caller X, A, Y, ;caller return address(-1) low, high, ;&B8, &92, superroutine X, A, Y, ;superroutine return address(-1) low, high ;therefore &010D..E,S = address of the immediate operand, less one. .Q2C7 ;Get byte immediate 92C7 20 00 92 JSR Q200 ;save AXY 92CA BA TSX ;transfer stack pointer to X 92CB A0 FE LDY #&FE ;set Y = reverse counter 92CD 38 SEC ;set C=1 to add 1 .Q2CE 92CE BD 0D 01 LDA &010D,X ;get byte of return address 92D1 69 00 ADC #&00 ;increment low or carry to high 92D3 9D 0D 01 STA &010D,X ;put back in stack to skip byte 92D6 99 B4 FF STA &FFB4,Y ;and copy to &B2..&B3 as pointer 92D9 E8 INX ;advance stack pointer 92DA C8 INY ;advance workspace pointer 92DB D0 F1 BNE Q2CE ;loop until two bytes copied 92DD B1 B2 LDA (&B2),Y ;Y=0, fetch byte at pointer 92DF 9D 02 01 STA saved_a-2,X ;return in A 92E2 60 RTS ;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 05 01 STA saved_y,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 04 01 STA saved_a,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 gsflag ;if b6=1, this routine reached EOS 9460 70 09 BVS Q46B ;(or C=1 to GSINIT!) so return space 9462 20 C5 FF JSR gsread ;else GSREAD 9465 90 07 BCC Q46E ;if not EOS return A=character, C=0 9467 66 E4 ROR gsflag 9469 66 E4 ROR gsflag ;else set b6=1, signal EOS to self .Q46B 946B A9 20 LDA #&20 ;return a space 946D 38 SEC .Q46E 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 <> ":" 94B2 D0 19 BNE Q4CD ;then exit C=0 94B4 20 C5 FF JSR gsread ;else call GSREAD 94B7 B0 15 BCS Q4CE ;if end-of-word exit C=1 94B9 20 81 94 JSR Q481 ;else get drive character 94BC B0 10 BCS Q4CE ;if end-of-word exit C=1 94BE 20 CF 94 JSR Q4CF ;else get volume letter 94C1 B0 0B BCS Q4CE ;if end-of-word exit C=1 94C3 C9 2E CMP #&2E ;else compare this char to "." 94C5 F0 03 BEQ Q4CA ;if equal call GSREAD and exit .Q4C7 94C7 4C D7 93 JMP Q3D7 ;else 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 ;EDOSPAT extensions, block 6 .Q56C ;OSARGS A=6, Y>0 set alloc len 956C B5 00 LDA &00,X ;compare requested allocation 956E C9 01 CMP #&01 ;(rounded up to whole sector) 9570 B5 01 LDA &01,X ;-current allocation 9572 F9 98 10 SBC &1098,Y 9575 B5 02 LDA &02,X 9577 F9 99 10 SBC &1099,Y 957A B5 03 LDA &03,X ;c=0 iff less than or equal to 957C E9 00 SBC #&00 ;current allocation 957E B9 88 10 LDA &1088,Y ;get channel flag 9581 10 62 BPL Q5E5 ;result or error if read only 9583 90 13 BCC Q598 ;set new allocation if no more 9585 8A TXA ;otherwise save OSARGS pointer 9586 48 PHA 9587 20 5D B6 JSR S65D ;extend file on disc 958A 68 PLA ;restore OSARGS pointer 958B AA TAX 958C 4C 6C 95 JMP Q56C ;and try to set allocation again .Q58F 958F 20 09 92 JSR Q209 ;copy 9592 EQUW &9A,&10 ;FROM EXT, &109A,Y 9594 EQUW &00,&00 ;TO OSARGS block, &0000,X 9596 EQUB &03,&13 ;3 bytes, from Y to X .Q598 9598 B5 00 LDA &00,X ;test LSB of request 959A F0 06 BEQ Q5A2 ;if not whole number of sectors 959C F6 01 INC &01,X ;then round up 3MSB 959E D0 02 BNE Q5A2 95A0 F6 02 INC &02,X ;and 2MSB .Q5A2 95A2 B9 9A 10 LDA &109A,Y ;does file(EXT) use more sectors 95A5 C9 01 CMP #&01 ;than allocation request? 95A7 B9 9B 10 LDA &109B,Y 95AA F5 01 SBC &01,X 95AC B9 9C 10 LDA &109C,Y 95AF F5 02 SBC &02,X 95B1 B0 DC BCS Q58F ;if so then request = extent 95B3 20 1B 98 JSR Q81B ;else check volume is the same 95B6 A9 00 LDA #&00 ;clear LSB file length 95B8 8D 4E 10 STA &104E 95BB B5 01 LDA &01,X ;copy 3MSB request 95BD 8D 53 10 STA &1053 ;to LSB length in sectors 95C0 8D 4F 10 STA &104F ;to 2MSB file length 95C3 99 98 10 STA &1098,Y ;and LSB allocated length 95C6 B5 02 LDA &02,X ;copy 2MSB request likewise 95C8 8D 54 10 STA &1054 95CB 20 7D B6 JSR S67D ;write to catalogue 95CE 20 0F A6 JSR R60F ;calculate absolute end of file 95D1 B9 96 10 LDA &1096,Y ;compare LBA of sector in buffer 95D4 CD 69 10 CMP &1069 ;-LBA of end (last+1 sec)of file 95D7 B9 97 10 LDA &1097,Y 95DA ED 6A 10 SBC &106A 95DD 90 06 BCC Q5E5 ;if within new allocation return 95DF A9 00 LDA #&00 ;else discard buffer 95E1 99 89 10 STA &1089,Y ;mark buffer empty: 95E4 18 CLC .Q5E5 ;Tried to set alloc of r/o file 95E5 A9 97 LDA #&97 ;A=offset of allocation - 1 95E7 90 11 BCC Q5FA ;return allocation at &1098..9,Y 95E9 4C B4 B6 JMP S6B4 ;else 'File read only' error. .Q5EC ;OSARGS A=5, Y=0 vol free space 95EC 20 06 92 JSR Q206 ;copy 95EF EQUW &07,&10 ;FROM default drv/vol/dir, &1007 95F1 EQUW &C7,&00 ;TO immediate drv/vol/dir, &00C7 95F3 EQUB &03 ;3 bytes 95F4 20 00 9B JSR QB00 ;load volume catalogue 95F7 20 1B A6 JSR R61B ;calculate free space on volume .Q5FA ;OSARGS A=4, Y>0 get alloc len 95FA 20 C2 89 JSR P9C2 ;copy to 3..2MSB 95FD 94 00 STY &00,X ;clear LSB of OSARGS block 95FF 60 RTS ;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 98 TYA ;test Y register 9627 30 03 BMI Q62C ;if b7=1 then skip version string 9629 20 2F 96 JSR Q62F ;else print version string .Q62C 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 B5 9A JSR QAB5 ;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 C9 83 JSR P3C9 ;else print EDOS banner w/2 newlines 9679 A0 00 LDY #&00 ;clear y for use as offset: .Q67B 967B B9 04 97 LDA Q704,Y ;get meta-default path and lib 967E C0 0D CPY #&0D ;have we got it all? .Q680 9680 91 A8 STA (&A8),Y ;store in private page 9682 A9 00 LDA #&00 ;a=0 to clear rest of page 9684 C8 INY ;increment offset 9685 90 F4 BCC Q67B ;if more path to copy then copy it 9687 D0 F7 BNE Q680 ;else clear rest of private page .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 8C 15 10 STY &1015 ;force interrupt has no parameters 969C 20 06 92 JSR Q206 ;copy default path to zero page 969F EQUW &00,&10 ;FROM default path, &1000 96A1 EQUW &C0,&00 ;TO current path, &00C0 96A3 EQUB &0A ;10 bytes; leafname, dir, vol, drv 96A4 A9 36 LDA #&36 ;&36 = EDOS pseudo-command 96A6 8D 16 10 STA &1016 ;2791 Force Interrupt 96A9 20 12 9B JSR QB12 ;issue plain OSWORD &7F 96AC BA TSX ;get value of Y on entry 96AD BD 05 01 LDA saved_y,X 96B0 D0 20 BNE Q6D2 ;if Y=0 exit with C=1, break out 96B2 20 00 9B JSR QB00 ;else softmount & load cat 96B5 20 09 96 JSR Q609 ;get boot option 96B8 F0 18 BEQ Q6D2 ;if boot is OFF, exit C=1 96BA 20 09 92 JSR Q209 ;else copy boot command 96BD EQUW &0C,&96 ;from &960C 96BF EQUW &58,&10 ;to string workspace at &1058 96C1 EQUB &04,&01 ;4 bytes, X indexed source 96C3 20 06 92 JSR Q206 ;copy 96C6 EQUW &4C,&97 ;FROM filename " $.!boot"+cr, Q74C 96C8 EQUW &5C,&10 ;TO address &105C 96CA EQUB &09 ;count 9 bytes 96CB A2 58 LDX #&58 ;call OSCLI on command string 96CD A0 10 LDY #&10 96CF 20 F7 FF JSR oscli .Q6D2 96D2 38 SEC ;set C=1 to break out of ROM call 96D3 60 RTS ;and exit .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 DD 9A JSR QADD ;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 .Q74C 974C EQUS " $.!boot" ;"$.!boot" name of boot file 9754 EQUB &0D ;CR ;EDOSPAT extensions, block 7 .Q755 9755 20 15 93 JSR Q315 ;*ADDRESS 9758 20 8B 97 JSR Q78B ;get afsp, get load address 975B B0 2B BCS Q788 ;if no address print syntax 975D 20 E4 97 JSR Q7E4 ;else set load and exec address 9760 20 8B 97 JSR Q78B ;get exec address 9763 B0 03 BCS Q768 ;if no address then exec=load 9765 20 E9 97 JSR Q7E9 ;else set exec address .Q768 9768 20 00 9B JSR QB00 ;load catalogue 976B 20 15 A5 JSR R515 ;ensure matching unlocked file 976E B0 17 BCS Q787 ;if no match then exit .Q770 9770 20 03 A6 JSR R603 ;else unpack its cat entry 9773 20 06 92 JSR Q206 ;copy 9776 EQUW &60,&10 ;FROM temp load and exec 9778 EQUW &48,&10 ;TO unpacked catalogue entry 977A EQUB &06 ;6 bytes 977B 20 06 A6 JSR R606 ;pack catalogue entry 977E 20 18 A5 JSR R518 ;find next unlocked match 9781 90 ED BCC Q770 ;loop for next file if found 9783 20 03 9B JSR QB03 ;else write catalogue 9786 38 SEC ;break out of ROM call & exit. .Q787 9787 60 RTS .Q788 9788 4C 09 81 JMP P109 ;Print syntax for command. .Q78B 978B A9 00 LDA #&00 ;Get address 978D 8D 58 10 STA &1058 ;clear address workspace 9790 8D 59 10 STA &1059 ;32 bits 9793 8D 5A 10 STA &105A 9796 8D 5B 10 STA &105B 9799 20 47 95 JSR Q547 ;call GSINIT C=0, GSREAD 979C B0 34 BCS Q7D2 ;if end of string then exit 979E 38 SEC ;else character counter = 0->1: .Q79F 979F 2E 5C 10 ROL &105C ;shift character counter 97A2 F0 2F BEQ Q7D3 ;if >8 chars then bad address 97A4 C9 3A CMP #&3A ;else compare char with "9" 97A6 B0 04 BCS Q7AC ;if more then treat as letter 97A8 C9 30 CMP #&30 ;else compare with "0" 97AA B0 0C BCS Q7B8 ;if valid digit add to wksp .Q7AC 97AC 29 DF AND #&DF ;else a letter. to uppercase 97AE C9 47 CMP #&47 ;is it more than "F"? 97B0 B0 21 BCS Q7D3 ;if so then bad address 97B2 C9 41 CMP #&41 ;is it less than "A"? 97B4 90 1D BCC Q7D3 ;if so then bad address 97B6 E9 37 SBC #&37 ;else convert to &A..F: .Q7B8 97B8 2A ROL A ;c=1, set c=D (b3 of digit) 97B9 0A ASL A ;a=CBA1.... to loop 4 times: 97BA 0A ASL A 97BB 0A ASL A 97BC 0A ASL A .Q7BD 97BD 2E 58 10 ROL &1058 ;shift c into b0 of workspace 97C0 2E 59 10 ROL &1059 ;shift workspace 1 bit left 97C3 2E 5A 10 ROL &105A ;32-bits 97C6 2E 5B 10 ROL &105B 97C9 0A ASL A ;c=next bit of digit 97CA D0 F1 BNE Q7BD ;loop until hex digit added 97CC 20 C5 FF JSR gsread ;call GSREAD for next character 97CF 90 CE BCC Q79F ;if not end-of-string then loop 97D1 18 CLC ;else exit C=0 for success. .Q7D2 97D2 60 RTS .Q7D3 97D3 20 18 90 JSR Q018 ;Raise "Bad address" error. 97D6 EQUB &0A ;error message, LF after 97D7 EQUB &FC ;error number &FC 97D8 EQUS "Bad address" ;message string "Bad address" 97E3 EQUB &00 ;terminator byte .Q7E4 97E4 A2 60 LDX #&60 ;Set load and exec address 97E6 20 EB 97 JSR Q7EB ;do 32-to-18 bit copy: .Q7E9 97E9 A2 63 LDX #&63 ;Set exec address .Q7EB 97EB AD 58 10 LDA &1058 ;Do 32-to-18 bit copy 97EE 9D 00 10 STA &1000,X ;from address workspace 97F1 AD 59 10 LDA &1059 ;to EDOS workspace, X indexed 97F4 9D 01 10 STA &1001,X ;transfer bottom two bytes 97F7 AD 5A 10 LDA &105A ;get third byte 97FA 29 03 AND #&03 ;mask off bits 0..2 97FC 9D 02 10 STA &1002,X ;store in EDOS workspace. 97FF 60 RTS ;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 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 Q839-&11,X ;else, point Y to file workspace 9835 B9 88 10 LDA &1088,Y ;put file flag byte in A .Q838 9838 60 RTS .Q839 9839 EQUB &00 ;indexed by X above 983A EQUB &18 ;table to start of workspace 983B EQUB &30 ;for channels &11..15 983C EQUB &48 983D EQUB &60 .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 .Q864 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 05 01 STA saved_y,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 04 01 ORA saved_a,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 .Q944 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 EQUB &03,&03 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 EQUB &0A,&03 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 EQUB &05,&33 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 EQUB &0A,&30 99F9 20 09 92 JSR Q209 ;copy absolute start sector 99FC EQUW &51,&10 ;to file workspace 99FE EQUW &94,&10 9A00 EQUB &02,&30 9A02 20 09 92 JSR Q209 ;copy number of sectors used 9A05 EQUW &53,&10 ;to allocated length 9A07 EQUW &98,&10 9A09 EQUB &02,&30 9A0B B9 88 10 LDA &1088,Y ;get channel flag 9A0E 2A ROL A 9A0F 10 09 BPL QA1A ;if open for reading/update 9A11 20 09 92 JSR Q209 ;then copy file length to EXT 9A14 EQUW &4E,&10 9A16 EQUW &9A,&10 9A18 EQUB &03,&30 .QA1A 9A1A B9 88 10 LDA &1088,Y ;get channel flag .QA1D 9A1D 60 RTS ;exit 9A1E EQUB &FF,&FF,&03,&FF ;table [0..15] of parameters 9A22 EQUB &FF,&03,&00,&40 ;for new open files 9A26 EQUB &00,&00,&00,&40 ;desired sector allocation &40 9A2A EQUB &00,&00,&00,&00 ;to open 5 files on a 100K disc .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 QA62 ;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 .QA62 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 8 .QAB5 9AB5 A2 00 LDX #&00 ;Call high OSBYTE 9AB7 A0 FF LDY #&FF ;set X&Y so not to change value 9AB9 4C F4 FF JMP osbyte .QABC 9ABC AD 10 10 LDA &1010 ;get drive from O7F block: ;.QABF 9ABF 29 03 AND #&03 ;limit number to 0..3 9AC1 09 30 ORA #&30 ;and make it an ASCII digit: ;.QAC3 9AC3 AA TAX ;copy to X as index .QAC4 9AC4 BD F0 0F LDA &0FF0,X ;look up density of this drive: ;.QAC7 9AC7 C9 0A CMP #&0A ;if 10, single density 9AC9 F0 08 BEQ QAD3 ;then return it in A 9ACB 09 02 ORA #&02 ;else if 16 or 18, double density 9ACD C9 12 CMP #&12 9ACF F0 02 BEQ QAD3 ;then return 18 in A #if defined _EP565 9AD1 A9 24 LDA #&24 ;else return 36, quad density #else /* _EP705 */ 9AD1 A9 0A LDA #&0A ;else return 10, single density #endif /* _EP565 */ .QAD3 9AD3 60 RTS .QAD4 ;Finish softmount 9AD4 A9 00 LDA #&00 ;track no. = 0 for *VERIFY 9AD6 8D 17 10 STA &1017 ;store in OSWORD &7F block 9AD9 BD FC 0F LDA &0FFC,X ;return Z=1 if single volume disc 9ADC 60 RTS .QADD 9ADD 20 3A 97 JSR Q73A ;test flag in private page 9AE0 D0 0F BNE QAF1 ;if abs wksp not ours, exit Z=0 .QAE2 ;OSARGS A=&FF, Y=0 flush all 9AE2 A2 11 LDX #&11 ;else start at channel &11: .QAE4 9AE4 20 00 98 JSR Q800 ;initialise for channel 9AE7 F0 03 BEQ QAEC ;if not in use try next channel 9AE9 20 0F 98 JSR Q80F ;else flush the channel. .QAEC 9AEC E8 INX ;increment handle (?&CD=random) 9AED E0 16 CPX #&16 ;have we done all handles? 9AEF D0 F3 BNE QAE4 ;if not then loop else exit Z=1 .QAF1 9AF1 60 RTS .QAF2 9AF2 8D 12 10 STA &1012 ;store updated address 2nd byte 9AF5 90 08 BCC QAFF ;if no carry out then exit 9AF7 EE 13 10 INC &1013 ;else carry out to top word 9AFA D0 03 BNE QAFF ;of OSWORD &7F address 9AFC EE 14 10 INC &1014 .QAFF 9AFF 60 RTS ;Disc operations .QB00 9B00 4C 4A 9B JMP QB4A ;Softmount & load current cat .QB03 9B03 4C E1 9B JMP QBE1 ;Write current catalogue .QB06 9B06 4C 1B 9B JMP QB1B ;Do LBA transfer .QB09 9B09 4C 50 9B JMP QB50 ;Load volume catalogue .QB0C 9B0C 4C 88 9B JMP QB88 ;Softmount disc .QB0F 9B0F 4C 02 9C JMP QC02 ;Call OSWORD &7F, report errors .QB12 9B12 4C FD 9C JMP QCFD ;Call OSWORD &7F .QB15 9B15 4C FF 9B JMP QBFF ;Call OSWORD &7F r/w w/errors .QB18 9B18 4C FA 9C JMP QCFA ;Call OSWORD &7F read/write #if defined _EP565 ;Note: on entry to QB15 and QB18: ?&1019 = sector count (no size code) #endif /* _EP565 */ ;Do LBA transfer. On entry A=no. of sectors, XY=absolute start sector, ;?&C9=drive, !&1011=address, ?&1016=8271 command. ;On exit XY=absolute end sector (last accessed+1), value used at &8EA3. ;Transfers the first track and tail-recurses until done. .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 #if defined _EP565 9B2A 20 6C 8F JSR PF6C ;mask off sector size field 9B2D 29 3F AND #&3F ;put back in OSWORD &7F block #else /* _EP705 */ 9B2A AD 19 10 LDA &1019 ;mask off sector size field 9B2D 29 DF AND #&DF ;put back in OSWORD &7F block #endif /* _EP565 */ 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 #if defined _EP565 9BA8 20 C4 9A JSR QAC4 ;get and validate density 9BAB 20 17 9D JSR QD17 ;try to load catalogue 9BAE F0 14 BEQ QBC4 ;if successful test stepping 9BB0 20 8B 8F JSR PF8B ;else cycle density and retry 9BB3 F0 0F BEQ QBC4 ;if successful test stepping 9BB5 20 8B 8F JSR PF8B ;else cycle density and retry 9BB8 F0 0A BEQ QBC4 ;if successful test stepping 9BBA D0 4C BNE QC08 ;if failed go and decode error. #else /* _EP705 */ 9BA8 F0 08 BEQ QBB2 ;0=autodetect. .QBB2 9BB2 20 C4 9A JSR QAC4 ;get and validate density 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: #endif /* _EP565 */ .QBBC 9BBC 20 17 9D JSR QD17 ;Attempt at specified density 9BBF F0 03 BEQ QBC4 ;if failed to load catalogue 9BC1 4C 08 9C JMP QC08 ;then 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 4C D4 9A JMP QAD4 ;track=0, Z=single volume disc .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 = number of parameters 9C0B BD 17 10 LDA &1017,X ;A = OSWORD &7F (8271) status 9C0E C9 12 CMP #&12 ;if status = &12 9C10 D0 16 BNE QC28 9C12 20 18 90 JSR Q018 ;start "Write protect" error 9C15 EQUB &08 9C16 EQUB &C7 9C17 EQUS "Write protect" 9C24 EQUB &00 ;terminator byte 9C25 4C B8 9C JMP QCB8 ;add disc address to error .QC28 9C28 C9 20 CMP #&20 ;else if status = &20 9C2A D0 1A BNE QC46 9C2C 20 18 90 JSR Q018 ;start "Deleted data read" error 9C2F EQUB &08 9C30 EQUB &C7 9C31 EQUS "Deleted data read" 9C42 EQUB &00 ;terminator byte 9C43 4C B8 9C JMP QCB8 ;add disc address to error .QC46 9C46 C9 0C CMP #&0C ;else if status = &0C 9C48 D0 15 BNE QC5F 9C4A 20 18 90 JSR Q018 ;start "ID CRC error" 9C4D EQUB &08 9C4E EQUB &C7 9C4F EQUS "ID CRC error" 9C5B EQUB &00 ;terminator byte 9C5C 4C B8 9C JMP QCB8 ;add disc address to error .QC5F 9C5F C9 18 CMP #&18 ;else if status = &18 9C61 D0 13 BNE QC76 9C63 20 18 90 JSR Q018 ;start "Seek error" error 9C66 EQUB &08 9C67 EQUB &C7 9C68 EQUS "Seek error" 9C72 EQUB &00 ;terminator byte 9C73 4C B8 9C JMP QCB8 ;add disc address to error .QC76 9C76 C9 0E CMP #&0E ;else if status = &0E 9C78 D0 17 BNE QC91 9C7A 20 18 90 JSR Q018 ;start "Data CRC error" error 9C7D EQUB &08 9C7E EQUB &C7 9C7F EQUS "Data CRC error" 9C8D EQUB &00 ;terminator byte 9C8E 4C B8 9C JMP QCB8 ;add disc address to error .QC91 9C91 C9 0A CMP #&0A ;else if status = &0A 9C93 D0 12 BNE QCA7 9C95 20 18 90 JSR Q018 ;start "Lost data" error 9C98 EQUB &08 9C99 EQUB &C7 9C9A EQUS "Lost data" 9CA3 EQUB &00 ;terminator byte 9CA4 4C B8 9C JMP QCB8 ;add disc address to error .QCA7 9CA7 20 18 90 JSR Q018 ;otherwise generic "Disc Fault" 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 " 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 06 (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 #if defined _EP565 9CEC EQUB &00,&00,&02 ;parameters #else /* _EP705 */ 9CEC EQUB &00,&00,&22 ;parameters #endif /* _EP565 */ .QCEF ;3-bytes copied to &1015 9CEF EQUW &01,&3D ;special register 06 (sector number) 9CF1 EQUB &06 .QCF2 ;Read DFS/disc catalogue 9CF2 8D 18 10 STA &1018 ;store sector offset 9CF5 4A LSR A 9CF6 9D FC 0F STA &0FFC,X ;store volume count for current drive 9CF9 98 TYA ;A=density of current attempt, unused .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 #if defined _EP565 9D21 D0 02 BNE QD25 ;not 0? Load disc cat, YAFI 9D23 A9 08 LDA #&08 ;0=autodetect: default 8 vols. .QD25 9D25 0A ASL A ;double to get sector address 9D26 DD F0 0F CMP &0FF0,X ;is it within bounds of track? 9D29 90 1E BCC QD49 ;then read disc catalogue else: 9D2B A9 00 LDA #&00 ;treat as single volume disc 9D2D 20 F2 9C JSR QCF2 ;read DFS catalogue #else /* _EP705 */ 9D21 D0 03 BNE QD26 ;not 0? Load disc cat, YAFI 9D23 20 72 8F JSR PF72 ;0=auto: 16 sec = 7 vols else 8 .QD26 9D26 0A ASL A ;double to get sector address 9D27 DD F0 0F CMP &0FF0,X ;is it within bounds of track? 9D2A 90 1D BCC QD49 ;then read disc catalogue else: 9D2C 20 7B 8F JSR PF7B ;treat as single volume disc 9D2F EA NOP ;read DFS catalogue #endif /* _EP565 */ 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 #if defined _EP565 9D4C D0 2E BNE QD7C ;if read failed then exit 9D4E 20 9C 8F JSR PF9C ;have we got density right? 9D51 D0 2A BNE QD7D ;if not complain bad layout #else /* _EP705 */ 9D4C 20 80 8F JSR PF80 ;validate disc catalogue 9D4F B0 2B BCS QD7C ;if read failed then exit 9D51 D0 2A BNE QD7D ;if bad complain bad layout #endif /* _EP565 */ 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 #if defined _EP565 9DA3 09 C0 ORA #&C0 ;Extended format, 0..63 sectors #else /* _EP705 */ 9DA3 09 20 ORA #&20 ;256 byte sectors #endif /* _EP565 */ 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 complement 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 ;print Tube coprocessor banner: A060 10 FB BPL R05D ;poll until character in FIFO 0 A062 AD E1 FE LDA tubeR1data ;then read data register 0 A065 F0 EA BEQ R051 ;if =NUL then exit C=1 A067 20 EE FF JSR oswrch ;else print the character & loop 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 ;claim Tube A073 4C 06 04 JMP tube_entry ;call tube .R076 A076 20 00 92 JSR Q200 ;Save AXY A079 38 SEC ;set up Tube flag A07A 6A ROR A ;b6=1, Tube in use A07B 6A ROR A ;b7=1 if writing to coprocessor A07C 8D 3A 10 STA &103A .R07F A07F A9 C1 LDA #&C1 ;poll Tube entry point w/A=&C1 A081 20 06 04 JSR tube_entry ;to claim Tube for DFS (%000001) A084 90 F9 BCC R07F ;until C=1 returned, then exit. 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 04 01 STA saved_a,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 ;clear Tube flag A0A0 8D 3A 10 STA &103A ;set A=&81,DFS is releasing Tube 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 TXS 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 osfile call A248 EQUW &D1,&05 ;R2 was 16 - jump osgbpb_call A24A EQUW &86,&88 A24C EQUW &96,&98 A24E EQUW &18,&18 A250 EQUW &82,&18 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 ;Copy Tube host code to &05FE, &FF bytes A330 EQUB &FE 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 Q000 ;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] ;EDOSPAT extensions, block 9 #ifndef _WHOLE .R4BA A4BA 60 RTS .R4BB ;Transfer bulk then last sector A4BB F0 03 BEQ R4C0 ;OSWORD doesn't like zero: exit A4BD 20 06 9B JSR QB06 ;otherwise transfer A sectors .R4C0 A4C0 AD 4E 10 LDA &104E ;get LSB file length A4C3 F0 F5 BEQ R4BA ;if whole no.of sectors then exit A4C5 AD 16 10 LDA &1016 ;only called with commands &0B,13 A4C8 69 6D ADC #&6D ;if reading from disc then b7=1 A4CA 29 80 AND #&80 ;mask off b0..b6 A4CC 8D 3A 10 STA &103A ;store b7 in Tube channel flag A4CF 0A ASL A ;C=1 if read A4D0 AD 13 10 LDA &1013 ;and high bytes of O7F address A4D3 2D 14 10 AND &1014 A4D6 49 FF EOR #&FF ;invert; if A>0 then Tube addr. A4D8 2D 7A 02 AND &027A ;A=0 if host addr or Tube absent A4DB F0 07 BEQ R4E4 ;in which case transfer to host A4DD A9 00 LDA #&00 ;else set A=1 if write,2 if read A4DF 69 01 ADC #&01 A4E1 20 5B BC JSR SC5B ;open Tube channel to O7F addr. .R4E4 A4E4 20 06 92 JSR Q206 ;copy A4E7 EQUW &11,&10 ;FROM OSWORD &7F address, &1011 A4E9 EQUW &CA,&00 ;TO file buffer pointer, &00CA A4EB EQUB &02 ;2 bytes A4EC 20 06 92 JSR Q206 ;set O7F address = &FFFF0E00 A4EF EQUW &E6,&9C ;FROM table, &9CE6 A4F1 EQUW &11,&10 ;TO OSWORD &7F address, &1011 A4F3 EQUB &04 ;4 bytes A4F4 AD 3A 10 LDA &103A ;test Tube channel flag A4F7 48 PHA ;save N for later A4F8 10 03 BPL R4FD ;if reading from disc A4FA 20 44 99 JSR Q944 ;then read sector to catalogue .R4FD A4FD 4C BE A8 JMP R8BE ;transfer end of file to user #endif ;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 .R515 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 .R55C 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 ;EDOSPAT extensions, block 10 .R5F1 ;Clear unused part of catalogue A5F1 A9 00 LDA #&00 ;set A=&00 .R5F3 A5F3 E0 F8 CPX #&F8 ;if beyond end of catalogue A5F5 B0 4C BCS R643 ;then exit A5F7 9D 08 0E STA &0E08,X ;else clear byte in sector 0 A5FA 9D 08 0F STA &0F08,X ;clear byte in sector 1 A5FD E8 INX ;increment offset A5FE D0 F3 BNE R5F3 ;and loop (always). ;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 BD BCS R5F1 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 EQUB &08,&01 A652 20 09 92 JSR Q209 ;Copy memory absolute indexed A655 EQUW &08,&0F A657 EQUW &48,&10 A659 EQUB &08,&01 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 S71B ;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 AD 61 10 LDA &1061 A750 ED 6C 10 SBC &106C A753 90 17 BCC R76C ;if <0 then print disc/volume error message A755 20 21 98 JSR Q821 ;else, print "need compacting" error message A758 EQUB &C6 A759 EQUS "needs compacting" A769 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,X ;into the next slot up A787 9D 10 0E STA &0E10,X ;going from end to start A78A BD 08 0F LDA &0F08,X ;and A78D 9D 10 0F STA &0F10,X 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 EQUB &08,&10 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 ;zeroth 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 .R8B2 A8B2 60 RTS .R8B3 A8B3 20 06 A5 JSR R506 ;select next file in catalogue A8B6 B0 FA BCS R8B2 ;if no more files exit A8B8 20 03 A6 JSR R603 ;else unpack fields from cat A8BB 4C 0F A6 JMP R60F ;calculate absolute end of file ;EDOSPAT extensions, block 11 #ifndef _WHOLE .R8BE ;Transfer end of file to user A8BE 8A TXA ;save absolute LBA in XY A8BF 48 PHA A8C0 98 TYA A8C1 48 PHA A8C2 A0 FF LDY #&FF ;set offset=&FF to start at 0: .R8C4 A8C4 C8 INY ;increment offset A8C5 BE 00 0E LDX &0E00,Y ;hold byte from sector .R8C8 A8C8 A9 00 LDA #&00 ;clear accumulator A8CA CC 4E 10 CPY &104E ;C=1 if offset is at/past EOF .R8CD A8CD 99 00 0E STA &0E00,Y ;store or clear byte in sector A8D0 C8 INY ;increment offset A8D1 F0 1D BEQ R8F0 ;if sector completed then finish A8D3 B0 F3 BCS R8C8 ;if EOF, clear rest of sector A8D5 88 DEY ;else Y=offset read/to write A8D6 2C 3A 10 BIT &103A ;test Tube channel flag A8D9 30 07 BMI R8E2 ;if reading from disc leave C=0 A8DB 38 SEC ;else C=1 A8DC 70 0B BVS R8E9 ;if writing from Tube fetch byte R8DE B1 CA LDA (&CA),Y ;else get byte from user memory R8E0 B0 EB BCS R8CD ;write byte in sector .R8E2 A8E2 8A TXA ;reading from disc; A=byte read A8E3 70 04 BVS R8E9 ;if reading to Tube store byte A8E5 91 CA STA (&CA),Y ;else put byte in user memory A8E7 90 DB BCC R8C4 ;and read next byte .R8E9 A8E9 20 09 A0 JSR R009 ;put/get byte to/from Tube A8EC 90 D6 BCC R8C4 ;if reading read next byte A8EE B0 DD BCS R8CD ;otherwise write byte in sector .R8F0 A8F0 68 PLA ;restore sector LBA to XY A8F1 A8 TAY ;X=LSB, A=MSB A8F2 68 PLA A8F3 AA TAX A8F4 50 03 BVC R8F9 ;if Tube was in use A8F6 20 0C A0 JSR R00C ;then close Tube channel .R8F9 A8F9 68 PLA ;recall transfer direction A8FA 10 01 BPL R8FD ;if reading from disc A8FC 60 RTS ;then exit .R8FD A8FD 4C 44 99 JMP Q944 ;else write sector #endif ;'Heavy' DFS commands .R900 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 F4 AE JSR REF4 ;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 .RBAC 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 EQUW &30,&10 ;FROM actual vol allocations at &1030 AC3C EQUW &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 EB AE JSR REEB ;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 #if defined _EP565 AC9C 20 54 8F JSR PF54 ;and in temp #else /* _EP705 */ AC9C 8D 80 10 STA &1080 ;and in temp #endif /* _EP565 */ 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 .RD4A ;Print *CATGEN heading AD4A 20 00 92 JSR Q200 ;Save AXY; .RD4D ;Print *CATGEN heading 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 AEBE 38 SEC ;set CF = 1 and exit AEBF 60 RTS ;EDOSPAT extensions, block 12 .REC1 #ifdef _WHOLE AEC1 85 BA STA &BA ;Extended load/save. store LSB AEC3 AD 54 10 LDA &1054 ;of sector count, get MSB AEC6 F0 0F BEQ RED7 ;if 0 then transfer LSB sectors #else AEC1 85 BA STA &BA ;Extended load/save. store 2MSB AEC3 AD 50 10 LDA &1050 ;of file length, get MSB AEC6 F0 0F BEQ RED7 ;if 0 then transfer 2MSB sectors #endif AEC8 85 BB STA &BB ;else store MSB in temp .RECA AECA A9 FF LDA #&FF ;transfer 255 sectors AECC 20 06 9B JSR QB06 ;XY=absolute LBA, updated AECF E6 BA INC &BA ;subtract 255 from LSB AED1 F0 F7 BEQ RECA ;if no borrow then repeat, MSB>0 AED3 C6 BB DEC &BB ;else borrow from MSB AED5 D0 F3 BNE RECA ;if result >0 then repeat .RED7 AED7 A5 BA LDA &BA ;else get size of final transfer #ifdef _WHOLE AED9 F0 0F BEQ REEA ;OSWORD doesn't like zero: exit AEDB 4C 06 9B JMP QB06 ;otherwise transfer and exit. #else AED9 4C BB A4 JMP R4BB ;transfer bulk then last sector. #endif .REDE AEDE E6 BD INC &BD ;Add 256 to OSGBPB data address AEE0 D0 08 BNE REEA ;2nd byte in zero page pointer .REE2 AEE2 EE 73 10 INC &1073 ;carry out to 3rd byte AEE5 D0 03 BNE REEA ;in copy of OSGBPB block AEE7 EE 74 10 INC &1074 ;and 4th byte. .REEA AEEA 60 RTS .REEB AEEB 8D 02 0E STA &0E02 ;store sector count low byte AEEE A9 20 LDA #&20 ;set catalogue version=&20 AEF0 8D 00 0E STA &0E00 ;to show count is big-endian. AEF3 60 RTS .REF4 AEF4 C9 02 CMP #&02 ;C=1 if more than one volume AEF6 A9 2E LDA #&2E ;default to 46 tracks in vol A AEF8 B0 02 BCS REFC ;A=46, C=1 if multiple volumes AEFA A9 4F LDA #&4F ;A=79, C=0 if single volume .REFC AEFC 8D 78 10 STA &1078 ;set number of tracks in vol A AEFF 60 RTS ;EDOSPAT extensions, block 13 .RF00 AF00 48 PHA ;OSFIND A>=&40 open a file AF01 29 C0 AND #&C0 ;mask b7 and b6 of reason code AF03 20 1E 98 JSR Q81E ;open the file AF06 68 PLA ;restore A on entry AF07 29 48 AND #&48 ;mask b6 and b3 AF09 C9 48 CMP #&48 ;if writing only or b3 clear AF0B D0 06 BNE RF13 ;then return AF0D 8A TXA ;else read/update with b3=1 AF0E D0 03 BNE RF13 ;if handle obtained then return AF10 4C 5C A5 JMP R55C ;else raise "File not found". .RF13 AF13 60 RTS .RF14 AF14 B9 9D 10 LDA &109D,Y ;OSGBPB read/write w/sector ops AF17 D0 66 BNE RF7F ;if not on sector boundary AF19 AD 78 10 LDA &1078 ;do a bytewise transfer AF1C 0D 77 10 ORA &1077 ;else OR high bytes of L AF1F F0 02 BEQ RF23 ;if either >0 AF21 A9 FF LDA #&FF ;then request=255 .RF23 AF23 0D 76 10 ORA &1076 ;else request=2nd byte of L AF26 F0 57 BEQ RF7F ;if request=0 do bytewise trans AF28 85 BA STA &BA ;else store request in temp AF2A 98 TYA ;copy channel pointer to A AF2B 2C 3A 10 BIT &103A ;test Tube channel flag AF2E 10 02 BPL RF32 ;if reading from disc AF30 09 03 ORA #&03 ;then point A to EXT mid/hi .RF32 AF32 AA TAX ;instead of allocated length. AF33 BD 98 10 LDA &1098,X ;copy to X, get alloc length low AF36 38 SEC ;subtract PTR middle byte AF37 F9 9E 10 SBC &109E,Y ;=maximum transfer size low AF3A 85 BB STA &BB ;store in another temp AF3C BD 99 10 LDA &1099,X ;get allocated length high AF3F A6 BA LDX &BA ;load request for later AF41 F9 9F 10 SBC &109F,Y ;subtract PTR high =maximum high AF44 90 39 BCC RF7F ;if maximum<0 do bytewise trans AF46 D0 08 BNE RF50 ;if max>=256 transfer sectors AF48 E4 BB CPX &BB ;else 0<=maximum<256. AF4A 90 04 BCC RF50 ;if request0 bytes AF77 F0 16 BEQ RF8F ;if no more to transfer, exit. AF79 A9 38 LDA #&38 ;generate microcode to restart AF7B 6A ROR A ;and reopen the Tube channel AF7C 4C 48 B4 JMP S448 ;which O7F closed, r..1 1100 .RF7F AF7F 2C 3A 10 BIT &103A ;bytewise transfer. test flag AF82 30 0E BMI RF92 ;if writing to disc AF84 20 E5 B6 JSR S6E5 ;get byte from memory AF87 20 4B B6 JSR S64B ;put byte to disc .RF8A AF8A 20 C8 B6 JSR S6C8 ;decrement L AF8D D0 85 BNE RF14 ;if more bytes then loop .RF8F AF8F 4C 24 B5 JMP S524 ;else exit. .RF92 AF92 20 21 B6 JSR S621 ;else get byte from disc AF95 B0 F8 BCS RF8F ;if EOF then exit AF97 20 E5 B6 JSR S6E5 ;else put byte to memory AF9A 4C 8A AF JMP RF8A ;decrement L and loop if >0. .RF9D AF9D 8D 16 10 STA &1016 ;Multi-sector op on open file. AFA0 86 BB STX &BB ;A=command, X=sector count AFA2 B9 93 10 LDA &1093,Y ;Y=channel pointer.copy drive AFA5 85 C9 STA &C9 ;to immediate drive for OSWORD. AFA7 B9 94 10 LDA &1094,Y ;get start LBA AFAA 18 CLC ;add PTR middle byte AFAB 79 9E 10 ADC &109E,Y ;=transfer start LBA low byte. AFAE AA TAX ;save in X AFAF B9 95 10 LDA &1095,Y ;get start LBA high byte AFB2 79 9F 10 ADC &109F,Y ;add PTR high byte. AFB5 84 BA STY &BA ;LBA now in XA. save pointer AFB7 A8 TAY ;set up LBA in XY AFB8 A5 BB LDA &BB ;set A=sector count AFBA 20 06 92 JSR Q206 ;copy data addr back to OSGBPB AFBD EQUW &BC,&00 ;FROM OSGBPB pointer, &00BC AFBF EQUW &71,&10 ;TO OSGBPB address, &1071 AFC1 EQUB &02 ;2 bytes AFC2 20 06 92 JSR Q206 ;copy OSGBPB address to OSWORD AFC5 EQUW &71,&10 ;FROM OSGBPB address, &1071 AFC7 EQUW &11,&10 ;TO OSWORD &7F address, &1011 AFC9 EQUB &04 ;4 bytes AFCA 20 06 9B JSR QB06 ;do LBA transfer AFCD A4 BB LDY &BB ;set Y=sector count AFCF 98 TYA ;copy to A AFD0 18 CLC ;add to data address 2nd byte AFD1 65 BD ADC &BD AFD3 85 BD STA &BD AFD5 8D 72 10 STA &1072 ;copy to OSGBPB for Tube reopen AFD8 90 03 BCC RFDD ;carry out to hi bytes in OSGBPB AFDA 20 E2 AE JSR REE2 ;block .RFDD AFDD A2 FD LDX #&FD ;X=&FD reverse counter AFDF 98 TYA ;A=sector count AFE0 49 FF EOR #&FF ;negate it AFE2 38 SEC ;reverse-subtract * 256 from L .RFE3 AFE3 7D 79 0F ADC &0F79,X AFE6 9D 79 0F STA &0F79,X AFE9 A9 FF LDA #&FF AFEB E8 INX AFEC D0 F5 BNE RFE3 AFEE 98 TYA ;A=sector count again AFEF A4 BA LDY &BA ;Y=channel pointer for return AFF1 18 CLC ;add * 256 to PTR AFF2 79 9E 10 ADC &109E,Y AFF5 99 9E 10 STA &109E,Y AFF8 8A TXA AFF9 79 9F 10 ADC &109F,Y AFFC 99 9F 10 STA &109F,Y AFFF 60 RTS ;EDOS API, part 1 .S000 B000 4C 0C B0 JMP S00C ;OSFILE .S003 B003 4C 12 B1 JMP S112 ;OSARGS .S006 B006 4C 7F B1 JMP S17F ;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 1A CPX #&1A ;does A equal 0..24 or &FF? B019 90 01 BCC S01C ;if so continue .S01B B01B 60 RTS ;else exit C=1. .S01C B01C 20 CB 91 JSR Q1CB ;set up microcode byte B01F 90 FA BCC S01B ;if ignored command then exit B021 BA TSX ;have A=1 returned on exit B022 A9 01 LDA #&01 ;as no hierarchical directories B024 9D 04 01 STA saved_a,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 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 or create 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 A2 FC LDX #&FC ;set X as reverse counter: .S048 B048 BD 82 0F LDA &0F82,X ;from OSFILE end address B04B FD 7E 0F SBC &0F7E,X ;subtract start address B04E 9D 6A 0F STA &0F6A,X ;to get length B051 9D 6E 0F STA &0F6E,X ;and sector count (clips start) B054 E8 INX ;loop for 4 bytes. B055 D0 F1 BNE S048 B057 20 4D B9 JSR S94D ;ensure length <512K, test LSB B05A F0 08 BEQ S064 ;if low byte >0 B05C EE 6B 10 INC &106B ;then round up sector count B05F D0 03 BNE S064 ;and carry out to high byte B061 EE 6C 10 INC &106C .S064 B064 A9 A0 LDA #&A0 ;&A0 = OSFILE reason code B066 20 18 A6 JSR R618 ;check perms/create file B069 46 CD LSR &CD B06B 90 AE BCC S01B B06D 20 06 92 JSR Q206 ;.....11 Save file. Copy addr 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 S342 ;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 save or create 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 ;.....10 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 .S09A B09A 46 CD LSR &CD B09C 90 45 BCC S0E3 B09E A2 48 LDX #&48 ;....1x0 Get file info B0A0 A0 72 LDY #&72 ;load addr from cat to OSFILE B0A2 20 74 B3 JSR S374 ;do 18 to 32 bit copy B0A5 A2 4B LDX #&4B ;exec addr from cat to OSFILE 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 08 LDA #&08 ;set low attribute byte = &08 B0C6 8D 7E 10 STA &107E ;as user can't 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 46 CD LSR &CD ;microcode shift register in OSGBPB etc B0D7 90 6A BCC S143 B0D9 20 21 A5 JSR R521 ;check file not locked B0DC 20 00 A6 JSR R600 ;...11x0 Delete file B0DF 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 ;...10x0 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 ;..1x0x0 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 ;.1xx0x0 Set attributes 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 ;.xxx0x0 Not save delete or info pack fields B10F 4C 03 9B JMP QB03 ;write catalogue and exit .S112 ;OSARGS B112 D8 CLD ;clear decimal flag per spec B113 20 09 B7 JSR S709 ;call OSARGS monitor B116 85 CD STA &CD ;when A=&FF flush routne flushes B118 20 00 92 JSR Q200 ;save AXY B11B 18 CLC ;map calls &FF..&06 to &00..&07 B11C 69 01 ADC #&01 B11E C9 08 CMP #&08 ;if call was &07..&FE exit C=1 B120 B0 21 BCS S143 B122 0A ASL A ;else double call number B123 AA TAX ;transfer to X to use as index B124 98 TYA ;if a file handle is given B125 F0 04 BEQ S12B B127 20 0C 98 JSR Q80C ;convert to a workspace pointer B12A E8 INX ;and increment index .S12B B12B BD 6E B1 LDA S16E,X ;get high byte of action address B12E 48 PHA ;save on stack B12F BD 5E B1 LDA S15E,X ;get low byte of action address B132 48 PHA ;save on stack B133 BD 41 B1 LDA S144-3,X ;get A to take into routine B136 48 PHA ;save on stack B137 BD 4E B1 LDA S14E,X ;get A to return to user B13A BA TSX B13B 9D 07 01 STA saved_a+3,X ;have it returned on exit B13E BD 06 01 LDA saved_x+3,X ;restore X on entry B141 AA TAX ;=OSARGS pointer B142 68 PLA ;pop A for routine .S143 ;OSARGS A=0,2,3,6 B143 60 RTS .S144 B144 EQUB &9D,&82,&00,&00 ;Table of values of A on entry B148 EQUB &9A,&00,&80,&5F ;to routine, 0,Y..5 B14C EQUB &97,&5F ;other values =don't care .S14E B14E EQUB &00,&00,&04,&00 ;Table of values of A to return B152 EQUB &DC,&FF,&01,&00 ;to user, &FF..6,Y B156 EQUB &FF,&FF,&00,&00 B15A EQUB &00,&00,&06,&00 .S15E B15E EQUB &E1,&0E,&42,&C1 ;Table of low bytes of action B162 EQUB &E4,&AA,&42,&C1 ;addresses (- 1 for RTS) B166 EQUB &42,&AA,&EA,&F9 B16A EQUB &EB,&D3,&42,&6B .S16E B16E EQUB &9A,&98,&B1,&89 ;Table of high bytes of action B172 EQUB &89,&85,&B1,&89 ;addresses B176 EQUB &B1,&85,&89,&95 B17A EQUB &95,&89,&B1,&95 .S17F ;OSFIND B17F 20 00 92 JSR Q200 ;Save AXY B182 20 15 B7 JSR S715 ;Call OSFIND Monitor B185 C9 40 CMP #&40 ;is it a CLOSE# ? B187 B0 0F BCS S198 ;if so, then: B189 85 CD STA &CD ;b7=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 00 AF JSR RF00 ;open a file B1A3 8A TXA ;return channel in A B1A4 BA TSX ;SP -> X B1A5 9D 04 01 STA saved_a,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 A2 4B LDX #&4B ;point X to 18 bit exec addr B2F7 20 72 B3 JSR S372 ;expand to 32 bits in O7F block B2FA AD 13 10 LDA &1013 ;AND high bytes together B2FD 2D 14 10 AND &1014 ;if execution address B300 49 FF EOR #&FF ;11111111;has high bits clear B302 2D 7A 02 AND &027A ;and Tube is present B305 D0 03 BNE S30A ;then call address over Tube B307 6C 11 10 JMP (&1011) ;else call the host address .S30A B30A A2 11 LDX #&11 ;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 inclusive 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 60 RTS ;don't call GSINIT, exit. .S33D ;Load file. B33D 20 70 B3 JSR S370 ;copy addr to O7F .S340 B340 A9 13 LDA #&13 ;store read command in block .S342 B342 8D 16 10 STA &1016 B345 AE 51 10 LDX &1051 ;absolute start sector in XY B348 AC 52 10 LDY &1052 #ifdef _WHOLE B34B AD 53 10 LDA &1053 ;sector length (mod 256) in A #else B34B AD 4F 10 LDA &104F ;2MSB file length in A #endif B34E 4C C1 AE JMP REC1 ;do extended transfer and exit .S351 B351 48 PHA ;Copy 32 bit to 18 bit address B352 BD 03 10 LDA &1003,X ;from 1000,X to 1000,Y B355 F0 41 BEQ S398 ;if top byte=0 it's a Tube addr B357 3D 02 10 AND &1002,X ;else test top two bytes B35A C9 FF CMP #&FF ;are they both &FF? B35C D0 41 BNE S39F ;if not then addr out of range .S35E B35E 20 09 92 JSR Q209 ;else a host address. B361 EQUW &00,&10 ;copy bottom two bytes B363 EQUW &00,&10 B365 EQUB &02,&31 .S367 B367 29 03 AND #&03 ;mask &FF to &03, top two bits B369 99 02 10 STA &1002,Y ;store b17,b16 of address B36C 68 PLA ;restore A and exit. B36D 60 RTS .S370 B370 A2 48 LDX #&48 ;Copy load address .S372 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 EQUB &02,&31 B37E BD 02 10 LDA &1002,X ;are b17 and b16 both set? B381 29 03 AND #&03 B383 C9 03 CMP #&03 B385 F0 0A BEQ S391 ;if so then it's a host address B387 99 02 10 STA &1002,Y ;else it's a Tube address. B38A A9 00 LDA #&00 ;clear top byte .S38C B38C 99 03 10 STA &1003,Y ;store 3rd byte B38F 68 PLA ;restore A and exit. B390 60 RTS .S391 B391 A9 FF LDA #&FF ;set top two bytes to &FFFF B393 99 02 10 STA &1002,Y ;for host, and exit. B396 D0 F4 BNE S38C .S398 B398 BD 02 10 LDA &1002,X ;32 bit Tube address to 18 bit. B39B C9 03 CMP #&03 ;is second byte 0 to 2? B39D 90 BF BCC S35E ;if so store it and copy LSBs .S39F B39F A9 FF LDA #&FF ;else out of range. B3A1 99 00 10 STA &1000,Y ;input address unrepresentable B3A4 99 01 10 STA &1001,Y ;so set it as &3FFFF. B3A7 D0 BE BNE S367 ;EDOSPAT extensions, block 14 .S3AE B3AE A9 02 LDA #&02 ;Return binary 2 plus default B3B0 20 E5 B6 JSR S6E5 ;or library drive number B3B3 B9 09 10 LDA &1009,Y ;to OSGBPB data address B3B6 4C E5 B6 JMP S6E5 ;(so volume letter can be added) #if defined _CHALL5 .S3B9 B3B9 EQUD &32,&34,&33,&35 ;Latch table for drives 0..3 .S3BD B3BD EQUW &00,&20 ;Density mask table, 0=single B3BF EQUW &20,&20 ;&20=double, (quad unused). #elif defined _W17705 .S3B9 B3B9 EQUD &01,&05,&03,&07 ;Latch table for drives 0..3 .S3BD B3BD EQUW &00,&01 ;Density mask table, 0=single B3BF EQUW &01,&01 ;&01=double, (quad unused). #elif defined _A17705 .S3B9 B3B9 EQUD &29,&2A,&2D,&2E ;Latch table for drives 0..3 .S3BD B3BD EQUW &00,&08 ;Density mask table, 0=single B3BF EQUW &08,&08 ;&08=double, (quad unused). #elif defined _M17705 .S3B9 B3B9 EQUD &25,&26,&35,&36 ;Latch table for drives 0..3 .S3BD B3BD EQUW &00,&20 ;Density mask table, 0=single B3BF EQUW &20,&20 ;&20=double, (quad unused). #elif defined _PG4005 .S3B9 B3B9 EQUD &39,&3A,&3D,&3E ;Latch table for drives 0..3 .S3BD B3BD EQUW &00,&08 ;Density mask table, 0=single B3BF EQUW &08,&08 ;&08=double, (quad unused). #elif defined _O27914 .S3B9 B3B9 EQUD &00,&01,&02,&03 ;Latch table for drives 0..3 .S3BD B3BD EQUW &00,&40 ;Density mask table, 0=single B3BF EQUW &C0,&C0 ;&40=double, &C0=quad. #elif defined _A17724 .S3B9 B3B9 EQUD &29,&2A,&2D,&2E ;Latch table for drives 0..3 .S3BD B3BD EQUW &00,&08 ;Density mask table, 0=single B3BF EQUW &88,&88 ;&08=double, &88=quad. #elif defined _M17724 .S3B9 B3B9 EQUD &25,&26,&35,&36 ;Latch table for drives 0..3 .S3BD B3BD EQUW &00,&20 ;Density mask table, 0=single B3BF EQUW &A0,&A0 ;&20=double, &A0=quad. #else /* _O27915, _O27935 or _O17705 */ .S3B9 B3B9 EQUD &00,&01,&02,&03 ;Latch table for drives 0..3 .S3BD B3BD EQUW &00,&40 ;Density mask table, 0=single B3BF EQUW &40,&40 ;&40=double, (quad unused). #endif /* _CHALL5 */ ;+---+---+---+---+---+---+---+---+--------+---+---+ ;|b 7|b 6|b 5|b 4|b 3|b 2|b 1|b 0| |b 1|b 0| ;+---+---+---+---+---+---+---+---+--------+---+---+ ;|CLK|DEN| - | - | - | - |SEL|DS | 2791HD |SEL|DS | ;| - | - |RES|INT|DEN|SEL|DS1|DS0| B+ | | ;| - | - |DEN|SEL|DS2|RES|DS1|DS0| Master | --X-- | ;+---+---+---+---+---+---+---+---+--------+---+---+ ;| 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | X = 00 | 0 | 0 | ;+---+---+---+---+---+---+---+---+--------+-------+ ;| 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | X = 01 | 0 | 1 | ;+---+---+---+---+---+---+---+---+--------+-------+ ;| 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | X = 02 | 1 | 0 | ;+---+---+---+---+---+---+---+---+--------+-------+ ;| 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | X = 03 | 1 | 1 | ;+---+---+---+---+---+---+---+---+--------+-------+ ;+---+---+---+---+---+---+---+---+--------+ ;|b 7|b 6|b 5|b 4|b 3|b 2|b 1|b 0| | ;+---+---+---+---+---+---+---+---+--------+ ;|CLK|DEN| - | - | - | - |SEL|DS | 2791HD | ;| - | - |RES|INT|DEN|SEL|DS1|DS0| B+ | ;| - | - |DEN|SEL|DS2|RES|DS1|DS0| Master | ;+---+---+---+---+---+---+---+---+--------+ ;| 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | Y = 00 | ;+---+---+---+---+---+---+---+---+--------+ ;| 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | Y = 01 | ;+---+---+---+---+---+---+---+---+--------+ ;| 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | Y = 02 | ;+---+---+---+---+---+---+---+---+--------+ ;| 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | Y = 03 | ;+---+---+---+---+---+---+---+---+--------+ .S3C1 ;OSWORD &71, &7D, &7E B3C1 A4 F0 LDY &F0 ;copy OSWORD block pointer B3C3 84 BE STY &BE ;to scratch space B3C5 A4 F1 LDY &F1 ;as OSWORD &7F will overwrite B3C7 84 BF STY &BF B3C9 20 06 92 JSR Q206 ;Copy memory absolute B3CC EQUW &07,&10 ;FROM default dir vol and drive at &1007 B3CE EQUW &C7,&00 ;TO immediate dir'y at &00C7 B3D0 EQUB &03 ;count B3D1 20 00 9B JSR QB00 ;softmount and catalogue drive B3D4 AA TAX ;save call number in X B3D5 A0 00 LDY #&00 ;clear Y for later B3D7 AD 04 0F LDA &0F04 ;get cycle number of catalogue B3DA E0 7D CPX #&7D ;if command is OSWORD &7D B3DC F0 1A BEQ S3F8 ;then return cycle number and exit B3DE 98 TYA ;else low byte of size =0 B3DF 91 BE STA (&BE),Y B3E1 AD 06 0F LDA &0F06 ;get high byte of sector count B3E4 29 07 AND #&07 ;mask b2..0 (volumes <360 KiB) B3E6 AA TAX ;x=high byte B3E7 AD 07 0F LDA &0F07 ;get low byte of sector count B3EA B0 09 BCS S3F5 ;if OSWORD &7E return vol size B3EC 20 1B A6 JSR R61B ;else calculate free space B3EF AD 60 10 LDA &1060 ;a=low byte B3F2 AE 61 10 LDX &1061 ;x=high byte .S3F5 B3F5 C0 02 CPY #&02 ;is this the 3rd (4th) byte? B3F7 C8 INY ;increment pointer, now 1..3 .S3F8 B3F8 91 BE STA (&BE),Y ;store A in user's block B3FA 8A TXA ;put next byte to store in A B3FB A2 00 LDX #&00 ;byte after that will be zero B3FD 90 F6 BCC S3F5 ;loop until 3 (4) bytes written 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 AD 71 10 LDA &1071 ;copy address in OSGBPB block B43E 85 BC STA &BC ;to zero page pointer B440 AD 72 10 LDA &1072 ;which is the authoritative copy B443 85 BD STA &BD ;of the low bytes. B445 BD 69 B5 LDA S569,X ;OSGBPB microcode table 1..8 .S448 B448 85 CD STA &CD ;store in shift register B44A 29 80 AND #&80 ;10000000,take high bit of microcode B44C 8D 3A 10 STA &103A ;1=read, store in Tube flag B44F 0A ASL A ;C=read/write flag, A=0 B450 BA TSX ;have A=0 returned on exit to indicate B451 9D 04 01 STA saved_a,X ;the command is implemented B454 AD 73 10 LDA &1073 ;test high word of address B457 2D 74 10 AND &1074 B45A 49 FF EOR #&FF ;A=0 if in I/O space, invert B45C 2D 7A 02 AND &027A ;A=0 if Tube absent too B45F F0 0C BEQ S46D ;in which case skip forward B461 A9 00 LDA #&00 ;else a Tube transfer. B463 2A ROL A ;set A=0 if writing to disc, A=1 if reading B464 49 00 EOR #&00 ;no-op 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 B478 EQUB &03 ;count 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 .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 35 B5 JMP S535 .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 AE B3 JSR S3AE ;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 47 B5 JMP S547 ;set C correctly and exit .S504 B504 AE 70 10 LDX &1070 ;....00 Read/write/restart B507 46 CD LSR &CD ;get handle B509 90 0A BCC S515 B50B 20 03 98 JSR Q803 ;...100 Read/restart B50E 46 CD LSR &CD ;check file is open B510 90 06 BCC S518 .S512 B512 4C 14 AF JMP RF14 ;..1100 Restart read or write. .S515 B515 20 AF B6 JSR S6AF ;...000 Write. check writeable .S518 B518 46 CD LSR &CD ;..0100 / ...000 Read/write B51A 90 03 BCC S51F B51C 20 AD 89 JSR P9AD ;.10100 / ..1000 Set PTR .S51F B51F 20 D6 B6 JSR S6D6 ;.x0100 / ..x000 Compare L=0 B522 D0 EE BNE S512 ;if bytes remain, restart .S524 B524 20 5B B5 JSR S55B ;else clear EOF warning flag B527 20 09 92 JSR Q209 ;copy PTR to OSGBPB block B52A EQUW &9D,&10 ;FROM PTR, &109D,Y B52C EQUW &79,&10 ;TO OSGBPB block, &1079 B52E EQUB &03,&03 ;3 bytes, Y indexed FROM B530 A9 00 LDA #&00 ;clear high byte B532 8D 7C 10 STA &107C ;of OSGBPB returned pointer .S535 B535 20 06 92 JSR Q206 ;copy address to OSGBPB block B538 EQUW &BC,&00 ;FROM OSGBPB pointer, &00BC B53A EQUW &71,&10 ;TO OSGBPB address, &1071 B53C EQUB &02 ;2 bytes B53D A0 0C LDY #&0C ;copy OSGBPB block to user's .S53F B53F B9 70 10 LDA &1070,Y ;block B542 91 BE STA (&BE),Y B544 88 DEY B545 10 F8 BPL S53F .S547 B547 46 CD LSR &CD ;take next bit of microcode B549 90 05 BCC S550 ;if clear C=0 on exit B54B 20 D6 B6 JSR S6D6 ;else test L B54E C9 01 CMP #&01 ;C=1 if L>0 .S550 B550 2C 3A 10 BIT &103A ;test transfer flag B553 50 05 BVC S55A ;if a Tube transfer B555 08 PHP B556 20 0C A0 JSR R00C ;then close the Tube channel. B559 28 PLP .S55A B55A 60 RTS ;return C. .S55B B55B B9 88 10 LDA &1088,Y ;Clear EOF warning flag. B55E 29 FE AND #&FE B560 99 88 10 STA &1088,Y B563 60 RTS .S569 B569 EQUD &18,&10,&B4,&A4 ;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 EQUB &03,&33 .S613 B613 68 PLA ;return A=offset of byte in buf 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 B1 CA LDA (&CA),Y ;get byte that PTR had PTd to B62F 18 CLC ;return C=0 not at end-of-file .S630 B630 BA TSX ;have A returned on exit. B631 9D 04 01 STA saved_a,X B634 60 RTS .S635 B635 B9 88 10 LDA &1088,Y ;we've read past end-of-file. B638 09 01 ORA #&01 ;set EOF-warning-given flag B63A D9 88 10 CMP &1088,Y ;set Z=1 iff it was set already B63D 99 88 10 STA &1088,Y ;update channel flags B640 D0 17 BNE S659 ;if first EOF return C=1, A=&FE B642 20 18 90 JSR Q018 ;raise "EOF" error B645 EQUB &0A ;error message, LF after 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 20 5E B9 JSR S95E ;compare PTR - allocated length B651 90 4A BCC S69D ;if <0 write the byte B653 20 5D B6 JSR S65D ;else extend the file B656 4C 4E B6 JMP S64E ;and try to put the byte again. .S659 B659 A9 FE LDA #&FE ;return A=&FE on first EOF B65B D0 D3 BNE S630 .S65D B65D 20 1B 98 JSR Q81B ;Extend. check volume is same B660 20 15 A6 JSR R615 ;determine if room to extend B663 90 25 BCC S68A ;if <=0 then "Can't extend" B665 F0 23 BEQ S68A B667 A9 00 LDA #&00 ;LSB file length = 0 B669 8D 4E 10 STA &104E B66C 20 1E A6 JSR R61E ;get ceiling over file into AX B66F 38 SEC B670 ED 51 10 SBC &1051 ;subtract absolute start sector B673 8D 4F 10 STA &104F ;store in middle byte of length B676 99 98 10 STA &1098,Y ;and allocated length of f.h. B679 8A TXA ;thereby fully extending file. B67A ED 52 10 SBC &1052 .S67D B67D 8D 50 10 STA &1050 B680 99 99 10 STA &1099,Y B683 20 06 A6 JSR R606 ;pack fields into catalogue B686 20 03 9B JSR QB03 ;write catalogue B689 60 RTS ;and exit. .S68A B68A 20 18 90 JSR Q018 ;Raise "Can't extend" error B68D EQUB &0A ;error message, LF after B68E EQUB &BF ;error number &BF B68F EQUS "Can't extend" ;message string "Can't extend" B69B EQUB &00 ;terminator byte .S69D B69D 20 96 B5 JSR S596 ;Write byte. increment PTR B6A0 48 PHA ;save buffer offset B6A1 A9 02 LDA #&02 B6A3 99 89 10 STA &1089,Y ;mark buffer dirty B6A6 68 PLA B6A7 A8 TAY B6A8 BA TSX B6A9 BD 04 01 LDA saved_a,X ;write byte into buffer B6AC 91 CA STA (&CA),Y .S6AE B6AE 60 RTS .S6AF ;Check file is writeable B6AF 20 03 98 JSR Q803 B6B2 30 FA BMI S6AE .S6B4 B6B4 20 18 90 JSR Q018 B6B7 EQUB &0A B6B8 EQUB &C1 B6B9 EQUS "File read only" B6C7 EQUB &00 ;terminator byte .S6C8 B6C8 A2 FF LDX #&FF ;Decrement count of bytes .S6CA B6CA E8 INX ;remaining to be transferred B6CB BD 75 10 LDA &1075,X B6CE F0 FA BEQ S6CA .S6D0 B6D0 DE 75 10 DEC &1075,X B6D3 CA DEX B6D4 10 FA BPL S6D0 .S6D6 B6D6 AD 75 10 LDA &1075 ;Compare L=0, return Z B6D9 0D 76 10 ORA &1076 B6DC 0D 77 10 ORA &1077 B6DF 0D 78 10 ORA &1078 .S6E2 B6E2 60 RTS .S6E3 B6E3 A9 01 LDA #&01 ;Send binary 1 .S6E5 B6E5 A2 00 LDX #&00 ;Transfer byte between GBPB B6E7 2C 3A 10 BIT &103A ;buffer and memory B6EA 70 0A BVS S6F6 ;103A: b6=Tube, b7=write to mem B6EC 30 04 BMI S6F2 B6EE A1 BC LDA (&BC,X) B6F0 50 07 BVC S6F9 .S6F2 B6F2 81 BC STA (&BC,X) B6F4 50 03 BVC S6F9 .S6F6 B6F6 20 09 A0 JSR R009 .S6F9 B6F9 E6 BC INC &BC B6FB D0 E5 BNE S6E2 B6FD 4C DE AE JMP REDE ;increment top 3 bytes of data address ;Monitor #ifdef _NOMON .S700 B700 60 RTS ;OSWORD Monitor .S703 B703 60 RTS ;ROM Service call monitor .S706 B706 60 RTS ;OSFILE Monitor .S709 B709 60 RTS ;OSARGS Monitor .S70C B70C 60 RTS ;OSBGET Monitor .S70F B70F 60 RTS ;OSBPUT Monitor .S712 B712 60 RTS ;OSGBPB Monitor .S715 B715 60 RTS ;OSFIND Monitor .S718 B718 60 RTS ;Filing system call monitor #else .S700 B700 4C 1E B7 JMP S71E ;OSWORD Monitor .S703 B703 4C 5E B7 JMP S75E ;ROM Service call monitor .S706 B706 4C 88 B7 JMP S788 ;OSFILE Monitor .S709 B709 4C B8 B7 JMP S7B8 ;OSARGS Monitor .S70C B70C 4C D8 B7 JMP S7D8 ;OSBGET Monitor .S70F B70F 4C EE B7 JMP S7EE ;OSBPUT Monitor .S712 B712 4C 05 B8 JMP S805 ;OSGBPB Monitor .S715 B715 4C 30 B8 JMP S830 ;OSFIND Monitor .S718 B718 4C 4C B8 JMP S84C ;Filing system call monitor #endif .S71B B71B 4C A0 B8 JMP S8A0 ;File access monitor .S71E ;OSWORD Monitor B71E 48 PHA B71F A9 08 LDA #&08 ;test *OPT 1 monitor bit 3 B721 20 34 B9 JSR S934 B724 68 PLA B725 90 60 BCC S787 ;if clear then exit B727 20 00 92 JSR Q200 ;else save AXY B72A A5 EF LDA &EF ;restore registers B72C A6 F0 LDX &F0 ;on entry to OSWORD B72E A4 F1 LDY &F1 B730 20 CF B8 JSR S8CF ;start monitor message B733 20 18 90 JSR Q018 ;print immediate "O" B736 EQUB &40 ;plus hex byte in A B737 EQUS "O" ;(OSWORD call type) B738 EQUB &00 B739 A9 64 LDA #&64 ;d=drive number B73B 20 EE B8 JSR S8EE B73E A9 61 LDA #&61 ;a=address B740 20 FE B8 JSR S8FE B743 20 28 B9 JSR S928 ;load & skip no. of parameters B746 AA TAX B747 A9 63 LDA #&63 ;c=command B749 20 EE B8 JSR S8EE B74C 8A TXA ;if no parameters skip B74D F0 0C BEQ S75B .S74F B74F 20 28 B9 JSR S928 ;else get parameter B752 20 03 90 JSR Q003 ;print space B755 20 19 B9 JSR S919 ;print parameter B758 CA DEX ;repeat until all printed B759 D0 F4 BNE S74F ;then exit monitor .S75B B75B 4C AF B8 JMP S8AF .S75E ;ROM Service call monitor B75E 48 PHA B75F A9 02 LDA #&02 ;test *OPT 1 monitor bit 1 B761 20 34 B9 JSR S934 B764 68 PLA B765 90 20 BCC S787 ;if clear then exit B767 20 00 92 JSR Q200 ;else save AXY B76A 20 CF B8 JSR S8CF ;start monitor message B76D 20 18 90 JSR Q018 ;print "ROM call "+hex byte B770 EQUB &40 ;(call type) B771 EQUS "ROM call " B77A EQUB &00 B77B 98 TYA B77C 20 18 90 JSR Q018 ;print parameter using B77F EQUB &40 ;immediate call as value B780 EQUS " p=" ;is in register not memory B783 EQUB &00 B784 4C AF B8 JMP S8AF ;exit monitor .S787 B787 60 RTS .S788 ;OSFILE Monitor B788 20 C0 B8 JSR S8C0 ;print header B78B 90 FA BCC S787 ;or quit if monitor b2 clear B78D 20 00 92 JSR Q200 ;save AXY B790 20 18 90 JSR Q018 ;print "OSFILE "+call type B793 EQUB &40 B794 EQUS "OSFILE " B79B EQUB &00 B79C A9 66 LDA #&66 ;f=filename pointer B79E 20 F4 B8 JSR S8F4 B7A1 A9 64 LDA #&64 ;d=load address B7A3 20 FE B8 JSR S8FE B7A6 A9 65 LDA #&65 ;e=execution address B7A8 20 FE B8 JSR S8FE B7AB A9 6C LDA #&6C ;l=length B7AD 20 FE B8 JSR S8FE B7B0 A9 61 LDA #&61 ;a=attributes B7B2 20 FE B8 JSR S8FE ;exit monitor B7B5 4C AF B8 JMP S8AF .S7B8 ;OSARGS Monitor B7B8 20 C0 B8 JSR S8C0 ;print header B7BB 90 CA BCC S787 ;or quit if b2 clear B7BD 20 00 92 JSR Q200 ;save AXY B7C0 20 18 90 JSR Q018 ;print "OSARGS "+call type B7C3 EQUB &40 B7C4 EQUS "OSARGS " B7CB EQUB &00 B7CC 8A TXA ;transfer X to A B7CD 20 18 90 JSR Q018 ;z=zero page address B7D0 EQUB &40 ;might not contain data yet B7D1 EQUS " z=" ;so not printing! B7D4 EQUB &00 ;h=handle; exit monitor B7D5 4C 48 B8 JMP S848 .S7D8 ;OSBGET Monitor B7D8 20 C0 B8 JSR S8C0 ;print header B7DB 90 AA BCC S787 ;or quit if b2 clear B7DD 20 00 92 JSR Q200 ;save AXY B7E0 20 18 90 JSR Q018 ;print "OSBGET ", no call type B7E3 EQUB &00 B7E4 EQUS "OSBGET" B7EA EQUB &00 ;h=handle; exit monitor B7EB 4C 48 B8 JMP S848 .S7EE ;OSBPUT Monitor B7EE 20 C0 B8 JSR S8C0 ;print header B7F1 90 94 BCC S787 ;or quit if b2 clear B7F3 20 00 92 JSR Q200 ;save AXY B7F6 20 18 90 JSR Q018 ;print "OSBPUT " B7F9 EQUB &40 ;call type = byte to write B7FA EQUS "OSBPUT " ;h=handle; exit monitor B801 EQUB &00 B802 4C 48 B8 JMP S848 .S805 ;OSGBPB Monitor B805 20 C0 B8 JSR S8C0 ;print header B808 90 7C BCC S886 ;or quit if b2 clear B80A 20 00 92 JSR Q200 ;save AXY B80D 20 18 90 JSR Q018 ;print "OSGBPB "+call type B810 EQUB &40 B811 EQUS "OSGBPB " B818 EQUB &00 B819 A9 68 LDA #&68 ;h=handle B81B 20 EE B8 JSR S8EE B81E A9 6D LDA #&6D ;m=address B820 20 FE B8 JSR S8FE B823 A9 6C LDA #&6C ;l=length B825 20 FE B8 JSR S8FE B828 A9 70 LDA #&70 ;p=pointer B82A 20 FE B8 JSR S8FE ;exit monitor B82D 4C AF B8 JMP S8AF .S830 ;OSFIND monitor B830 20 C0 B8 JSR S8C0 ;print header B833 90 51 BCC S886 ;or quit if b2 clear B835 20 00 92 JSR Q200 ;save AXY B838 20 18 90 JSR Q018 ;print "OSFIND "+call type B83B EQUB &40 B83C EQUS "OSFIND " B843 EQUB &00 B844 C9 40 CMP #&40 ;if not CLOSE then print B846 B0 43 BCS S88B ;$=string and exit; else: .S848 B848 98 TYA ;print " h=" plus hex byte in Y B849 4C 7B B8 JMP S87B ;then exit monitor .S84C ;Filing system call monitor B84C 20 C0 B8 JSR S8C0 ;print header B84F 90 35 BCC S886 ;or quit if b2 clear B851 20 00 92 JSR Q200 ;save AXY B854 20 18 90 JSR Q018 ;print "OSFSC "+call type B857 EQUB &40 B858 EQUS "OSFSC " B85E EQUB &00 B85F C9 01 CMP #&01 ;if type=1 print h=handle, exit B861 F0 17 BEQ S87A B863 B0 22 BCS S887 ;if type>1 print string/ignore B865 8A TXA ;else print x=X, y=Y, exit B866 20 18 90 JSR Q018 B869 EQUB &40 B86A EQUS " x=" B86D EQUB &00 B86E 98 TYA B86F 20 18 90 JSR Q018 B872 EQUB &40 B873 EQUS " y=" B876 EQUB &00 B877 4C AF B8 JMP S8AF .S87A ;Print file handle in X B87A 8A TXA ;transfer X to A: .S87B ;Print file handle in A B87B 20 18 90 JSR Q018 ;print " h=" plus hex byte in A B87E EQUB &40 ;then exit monitor B87F EQUS " h=" B882 EQUB &00 B883 4C AF B8 JMP S8AF .S886 B886 60 RTS .S887 B887 C9 06 CMP #&06 ;if type>=6 exit, else: B889 B0 24 BCS S8AF .S88B B88B 20 18 90 JSR Q018 ;Dump string value and exit mon B88E EQUB &00 B88F EQUS " $=" B892 EQUB &00 .S893 B893 20 28 B9 JSR S928 B896 C9 0D CMP #&0D ;string terminated by CR B898 F0 15 BEQ S8AF B89A 20 00 90 JSR Q000 ;print character in A B89D 4C 93 B8 JMP S893 .S8A0 ;File access monitor B8A0 48 PHA B8A1 A9 01 LDA #&01 ;test *OPT 1 monitor bit 0 B8A3 20 34 B9 JSR S934 B8A6 68 PLA B8A7 90 DD BCC S886 ;if clear then exit B8A9 20 00 92 JSR Q200 ;else save AXY B8AC 20 06 A4 JSR R406 ;print *INFO line,fall through: .S8AF B8AF AD 0E 10 LDA &100E ;Exit monitor. B8B2 10 09 BPL S8BD ;get *OPT 1 monitor byte .S8B4 B8B4 CA DEX ;pause if b7=1 B8B5 D0 FD BNE S8B4 B8B7 88 DEY B8B8 D0 FA BNE S8B4 B8BA 4A LSR A B8BB D0 F7 BNE S8B4 .S8BD B8BD 4C E7 FF JMP osnewl ;print newline and exit .S8C0 ;Print header B8C0 48 PHA B8C1 A9 04 LDA #&04 ;test *OPT 1 monitor bit 2 B8C3 2D 0E 10 AND &100E B8C6 18 CLC B8C7 F0 23 BEQ S8EC ;if clear then exit C=0 B8C9 20 3A B9 JSR S93A ;else is an error msg building? B8CC 68 PLA B8CD 90 1E BCC S8ED ;if so then exit C=0, else: .S8CF B8CF 20 18 90 JSR Q018 ;Start monitor message B8D2 EQUB &00 B8D3 EQUS "EDOS: " B8D9 EQUB &00 ;terminator byte B8DA 48 PHA ;set up LDA instruction B8DB A9 AD LDA #&AD ;in stack page B8DD 8D 20 01 STA &0120 ;to load from address in XY B8E0 8E 21 01 STX &0121 B8E3 8C 22 01 STY &0122 B8E6 A9 60 LDA #&60 ;follow with RTS B8E8 8D 23 01 STA &0123 B8EB 38 SEC ;return C=1 since mon bit set .S8EC B8EC 68 PLA ;restore A on entry; exit. .S8ED B8ED 60 RTS .S8EE B8EE 20 1D B9 JSR S91D ;Dump 8-bit value. B8F1 4C 19 B9 JMP S919 .S8F4 B8F4 20 1D B9 JSR S91D ;Dump 16-bit value. B8F7 48 PHA ;print " n=", push low byte B8F8 20 28 B9 JSR S928 ;get high byte B8FB 4C 15 B9 JMP S915 ;print hex word .S8FE B8FE 20 1D B9 JSR S91D ;Dump 32-bit value. B901 48 PHA ;print " n=", push low byte B902 20 28 B9 JSR S928 ;push low middle byte B905 48 PHA B906 20 28 B9 JSR S928 ;push high middle byte B909 48 PHA B90A 20 28 B9 JSR S928 ;get high byte. Fall through: B90D 20 19 B9 JSR S919 ;Print 32-bit hex word (JMP) B910 68 PLA ;high byte in A, other bytes B911 20 19 B9 JSR S919 ;on stack, pushed in ascending B914 68 PLA ;order. Fall through: .S915 B915 20 19 B9 JSR S919 ;Print 16-bit hex word (JMP) B918 68 PLA ;high byte in A, low byte .S919 B919 38 SEC ;on stack. print hex byte B91A 4C 0F 90 JMP Q00F .S91D B91D 20 03 90 JSR Q003 ;Print " n=" & get byte value B920 20 00 90 JSR Q000 ;print character in A B923 A9 3D LDA #&3D ;print = sign B925 20 00 90 JSR Q000 ;Print character in A, fall through: .S928 B928 20 20 01 JSR &0120 ;call LDA in stack page B92B EE 21 01 INC &0121 ;increment LDA address B92E D0 03 BNE S933 B930 EE 22 01 INC &0122 .S933 B933 60 RTS .S934 B934 2D 0E 10 AND &100E ;Test bit of *OPT 1 monitor B937 18 CLC ;if bit masked by A is clear B938 F0 0E BEQ S948 ;then exit C=0, do not print .S93A B93A 98 TYA ;else save Y B93B 48 PHA B93C A4 F4 LDY &F4 ;get EDOS ROM slot number in Y B93E B9 A1 02 LDA &02A1,Y ;get ROM type byte from table B941 29 F7 AND #&F7 ;clear b3=error msg in progress B943 D9 A1 02 CMP &02A1,Y ;c=1 if b3=0, c=0 if b3=1 B946 68 PLA ;c=1 means no error, ok to print B947 A8 TAY ;restore Y and exit .S948 B948 60 RTS ;EDOSPAT extensions, block 15 .S94D B94D AA TAX ;test MSB of 32-bit length just B94E D0 0B BNE S95B ;calculated;if >0 then disc full B950 AD 68 10 LDA &1068 ;else test bits 23..19 of length B953 29 F8 AND #&F8 ;if any set then file >=512 KiB B955 D0 04 BNE S95B ;so raise "Disc full" error B957 AD 66 10 LDA &1066 ;test LSB, Z=0 round up sectors. B95A 60 RTS .S95B B95B 4C 6C A7 JMP R76C ;print "Disc full" error. .S95E B95E B9 9E 10 LDA &109E,Y ;compare PTR - allocated length B961 D9 98 10 CMP &1098,Y ;load 2MSB PTR, comp LSB alloc B964 B9 9F 10 LDA &109F,Y ;load MSB PTR, sub MSB alloc B967 F9 99 10 SBC &1099,Y ;return C=0 if PTR within alloc B96A 60 RTS .S96B ;OSWORD gatekeeping B96B C9 71 CMP #&71 ;compare call number with &71 B96D F0 0D BEQ S97C ;if equal then test workspace B96F C9 7D CMP #&7D ;else compare with &7D B971 90 20 BCC S993 ;if not ours then exit C=0 B973 C9 7F CMP #&7F ;else compare with &7F B975 90 05 BCC S97C ;less means vol qry, test wksp B977 2C 8F 02 BIT &028F ;else test keyboard link 1 B97A 10 17 BPL S993 ;always accept &7F if made. C=1 .S97C B97C 08 PHP ;else save interrupt state B97D 78 SEI ;interrupts off (temp memory) B97E 48 PHA ;save call number B97F A5 A8 LDA &A8 ;localise private page pointer B981 48 PHA ;(as zero page may not be ours) B982 A6 A9 LDX &A9 B984 20 3A 97 JSR Q73A ;test flag in private page B987 49 41 EOR #&41 ;A=&FF if the workspace is ours B989 86 A9 STX &A9 ;restore private page pointer B98B AA TAX ;save the result B98C 68 PLA ;restore private page pointer B98D 85 A8 STA &A8 B98F 68 PLA ;restore call number B990 28 PLP ;restore interrupt state B991 E0 FF CPX #&FF ;C=1 iff we own the workspace. .S993 B993 60 RTS .S994 B994 2C 8F 02 BIT &028F ;test bit 7 FDC register access emulators. B997 10 06 BPL S99F ;if unset, branch .S999 #if defined _BPLUS B999 AD 85 FE LDA fdc_trck #elif defined _MASTER B999 AD 29 FE LDA fdc_trck #elif defined _CHALL5 B999 AD F9 FC LDA fdc_trck #elif defined _PG4005 B999 AD C5 FC LDA fdc_trck #else /* _O27915, _O27935, _O17705 or _O27914 */ B999 AD 81 FE LDA fdc_trck #endif /* _BPLUS */ #if defined _WD2791 B99C 49 FF EOR #&FF ;invert for 2791 #else /* _WD1770, _WD1772 or _WD2793 */ B99C 49 00 EOR #&00 ;null invert for 1770 #endif /* _WD2791 */ B99E 60 RTS .S99F B99F 4C 99 B9 JMP S999 .S9A2 B9A2 2C 8F 02 BIT &028F ;test bit 7 FDC register access emulators. B9A5 10 06 BPL S9AD ;if unset, branch .S9A7 #if defined _BPLUS B9A7 AD 86 FE LDA fdc_sect #elif defined _MASTER B9A7 AD 2A FE LDA fdc_sect #elif defined _CHALL5 B9A7 AD FA FC LDA fdc_sect #elif defined _PG4005 B9A7 AD C6 FC LDA fdc_sect #else /* _O27915, _O27935, _O17705 or _O27914 */ B9A7 AD 82 FE LDA fdc_sect #endif /* _BPLUS */ #if defined _WD2791 B9AA 49 FF EOR #&FF ;invert for 2791 #else /* _WD1770, _WD1772 or _WD2793 */ B9AA 49 00 EOR #&00 ;null invert for 1770 #endif /* _WD2791 */ B9AC 60 RTS .S9AD B9AD 4C A7 B9 JMP S9A7 .S9B0 ;setup drive control register, X = drive number, Y = density B9B0 2C 8F 02 BIT &028F ;test bit 7 FDC register access emulators. B9B3 10 04 BPL S9B9 ;if unset, branch .S9B5 #if defined _BPLUS B9B5 8D 80 FE STA fdc_cntrl #elif defined _MASTER B9B5 8D 24 FE STA fdc_cntrl #elif defined _CHALL5 B9B5 8D FC FC STA fdc_cntrl #elif defined _PG4005 B9B5 8D C0 FC STA fdc_cntrl #else /* _O27915, _O27935, _O17705 or _O27914 */ B9B5 8D 84 FE STA fdc_cntrl #endif /* _BPLUS */ B9B8 60 RTS .S9B9 B9B9 4C B5 B9 JMP S9B5 ;A = &D0 (11010000) .S9BC ;send Force Interrupt to command register B9BC 2C 8F 02 BIT &028F ;test bit 7 FDC register access emulators. B9BF 10 06 BPL S9C7 ;if unset, branch .S9C1 #if defined _WD2791 B9C1 49 FF EOR #&FF ;A = &D0 (11010000), invert for 2791 #else /* _WD1770, _WD1772 or _WD2793 */ B9C1 49 00 EOR #&00 ;null invert for 1770 #endif /* _WD2791 */ #if defined _BPLUS B9C3 8D 84 FE STA fdc_comm #elif defined _MASTER B9C3 8D 28 FE STA fdc_comm #elif defined _CHALL5 B9C3 8D F8 FC STA fdc_comm #elif defined _PG4005 B9C3 8D C4 FC STA fdc_comm #else /* _O27915, _O27935, _O17705 or _O27914 */ B9C3 8D 80 FE STA fdc_comm ;send Force Interrupt #endif /* _BPLUS */ B9C6 60 RTS .S9C7 B9C7 4C C1 B9 JMP S9C1 .S9CA ;test and write to track register B9CA 2C 8F 02 BIT &028F ;test bit 7 FDC register access emulators. B9CD 10 06 BPL S9D5 ;if unset, branch .S9CF #if defined _WD2791 B9CF 49 FF EOR #&FF ;invert for 2791 #else /* _WD1770, _WD1772 or _WD2793 */ B9CF 49 00 EOR #&00 ;null invert for 1770 #endif /* _WD2791 */ #if defined _BPLUS B9D1 8D 85 FE STA fdc_trck #elif defined _MASTER B9D1 8D 29 FE STA fdc_trck #elif defined _CHALL5 B9D1 8D F9 FC STA fdc_trck #elif defined _PG4005 B9D1 8D C5 FC STA fdc_trck #else /* _O27915, _O27935, _O17705 or _O27914 */ B9D1 8D 81 FE STA fdc_trck #endif /* _BPLUS */ B9D4 60 RTS .S9D5 B9D5 4C CF B9 JMP S9CF .S9D8 ;test and write to sector register B9D8 2C 8F 02 BIT &028F ;test bit 7 FDC register access emulators. B9DB 10 06 BPL S9E3 ;if unset, branch .S9DD #if defined _WD2791 B9DD 49 FF EOR #&FF ;invert for 2791 #else /* _WD1770, _WD1772 or _WD2793 */ B9DD 49 00 EOR #&00 ;null invert for 1770 #endif /* _WD2791 */ #if defined _BPLUS B9DF 8D 86 FE STA fdc_sect #elif defined _MASTER B9DF 8D 2A FE STA fdc_sect #elif defined _CHALL5 B9DF 8D FA FC STA fdc_sect #elif defined _PG4005 B9DF 8D C6 FC STA fdc_sect #else /* _O27915, _O27935, _O17705 or _O27914 */ B9DF 8D 82 FE STA fdc_sect #endif /* _BPLUS */ B9E2 60 RTS .S9E3 B9E3 4C DD B9 JMP S9DD .S9E6 B9E6 2C 8F 02 BIT &028F ;if unset, branch B9E9 10 06 BPL S9F1 ;test bit 7 FDC register access emulators. .S9EB #if defined _WD2791 B9EB 49 FF EOR #&FF ;invert for 2791 #else /* _WD1770, _WD1772 or _WD2793 */ B9EB 49 00 EOR #&00 ;null invert for 1770 #endif /* _WD2791 */ #if defined _BPLUS B9ED 8D 87 FE STA fdc_data #elif defined _MASTER B9ED 8D 2B FE STA fdc_data #elif defined _CHALL5 B9ED 8D FB FC STA fdc_data #elif defined _PG4005 B9ED 8D C7 FC STA fdc_data #else /* _O27915, _O27935, _O17705 or _O27914 */ B9ED 8D 83 FE STA fdc_data #endif /* _BPLUS */ B9F0 60 RTS .S9F1 B9F1 4C EB B9 JMP S9EB .S9F4 B9F4 2C 8F 02 BIT &028F ;if unset, branch B9F7 10 04 BPL S9FD ;test bit 7 FDC register access emulators. .S9F9 #if defined _O27935 B9F9 EE 82 FE INC fdc_sect ;WD2791 uses DEC fdc_sect #elif defined _O17705 B9F9 EE 82 FE INC fdc_sect ;WD2791 uses DEC fdc_sect #elif defined _CHALL5 B9F9 EE FA FC INC fdc_sect ;WD2791 uses DEC fdc_sect #elif defined _W17705 B9F9 EE 86 FE INC fdc_sect ;WD2791 uses DEC fdc_sect #elif defined _A17705 B9F9 EE 86 FE INC fdc_sect ;WD2791 uses DEC fdc_sect #elif defined _M17705 B9F9 EE 2A FE INC fdc_sect ;WD2791 uses DEC fdc_sect #elif defined _PG4005 B9F9 EE C6 FC INC fdc_sect ;WD2791 uses DEC fdc_sect #elif defined _A17724 B9F9 EE 86 FE INC fdc_sect ;WD2791 uses DEC fdc_sect #elif defined _M17724 B9F9 EE 2A FE INC fdc_sect ;WD2791 uses DEC fdc_sect #else /* _O27915 or _O27914 */ B9F9 CE 82 FE DEC fdc_sect ;WD1770 uses INC fdc_sect #endif /* _O27935 */ B9FC 60 RTS .S9FD B9FD 4C F9 B9 JMP S9F9 ;EDOS API, part 3: OSWORD .SA00 ;OSWORD BA00 20 00 92 JSR Q200 ;Save AXY BA03 18 CLC ;clear carry flag BA04 A5 EF LDA &EF ;if OSWORD call >=&80 BA06 30 05 BMI SA0D ;then return BA08 20 6B B9 JSR S96B ;if not ours/no wksp then return BA0B B0 01 BCS SA0E ;(C=0; passed to lower ROMs) .SA0D BA0D 60 RTS .SA0E BA0E 58 CLI BA0F C9 7F CMP #&7F ;if not &7F (ie &71, &7D or &7E) BA11 F0 03 BEQ SA16 ;then process via hook BA13 4C C1 B3 JMP S3C1 .SA16 BA16 A0 06 LDY #&06 ;else &7F disc op. BA18 B1 F0 LDA (&F0),Y ;get command byte BA1A 29 3F AND #&3F ;00111111 mask it BA1C A2 00 LDX #&00 ;search for it in table .SA1E BA1E DD FD BA CMP SAFD,X ;OSWORD &7F 8271 command lookup table BA21 F0 0E BEQ SA31 ;if found carry on BA23 48 PHA ;else go to next row BA24 8A TXA ;8 bytes in each row BA25 18 CLC BA26 69 08 ADC #&08 BA28 AA TAX BA29 68 PLA BA2A E0 70 CPX #&70 ;have we reached end of table? BA2C D0 F0 BNE SA1E ;if so unrecognised command .SA2E BA2E 4C FC BA JMP SAFC ;so quit C=1 (hook) .SA31 BA31 BD FE BA LDA SAFE,X ;get microcode BA34 29 10 AND #&10 ;if b4 set BA36 F0 13 BEQ SA4B BA38 A0 07 LDY #&07 ;then get first 8271 parameter BA3A B1 F0 LDA (&F0),Y ;(special register number) BA3C C9 06 CMP #&06 ;if none of these values BA3E F0 0B BEQ SA4B ;&06 = WD2791 sector register BA40 C9 12 CMP #&12 ;&12 = unit 0 current track BA42 F0 07 BEQ SA4B BA44 C9 1A CMP #&1A ;&1A = unit 1 current track BA46 F0 03 BEQ SA4B ;then quit C=1 BA48 38 SEC BA49 B0 E3 BCS SA2E .SA4B BA4B 20 00 B7 JSR S700 ;call OSWORD monitor BA4E A0 00 LDY #&00 ;get O7F drive number BA50 B1 F0 LDA (&F0),Y ;A = OSWORD X register value BA52 10 01 BPL SA55 ;if top bit clear, branch BA54 C8 INY ;else, copy it to workspace. .SA55 BA55 B1 F0 LDA (&F0),Y ;copy rest of block to worksp. BA57 99 10 10 STA &1010,Y ;OSWORD &7F block BA5A C8 INY BA5B C0 0C CPY #&0C BA5D D0 F6 BNE SA55 BA5F 20 06 92 JSR Q206 ;copy BA62 EQUW &F0,&00 ;FROM user O7F block address &00F0 BA64 EQUW &1C,&10 ;TO workspace at &101C BA66 EQUB &02 ;count BA67 EA NOP BA68 EA NOP BA69 EA NOP BA6A BD FE BA LDA SAFE,X ;get microcode BA6D 29 60 AND #&60 ;01100000 ;if b5 and b6 clear BA6F F0 1A BEQ SA8B ;then start O7F command BA71 AD 17 10 LDA &1017 ;else get track number BA74 20 40 BE JSR SE40 ;test if drive double-stepped BA77 90 01 BCC SA7A ;if so BA79 0A ASL A ;then double track number. .SA7A BA7A 20 CF BB JSR SBCF ;seek that track BA7D C9 FF CMP #&FF ;if Escape pressed during seek BA7F D0 03 BNE SA84 BA81 4C 9A BB JMP SB9A ;save status and ack. error. .SA84 BA84 29 99 AND #&99 ;if { NotReady RecordNotFound BA86 F0 03 BEQ SA8B ;CRCError Busy } any are set BA88 4C 6D BB JMP SB6D ;then finish O7F, else: .SA8B BA8B BD FE BA LDA SAFE,X ;Start O7F command. BA8E 29 20 AND #&20 ;00100000 ;test b5 of microcode BA90 F0 08 BEQ SA9A ;if set BA92 20 43 BC JSR SC43 ;prepare for read/write BA95 D0 03 BNE SA9A ;if no. sectors to transfer =0 BA97 4C 6D BB JMP SB6D ;then finish O7F, else: .SA9A BA9A BD FE BA LDA SAFE,X ;get microcode BA9D 29 03 AND #&03 ;00000011 ;test two low bits BA9F F0 20 BEQ SAC1 ;if either one is set BAA1 A8 TAY BAA2 20 06 92 JSR Q206 ;save original transfer address in z.p. BAA5 EQUW &11,&10 ;FROM address &1011 BAA7 EQUW &A2,&00 ;TO address &00A2 BAA9 EQUB &02 ;count BAAA 49 00 EOR #&00 ;no-op BAAC 49 00 EOR #&00 BAAE AD 13 10 LDA &1013 ;part of OSWORD &7F block BAB1 2D 14 10 AND &1014 ;test high bits of address BAB4 49 FF EOR #&FF ;invert - if any are clear BAB6 2D 7A 02 AND &027A ;and Tube is present, then: BAB9 F0 17 BEQ SAD2 BABB 98 TYA BABC 20 5B BC JSR SC5B ;open channel 3 for data BABF 85 A6 STA &A6 ;set Tube flag >0 .SAC1 BAC1 BC 01 BB LDY SB01,X ;get offset of NMI code BAC4 F0 28 BEQ SAEE ;if zero there's no NMI handler #if defined _EP565 BAC6 20 09 92 JSR Q209 ;Copy NMI handler BAC9 EQUW &AF,&BE ;from &BEAF BACB EQUW &00,&0D ;to &0D00 BACD EQUB &10,&03 ;&10 bytes, from Y #else /* _EP705 */ BAC6 20 09 92 JSR Q209 ;Copy NMI handler BAC9 EQUW &A4,&BE ;from &BEA4 BACB EQUW &00,&0D ;to &0D00 BACD EQUB &20,&03 ;&20 bytes, from Y #endif /* _EP565 */ BACF 4C EE BA JMP SAEE .SAD2 BAD2 BC FF BA LDY SAFF,X ;an I/O transfer. Get NMI BAD5 F0 17 BEQ SAEE ;offset, no handler if zero. #if defined _EP565 BAD7 20 09 92 JSR Q209 ;Copy NMI handler BADA EQUW &AF,&BE ;from &BEAF BADC EQUW &00,&0D ;to &0D00 BADE EQUB &10,&03 ;&10 bytes, from Y BAE0 BC 00 BB LDY SB00,X ;does NMI take an address? BAE3 F0 09 BEQ SAEE ;0=no address / fixed address BAE5 AD 12 10 LDA &1012 ;if so copy O7F address BAE8 99 00 0D STA &0D00,Y ;2nd byte into NMI handler BAEB 49 00 EOR #&00 ;(the address of an LDA/STA.) BAED EA NOP #else /* _EP705 */ BAD7 20 09 92 JSR Q209 ;Copy NMI handler BADA EQUW &A4,&BE ;from &BEA4 BADC EQUW &00,&0D ;to &0D00 BADE EQUB &20,&03 ;&20 bytes, from Y BAE0 BC 00 BB LDY SB00,X ;does NMI take an address? BAE3 F0 09 BEQ SAEE ;0=no address / fixed address BAE5 20 09 92 JSR Q209 ;if so copy bytes BAE8 EQUW &11,&10 ;from O7F address low at &1011 BAEA EQUW &FF,&0C ;to NMI handler at &0CFF(the address of an LDA/STA.) BAEC EQUB &02,&30 ;2 bytes, to Y #endif /* _EP565 */ .SAEE BAEE BD 02 BB LDA SB02,X ;get 2793 command #if defined _WD2791 BAF1 49 FF EOR #&FF ;invert for 2791 #else /* _WD1770, _WD1772 or _WD2793 */ BAF1 49 00 EOR #&00 ;null invert for 1770 #endif /* _WD2791 */ BAF3 A8 TAY BAF4 BD 04 BB LDA SB04,X ;get jump-table address BAF7 48 PHA ;A -> (SP) = MSB BAF8 BD 03 BB LDA SB03,X ;for command routine (minus 1 for RTS) BAFB 48 PHA ;A -> (SP) = LSB .SAFC BAFC 60 RTS ;and jump to the routine. ;The microcode byte at &BAFE,X is made up as follows: ;&01 ......01 PIO write to disc, source address required ;&02 ......10 PIO read from disc, target address required ;&10 ...1.... Read/write 8271 special registers ;&40 .1...... Motor operation (seek required) ;&60 .11..... Sector operation (scans or reads sector IDs) ;&80 1....... Not used; set if operation accesses or overwrites ; sector data area (i.e. read/write sectors, and format) .SAFD ;OSWORD &7F 8271 command lookup table. BAFD EQUB &36 ; &36 Force interrupt .SAFE ;microcode table BAFE EQUB &00 ; 0 = no microcoded actions .SAFF ;1 + offset of I/O ISR BAFF EQUB &00 ; 0 = no ISR needed .SB00 ;1 + offset of address within I/O ISR BB00 EQUB &00 ; 0 = fixed or no address .SB01 ;1 + offset of Tube ISR BB01 EQUB &00 ; 0 = no ISR needed .SB02 ;equivalent 2793 command BB02 EQUB &D0 ; &D0 = Force Interrupt .SB03 ;OSWORD &7F command jump table BB03 EQUB &4E ;\ .SB04 ; >&BE4E+1 = &BE4F = send Force Interrupt to command register BB04 EQUB &BE ;/ #if defined _EP565 BB05 EQUB &13 ;&13 Read data BB06 EQUB &E2,&21,&07,&31,&80 ;parameters BB0B EQUW &69,&BC ;&BC69+1=&BC6A = Read data command BB0D EQUB &0B ;&0B Write data BB0E EQUB &E1,&01,&0D,&11,&A0 ;parameters BB13 EQUW &65,&BC ;&BC65+1=&BC66 = Write data command BB15 EQUB &29 ;&29 Seek BB16 EQUB &40,&00,&00,&00,&00 ;parameters BB1B EQUW &BE,&BC ;&BCBE+1=&BCBF = Seek command BB1D EQUB &1F ;&1F Verify data BB1E EQUB &E0,&61,&00,&61,&80 ;parameters BB23 EQUW &65,&BC ;&BC65+1=&BC66 = Write data command BB25 EQUB &17 ;&17 Read data & deleted data BB26 EQUB &E2,&21,&07,&31,&80 ;parameters BB2B EQUW &65,&BC ;&BC65+1=&BC66 = Write data command BB2D EQUB &0F ;&0F Write deleted data BB2E EQUB &E1,&01,&0D,&11,&A1 ;parameters BB33 EQUW &65,&BC ;&BC65+1=&BC66 = Write data command BB35 EQUB &1B ;&1B Read ID BB36 EQUB &62,&41,&07,&51,&C4 ;parameters BB3B EQUW &AD,&BC ;&BCAD+1=&BCAE = Read ID command BB3D EQUB &23 ;&23 Format track BB3E EQUB &C1,&71,&00,&71,&F4 ;parameters BB43 EQUW &CF,&BC ;&BCCF+1=&BCD0 = Format command BB45 EQUB &24 ;&24 (Write track) BB46 EQUB &41,&01,&0D,&11,&F4 ;parameters BB4B EQUW &A5,&BD ;&BDA5+1=&BDA6 = Do disc op and finish O7F BB4D EQUB &25 ;&25 (Read track) BB4E EQUB &42,&21,&07,&31,&E4 ;parameters BB53 EQUW &A5,&BD ;&BDA5+1=&BDA6 = Do disc op and finish O7F #else /* _EP705 */ BB05 EQUB &13 ;&13 Read data BB06 EQUB &E2,&31,&10,&4D,&80 ;parameters BB0B EQUW &69,&BC ;&BC69+1=&BC6A = Read data command BB0D EQUB &0B ;&0B Write data BB0E EQUB &E1,&01,&0B,&1D,&A0 ;parameters BB13 EQUW &65,&BC ;&BC65+1=&BC66 = Write data command BB15 EQUB &29 ;&29 Seek BB16 EQUB &40,&00,&00,&00,&00 ;parameters BB1B EQUW &BE,&BC ;&BCBE+1=&BCBF = Seek command BB1D EQUB &1F ;&1F Verify data BB1E EQUB &E0,&99,&00,&99,&80 ;parameters BB23 EQUW &65,&BC ;&BC65+1=&BC66 = Write data command BB25 EQUB &17 ;&17 Read data & deleted data BB26 EQUB &E2,&31,&10,&4D,&80 ;parameters BB2B EQUW &65,&BC ;&BC65+1=&BC66 = Write data command BB2D EQUB &0F ;&0F Write deleted data BB2E EQUB &E1,&01,&0B,&1D,&A1 ;parameters BB33 EQUW &65,&BC ;&BC65+1=&BC66 = Write data command BB35 EQUB &1B ;&1B Read ID BB36 EQUB &62,&61,&14,&81,&C4 ;parameters BB3B EQUW &AD,&BC ;&BCAD+1=&BCAE = Read ID command BB3D EQUB &23 ;&23 Format track BB3E EQUB &C1,&9D,&00,&9D,&F4 ;parameters BB43 EQUW &CF,&BC ;&BCCF+1=&BCD0 = Format command BB45 EQUB &24 ;&24 (Write track) BB46 EQUB &41,&01,&0B,&1D,&F4 ;parameters BB4B EQUW &A5,&BD ;&BDA5+1=&BDA6 = Do disc op and finish O7F BB4D EQUB &25 ;&25 (Read track) BB4E EQUB &42,&31,&10,&4D,&E4 ;parameters BB53 EQUW &A5,&BD ;&BDA5+1=&BDA6 = Do disc op and finish O7F #endif /* _EP565 */ BB55 EQUB &2C ;&2C Read drive status BB56 EQUB &00,&00,&00,&00,&00 ;parameters BB5B EQUW &AB,&BD ;&BDAB+1=&BDAC = Read drive status BB5D EQUB &3A ;&3A Write special registers BB5E EQUB &10,&00,&00,&00,&00 ;parameters BB63 EQUW &E9,&BD ;&BDE9+1=&BDEA = Write special registers BB65 EQUB &3D ;&3D Read special registers BB66 EQUB &10,&00,&00,&00,&00 ;parameters BB6B EQUW &11,&BE ;&BE11+1=&BE12 = Read special registers .SB6D BB6D C9 FF CMP #&FF ;Finish OSWORD &7F. BB6F F0 15 BEQ SB86 ;Bogus status? else 2791 result BB71 29 7C AND #&7C ;01111100 ;mask off { NotReady Track BB73 F0 11 BEQ SB86 ;Index } if other bits then BB75 A2 05 LDX #&05 ;error. search in table .SB77 BB77 DD C3 BB CMP SBC3,X BB7A F0 07 BEQ SB83 ;found. BB7C CA DEX BB7D 10 F8 BPL SB77 BB7F 09 01 ORA #&01 ;00000001 ;not found. BB81 D0 03 BNE SB86 .SB83 BB83 BD C9 BB LDA SBC9,X ;if found get 8271 equivalent .SB86 BB86 48 PHA ;save command status BB87 AD A6 00 LDA &00A6 ;was it a Tube transfer? BB8A F0 03 BEQ SB8F ;if so BB8C 20 0C A0 JSR R00C ;close Tube channel 3. .SB8F BB8F AC 5F 0D LDY &0D5F ;Y = previous owner BB92 A2 0B LDX #&0B ;X = reason code = release NMI BB94 A9 8F LDA #&8F ;issue ROM call &0B BB96 20 F4 FF JSR osbyte BB99 68 PLA ;restore command status .SB9A BB9A AC 1C 10 LDY &101C ;copy user's O7F block address BB9D 84 F0 STY &F0 ;from EDOS workspace BB9F AC 1D 10 LDY &101D ;to MOS control block pointer BBA2 84 F1 STY &F1 ;so that MOS restores X on exit BBA4 AA TAX BBA5 AD 15 10 LDA &1015 ;get no. parameters to command BBA8 18 CLC ;add 7 to point to status byte BBA9 69 07 ADC #&07 ;in user's O7F block BBAB A8 TAY BBAC 8A TXA BBAD 91 F0 STA (&F0),Y ;store O7F result there BBAF C9 FF CMP #&FF ;if not the bogus status &FF BBB1 D0 0C BNE SBBF ;then claim OSWORD call & exit BBB3 AD 16 10 LDA &1016 ;else test O7F command BBB6 29 3F AND #&3F ;if =&7D read special registers BBB8 C9 3D CMP #&3D ;then &FF is a valid result BBBA F0 03 BEQ SBBF ;so claim OSWORD call & exit BBBC 4C AC AB JMP RBAC ;else raise "Escape" error. .SBBF BBBF 38 SEC ;end OSWORD BBC0 60 RTS ;& break ROM call chain. .SBC3 ;2793 error table 0..5 BBC3 EQUB &04,&08,&10 BBC6 EQUB &18,&20,&40 .SBC9 ;8271 equivalent errors BBC9 EQUB &0A,&0E,&18 BBCC EQUB &0C,&20,&12 .SBCF ;seek that track BBCF 20 00 92 JSR Q200 ;Save AXY BBD2 48 PHA BBD3 A0 FF LDY #&FF ;Y = parameter passed = &FF ;Y preset to &FF so that Y=&FF ;on exit indicates that no ROM ;claims previous ownership of ;the NMI resource. BBD5 A2 0C LDX #&0C ;X = reason code = claim NMI BBD7 A9 8F LDA #&8F ;A = call No. BBD9 20 F4 FF JSR osbyte ;call OSBYTE &8F = Paged ROM Service Request BBDC A9 40 LDA #&40 ;= RTI instruction BBDE 8D 00 0D STA &0D00 ;store it at NMI entry point BBE1 8C 5F 0D STY &0D5F ;Y = previous owner #if defined _EP565 BBE4 20 06 92 JSR Q206 ;copy memory absolute BBE7 EQUW &66,&BE ;from disc op code at &BE66 BBE9 EQUW &0F,&0D ;to &0D0F BBEB EQUB &49 ;No. of bytes = &49, &0D0F..57 #else /* _EP705 */ BBE4 20 06 92 JSR Q206 ;copy memory absolute BBE7 EQUW &66,&BE ;from disc op code at &BE66 BBE9 EQUW &20,&0D ;to &0D20 BBEB EQUB &3E ;No. of bytes = &3E, &0D20..5D #endif /* _EP565 */ BBEC A9 10 LDA #&10 ;set retry counter = 16 BBEE 8D 5E 0D STA &0D5E BBF1 A9 00 LDA #&00 ;set Tube flag = 0 BBF3 85 A6 STA &A6 BBF5 85 A7 STA &A7 ;set status = 0 BBF7 20 BC 9A JSR QABC ;get density of OSWORD &7F drive BBFA 4A LSR A ;A: &0A=SD, &12=DD, &1E=QD, &24=QD BBFB 4A LSR A ;integer divide by 8 to get: BBFC 4A LSR A ;1=single, 2=double, 3=quad, 4=quad. BBFD A8 TAY ;copy to Y as index BBFE BD 89 B3 LDA S3B9-&30,X ;get latch value for drive BC01 59 BC B3 EOR S3BD-&01,Y ;apply latch mask for density BC04 EA NOP BC05 20 B0 B9 JSR S9B0 ;setup drive control register BC08 20 36 BE JSR SE36 ;get track no. under head BC0B 20 CA B9 JSR S9CA ;test and write to track register BC0E 49 00 EOR #&00 ;no-op BC10 A0 08 LDY #&08 ;=Restore command BC12 68 PLA ;recover logical track number BC13 F0 07 BEQ SC1C ;if >0 BC15 20 E6 B9 JSR S9E6 ;store data register BC18 49 00 EOR #&00 BC1A A0 18 LDY #&18 ;=Seek command .SC1C BC1C 8C A5 00 STY &00A5 ;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 = stepping BC28 0D A5 00 ORA &00A5 ;merge into 2791 command #if defined _WD2791 BC2B 49 FF EOR #&FF ;invert for 2791 #else /* _WD1770, _WD1772 or _WD2793 */ BC2B 49 00 EOR #&00 ;null invert for 1770 #endif /* _WD2791 */ 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 94 B9 JSR S994 ;load track register BC38 49 00 EOR #&00 ;no-op BC3A 9D 1E 10 STA &101E,X ;set new track no. under head BC3D 68 PLA BC3E BA TSX BC3F 9D 04 01 STA saved_a,X ;return status in A BC42 60 RTS .SC43 ;Prepare for read/write. BC43 AD 17 10 LDA &1017 ;A = track number BC46 20 CA B9 JSR S9CA ;test and write to track register BC49 49 00 EOR #&00 ;no-op BC4B AD 18 10 LDA &1018 ;get O7F sector no. BC4E 20 D8 B9 JSR S9D8 ;test and write to sector register BC51 49 00 EOR #&00 ;no-op .SC53 #if defined _EP565 BC53 20 6C 8F JSR PF6C ;Get no. sectors BC56 29 3F AND #&3F ;00111111 ;mask off sector size bits #else /* _EP705 */ BC53 AD 19 10 LDA &1019 ;Get no. sectors BC56 29 1F AND #&1F ;00011111 ;mask off sector size bits #endif /* _EP565 */ 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 .SC66 ;called from jump table at &BB13 etc BC66 A9 00 LDA #&00 ;Write data command BC68 F0 02 BEQ SC6C .SC6A ;called from jump table at &BB0B BC6A A9 FF LDA #&FF ;Read data command .SC6C BC6C 8D 5E 0D STA &0D5E .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 A7 00 STA &00A7 ;Scrub sector. save status BC81 AD 5E 0D LDA &0D5E ;if Write Data command BC84 F0 1B BEQ SCA1 ;then we requested it, carry on BC86 AD A6 00 LDA &00A6 ;else is Read. if I/O transfer BC89 D0 06 BNE SC91 #if defined _EP565 BC8B CE 0D 0D DEC &0D0D ;then decrement fetch page #else /* _EP705 */ BC8B CE 0B 0D DEC &0D0B ;then decrement fetch page #endif /* _EP565 */ 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 F4 B9 JSR S9F4 ;increment sector register BCA4 C6 A4 DEC &A4 ;decrement sector count BCA6 D0 C7 BNE SC6F ;loop if more sectors BCA8 AD A7 00 LDA &00A7 ;else retrieve status .SCAB BCAB 4C 6D BB JMP SB6D ;post disc op .SCAE ;called from jump table at &BB3B #if defined _EP565 BCAE 20 5B BE JSR SE5B ;Read ID command. do disc op BCB1 D0 11 BNE SCC4 ;if error then determine type BCB3 20 76 8F JSR PF76 ;else backspace over CRC # if defined _WD2791 BCB6 A0 3F LDY #&3F ;cmd=ReadAdr w/o settling delay # else /* _WD1772 */ BCB6 A0 C0 LDY #&C0 ;cmd=ReadAdr w/o settling delay # endif /* _WD2791 */ BCB8 C6 A4 DEC &A4 ;decrement sector counter BCBA D0 F2 BNE SCAE ;repeat command if more. BCBC 49 00 EOR #&00 ;no-op BCBE EA NOP #else /* _EP705 */ 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 clear b2 of command # if defined _WD2791 BCB8 09 04 ORA #&04 ;00000100 ;{ SettlingDelay } # else /* _WD1770 or _WD2793 */ BCB8 29 FB AND #&FB ;11111011 ;{ SettlingDelay } # endif /* _WD2791 */ BCBA A8 TAY BCBB C6 A4 DEC &A4 ;decrement sector counter BCBD D0 EF BNE SCAE ;repeat command if more. #endif /* _EP565 */ .SCBF ;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 5E 0D DEC &0D5E ;decrement retry counter BCCB F0 F4 BEQ SCC1 ;exit if run out BCCD 4C 8B BA JMP SA8B ;else restart command. ;Format command .SCD0 ;called from jump table at &BB43 BCD0 8C A5 00 STY &00A5 BCD3 20 53 BC JSR SC53 ;set &A4 = no. of sectors BCD6 4A LSR A ;integer divide by 16 to get: BCD7 4A LSR A ;0=single, 1=double density. BCD8 4A LSR A BCD9 4A LSR A BCDA A8 TAY ;copy to Y as index BCDB 4A LSR A ;rotate into bit 7 BCDC 6A ROR A ;0=single, &80=double density. BCDD 85 A0 STA &A0 ;set as top bit of density flag BCDF 20 BC 9A JSR QABC ;put O7F drive in X, discard A BCE2 BD 89 B3 LDA S3B9-&30,X ;get latch value for drive BCE5 59 BD B3 EOR S3BD,Y ;apply latch mask for density BCE8 A0 00 LDY #&00 ;zero indirect indexed offset BCEA 84 A1 STY &A1 ;and RLE table index BCEC EA NOP BCED 20 B0 B9 JSR S9B0 ;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 B9 8F JSR PFB9 ;run out to end of RLE table BD3B AC A5 00 LDY &00A5 ;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 04 01 LDA saved_a,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 A6 00 LDA &00A6 ;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 #if defined _EP565 BD8D 20 C5 8F JSR PFC5 ;invert and store byte value #else /* _EP705 */ BD8D 99 00 0E STA &0E00,Y ;store byte value #endif /* _EP565 */ 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 at &BB4B/&BB53 BDA6 20 5B BE JSR SE5B ;Do disc op and finish O7F. BDA9 4C 6D BB JMP SB6D .SDAC ;called from jump table at &BB5B 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 86 BB JMP SB86 ;store result and exit ;Note: Both the WD2791's sector register and the 8271's Scan Sector ;register contain the sector number where an error occurs, but when ;a successful multiple Read/Write Sector command is interrupted ;the WD2791's sector register is left containing a sector number ;one higher than the last one encountered. ;Write special registers .SDEA ;called from jump table at &BB63 BDEA AD 17 10 LDA &1017 ;A = track number BDED C9 06 CMP #&06 BDEF F0 14 BEQ SE05 ;if not register 6 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 ;&06 (Current sector) BE08 20 D8 B9 JSR S9D8 ;test and write to sector register BE0B 49 00 EOR #&00 ;no-op BE0D A9 00 LDA #&00 ;return zero status BE0F 4C 9A BB JMP SB9A ;Read special registers .SE12 ;called from jump table at &BB6B BE12 AD 17 10 LDA &1017 ;A = track number BE15 C9 06 CMP #&06 BE17 F0 0C BEQ SE25 ;if not register 6 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 A2 B9 JSR S9A2 ;read sector register BE28 49 00 EOR #&00 ;no-op 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 BE32 4A LSR A 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 .SE4F ;called from jump table at &BB03 BE4F A9 D0 LDA #&D0 ;A = Force interrupt, 11010000 BE51 20 BC B9 JSR S9BC ;send Force Interrupt to command register BE54 49 00 EOR #&00 ;no-op 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 #if defined _EP565 BE5D 8D 49 0D STA &0D49 ;number in NMI area BE60 AD 87 10 LDA &1087 ;get *OPT 9 saverom BE63 4C 30 BF JMP SF30 ;jump to disc operation busywait #else /* _EP705 */ BE5D 8D 56 0D STA &0D56 ;number in NMI area BE60 AD 87 10 LDA &1087 ;get *OPT 9 saverom BE63 4C 60 BF JMP SF60 ;jump to disc operation busywait #endif /* _EP565 */ #if defined _EP565 ;disc op code/Disc ancillary loop ;called by routine at &BBDF to copy &4B bytes to &0D0F BE66 EQUB &00 ;0 to clear NMI semaphore BE67 85 F4 STA rmslrg ;Disc ancillary loop BE69 8D 30 FE STA romselr ;copied to &0D0F, starts &0D10 .SE6C # if defined _BPLUS BE6C AD 84 FE LDA fdc_stat ;set ROM back to *OPT 9 saverom # elif defined _MASTER BE6C AD 28 FE LDA fdc_stat ;set ROM bank to *OPT 9 saverom # else /* _O27914 */ BE6C AD 80 FE LDA fdc_stat ;set ROM bank to *OPT 9 saverom # endif /* _BPLUS */ # if defined _WD2791 BE6F 49 5F EOR #&5F ;if { NotReady SpinUpComplete } BE71 29 A0 AND #&A0 ;then wait. (Core must clear # else /* _WD1772 */ BE6F 49 20 EOR #&20 ;if { NotReady SpinUpComplete } BE71 29 A0 AND #&A0 ;then wait. (Core must clear # endif /* _WD2791 */ BE73 F0 F7 BEQ SE6C ;other cases of NotReady) BE75 08 PHP ;save interrupt state BE76 78 SEI ;disable interrupts (volatile) BE77 AD 00 0E LDA &0E00 ;fetch first byte for ISR BE7A EA NOP ;(address or LDA/LDX pasted) # if defined _BPLUS BE7B 8C 84 FE STY fdc_comm ;issue FDC command # elif defined _MASTER BE7B 8C 28 FE STY fdc_comm ;issue FDC command # else /* _O27914 */ BE7B 8C 80 FE STY fdc_comm ;issue FDC command # endif /* _BPLUS */ BE7E A0 14 LDY #&14 ;allow status register .SE80 BE80 88 DEY ;to settle (50 us) BE81 D0 FD BNE SE80 .SE83 # if defined _BPLUS BE83 AC 84 FE LDY fdc_stat ;poll status register # elif defined _MASTER BE83 AC 28 FE LDY fdc_stat ;poll status register # else /* _O27914 */ BE83 AC 80 FE LDY fdc_stat ;poll status register # endif /* _BPLUS */ # if defined _WD2791 BE86 10 FB BPL SE83 ;loop until Ready # else /* _WD1772 */ BE86 10 FB BPL SE83 ;loop until Ready # endif /* _WD2791 */ BE88 84 A0 STY &A0 ;test bit 0 BE8A 46 A0 LSR &A0 # if defined _WD2791 BE8C 90 F5 BCC SE83 ;loop until not Busy also # else /* _WD1772 */ BE8C B0 F5 BCS SE83 ;loop until not Busy also # endif /* _WD2791 */ BE8E 8E 21 0D STX &0D21 ;save ISR A and X for next call BE91 8D 23 0D STA &0D23 BE94 A9 A2 LDA #&A2 ;=LDX immediate BE96 8D 20 0D STA &0D20 BE99 A9 A9 LDA #&A9 ;=LDA immediate BE9B 8D 22 0D STA &0D22 ;now our state is saved BE9E 28 PLP ;restore interrupt state BE9F A9 FF LDA #&FF ;load slot number of EDOS ROM BEA1 85 F4 STA rmslrg ;page EDOS ROM back in BEA3 8D 30 FE STA romselr BEA6 98 TYA ;move last status to A BEA7 A6 A1 LDX &A1 ;restore 8271 cmd table index BEA9 AC A5 00 LDY &00A5 ;restore FDC command # if defined _WD2791 BEAC 49 FF EOR #&FF ;present status and set flags. # else /* _WD1772 */ BEAC 49 80 EOR #&80 ;present status and set flags. # endif /* _WD2791 */ BEAE 60 RTS # if defined _A17724 BEB0 49 00 EOR #&00 ;NMI write from I/O BEB2 8D 87 FE STA fdc_data ;all ISRs copied to &0D00 BEB5 E8 INX ;send byte in hand to FDC BEB6 D0 03 BNE SEBB ;pre-increment pointer BEB8 EE 0D 0D INC &0D0D .SEBB BEBB BD 00 0D LDA &0D00,X ;fetch next byte and exit. BEBE 40 RTI BEBF EQUB &01 ;&01:needs A=I/O byte, X=ptr low BEC0 49 00 EOR #&00 ;NMI write from Tube BEC2 8D 87 FE STA fdc_data ;send byte in hand to FDC BEC5 AD E5 FE LDA tubeR3data ;fetch next byte and exit. BEC8 40 RTI BECF EQUB &03 ;&03: needs A=byte from Tube BED0 AD 87 FE LDA fdc_data ;NMI read to I/O BED3 49 00 EOR #&00 ;get byte from FDC BED5 9D 00 0D STA &0D00,X ;store it BED8 E8 INX ;post-increment address and exit BED9 D0 03 BNE SEDE BEDB EE 07 0D INC &0D07 .SEDE BEDE 40 RTI BEDF EQUB &02 ;&02: needs X=ptr low BEE0 AD 87 FE LDA fdc_data ;NMI read to Tube BEE3 49 00 EOR #&00 ;get byte from FDC BEE5 8D E5 FE STA tubeR3data ;send it to Tube, exit BEE8 40 RTI BEEF EQUB &00 ;&00: no entry conditions BEF0 AD 87 FE LDA fdc_data ;NMI read IDs to I/O BEF3 49 00 EOR #&00 ;get byte from FDC BEF5 9D 00 0D STA &0D00,X ;store it BEF8 E8 INX ;post-increment address and exit BEF9 D0 03 BNE SEFE BEFB EE 07 0D INC &0D07 .SEFE BEFE 40 RTI BEFF EQUB &02 ;&02: needs X=ptr low BF00 AD 87 FE LDA fdc_data ;NMI read IDs to Tube BF03 49 00 EOR #&00 ;get byte from FDC BF05 CA DEX ;decrement counter BF06 30 03 BMI SF0B ;discard byte if <0 BF08 8D E5 FE STA tubeR3data ;else send to Tube. exit .SF0B BF0B 40 RTI BF0F EQUB &04 ;&04: needs X=4 each call BF10 2C 87 FE BIT fdc_data ;NMI verify BF13 40 RTI ;get byte, discard and exit BF14 EQUS "HiMartinB:)" BF1F EQUB &00 ;&00: no entry conditions BF20 8D 87 FE STA fdc_data ;NMI format from RLE table BF23 DE 00 0F DEC &0F00,X ;send byte to FDC BF26 D0 04 BNE SF2C ;decrement counter, if zero BF28 E8 INX ;then increment index BF29 BD 00 0E LDA &0E00,X ;and get next run of bytes. .SF2C BF2C 40 RTI BF2F EQUB &00 ;&00: needs X=0 # elif defined _M17724 BEB0 49 00 EOR #&00 ;NMI write from I/O BEB2 8D 2B FE STA fdc_data ;all ISRs copied to &0D00 BEB5 E8 INX ;send byte in hand to FDC BEB6 D0 03 BNE SEBB ;pre-increment pointer BEB8 EE 0D 0D INC &0D0D .SEBB BEBB BD 00 0D LDA &0D00,X ;fetch next byte and exit. BEBE 40 RTI BEBF EQUB &01 ;&01:needs A=I/O byte, X=ptr low BEC0 49 00 EOR #&00 ;NMI write from Tube BEC2 8D 2B FE STA fdc_data ;send byte in hand to FDC BEC5 AD E5 FE LDA tubeR3data ;fetch next byte and exit. BEC8 40 RTI BECF EQUB &03 ;&03: needs A=byte from Tube BED0 AD 2B FE LDA fdc_data ;NMI read to I/O BED3 49 00 EOR #&00 ;get byte from FDC BED5 9D 00 0D STA &0D00,X ;store it BED8 E8 INX ;post-increment address and exit BED9 D0 03 BNE SEDE BEDB EE 07 0D INC &0D07 .SEDE BEDE 40 RTI BEDF EQUB &02 ;&02: needs X=ptr low BEE0 AD 2B FE LDA fdc_data ;NMI read to Tube BEE3 49 00 EOR #&00 ;get byte from FDC BEE5 8D E5 FE STA tubeR3data ;send it to Tube, exit BEE8 40 RTI BEEF EQUB &00 ;&00: no entry conditions BEF0 AD 2B FE LDA fdc_data ;NMI read IDs to I/O BEF3 49 00 EOR #&00 ;get byte from FDC BEF5 9D 00 0D STA &0D00,X ;store it BEF8 E8 INX ;post-increment address and exit BEF9 D0 03 BNE SEFE BEFB EE 07 0D INC &0D07 .SEFE BEFE 40 RTI BEFF EQUB &02 ;&02: needs X=ptr low BF00 AD 2B FE LDA fdc_data ;NMI read IDs to Tube BF03 49 00 EOR #&00 ;get byte from FDC BF05 CA DEX ;decrement counter BF06 30 03 BMI SF0B ;discard byte if <0 BF08 8D E5 FE STA tubeR3data ;else send to Tube. exit .SF0B BF0B 40 RTI BF0F EQUB &04 ;&04: needs X=4 each call BF10 2C 2B FE BIT fdc_data ;NMI verify BF13 40 RTI ;get byte, discard and exit BF14 EQUS "HiMartinB:)" BF1F EQUB &00 ;&00: no entry conditions BF20 8D 2B FE STA fdc_data ;NMI format from RLE table BF23 DE 00 0F DEC &0F00,X ;send byte to FDC BF26 D0 04 BNE SF2C ;decrement counter, if zero BF28 E8 INX ;then increment index BF29 BD 00 0E LDA &0E00,X ;and get next run of bytes. .SF2C BF2C 40 RTI BF2F EQUB &00 ;&00: needs X=0 # else /* _O27914 */ BEB0 49 FF EOR #&FF ;NMI write from I/O BEB2 8D 83 FE STA fdc_data ;all ISRs copied to &0D00 BEB5 E8 INX ;invert,send byte in hand to FDC BEB6 D0 03 BNE SEBB ;pre-increment pointer BEB8 EE 0D 0D INC &0D0D .SEBB BEBB BD 00 0D LDA &0D00,X ;fetch next byte and exit. BEBE 40 RTI BEBF EQUB &01 ;&01:needs A=I/O byte, X=ptr low BEC0 49 FF EOR #&FF ;NMI write from Tube BEC2 8D 83 FE STA fdc_data ;invert byte in hand, send to FDC BEC5 AD E5 FE LDA tubeR3data ;fetch next byte and exit. BEC8 40 RTI BECF EQUB &03 ;&03: needs A=byte from Tube BED0 AD 83 FE LDA fdc_data ;NMI read to I/O BED3 49 FF EOR #&FF ;get byte from FDC, invert BED5 9D 00 0D STA &0D00,X ;store it BED8 E8 INX ;post-increment address and exit BED9 D0 03 BNE SEDE BEDB EE 07 0D INC &0D07 .SEDE BEDE 40 RTI BEDF EQUB &02 ;&02: needs X=ptr low BEE0 AD 83 FE LDA fdc_data ;NMI read to Tube BEE3 49 FF EOR #&FF ;get byte from FDC, invert BEE5 8D E5 FE STA tubeR3data ;send it to Tube, exit BEE8 40 RTI BEEF EQUB &00 ;&00: no entry conditions BEF0 AD 83 FE LDA fdc_data ;NMI read IDs to I/O BEF3 49 FF EOR #&FF ;get byte from FDC, invert BEF5 9D 00 0D STA &0D00,X ;store it BEF8 E8 INX ;post-increment address and exit BEF9 D0 03 BNE SEFE BEFB EE 07 0D INC &0D07 .SEFE BEFE 40 RTI BEFF EQUB &02 ;&02: needs X=ptr low BF00 AD 83 FE LDA fdc_data ;NMI read IDs to Tube BF03 49 FF EOR #&FF ;get byte from FDC, invert BF05 CA DEX ;decrement counter BF06 30 03 BMI SF0B ;discard byte if <0 BF08 8D E5 FE STA tubeR3data ;else send to Tube. exit .SF0B BF0B 40 RTI BF0F EQUB &04 ;&04: needs X=4 each call BF10 2C 83 FE BIT fdc_data ;NMI verify BF13 40 RTI ;get byte, discard and exit BF14 EQUS "HiMartinB:)" BF1F EQUB &00 ;&00: no entry conditions BF20 8D 83 FE STA fdc_data ;NMI format from RLE table BF23 DE 00 0F DEC &0F00,X ;send byte to FDC BF26 D0 04 BNE SF2C ;decrement counter, if zero BF28 E8 INX ;then increment index BF29 BD 00 0E LDA &0E00,X ;and get next run of bytes. .SF2C BF2C 40 RTI BF2F EQUB &00 ;&00: needs X=0 # endif /* _A17724 */ .SF30 BF30 86 A1 STX &A1 ;Jump to disc operation busywait BF32 AE 0F 0D LDX &0D0F ;save 8271 cmd table index BF35 F0 12 BEQ SF49 ;put NMI semaphore in X BF37 E0 04 CPX #&04 ;if X=0, leave prefetch alone BF39 F0 0B BEQ SF46 ;if X=4, make it so in the loop BF3B 4E 0F 0D LSR &0D0F ;else if X=1 or X=3 BF3E B0 17 BCS SF57 ;then set up prefetch address BF40 4E 0F 0D LSR &0D0F ;else X=2, clear NMI semaphore .SF43 BF43 AE 11 10 LDX &1011 ;set X=low byte of address .SF46 BF46 8E 21 0D STX &0D21 ;make it so in the loop. .SF49 BF49 2C 8F 02 BIT &028F ;test keyboard link 1 BF4C 10 06 BPL SF54 ;if made then jump via hook .SF4E BF4E 8C A5 00 STY &00A5 ;else preserve FDC command BF51 4C 10 0D JMP &0D10 ;and jump to disc op loop. .SF54 BF54 4C 4E BF JMP SF4E .SF57 BF57 A2 AD LDX #&AD ;=LDA absolute BF59 8E 20 0D STX &0D20 ;set up to prefetch from address BF5C A2 EA LDX #&EA ;=NOP BF5E 8E 23 0D STX &0D23 BF61 A2 FE LDX #tubeR3data DIV 256 ;high byte of Tube FIFO 3 address BF63 4E 0F 0D LSR &0D0F ;if X=3 BF66 B0 03 BCS SF6B ;then set to prefetch from Tube BF68 AE 12 10 LDX &1012 ;else get I/O address high byte. .SF6B BF6B 8E 22 0D STX &0D22 ;store high byte of LDA absolute BF6E 90 D3 BCC SF43 ;if X=1 set I/O address low byte BF70 A2 E5 LDX #tubeR3data MOD 256 ;else store low byte of FIFO 3 BF72 B0 D2 BCS SF46 ;in LDA absolute BFFF 00 BRK ;make 16 KiB ROM image ;Note: The disc operation busy loop (&0D10..58) modifies itself on exit ;to restore the values of A and X on the next call. During motor ;operations it is called once for the seek and again for the main ;action(s). On exit from the seek it preserves the value of X on entry ;(i.e. 0) and an ISR with a zero semaphore does not change it ;(especially Format, which is what we want.) Some other ISRs have to ;reinstall the LDA absolute instruction before the main action, viz.: ; ;On entry to SF30: A=saverom, X=undef, Y=command ;If ?&0D0F = 0: rdtu veri form, subsequent sector reads/writes ;on the same track, preliminary seek and non-motor ops ; On entry to &0D10: ; ?&0D0F = 0 ; !&0D20 = preserved (LDX #&00: LDA #?&0E00) (rdtu veri form); ; !&0D20 = preserved (LDX #undef: LDA #undef) (subsequent); ; !&0D20 = preserved (LDA &0E00: NOP) (seek, non-motor ops) ; X = &00 (clobbered by same value) (form); ; X = &00 (clobbered by same value, discarded) (rdtu veri); ; X = &00 (clobbered) (subsequent); ; X = &00 (saved for next call to &0D10) (otherwise) ; On exit from &0D58: ; !&0D20 = LDX #undef: LDA #undef (form, subsequent) ; !&0D20 = LDX #&00: LDA #undef (rdtu) ; !&0D20 = LDX #&00: LDA #?&0E00 (otherwise) ;If ?&0D0F = 1: wrio ; On entry to &0D10: ; ?&0D0F = 0 ; !&0D20 = LDA !&1011: NOP ; X = ?&1011 (used by wrio) ;If ?&0D0F = 2: rdio idio ; On entry to &0D10: ; ?&0D0F = 0 ; !&0D20 = LDX #?&1011: LDA #?&0E00 (A discarded) ; X = ?&1011 (clobbered by same value) ;If ?&0D0F = 3: wrtu ; On entry to &0D10: ; ?&0D0F = 0 ; !&0D20 = LDA tubeR3data: NOP ; X = tubeR3data MOD 256 (discarded) ;If ?&0D0F = 4: idtu ; On entry to &0D10: ; ?&0D0F = 4 ; !&0D20 = LDX #&04: LDA #?&0E00 (A discarded) ; X = &04 (clobbered by same value) #else /* _EP705 */ ;disc op code/Disc ancillary loop ;called by routine at &BBDF to copy &3F bytes to &0D20 BE66 85 F4 STA rmslrg ;set ROM bank to *OPT 9 saverom BE68 8D 30 FE STA romselr .SE6B # if defined _BPLUS BE6B AD 84 FE LDA fdc_stat ;FDC status -> A # elif defined _MASTER BE6B AD 28 FE LDA fdc_stat ;FDC status -> A # elif defined _CHALL5 BE6B AD F8 FC LDA fdc_stat ;FDC status -> A # elif defined _PG4005 BE6B AD C4 FC LDA fdc_stat ;FDC status -> A # else /* _O27915, _O27935 or _O17705 */ BE6B AD 80 FE LDA fdc_stat ;FDC status -> A # endif /* _BPLUS */ # if defined _WD2791 BE6E 49 5F EOR #&5F ;00100000 - if { NotReady SpinUpComplete } toggle bit 5 = spinup BE70 29 A0 AND #&A0 ;10100000 - mask bits 0-5 and 7 (bit 6 = WRP) # elif defined _WD2793 BE6E 49 A0 EOR #&A0 ;00100000 - if { NotReady SpinUpComplete } toggle bit 5 = spinup BE70 29 A0 AND #&A0 ;10100000 - mask bits 0-5 and 7 (bit 6 = WRP) # else /* _WD1770 */ 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) # endif /* _WD2791 */ BE72 F0 F7 BEQ SE6B # if defined _BPLUS BE74 8C 84 FE STY fdc_comm ;Y -> FDC command register # elif defined _MASTER BE74 8C 28 FE STY fdc_comm ;Y -> FDC command register # elif defined _CHALL5 BE74 8C F8 FC STY fdc_comm ;Y -> FDC command register # elif defined _PG4005 BE74 8C C4 FC STY fdc_comm ;Y -> FDC command register # else /* _O27915, _O27935 or _O17705 */ BE74 8C 80 FE STY fdc_comm ;Y -> FDC command register # endif /* _BPLUS */ BE77 A9 14 LDA #&14 ;allow status register .SE79 BE79 E9 01 SBC #&01 ;to settle (50 us) BE7B D0 FC BNE SE79 .SE7D ;poll status register # if defined _BPLUS BE7D AD 84 FE LDA fdc_stat ;FDC status -> A # elif defined _MASTER BE7D AD 28 FE LDA fdc_stat ;FDC status -> A # elif defined _CHALL5 BE7D AD F8 FC LDA fdc_stat ;FDC status -> A # elif defined _PG4005 BE7D AD C4 FC LDA fdc_stat ;FDC status -> A # else /* _O27915, _O27935 or _O17705 */ BE7D AD 80 FE LDA fdc_stat ;FDC status -> A # endif /* _BPLUS */ # if defined _WD2791 BE80 49 FF EOR #&FF ;toggle bit 7 = Motor On # elif defined _WD2793 BE80 49 00 EOR #&00 ;toggle bit 7 = Motor On # else /* _WD1770 */ BE80 49 80 EOR #&80 ;toggle bit 7 = Motor On # endif /* _WD2791 */ BE82 10 12 BPL SE96 ;if Ready then test Busy flag BE84 AD 16 10 LDA &1016 ;else if top bit of O7F command BE87 25 FF AND &FF ;or Escape flag clear BE89 10 F2 BPL SE7D ;then poll again BE8B A9 00 LDA #&00 ;else issue Restore command # if defined _WD2791 BE8D 49 FF EOR #&FF ;invert for 2791 # else /* _WD1770 or _WD2793 */ BE8D 49 00 EOR #&00 ;null invert for 1770 # endif /* _WD2791 */ # if defined _BPLUS BE8F 8D 84 FE STA fdc_comm ;zero FDC command register = restore # elif defined _MASTER BE8F 8D 28 FE STA fdc_comm ;zero FDC command register = restore # elif defined _CHALL5 BE8F 8D F8 FC STA fdc_comm ;zero FDC command register = restore # elif defined _PG4005 BE8F 8D C4 FC STA fdc_comm ;zero FDC command register = restore # else /* _O27915, _O27935 or _O17705 */ BE8F 8D 80 FE STA fdc_comm ;zero FDC command register = restore # endif /* _BPLUS */ BE92 A9 FF LDA #&FF ;&FF -> A BE94 D0 04 BNE SE9A ;and exit with bogus status .SE96 BE96 6A ROR A ;if busy flag set BE97 B0 E4 BCS SE7D ;then poll again BE99 2A ROL A .SE9A BE9A 48 PHA BE9B A9 FF LDA #&FF ;else restore ROM bank (EDOS) BE9D 85 F4 STA rmslrg BE9F 8D 30 FE STA romselr BEA2 68 PLA ;and return status register BEA3 60 RTS # if defined _O27935 ; ;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 80 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 ;null invert for 2793 BEB3 8D 83 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 80 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 ;null invert for 2793 BECF 8D 83 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 80 FE BIT fdc_stat BEDC F0 10 BEQ SEEE BEDE AD 83 FE LDA fdc_data BEE1 49 00 EOR #&00 ;null invert for 2793 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 80 FE BIT fdc_stat BEF8 F0 08 BEQ SF02 BEFA AD 83 FE LDA fdc_data ;fetch from data register BEFD 49 00 EOR #&00 ;null invert for 2793 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 80 FE BIT fdc_stat BF0C F0 14 BEQ SF22 BF0E AD 83 FE LDA fdc_data ;read data register BF11 49 00 EOR #&00 ;null invert for 2793 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 BF24 40 RTI BF25 85 A0 STA &A0 ;NMI read ID Tube BF27 A9 02 LDA #&02 BF29 2C 80 FE BIT fdc_stat BF2C F0 0C BEQ SF3A BF2E AD 83 FE LDA fdc_data ;fetch from data register BF31 49 00 EOR #&00 ;null invert for 2793 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 83 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 80 FE BIT fdc_stat BF48 F0 13 BEQ SF5D BF4A AD 00 0E LDA &0E00 ;get byte from table BF4D 49 00 EOR #&00 ;null invert for 2793 BF4F 8D 83 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 # elif defined _O17705 ; ;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 80 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 ;null invert for 1770 BEB3 8D 83 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 80 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 ;null invert for 1770 BECF 8D 83 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 80 FE BIT fdc_stat BEDC F0 10 BEQ SEEE BEDE AD 83 FE LDA fdc_data BEE1 49 00 EOR #&00 ;null 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 80 FE BIT fdc_stat BEF8 F0 08 BEQ SF02 BEFA AD 83 FE LDA fdc_data ;fetch from data register BEFD 49 00 EOR #&00 ;null 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 80 FE BIT fdc_stat BF0C F0 14 BEQ SF22 BF0E AD 83 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 BF24 40 RTI BF25 85 A0 STA &A0 ;NMI read ID Tube BF27 A9 02 LDA #&02 BF29 2C 80 FE BIT fdc_stat BF2C F0 0C BEQ SF3A BF2E AD 83 FE LDA fdc_data ;fetch from data register BF31 49 00 EOR #&00 ;null invert for 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 83 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 80 FE BIT fdc_stat BF48 F0 13 BEQ SF5D BF4A AD 00 0E LDA &0E00 ;get byte from table BF4D 49 00 EOR #&00 ;null invert for 1770 BF4F 8D 83 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 # elif defined _CHALL5 ; ;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 F8 FC 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 ;null invert for 1770 BEB3 8D FB FC 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 F8 FC BIT fdc_stat BEC8 F0 08 BEQ SED2 BECA AD E5 FE LDA tubeR3data ;Fetch from Tube FIFO 3 BECD 49 00 EOR #&00 ;null invert for 1770 BECF 8D FB FC 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 F8 FC BIT fdc_stat BEDC F0 10 BEQ SEEE BEDE AD FB FC LDA fdc_data BEE1 49 00 EOR #&00 ;null 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 F8 FC BIT fdc_stat BEF8 F0 08 BEQ SF02 BEFA AD FB FC LDA fdc_data ;fetch from data register BEFD 49 00 EOR #&00 ;null 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 F8 FC BIT fdc_stat BF0C F0 14 BEQ SF22 BF0E AD FB FC 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 BF24 40 RTI BF25 85 A0 STA &A0 ;NMI read ID Tube BF27 A9 02 LDA #&02 BF29 2C F8 FC BIT fdc_stat BF2C F0 0C BEQ SF3A BF2E AD FB FC LDA fdc_data ;fetch from data register BF31 49 00 EOR #&00 ;null invert for 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 FB FC 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 F8 FC BIT fdc_stat BF48 F0 13 BEQ SF5D BF4A AD 00 0E LDA &0E00 ;get byte from table BF4D 49 00 EOR #&00 ;null invert for 1770 BF4F 8D FB FC 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 # elif defined _W17705 ; ;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 BEAC F0 10 BEQ SEBE ;else read memory then ignore interrupt BEAE AD 00 0D LDA &0D00 BEB1 49 00 EOR #&00 ;null invert for 1770 BEB3 8D 87 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 BEC8 F0 08 BEQ SED2 BECA AD E5 FE LDA tubeR3data ;Fetch from Tube FIFO 3 BECD 49 00 EOR #&00 ;null invert for 1770 BECF 8D 87 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 BEDC F0 10 BEQ SEEE BEDE AD 87 FE LDA fdc_data BEE1 49 00 EOR #&00 ;null 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 BEF8 F0 08 BEQ SF02 BEFA AD 87 FE LDA fdc_data ;fetch from data register BEFD 49 00 EOR #&00 ;null 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 BF0C F0 14 BEQ SF22 BF0E AD 87 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 BF24 40 RTI BF25 85 A0 STA &A0 ;NMI read ID Tube BF27 A9 02 LDA #&02 BF29 2C 84 FE BIT fdc_stat BF2C F0 0C BEQ SF3A BF2E AD 87 FE LDA fdc_data ;fetch from data register BF31 49 00 EOR #&00 ;null invert for 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 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 BF48 F0 13 BEQ SF5D BF4A AD 00 0E LDA &0E00 ;get byte from table BF4D 49 00 EOR #&00 ;null invert for 1770 BF4F 8D 87 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 # elif defined _A17705 ; ;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 BEAC F0 10 BEQ SEBE ;else read memory then ignore interrupt BEAE AD 00 0D LDA &0D00 BEB1 49 00 EOR #&00 ;null invert for 1770 BEB3 8D 87 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 BEC8 F0 08 BEQ SED2 BECA AD E5 FE LDA tubeR3data ;Fetch from Tube FIFO 3 BECD 49 00 EOR #&00 ;null invert for 1770 BECF 8D 87 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 BEDC F0 10 BEQ SEEE BEDE AD 87 FE LDA fdc_data BEE1 49 00 EOR #&00 ;null 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 BEF8 F0 08 BEQ SF02 BEFA AD 87 FE LDA fdc_data ;fetch from data register BEFD 49 00 EOR #&00 ;null 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 BF0C F0 14 BEQ SF22 BF0E AD 87 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 BF24 40 RTI BF25 85 A0 STA &A0 ;NMI read ID Tube BF27 A9 02 LDA #&02 BF29 2C 84 FE BIT fdc_stat BF2C F0 0C BEQ SF3A BF2E AD 87 FE LDA fdc_data ;fetch from data register BF31 49 00 EOR #&00 ;null invert for 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 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 BF48 F0 13 BEQ SF5D BF4A AD 00 0E LDA &0E00 ;get byte from table BF4D 49 00 EOR #&00 ;null invert for 1770 BF4F 8D 87 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 # elif defined _M17705 ; ;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 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 ;null invert for 1770 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 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 ;null invert for 1770 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 28 FE BIT fdc_stat BEDC F0 10 BEQ SEEE BEDE AD 2B FE LDA fdc_data BEE1 49 00 EOR #&00 ;null 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 28 FE BIT fdc_stat BEF8 F0 08 BEQ SF02 BEFA AD 2B FE LDA fdc_data ;fetch from data register BEFD 49 00 EOR #&00 ;null 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 28 FE BIT fdc_stat BF0C F0 14 BEQ SF22 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 BF24 40 RTI BF25 85 A0 STA &A0 ;NMI read ID Tube BF27 A9 02 LDA #&02 BF29 2C 28 FE BIT fdc_stat BF2C F0 0C BEQ SF3A BF2E AD 2B FE LDA fdc_data ;fetch from data register BF31 49 00 EOR #&00 ;null invert for 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 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 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 ;null invert for 1770 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 # elif defined _PG4005 ; ;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 C4 FC 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 ;null invert for 1770 BEB3 8D C7 FC 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 C4 FC BIT fdc_stat BEC8 F0 08 BEQ SED2 BECA AD E5 FE LDA tubeR3data ;Fetch from Tube FIFO 3 BECD 49 00 EOR #&00 ;null invert for 1770 BECF 8D C7 FC 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 C4 FC BIT fdc_stat BEDC F0 10 BEQ SEEE BEDE AD C7 FC LDA fdc_data BEE1 49 00 EOR #&00 ;null 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 C4 FC BIT fdc_stat BEF8 F0 08 BEQ SF02 BEFA AD C7 FC LDA fdc_data ;fetch from data register BEFD 49 00 EOR #&00 ;null 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 C4 FC BIT fdc_stat BF0C F0 14 BEQ SF22 BF0E AD C7 FC 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 BF24 40 RTI BF25 85 A0 STA &A0 ;NMI read ID Tube BF27 A9 02 LDA #&02 BF29 2C C4 FC BIT fdc_stat BF2C F0 0C BEQ SF3A BF2E AD C7 FC LDA fdc_data ;fetch from data register BF31 49 00 EOR #&00 ;null invert for 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 C7 FC 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 C4 FC BIT fdc_stat BF48 F0 13 BEQ SF5D BF4A AD 00 0E LDA &0E00 ;get byte from table BF4D 49 00 EOR #&00 ;null invert for 1770 BF4F 8D C7 FC 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 # else /* _O27915 */ ; ;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 80 FE BIT fdc_stat BEAC D0 10 BNE SEBE ;else read memory then ignore interrupt BEAE AD 00 0D LDA &0D00 BEB1 49 FF EOR #&FF ;invert for 2791 BEB3 8D 83 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 80 FE BIT fdc_stat BEC8 D0 08 BNE SED2 BECA AD E5 FE LDA tubeR3data ;Fetch from Tube FIFO 3 BECD 49 FF EOR #&FF ;invert for 2791 BECF 8D 83 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 80 FE BIT fdc_stat BEDC D0 10 BNE SEEE BEDE AD 83 FE LDA fdc_data BEE1 49 FF EOR #&FF ;invert for 2791 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 80 FE BIT fdc_stat BEF8 D0 08 BNE SF02 BEFA AD 83 FE LDA fdc_data ;fetch from data register BEFD 49 FF EOR #&FF ;invert for 2791 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 80 FE BIT fdc_stat BF0C D0 14 BNE SF22 BF0E AD 83 FE LDA fdc_data ;read data register BF11 49 FF EOR #&FF ;invert for 2791 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 BF24 40 RTI BF25 85 A0 STA &A0 ;NMI read ID Tube BF27 A9 02 LDA #&02 BF29 2C 80 FE BIT fdc_stat BF2C D0 0C BNE SF3A BF2E AD 83 FE LDA fdc_data ;fetch from data register BF31 49 FF EOR #&FF ;invert for 2791 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 83 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 80 FE BIT fdc_stat BF48 D0 13 BNE SF5D BF4A AD 00 0E LDA &0E00 ;get byte from table BF4D 49 FF EOR #&FF ;invert for 2791 BF4F 8D 83 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 # endif /* _O27935 */ .SF60 BF60 2C 8F 02 BIT &028F ;Jump to disc operation busywait BF63 10 03 BPL SF68 ;with hook if kybd 1 link made. .SF65 BF65 4C 20 0D JMP &0D20 .SF68 BF68 4C 65 BF JMP SF65 #endif /* _EP565 */ BFFF 00 BRK ;make 16 KiB ROM image ;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 ;00A5 Temp. 2791 command (may not be the exact one issued) ;00A6 >0 = Disc op is transferring to Tube ;00A7 Temporary for status after disc operation ;00A8 Catalogue flag in medium *commands 0=empty 1=clean >1=dirty ;00A8..A9 Pointer to CHRN table in *FORMAT ;00A8..A9 Pointer to private page when stowing/restoring workspace ;00A9..AA Pointer to backup/copy second catalogue buffer ;00AA..AB Pointer to extended vector table while setting up FS ;00AB Pointer to first free entry in catalogue 2 ;00AC High byte of data buffer address, low byte = 0 ;00AD Data buffer size in pages ;00AE Sector count in *BACKUP, *COPY ;00AF Temporary for Y in *BACKUP, *COPY: 0=source 1=target ;00B2..B3 Pointer to parameter byte in get byte immediate ;00B2..B3 Pointer to hex word in print-absolute ;00B2..B3 Pointer to source in copy memory absolute ;00B4..B5 Pointer to target in copy memory absolute ;00B6 No. bytes to copy in copy memory absolute ;00B7 Indexing argument in copy memory 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 ;00BA..BB Temporary count of sectors remaining in extended load/save ;00BC..BD Pointer to user memory in OSGBPB ;00BE..BF Pointer to user's OSGBPB block ;00BC..BF Temporary copy of pointer from 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) ;00CA..CB Pointer to user memory while transferring last sector of file ;00CC Pointer to file entry in catalogue ;00CD Microcode shift register in OSGBPB, OSFIND/OSARGS, OSFILE, ; OSWORD &7F ; (in Q815) b7=0 Close file b7=1 Flush file only ;00CE 0=ambiguous spec not allowed 1=ambiguous spec allowed, ; current spec is specific &FF=current spec is ambiguous ;0100 Offset of next character of error message (from &0100); >=1 ;0100 BRK instruction followed by error message ;0101 Error number ;0102..24 Error message string terminated by NUL ; (longest error may be "Deleted data read on drive 0.79.17") ;0120..23 Trampoline to fetch byte of control block for monitor print ;02A1,Y ROM type byte (Y=?&F4) ; b3=Error message is being prepared ; b2=*SPOOL output was enabled before printing EDOS message ; NB Illegal usage; b3..0 reserved as CPU type field ;0D5E Retry counter in Read ID command ;0D5E 0 = accept deleted data, &FF = scrub deleted data ;0D5F ID of previous NMI owner during disc operation ;0DF0,X High byte of address of private page (X=?&F4) ;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..57 Catalogue block 1 ;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..6F Catalogue block 2, for creating catalogue entries ;1058..64 OSCLI boot command string ;1058..5B Address parameter (32 bit, used by *ADDRESS) ;105C Temporary workspace used by *ADDRESS ;1060..61 Result from 'calculate free space on volume' routine ;1060..61 Input to 'print decimal word' routine ;1060..62 Load address (18 bit, used by *ADDRESS) ;1063..65 Execution address (18 bit, used by *ADDRESS) ;1060..6F Table from &9A1E..2D for newly created files ;1060..62 cf. 1048..4A Load address of new file (18 bit) ;1063..65 cf. 104B..4D Execution address of new file (18 bit) ;1066..68 cf. 104E..50 Initial file length ;1069..6A cf. 1051..52 Absolute end sector (last used +1) ;106B..6C cf. 1053..54 Desired sector allocation ;106D Overwritten during OSFILE 0 ;1070..81 OSFILE/OSGBPB block ;107F..81 Temporary copy of file pointer during OSARGS, OSGBPB ;1070..81 Workspace used by *BACKUP and *COPY ;1070 Source drive ;1071 Target drive ;1072 Source volume ;1073 Target volume ;1074..75 =&13,&0B 8271 read/write commands for source, target ;1076..77 Low byte of sectors-to-go for source, target ;1078..79 High byte of sectors-to-go for source, target ;107A..7B Low byte of start sector for source, target ;107C..7D High byte of start sector for source, target ;1080 b7 = Single disc operation (*COMPACT) ; b6 = Prompt to change discs b0 = b6? ;1081 High byte of volume size of source disc ; (to select 18/19 bit fields in catalogue 2) ;1070..81 Workspace used by *FORMAT, *CATGEN ;1070..73 Density,tracks,track stepping,volumes ;1072 Pointer to *command table entry in *CATGEN ;1074 Outstep (track skew) ;1076 4 * sector count (density) ;1077 Sector iterator ;1078..7F No. tracks in each volume of disc to format ;1080 1 + Maximum number of tracks per volume ;1081 Total number of tracks allocated to volumes ;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 -D_O27915 -b 8000 -o o27915 ep705.asm.txt ; perl asm2bin.pl -D_O27935 -b 8000 -o o27935 ep705.asm.txt ; perl asm2bin.pl -D_O17705 -b 8000 -o o17705 ep705.asm.txt ; perl asm2bin.pl -D_CHALL5 -b 8000 -o chall5 ep705.asm.txt ; perl asm2bin.pl -D_W17705 -b 8000 -o w17705 ep705.asm.txt ; perl asm2bin.pl -D_A17705 -b 8000 -o a17705 ep705.asm.txt ; perl asm2bin.pl -D_M17705 -b 8000 -o m17705 ep705.asm.txt ; perl asm2bin.pl -D_PG4005 -b 8000 -o pg4005 ep705.asm.txt ; perl asm2bin.pl -D_O27914 -b 8000 -o o27914 ep705.asm.txt ; perl asm2bin.pl -D_A17724 -b 8000 -o a17724 ep705.asm.txt ; perl asm2bin.pl -D_M17724 -b 8000 -o m17724 ep705.asm.txt ;-------->8--- ;#!/usr/bin/perl ; ;#Usage: perl asm2bin.pl ;# {-D SYMBOL[=VALUE]} [-E|-d] [-b BASE] ;# -o OUTFILE [FILE...] ; ;use Getopt::Std; ;use IO::Seekable qw(SEEK_SET SEEK_CUR SEEK_END); ; ;@x=(2); $t[6]=2; $t[7]=4; ; ;for($i=0;$i<@ARGV && ($arg = $ARGV[$i]) ne '--'; ++$i) { ; if(substr($arg,0,2) eq '-D') { ; if(($dfn=substr($arg,2)) eq '') { ; $dfn = $ARGV[++$i]; ; } ; if(($x=index($dfn,'=')) > 0) { ; $symbol{substr($dfn,0,$x)} = substr($dfn,$x+1); ; } elsif($dfn ne '') { ; $symbol{$dfn} = 1; ; } ; } ;} ; ;getopts("D:Eb:do:"); ;die "No output file specified" if $opt_o eq ''; ;$opt_b = hex($opt_b); ; ;open(BIN,"+>$opt_o") or die; ;binmode(BIN) unless $opt_E; ;while(<>) { ; y/\n\r//d; ; if(substr($_,0,1) ne '#') { ; while(($key, $value) = each %symbol) { ; $x=0; ; while(($x = index($_,$key,$x)) >= 0) { ; substr($_,$x,length($key),$value); ; $x+=length($value); ; } ; } ; } ; if(/^#\s*()ifdef\s+(\S*)$/ ; || /^#\s*((?:el)?)if\s+defined\s*\(\s*(\S*)\s*\)/ ; || /^#\s*((?:el)?)if\s+defined\s*(\S*)/) { ; unshift@x,4 if$1 eq''; ; $x[0]=$t[$x[0]|$x[1]&2|!exists($symbol{$2})];$_=''; ; }elsif(/^#\s*()ifndef\s+(\S*)$/ ; || /^#\s*((?:el)?)if\s+\!\s*defined\s*\(\s*(\S*)\s*\)/ ; || /^#\s*((?:el)?)if\s+\!\s*defined\s*(\S*)/) { ; unshift@x,4 if$1 eq''; ; $x[0]=$t[$x[0]|$x[1]&2|exists($symbol{$2})];$_=''; ; }elsif(/^#\s*((?:el)?)if\s+\!\s*(\S*)\s*$/) { ; unshift@x,4 if$1 eq''; ; $x[0]=$t[$x[0]|$x[1]&2|($2 !=0)];$_=''; ; }elsif(/^#\s*((?:el)?)if\s+(\S*)\s*$/) { ; unshift@x,4 if$1 eq''; ; $x[0]=$t[$x[0]|$x[1]&2|($2 ==0)];$_=''; ; }elsif(/^#\s*else(?!\S)/) { ; $x[0]=$t[$x[0]|$x[1]&2];$_=''; ; }elsif(/^#\s*endif(?!\S)/) { ; shift@x;@x=(2)unless@x;$_=''; ; }elsif($x[0] & 2 && /^#\s*define\s+(\S+)\s*(.*)$/) { ; $symbol{$1}=$2;$_=''; ; }elsif($x[0] & 2 && /^#\s*undef\s+(\S+)/) { ; delete $symbol{$1};$_=''; ; } ; if($opt_E) { ; print BIN ($x[0] & 2 ? $_ : ''), "\n"; next; ; }elsif(($x[0] & 2)==0) { ; next; ; } ; 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 ep705.asm.txt